summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-11-09 09:00:43 +0100
committerAndreas Rumpf <rumpf_a@web.de>2018-11-09 09:03:28 +0100
commitc0fc2f57263058b22d49b4d4d3222b40aa9e5f85 (patch)
tree5180a55d2142430c8acefb993a0dcd030ec980be
parentfdd09ad0902eb7967d7bffe7777cf2a12ca4d88a (diff)
downloadNim-c0fc2f57263058b22d49b4d4d3222b40aa9e5f85.tar.gz
fixes #9619
-rw-r--r--changelog.md5
-rw-r--r--lib/pure/parseopt.nim11
-rw-r--r--tests/misc/tparseopt.nim77
3 files changed, 55 insertions, 38 deletions
diff --git a/changelog.md b/changelog.md
index 1372faa62..54daa7379 100644
--- a/changelog.md
+++ b/changelog.md
@@ -72,6 +72,11 @@ proc enumToString*(enums: openArray[enum]): string =
 
 - Complex type is now generic and not a tuple anymore.
 
+- The `parseopt` module now supports a new flag `allowWhitespaceAfterColon`
+  (default value: true) that can be set to `false` for better Posix
+  interoperability. (Bug #9619.)
+
+
 ### Language additions
 
 - Vm suport for float32<->int32 and float64<->int64 casts was added.
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index c91134738..c4da88e1d 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -47,6 +47,7 @@ type
     cmd*: string              #  cmd,pos exported so caller can catch "--" as..
     pos*: int                 # ..empty key or subcmd cmdArg & handle specially
     inShortState: bool
+    allowWhitespaceAfterColon: bool
     shortNoVal: set[char]
     longNoVal: seq[string]
     cmds: seq[string]
@@ -95,7 +96,8 @@ when declared(os.paramCount):
   # access the command line arguments then!
 
   proc initOptParser*(cmdline = "", shortNoVal: set[char]={},
-                      longNoVal: seq[string] = @[]): OptParser =
+                      longNoVal: seq[string] = @[];
+                      allowWhitespaceAfterColon = true): OptParser =
     ## inits the option parser. If ``cmdline == ""``, the real command line
     ## (as provided by the ``OS`` module) is taken.  If ``shortNoVal`` is
     ## provided command users do not need to delimit short option keys and
@@ -108,6 +110,7 @@ when declared(os.paramCount):
     result.inShortState = false
     result.shortNoVal = shortNoVal
     result.longNoVal = longNoVal
+    result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
     if cmdline != "":
       result.cmd = cmdline
       result.cmds = parseCmdLine(cmdline)
@@ -124,7 +127,8 @@ when declared(os.paramCount):
     result.val = TaintedString""
 
   proc initOptParser*(cmdline: seq[TaintedString], shortNoVal: set[char]={},
-                      longNoVal: seq[string] = @[]): OptParser =
+                      longNoVal: seq[string] = @[];
+                      allowWhitespaceAfterColon = true): OptParser =
     ## inits the option parser. If ``cmdline.len == 0``, the real command line
     ## (as provided by the ``OS`` module) is taken. ``shortNoVal`` and
     ## ``longNoVal`` behavior is the same as for ``initOptParser(string,...)``.
@@ -133,6 +137,7 @@ when declared(os.paramCount):
     result.inShortState = false
     result.shortNoVal = shortNoVal
     result.longNoVal = longNoVal
+    result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
     result.cmd = ""
     if cmdline.len != 0:
       result.cmds = newSeq[string](cmdline.len)
@@ -210,7 +215,7 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
         inc(i)
         while i < p.cmds[p.idx].len and p.cmds[p.idx][i] in {'\t', ' '}: inc(i)
         # if we're at the end, use the next command line option:
-        if i >= p.cmds[p.idx].len and p.idx < p.cmds.len:
+        if i >= p.cmds[p.idx].len and p.idx < p.cmds.len and p.allowWhitespaceAfterColon:
           inc p.idx
           i = 0
         p.val = TaintedString p.cmds[p.idx].substr(i)
