summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md8
-rw-r--r--lib/prelude.nim6
-rw-r--r--lib/pure/parseopt.nim285
-rw-r--r--tests/js/tstdlib_imports.nim2
-rw-r--r--tests/test_nimscript.nims8
5 files changed, 165 insertions, 144 deletions
diff --git a/changelog.md b/changelog.md
index 5adb15ff9..3e85d2d05 100644
--- a/changelog.md
+++ b/changelog.md
@@ -147,6 +147,14 @@ provided by the operating system.
   issues like https://github.com/nim-lang/Nim/issues/13063 (which affected error messages)
   for modules importing `std/wrapnils`.
 
+- `parseopt.initOptParser` has been made available and `parseopt` has been
+  added back to `prelude` for all backends. Previously `initOptParser` was
+  unavailable if the `os` module did not have `paramCount` or `paramStr`,
+  but the use of these in `initOptParser` were conditionally to the runtime
+  arguments passed to it, so `initOptParser` has been changed to raise
+  `ValueError` when the real command line is not available. `parseopt` was
+  previously excluded from `prelude` for JS, as it could not be imported.
+
 ## Language changes
 
 - `nimscript` now handles `except Exception as e`.
diff --git a/lib/prelude.nim b/lib/prelude.nim
index 4d8c7d7f0..e8f21fc99 100644
--- a/lib/prelude.nim
+++ b/lib/prelude.nim
@@ -16,8 +16,6 @@
 ## Same as:
 ##
 ## .. code-block:: nim
-##   import os, strutils, times, parseutils, hashes, tables, sets, sequtils
-##   when not defined(js): import parseopt
+##   import os, strutils, times, parseutils, hashes, tables, sets, sequtils, parseopt
 
