diff --git a/changelog.md b/changelog.md index 665346ad7009e..b17da9bde505c 100644 --- a/changelog.md +++ b/changelog.md @@ -35,6 +35,10 @@ errors. - Adds a new warning `--warning:ImplicitRangeConversion` that detects downsizing implicit conversions to range types (e.g., `int -> range[0..255]` or `range[1..256] -> range[0..255]`) that could cause runtime panics. Safe conversions like `range[0..255] -> range[0..65535]` and explicit casts do not trigger warnings. `int` to `Natural` and `Positive` conversions do not trigger warnings, which can be enabled with `--warning:systemRangeConversion`. + +- `std/cmdline.commandLineParams()` for NimScript now consistently returns only the script arguments (excluding the `nim` executable and its flags), fixing inconsistency between `std/cmdline` and `std/parseopt`. + + ## Standard library additions and changes [//]: # "Additions:" diff --git a/lib/std/cmdline.nim b/lib/std/cmdline.nim index 140c458f22474..72d178f8b2528 100644 --- a/lib/std/cmdline.nim +++ b/lib/std/cmdline.nim @@ -279,9 +279,15 @@ when declared(paramCount) or defined(nimdoc): proc commandLineParams*(): seq[string] = ## Convenience proc which returns the command line parameters. ## - ## This returns **only** the parameters. If you want to get the application + ## Unlike `paramStr proc`_, returns **only** the parameters. + ## If you want to get the application ## executable filename, call `getAppFilename() `_. ## + ## When used from NimScript, arguments preceding and including the first + ## `.nims` file are excluded, returning only the arguments intended for the + ## script. If no token ending with `.nims` (case-insensitive) is present + ## in the command line, this returns an empty sequence. + ## ## **Availability**: On Posix there is no portable way to get the command ## line from a DLL and thus the proc isn't defined in this environment. You ## can test for its availability with `declared() @@ -303,8 +309,23 @@ when declared(paramCount) or defined(nimdoc): ## # Do something else! ## ``` result = @[] - for i in 1..paramCount(): - result.add(paramStr(i)) + when defined(nimscript): + func isNimScriptExt(s: openArray[char]): bool = + let L = s.len + (L >= 5 and s[L-5] == '.' and ( + (s[L-4] in {'n', 'N'}) and + (s[L-3] in {'i', 'I'}) and + (s[L-2] in {'m', 'M'}) and + (s[L-1] in {'s', 'S'}))) + var firstNimsFound = false + for i in 0..paramCount(): # nimscript needs to check index 0 + if firstNimsFound: + result.add(paramStr(i)) + elif isNimScriptExt(paramStr(i)): + firstNimsFound = true + else: + for i in 1..paramCount(): + result.add(paramStr(i)) else: proc commandLineParams*(): seq[string] {.error: "commandLineParams() unsupported by dynamic libraries".} = diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index cf81f6d8672ee..6cb14ef006304 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -57,11 +57,19 @@ proc warningImpl(arg, orig: string) = discard proc hintImpl(arg, orig: string) = discard proc paramStr*(i: int): string = - ## Retrieves the `i`'th command line parameter. + ## Retrieves the `i`'th raw command line parameter seen by the Nim + ## compiler or script host. + ## + ## Use `commandLineParams proc `_ for the + ## stripped arguments intended for the current script. builtin proc paramCount*(): int = - ## Retrieves the number of command line parameters. + ## Retrieves the number of raw command line parameters seen by the Nim + ## compiler or script host. + ## + ## Use `commandLineParams proc `_ for the + ## stripped arguments intended for the current script. builtin proc switch*(key: string, val="") = diff --git a/tests/misc/trunner.nim b/tests/misc/trunner.nim index ac13bc5723a76..2f22cbe39584c 100644 --- a/tests/misc/trunner.nim +++ b/tests/misc/trunner.nim @@ -311,6 +311,22 @@ tests/newconfig/bar/mfoo.nims""".splitLines expected.add &"Hint: used config file '{b}' [Conf]\n" doAssert outp.endsWith expected, outp & "\n" & expected + block: # commandLineParams vs paramCount/paramStr in config.nies + let implicitCmd = fmt"{nim} check --hints:off tests/newconfig/cmdline/_/test.nim" + const implicitExp = """nims cmdline test: + scriptArgs=[]; (paramCount > 0)==true; rawHasNims=false; rawHasMain=true; + parseopt got args: 0 +""" + check execCmdEx(implicitCmd) == (implicitExp, 0) + + let explicitCmd = + fmt"""{nim} e --hints:off tests/newconfig/cmdline/tcmdline.nims arg1 "arg2"""" + const explicitExp = """nims cmdline test: + scriptArgs=[arg1, arg2]; (paramCount > 0)==true; rawHasNims=true; rawHasMain=false; + parseopt got args: 2 +""" + check execCmdEx(explicitCmd) == (explicitExp, 0) + block: # bug #8219 let file = "tests/newconfig/mconfigcheck.nims" let cmd = fmt"{nim} check --hints:off {file}" diff --git a/tests/newconfig/cmdline/_/config.nims b/tests/newconfig/cmdline/_/config.nims new file mode 100644 index 0000000000000..009d66081e816 --- /dev/null +++ b/tests/newconfig/cmdline/_/config.nims @@ -0,0 +1 @@ +include ".."/"tcmdline.nims" diff --git a/tests/newconfig/cmdline/_/test.nim b/tests/newconfig/cmdline/_/test.nim new file mode 100644 index 0000000000000..08a6621edf589 --- /dev/null +++ b/tests/newconfig/cmdline/_/test.nim @@ -0,0 +1 @@ +discard diff --git a/tests/newconfig/cmdline/tcmdline.nims b/tests/newconfig/cmdline/tcmdline.nims new file mode 100644 index 0000000000000..3fa616245cecd --- /dev/null +++ b/tests/newconfig/cmdline/tcmdline.nims @@ -0,0 +1,24 @@ +from std/strutils import endsWith, join +from std/os import commandLineParams +import std/parseopt + +let cmdParams = commandLineParams().join(", ") +var + rawHasNims = false + rawHasMain = false + parsed: seq[string] + +for i in 1..paramCount(): + let arg = paramStr(i) + rawHasNims = rawHasNims or arg.endsWith(".nims") + rawHasMain = rawHasMain or arg.endsWith("test.nim") + +# parseopt follows commandLineParams for NimScript. +var p = initOptParser() +for _, key, val in p.getopt(): + parsed.add key + +echo "nims cmdline test:\n", + " scriptArgs=[", cmdParams, "]; (paramCount > 0)==", paramCount() > 0, + "; rawHasNims=", rawHasNims, "; rawHasMain=", rawHasMain, ";\n", + " parseopt got args: ", parsed.len diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims index 15e9d878d8954..f03ecfd5c70ed 100644 --- a/tests/test_nimscript.nims +++ b/tests/test_nimscript.nims @@ -134,8 +134,16 @@ block: # cpDir, cpFile, dirExists, fileExists, mkDir, mvDir, mvFile, rmDir, rmF rmDir(dname) block: - # check parseopt can get command line: - discard initOptParser() + # parsing live input tested in misc/trunner + let cmdParams = commandLineParams() + doAssert cmdParams.len == 0, "commandLineParams should strip compiler args" + var parsed: seq[string] + var p = initOptParser() + for _, key, val in p.getopt(): + parsed.add key + parsed.add val + doAssert parsed.len == 0, "initOptParser should strip compiler args" + doAssert parsed == cmdParams, "initOptParser.getopt != commandLineParams" # issue #24780: