Kommandozeile parsen

Schnipsel, Ideen und Lösungsvorschläge
Antworten
nibbana
Foriker
Beiträge: 143
Registriert: Fr 16. Dez 2005, 21:32
Kontaktdaten:

Kommandozeile parsen

Beitrag von nibbana » Do 22. Dez 2005, 21:21

Dann werde ich hier mal den Anfang wagen. Das ist mein erster Versuch etwas sinnvolles in gambas
zuschreiben. Also bitte nicht so sehr auf den Stil achten.

Was ist Linux ohne Shell? Und was ist die Kommonadozeile ohne Optionen? Deshalb mal ein Vorschlag für einen Optionsparser.

Code: Alles auswählen

' Gambas class file: OptParse.class

' Als erstes wird der Parser und 2 Variable declariert und erzeugt
' >> DIM parser as NEW OptParser
' >> DIM args as String[]
' >> DIM opts as Variant[]
'
' Dann werden alle Optionen angegeben. Die einzelnen Argumente:
'    1. langer Name, ein "=" kennzeichnet einen folgenden Parameter
'    2. kurzer Name, optional
'    3. ein Hilfetext, wird bei --help ausgegeben, optional
'    4. ein Defaultwert, optional
' >> parser.append("input=", "i", "input file name", "input.txt")
' >> parser.append("output=", "o", "output file name", "output.txt")
' >> parser.append("dummy1", "d")
' >> parser.append("dummy2")
'
' Der Parser kennt auch noch einige Property
' Eine kurze Hilfe für den Aufruf des Programms
' >> parser.usage(Application.name & " [opts] args")
' Ein Copyright-Vermerk
' >> parser.copyright("das stammt von mir")
' Ein eine kurze Erklärung
' >> parser.info("ein sinnloses Programm")
'
' Jetz erfolgt die eigentliche Arbeit
' >> parser.parse()
'
' Danach bekommt man eine Collection mit den langen Optionsnamen als Schlüssel
' >> opts = parser.opts
' und in einem String[] alle Argumente
' >> args = parser.args
'
' Noch ein Hinweis: Die Optionen --help -h und --version sind bereits
' vordefiniert

PRIVATE optListe AS NEW Variant[]
PRIVATE cHash AS NEW Collection
PRIVATE sArgs AS NEW String[]
PRIVATE sUsage AS String = ""
PRIVATE sCopyright AS String = ""
PRIVATE sInfo AS String = ""

PROPERTY READ opts AS Collection
PROPERTY READ args AS String[]
PROPERTY usage AS String
PROPERTY copyright AS String
PROPERTY info AS String

PUBLIC SUB append(longOpts AS Variant, OPTIONAL shortOpts AS String = "", OPTIONAL help AS String = "", OPTIONAL def AS String = "")

  DIM opt AS Variant[]

  opt = Array(longOpts, shortOpts, help, def)
  optListe.Push(opt)

END

PUBLIC SUB parse()

  DIM idx AS Integer
  DIM opt AS String
  DIM option AS Variant[]

  FOR EACH option IN optListe
    IF hasArg(option[0]) THEN
      cHash[Left(option[0], -1)] = option[3]
    ELSE
      cHash[option[0]] = option[3]
    ENDIF
  NEXT

  idx = 1
  WHILE idx < application.Args.count
    opt = application.Args[idx]
    INC idx

    IF opt = "-h" OR opt = "--help" THEN
      printHelp()
    ENDIF

    IF opt = "--version" THEN
      printVersion()
    ENDIF

    IF Left(opt, 2) = "--" THEN
      idx = getLongOpts(idx, Mid(opt, 3))
    ELSE IF Left(opt, 1) = "-" THEN
      idx = getShortOpts(idx, Mid(opt, 2))
    ELSE
      sArgs.Push(opt)
    ENDIF
  WEND

  CATCH
    PRINT "Fehler : " & ERROR.Text
    PRINT
    printHelp()

END

PRIVATE FUNCTION getLongOpts(idx AS Integer, opt AS String) AS Integer

  DIM lopt AS String
  DIM arg AS String
  DIM option AS Variant[]

  FOR EACH option IN optListe
    lopt = option[0]
    IF hasArg(lopt) THEN
      IF opt = Left(lopt, -1) THEN
        arg = Application.Args[idx]
        INC idx
        IF idx > application.Args.Count THEN
          Error.Raise("option --" & opt & " ohne parameter")
        ENDIF
        cHash[opt] = arg
        RETURN idx
      ENDIF
    ELSE
      IF opt = lopt THEN
        cHash[opt] = TRUE
        RETURN idx
      ENDIF
    ENDIF
  NEXT

  Error.Raise("unbekannte option --" & opt)

END

PRIVATE FUNCTION getShortOpts(idx AS Integer, opt AS String) AS Integer

  DIM option AS Variant[]
  DIM lopt AS String
  DIM arg AS String

  FOR EACH option IN optListe
    lopt = option[0]
    IF hasArg(lopt) THEN
      IF opt = option[1] THEN
        arg = Application.Args[idx]
        INC idx
        IF idx > application.Args.Count THEN
          Error.Raise("option -" & opt & " ohne parameter")
        ENDIF
        cHash[Left(lopt, -1)] = arg
        RETURN idx
      ENDIF
    ELSE
      IF opt = option[1] THEN
        cHash[lopt] = TRUE
        RETURN idx
      ENDIF
    ENDIF
  NEXT

  error.Raise("unbekannte option -" & opt)

END

PRIVATE SUB printVersion()

  PRINT application.Version
  QUIT

END

PRIVATE SUB printHelp()

  DIM opt AS Variant
  DIM txt AS String
  DIM lopt AS String
  DIM sopt AS String

  PRINT Application.Name & "  V." & Application.Version
  IF sUsage THEN
    PRINT "usage: " & sUsage
  ENDIF
  IF sCopyright THEN
    PRINT "(C) " & sCopyright
  ENDIF
  IF sInfo THEN
    PRINT
    PRINT sInfo
  ENDIF

  PRINT
  PRINT "options:"
  PRINT " --help \t-h\tshow this help message and exit"
  PRINT " --version\t\tshow program's version number and exit"
  FOR EACH opt IN optListe
    sopt = ""
    IF hasArg(opt[0]) THEN
      lopt = Subst("--&1&2", opt[0], Upper(Left(opt[0], -1)))
      IF opt[1] THEN
        sopt = Subst("-&1 &2", opt[1], Upper(Left(opt[0], -1)))
      ENDIF
    ELSE
      lopt = Subst("--&1", opt[0])
      IF opt[1] THEN
        sopt = Subst("-&1", opt[1])
      ENDIF
    ENDIF
    txt = Subst(" &1 \t&2 \t&3 [&4]", lopt, sopt, opt[2], opt[3])
    PRINT txt
  NEXT
  QUIT

END

PRIVATE FUNCTION hasArg(s AS String) AS Boolean
  RETURN Right(s, 1) = "="
END

FUNCTION opts_Read() AS Collection
  RETURN cHash
END

FUNCTION args_Read() AS String[]
  RETURN sArgs
END

FUNCTION usage_Read() AS String
  RETURN sUsage
END

SUB usage_Write(text AS String)
  sUsage = text
END

FUNCTION copyright_Read() AS String
  RETURN sCopyright
END

SUB copyright_Write(text AS String)
  sCopyright = text
END

FUNCTION info_Read() AS String
  RETURN sInfo
END

SUB info_Write(text AS String)
  sInfo = text
END


mfg.nibbana
"Ich denke, also bin ich." (Descartes)

"Ich denke nicht, also was?" (Zen Meister Seung Sahn)

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast