CmdLineParser.st
branchjv
changeset 20076 ff2f4d06a2fa
parent 19989 cac9cb31ce9e
child 20077 e0e720fce465
--- a/CmdLineParser.st	Tue Jun 28 07:34:09 2016 +0100
+++ b/CmdLineParser.st	Wed Jun 29 00:18:22 2016 +0100
@@ -14,7 +14,7 @@
 "{ NameSpace: Smalltalk }"
 
 Object subclass:#CmdLineParser
-	instanceVariableNames:'options argv'
+	instanceVariableNames:'options ignoreUnknownOptions'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'System-Support-Command line'
@@ -36,6 +36,14 @@
 "
 ! !
 
+!CmdLineParser class methodsFor:'instance creation'!
+
+new
+    "return an initialized instance"
+
+    ^ self basicNew initialize.
+! !
+
 !CmdLineParser class methodsFor:'parsing'!
 
 parse: argv for: object
@@ -47,17 +55,6 @@
 
 !CmdLineParser methodsFor:'accessing'!
 
-args
-    ^ argv
-!
-
-args:aCollection
-
-    argv := aCollection
-
-    "Modified: / 08-06-2009 / 13:24:02 / Jan Vrany <vranyj1@fel.cvut.cz>"
-!
-
 cmdlineOptionHelp
 
     ^CmdLineOption new
@@ -69,6 +66,21 @@
     "Created: / 08-06-2009 / 14:54:11 / Jan Vrany <vranyj1@fel.cvut.cz>"
 !
 
+ignoreUnknownOptions
+    ^ ignoreUnknownOptions
+!
+
+ignoreUnknownOptions:aBoolean
+    "When set to true, unknown options are silently ignored and added to
+     a list of positional arguments returned by #parse:.
+     When set to false, an error is triggered when an unknown option is 
+     encountered (this is the default behaviour)"
+
+    ignoreUnknownOptions := aBoolean.
+
+    "Modified (comment): / 29-06-2016 / 00:03:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 options
     ^ options
 !
@@ -130,45 +142,55 @@
 
     "Created: / 08-06-2009 / 13:06:23 / Jan Vrany <vranyj1@fel.cvut.cz>"
     "Modified: / 06-11-2011 / 21:40:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+initialize
+    "Invoked when a new instance is created."
+
+    "/ please change as required (and remove this comment)
+    "/ options := nil.
+    ignoreUnknownOptions := false.
+
+    "/ super initialize.   -- commented since inherited method does nothing
+
+    "Modified: / 29-06-2016 / 00:04:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !CmdLineParser methodsFor:'parsing'!
 
-parse 
+parse: argv 
     "
-     Parses argv array. 
-     Returns array of unparsed (i.e. non-option) arguments
+     Parses argv array. Returns array of unparsed (i.e. non-options / unknown options) arguments
     "
 
-    | i |
-    i := 1.
-    [i <= argv size] whileTrue:
-        [|arg option |
-        arg := argv at:i.
-        "arg is not an option"
-        arg first ~= $-
-            ifTrue:
-                [^argv copyFrom: i].
-        i := self parseArg: i
-    ].
-    ^#()
+    | unparsed current |
+
+    unparsed := OrderedCollection new.
+    current := 1.
+    [current <= argv size] whileTrue: [ 
+        | arg next |
 
-    "Created: / 08-06-2009 / 13:26:22 / Jan Vrany <vranyj1@fel.cvut.cz>"
-    "Modified: / 08-06-2009 / 14:38:33 / Jan Vrany <vranyj1@fel.cvut.cz>"
-!
-
-parse:aCollection 
-    "
-     Parses argv array. Returns array of unparsed (i.e. non-option)
-     arguments
-    "
-
-    ^self
-        args: aCollection;
-        parse.
+        arg := argv at:current.
+        arg first == $- ifTrue:[
+            "/ maybe an option
+            next := self parse: argv argAt: current.
+            next == 0 ifTrue:[
+                "/ Option has not been recognized
+                unparsed add: arg.
+                next := current + 1.
+            ]
+        ] ifFalse:[ 
+            "/ not an option
+            unparsed addAll: (argv copyFrom: current).
+            next := argv size + 1.
+        ].
+        current := next.
+    ].
+    ^ unparsed
 
     "Created: / 28-01-2009 / 12:08:29 / Jan Vrany <vranyj1@fel.cvut.cz>"
     "Modified: / 08-06-2009 / 13:26:26 / Jan Vrany <vranyj1@fel.cvut.cz>"