-import os, strutils, times, parseutils, hashes, tables, sets, sequtils
-when not defined(js): import parseopt
+import os, strutils, times, parseutils, hashes, tables, sets, sequtils, parseopt
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index e9e1e0e91..e79e53bd8 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -192,83 +192,94 @@ proc parseWord(s: string, i: int, w: var string,
       add(w, s[result])
       inc(result)
 
-when declared(os.paramCount):
-  # we cannot provide this for NimRtl creation on Posix, because we can't
-  # access the command line arguments then!
-
-  proc initOptParser*(cmdline = "", shortNoVal: set[char] = {},
-                      longNoVal: seq[string] = @[];
-                      allowWhitespaceAfterColon = true): OptParser =
-    ## Initializes the command line parser.
-    ##
-    ## If ``cmdline == ""``, the real command line as provided by the
-    ## ``os`` module is retrieved instead.
-    ##
-    ## ``shortNoVal`` and ``longNoVal`` are used to specify which options
-    ## do not take values. See the `documentation about these
-    ## parameters<#shortnoval-and-longnoval>`_ for more information on
-    ## how this affects parsing.
-    ##
-    ## See also:
-    ## * `getopt iterator<#getopt.i,OptParser>`_
-    runnableExamples:
-      var p = initOptParser()
-      p = initOptParser("--left --debug:3 -l -r:2")
-      p = initOptParser("--left --debug:3 -l -r:2",
-                        shortNoVal = {'l'}, longNoVal = @["left"])
+proc initOptParser*(cmdline = "", shortNoVal: set[char] = {},
+                    longNoVal: seq[string] = @[];
+                    allowWhitespaceAfterColon = true): OptParser =
+  ## Initializes the command line parser.
+  ##
+  ## If ``cmdline == ""``, the real command line as provided by the
+  ## ``os`` module is retrieved instead if it is available. If the
+  ## command line is not available, a `ValueError` will be raised.
+  ##
+  ## ``shortNoVal`` and ``longNoVal`` are used to specify which options
+  ## do not take values. See the `documentation about these
+  ## parameters<#shortnoval-and-longnoval>`_ for more information on
+  ## how this affects parsing.
+  ##
+  ## See also:
+  ## * `getopt iterator<#getopt.i,OptParser>`_
+  runnableExamples:
+    var p = initOptParser()
+    p = initOptParser("--left --debug:3 -l -r:2")
+    p = initOptParser("--left --debug:3 -l -r:2",
+                      shortNoVal = {'l'}, longNoVal = @["left"])
 
-    result.pos = 0
-    result.idx = 0
-    result.inShortState = false
-    result.shortNoVal = shortNoVal
-    result.longNoVal = longNoVal
-    result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
-    if cmdline != "":
-      result.cmds = parseCmdLine(cmdline)
+  result.pos = 0
+  result.idx = 0
+  result.inShortState = false
+  result.shortNoVal = shortNoVal
+  result.longNoVal = longNoVal
+  result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
+  if cmdline != "":
+    result.cmds = parseCmdLine(cmdline)
+  else:
+    when declared(paramCount):
+      result.cmds = newSeq[string](paramCount())
+      for i in countup(1, paramCount()):
+        result.cmds[i-1] = paramStr(i)
     else:
-      result.cmds = newSeq[string](os.paramCount())
-      for i in countup(1, os.paramCount()):
-        result.cmds[i-1] = os.paramStr(i)
+      # we cannot provide this for NimRtl creation on Posix, because we can't
+      # access the command line arguments then!
+      doAssert false, "empty command line given but" &
+        " real command line is not accessible"
 
-    result.kind = cmdEnd
-    result.key = ""
-    result.val = ""
+  result.kind = cmdEnd
+  result.key = ""
+  result.val = ""
 
-  proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
-                      longNoVal: seq[string] = @[];
-                      allowWhitespaceAfterColon = true): OptParser =
-    ## Initializes the command line parser.
-    ##
-    ## If ``cmdline.len == 0``, the real command line as provided by the
-    ## ``os`` module is retrieved instead. Behavior of the other parameters
-    ## remains the same as in `initOptParser(string, ...)
-    ## <#initOptParser,string,set[char],seq[string]>`_.
-    ##
-    ## See also:
-    ## * `getopt iterator<#getopt.i,seq[string],set[char],seq[string]>`_
-    runnableExamples:
-      var p = initOptParser()
-      p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"])
-      p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"],
-                        shortNoVal = {'l'}, longNoVal = @["left"])
+proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
+                    longNoVal: seq[string] = @[];
+                    allowWhitespaceAfterColon = true): OptParser =
+  ## Initializes the command line parser.
+  ##
+  ## If ``cmdline.len == 0``, the real command line as provided by the
+  ## ``os`` module is retrieved instead if it is available. If the
+  ## command line is not available, a `ValueError` will be raised.
+  ## Behavior of the other parameters remains the same as in
+  ## `initOptParser(string, ...)
+  ## <#initOptParser,string,set[char],seq[string]>`_.
+  ##
+  ## See also:
+  ## * `getopt iterator<#getopt.i,seq[string],set[char],seq[string]>`_
+  runnableExamples:
+    var p = initOptParser()
+    p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"])
+    p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"],
+                      shortNoVal = {'l'}, longNoVal = @["left"])
 
-    result.pos = 0
-    result.idx = 0
-    result.inShortState = false
-    result.shortNoVal = shortNoVal
-    result.longNoVal = longNoVal
-    result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
-    if cmdline.len != 0:
-      result.cmds = newSeq[string](cmdline.len)
-      for i in 0..<cmdline.len:
-        result.cmds[i] = cmdline[i]
+  result.pos = 0
+  result.idx = 0
+  result.inShortState = false
+  result.shortNoVal = shortNoVal
+  result.longNoVal = longNoVal
+  result.allowWhitespaceAfterColon = allowWhitespaceAfterColon
+  if cmdline.len != 0:
+    result.cmds = newSeq[string](cmdline.len)
+    for i in 0..<cmdline.len:
+      result.cmds[i] = cmdline[i]
+  else:
+    when declared(paramCount):
+      result.cmds = newSeq[string](paramCount())
+      for i in countup(1, paramCount()):
+        result.cmds[i-1] = paramStr(i)
     else:
-      result.cmds = newSeq[string](os.paramCount())
-      for i in countup(1, os.paramCount()):
-        result.cmds[i-1] = os.paramStr(i)
-    result.kind = cmdEnd
-    result.key = ""
-    result.val = ""
+      # we cannot provide this for NimRtl creation on Posix, because we can't
+      # access the command line arguments then!
+      doAssert false, "empty command line given but" &
+        " real command line is not accessible"
+  result.kind = cmdEnd
+  result.key = ""
+  result.val = ""
 
 proc handleShortOption(p: var OptParser; cmd: string) =
   var i = p.pos
@@ -366,23 +377,24 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
     inc p.idx
     p.pos = 0
 
-proc cmdLineRest*(p: OptParser): string {.rtl, extern: "npo$1".} =
-  ## Retrieves the rest of the command line that has not been parsed yet.
-  ##
-  ## See also:
-  ## * `remainingArgs proc<#remainingArgs,OptParser>`_
-  ##
-  ## **Examples:**
-  ##
-  ## .. code-block::
-  ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
-  ##   while true:
-  ##     p.next()
-  ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
-  ##       break
-  ##     else: continue
-  ##   doAssert p.cmdLineRest == "foo.txt bar.txt"
-  result = p.cmds[p.idx .. ^1].quoteShellCommand
+when declared(quoteShellCommand):
+  proc cmdLineRest*(p: OptParser): string {.rtl, extern: "npo$1".} =
+    ## Retrieves the rest of the command line that has not been parsed yet.
+    ##
+    ## See also:
+    ## * `remainingArgs proc<#remainingArgs,OptParser>`_
+    ##
+    ## **Examples:**
+    ##
+    ## .. code-block::
+    ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
+    ##   while true:
+    ##     p.next()
+    ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
+    ##       break
+    ##     else: continue
+    ##   doAssert p.cmdLineRest == "foo.txt bar.txt"
+    result = p.cmds[p.idx .. ^1].quoteShellCommand
 
 proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
   ## Retrieves a sequence of the arguments that have not been parsed yet.
@@ -442,54 +454,53 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
     if p.kind == cmdEnd: break
     yield (p.kind, p.key, p.val)
 
-when declared(initOptParser):
-  iterator getopt*(cmdline: seq[string] = commandLineParams(),
-                   shortNoVal: set[char] = {}, longNoVal: seq[string] = @[]):
-             tuple[kind: CmdLineKind, key, val: string] =
-    ## Convenience iterator for iterating over command line arguments.
-    ##
-    ## This creates a new `OptParser<#OptParser>`_. If no command line
-    ## arguments are provided, the real command line as provided by the
-    ## ``os`` module is retrieved instead.
-    ##
-    ## ``shortNoVal`` and ``longNoVal`` are used to specify which options
-    ## do not take values. See the `documentation about these
-    ## parameters<#shortnoval-and-longnoval>`_ for more information on
-    ## how this affects parsing.
-    ##
-    ## There is no need to check for ``cmdEnd`` while iterating.
-    ##
-    ## See also:
-    ## * `initOptParser proc<#initOptParser,seq[string],set[char],seq[string]>`_
-    ##
-    ## **Examples:**
-    ##
-    ## .. code-block::
-    ##
-    ##   # these are placeholders, of course
-    ##   proc writeHelp() = discard
-    ##   proc writeVersion() = discard
-    ##
-    ##   var filename: string
-    ##   let params = @["--left", "--debug:3", "-l", "-r:2"]
-    ##
-    ##   for kind, key, val in getopt(params):
-    ##     case kind
-    ##     of cmdArgument:
-    ##       filename = key
-    ##     of cmdLongOption, cmdShortOption:
-    ##       case key
-    ##       of "help", "h": writeHelp()
-    ##       of "version", "v": writeVersion()
-    ##     of cmdEnd: assert(false) # cannot happen
-    ##   if filename == "":
-    ##     # no filename has been written, so we show the help
-    ##     writeHelp()
-    var p = initOptParser(cmdline, shortNoVal = shortNoVal,
-        longNoVal = longNoVal)
-    while true:
-      next(p)
-      if p.kind == cmdEnd: break
-      yield (p.kind, p.key, p.val)
+iterator getopt*(cmdline: seq[string] = @[],
+                  shortNoVal: set[char] = {}, longNoVal: seq[string] = @[]):
+            tuple[kind: CmdLineKind, key, val: string] =
+  ## Convenience iterator for iterating over command line arguments.
+  ##
+  ## This creates a new `OptParser<#OptParser>`_. If no command line
+  ## arguments are provided, the real command line as provided by the
+  ## ``os`` module is retrieved instead.
+  ##
+  ## ``shortNoVal`` and ``longNoVal`` are used to specify which options
+  ## do not take values. See the `documentation about these
+  ## parameters<#shortnoval-and-longnoval>`_ for more information on
+  ## how this affects parsing.
+  ##
+  ## There is no need to check for ``cmdEnd`` while iterating.
+  ##
+  ## See also:
+  ## * `initOptParser proc<#initOptParser,seq[string],set[char],seq[string]>`_
+  ##
+  ## **Examples:**
+  ##
+  ## .. code-block::
+  ##
+  ##   # these are placeholders, of course
+  ##   proc writeHelp() = discard
+  ##   proc writeVersion() = discard
+  ##
+  ##   var filename: string
+  ##   let params = @["--left", "--debug:3", "-l", "-r:2"]
+  ##
+  ##   for kind, key, val in getopt(params):
+  ##     case kind
+  ##     of cmdArgument:
+  ##       filename = key
+  ##     of cmdLongOption, cmdShortOption:
+  ##       case key
+  ##       of "help", "h": writeHelp()
+  ##       of "version", "v": writeVersion()
+  ##     of cmdEnd: assert(false) # cannot happen
+  ##   if filename == "":
+  ##     # no filename has been written, so we show the help
+  ##     writeHelp()
+  var p = initOptParser(cmdline, shortNoVal = shortNoVal,
+      longNoVal = longNoVal)
+  while true:
+    next(p)
+    if p.kind == cmdEnd: break
+    yield (p.kind, p.key, p.val)
 
 {.pop.}
diff --git a/tests/js/tstdlib_imports.nim b/tests/js/tstdlib_imports.nim
index 7611b7dcb..6fe3772d3 100644
--- a/tests/js/tstdlib_imports.nim
+++ b/tests/js/tstdlib_imports.nim
@@ -46,7 +46,7 @@ import std/[
 
   # Parsers:
   htmlparser, json, lexbase, parsecfg, parsecsv, parsesql, parsexml,
-  # fails: parseopt
+  parseopt,
 
   # XML processing:
   xmltree, xmlparser,
diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims
index 9bfdff55e..2468699a4 100644
--- a/tests/test_nimscript.nims
+++ b/tests/test_nimscript.nims
@@ -48,7 +48,7 @@ import std/[
 
   # Parsers:
   htmlparser, json, lexbase, parsecfg, parsecsv, parsesql, parsexml,
-  # fails: parseopt
+  parseopt,
 
   # XML processing:
   xmltree, xmlparser,
@@ -113,4 +113,8 @@ block:  # cpDir, cpFile, dirExists, fileExists, mkDir, mvDir, mvFile, rmDir, rmF
   doAssert not dirExists(subDir)
   doAssert dirExists(subDir2)
   mvDir(subDir2, subDir)
-  rmDir(dname)
\ No newline at end of file
+  rmDir(dname)
+
+block:
+  # check parseopt can get command line:
+  discard initOptParser()