diff --git a/tests/misc/tparseopt.nim b/tests/misc/tparseopt.nim
index badbc59ad..651689398 100644
--- a/tests/misc/tparseopt.nim
+++ b/tests/misc/tparseopt.nim
@@ -9,6 +9,8 @@ kind: cmdLongOption	key:val  --  left:
 kind: cmdLongOption	key:val  --  debug:3
 kind: cmdShortOption	key:val  --  l:4
 kind: cmdShortOption	key:val  --  r:2
+cmdLongOption foo
+cmdLongOption path
 parseoptNoVal
 kind: cmdLongOption	key:val  --  left:
 kind: cmdLongOption	key:val  --  debug:3
@@ -34,44 +36,49 @@ from parseopt2 import nil
 
 
 block:
-    echo "parseopt"
-    for kind, key, val in parseopt.getopt():
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+  echo "parseopt"
+  for kind, key, val in parseopt.getopt():
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
 
-    # pass custom cmdline arguments
-    echo "first round"
-    var argv = "--left --debug:3 -l=4 -r:2"
-    var p = parseopt.initOptParser(argv)
-    for kind, key, val in parseopt.getopt(p):
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
-      break
-    # reset getopt iterator and check arguments are returned correctly.
-    echo "second round"
-    for kind, key, val in parseopt.getopt(p):
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+  # pass custom cmdline arguments
+  echo "first round"
+  var argv = "--left --debug:3 -l=4 -r:2"
+  var p = parseopt.initOptParser(argv)
+  for kind, key, val in parseopt.getopt(p):
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+    break
+  # reset getopt iterator and check arguments are returned correctly.
+  echo "second round"
+  for kind, key, val in parseopt.getopt(p):
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+
+  # bug #9619
+  var x = parseopt.initOptParser(@["--foo:", "--path"], allowWhitespaceAfterColon = false)
+  for kind, key, val in parseopt.getopt(x):
+    echo kind, " ", key
 
 block:
-    echo "parseoptNoVal"
-    # test NoVal mode with custom cmdline arguments
-    var argv = "--left --debug:3 -l -r:2 --debug 2 --debug=1 -r1 -r=0 -lr4"
-    var p = parseopt.initOptParser(argv,
-                                   shortNoVal = {'l'}, longNoVal = @["left"])
-    for kind, key, val in parseopt.getopt(p):
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+  echo "parseoptNoVal"
+  # test NoVal mode with custom cmdline arguments
+  var argv = "--left --debug:3 -l -r:2 --debug 2 --debug=1 -r1 -r=0 -lr4"
+  var p = parseopt.initOptParser(argv,
+                                  shortNoVal = {'l'}, longNoVal = @["left"])
+  for kind, key, val in parseopt.getopt(p):
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
 
 block:
-    echo "parseopt2"
-    for kind, key, val in parseopt2.getopt():
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+  echo "parseopt2"
+  for kind, key, val in parseopt2.getopt():
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
 
-    # pass custom cmdline arguments
-    echo "first round"
-    var argv: seq[string] = @["--left", "--debug:3", "-l=4", "-r:2"]
-    var p = parseopt2.initOptParser(argv)
-    for kind, key, val in parseopt2.getopt(p):
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
-      break
-    # reset getopt iterator and check arguments are returned correctly.
-    echo "second round"
-    for kind, key, val in parseopt2.getopt(p):
-      echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+  # pass custom cmdline arguments
+  echo "first round"
+  var argv: seq[string] = @["--left", "--debug:3", "-l=4", "-r:2"]
+  var p = parseopt2.initOptParser(argv)
+  for kind, key, val in parseopt2.getopt(p):
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val
+    break
+  # reset getopt iterator and check arguments are returned correctly.
+  echo "second round"
+  for kind, key, val in parseopt2.getopt(p):
+    echo "kind: ", kind, "\tkey:val  --  ", key, ":", val