+    "Modified: / 29-06-2016 / 00:15:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 parse: argv for: object
@@ -224,10 +246,11 @@
         ifNone:[ 
             longName = 'help' 
                 ifTrue:[self cmdlineOptionHelp]
-                ifFalse:[CmdLineOptionError raiseErrorString:'Unknown option: ' , longName ]]
+                ifFalse:[ignoreUnknownOptions ifTrue:[nil] ifFalse:[CmdLineOptionError raiseErrorString:'Unknown option: ' , longName ]]]
 
     "Created: / 30-01-2009 / 09:15:24 / Jan Vrany <vranyj1@fel.cvut.cz>"
     "Modified: / 08-06-2009 / 14:57:42 / Jan Vrany <vranyj1@fel.cvut.cz>"
+    "Modified: / 29-06-2016 / 00:05:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 optionByShort:shortName 
@@ -236,64 +259,71 @@
         ifNone:
             [ shortName == $h 
                 ifTrue:[self cmdlineOptionHelp]
-                ifFalse:[CmdLineOptionError raiseErrorString:'Unknown option: ' , shortName ]]
+                ifFalse:[ignoreUnknownOptions ifTrue:[nil] ifFalse:[CmdLineOptionError raiseErrorString:'Unknown option: ' , shortName ]]]
 
     "Created: / 30-01-2009 / 09:16:51 / Jan Vrany <vranyj1@fel.cvut.cz>"
     "Modified: / 08-06-2009 / 14:58:14 / Jan Vrany <vranyj1@fel.cvut.cz>"
+    "Modified: / 29-06-2016 / 00:05:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-parseArg:index 
-    "
-        Parses arg at index. Returns an index of
-        next arg to be parsed."
+parse:argv argAt: index 
+    "Parses arg at index. Returns an index of next arg to be parsed. If the options
+     is not recognized (i.e., is unknown), then either an error is triggered 
+     (when ignoreInknownOptions is false) or 0 is returned (when ignoreInknownOptions
+     is true)"
     
     |arg option param|
 
     arg := argv at:index.
-    arg second ~= $- 
-    ifTrue:
-        ["/ short option or bunch of those
+    arg second ~= $- ifTrue:[
+        "/ short option or bunch of those
         2 to:arg size do:[:subIndex | 
             option := self optionByShort:(arg at:subIndex).
-            option ifNotNil:
-                [option hasParam 
-                    ifFalse:[option process]
-                    ifTrue:
-                        ["Do additional check, if this short option
-                        is last."
-                        ((subIndex ~= arg size) or:[ (argv size) < (index + 1) ]) ifTrue:[
-                            self errorOptionRequiresArgument:option
-                        ].
-                        param := (argv at:index + 1).
-                        option process:param.
-                        ^ index + 2
-                        ]]].
-           ^ index + 1]
-    ifFalse:
-        ["/ long option starting with --
+            option notNil ifTrue: [
+                option hasParam ifFalse:[
+                    option process
+                ] ifTrue:[
+                    "Do additional check, if this short option is last."
+                    ((subIndex ~= arg size) or:[ (argv size) < (index + 1) ]) ifTrue:[
+                        self errorOptionRequiresArgument:option
+                    ].
+                    param := (argv at:index + 1).
+                    option process:param.
+                    ^ index + 2
+                ]
+           ] ifFalse:[ 
+               ^ 0
+           ].
+        ].
+        ^ index + 1
+    ] ifFalse: [
+        "/ long option starting with --
         | equalPos |
 
         (equalPos := arg indexOf:$=) == 0 ifTrue:[
             "/no arg specified
-            (option := self optionByLong:(arg copyFrom:3))
-                ifNotNil:[
+            (option := self optionByLong:(arg copyFrom:3)) notNil ifTrue:[
                     option hasParam ifTrue:[self errorOptionRequiresArgument:option].
-                    option process].
-            ^index + 1.
+                    option process
+            ] ifFalse:[ 
+                ^ 0
+            ].
+            ^ index + 1.
         ] ifFalse: [
             option := self optionByLong:(arg copyFrom:3 to: equalPos - 1).
             param := arg copyFrom: equalPos + 1.
-            option ifNotNil:
-                [option hasParam
-                    ifTrue:
-                        [option process: param]
-                    ifFalse:
-                        [self errorOptionHasNoArgument: option]]
-                ].            
-            ^index + 2
-        ]
+            option notNil ifTrue:[
+                option hasParam
+                    ifTrue: [option process: param]
+                    ifFalse: [self errorOptionHasNoArgument: option]
+            ] ifFalse:[ 
+                ^ 0
+            ].
+        ].            
+        ^ index + 2
+    ]
 
-    "Created: / 08-06-2009 / 14:38:53 / Jan Vrany <vranyj1@fel.cvut.cz>"
+    "Created: / 28-06-2016 / 23:55:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !CmdLineParser class methodsFor:'documentation'!