Move command line parameter code (#20946)
Command line paramater code moved from os.nim to cmdparam.nim Co-authored-by: IgorDeepakM <IgorDeepak@noreply.com>
This commit is contained in:
parent
8f728ace35
commit
84ea62ea0d
3 changed files with 318 additions and 272 deletions
275
lib/pure/os.nim
275
lib/pure/os.nim
|
|
@ -8,8 +8,8 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module contains basic operating system facilities like
|
## This module contains basic operating system facilities like
|
||||||
## retrieving environment variables, reading command line arguments,
|
## retrieving environment variables, working with directories,
|
||||||
## working with directories, running shell commands, etc.
|
## running shell commands, etc.
|
||||||
|
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
let myFile = "/path/to/my/file.nim"
|
let myFile = "/path/to/my/file.nim"
|
||||||
|
|
@ -22,8 +22,6 @@ runnableExamples:
|
||||||
## **See also:**
|
## **See also:**
|
||||||
## * `osproc module <osproc.html>`_ for process communication beyond
|
## * `osproc module <osproc.html>`_ for process communication beyond
|
||||||
## `execShellCmd proc`_
|
## `execShellCmd proc`_
|
||||||
## * `parseopt module <parseopt.html>`_ for command-line parser beyond
|
|
||||||
## `parseCmdLine proc`_
|
|
||||||
## * `uri module <uri.html>`_
|
## * `uri module <uri.html>`_
|
||||||
## * `distros module <distros.html>`_
|
## * `distros module <distros.html>`_
|
||||||
## * `dynlib module <dynlib.html>`_
|
## * `dynlib module <dynlib.html>`_
|
||||||
|
|
@ -48,6 +46,9 @@ import std/private/oscommon
|
||||||
include system/inclrtl
|
include system/inclrtl
|
||||||
import std/private/since
|
import std/private/since
|
||||||
|
|
||||||
|
import std/cmdline
|
||||||
|
export cmdline
|
||||||
|
|
||||||
import strutils, pathnorm
|
import strutils, pathnorm
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
|
|
@ -510,272 +511,6 @@ proc exclFilePermissions*(filename: string,
|
||||||
## setFilePermissions(filename, getFilePermissions(filename)-permissions)
|
## setFilePermissions(filename, getFilePermissions(filename)-permissions)
|
||||||
setFilePermissions(filename, getFilePermissions(filename)-permissions)
|
setFilePermissions(filename, getFilePermissions(filename)-permissions)
|
||||||
|
|
||||||
proc parseCmdLine*(c: string): seq[string] {.
|
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
|
||||||
## Splits a `command line`:idx: into several components.
|
|
||||||
##
|
|
||||||
## **Note**: This proc is only occasionally useful, better use the
|
|
||||||
## `parseopt module <parseopt.html>`_.
|
|
||||||
##
|
|
||||||
## On Windows, it uses the `following parsing rules
|
|
||||||
## <http://msdn.microsoft.com/en-us/library/17w5ykft.aspx>`_:
|
|
||||||
##
|
|
||||||
## * Arguments are delimited by white space, which is either a space or a tab.
|
|
||||||
## * The caret character (^) is not recognized as an escape character or
|
|
||||||
## delimiter. The character is handled completely by the command-line parser
|
|
||||||
## in the operating system before being passed to the argv array in the
|
|
||||||
## program.
|
|
||||||
## * A string surrounded by double quotation marks ("string") is interpreted
|
|
||||||
## as a single argument, regardless of white space contained within. A
|
|
||||||
## quoted string can be embedded in an argument.
|
|
||||||
## * A double quotation mark preceded by a backslash (\") is interpreted as a
|
|
||||||
## literal double quotation mark character (").
|
|
||||||
## * Backslashes are interpreted literally, unless they immediately precede
|
|
||||||
## a double quotation mark.
|
|
||||||
## * If an even number of backslashes is followed by a double quotation mark,
|
|
||||||
## one backslash is placed in the argv array for every pair of backslashes,
|
|
||||||
## and the double quotation mark is interpreted as a string delimiter.
|
|
||||||
## * If an odd number of backslashes is followed by a double quotation mark,
|
|
||||||
## one backslash is placed in the argv array for every pair of backslashes,
|
|
||||||
## and the double quotation mark is "escaped" by the remaining backslash,
|
|
||||||
## causing a literal double quotation mark (") to be placed in argv.
|
|
||||||
##
|
|
||||||
## On Posix systems, it uses the following parsing rules:
|
|
||||||
## Components are separated by whitespace unless the whitespace
|
|
||||||
## occurs within ``"`` or ``'`` quotes.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `parseopt module <parseopt.html>`_
|
|
||||||
## * `paramCount proc`_
|
|
||||||
## * `paramStr proc`_
|
|
||||||
## * `commandLineParams proc`_
|
|
||||||
|
|
||||||
result = @[]
|
|
||||||
var i = 0
|
|
||||||
var a = ""
|
|
||||||
while true:
|
|
||||||
setLen(a, 0)
|
|
||||||
# eat all delimiting whitespace
|
|
||||||
while i < c.len and c[i] in {' ', '\t', '\l', '\r'}: inc(i)
|
|
||||||
if i >= c.len: break
|
|
||||||
when defined(windows):
|
|
||||||
# parse a single argument according to the above rules:
|
|
||||||
var inQuote = false
|
|
||||||
while i < c.len:
|
|
||||||
case c[i]
|
|
||||||
of '\\':
|
|
||||||
var j = i
|
|
||||||
while j < c.len and c[j] == '\\': inc(j)
|
|
||||||
if j < c.len and c[j] == '"':
|
|
||||||
for k in 1..(j-i) div 2: a.add('\\')
|
|
||||||
if (j-i) mod 2 == 0:
|
|
||||||
i = j
|
|
||||||
else:
|
|
||||||
a.add('"')
|
|
||||||
i = j+1
|
|
||||||
else:
|
|
||||||
a.add(c[i])
|
|
||||||
inc(i)
|
|
||||||
of '"':
|
|
||||||
inc(i)
|
|
||||||
if not inQuote: inQuote = true
|
|
||||||
elif i < c.len and c[i] == '"':
|
|
||||||
a.add(c[i])
|
|
||||||
inc(i)
|
|
||||||
else:
|
|
||||||
inQuote = false
|
|
||||||
break
|
|
||||||
of ' ', '\t':
|
|
||||||
if not inQuote: break
|
|
||||||
a.add(c[i])
|
|
||||||
inc(i)
|
|
||||||
else:
|
|
||||||
a.add(c[i])
|
|
||||||
inc(i)
|
|
||||||
else:
|
|
||||||
case c[i]
|
|
||||||
of '\'', '\"':
|
|
||||||
var delim = c[i]
|
|
||||||
inc(i) # skip ' or "
|
|
||||||
while i < c.len and c[i] != delim:
|
|
||||||
add a, c[i]
|
|
||||||
inc(i)
|
|
||||||
if i < c.len: inc(i)
|
|
||||||
else:
|
|
||||||
while i < c.len and c[i] > ' ':
|
|
||||||
add(a, c[i])
|
|
||||||
inc(i)
|
|
||||||
add(result, a)
|
|
||||||
|
|
||||||
when defined(nimdoc):
|
|
||||||
# Common forward declaration docstring block for parameter retrieval procs.
|
|
||||||
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
|
||||||
## Returns the number of `command line arguments`:idx: given to the
|
|
||||||
## application.
|
|
||||||
##
|
|
||||||
## Unlike `argc`:idx: in C, if your binary was called without parameters this
|
|
||||||
## will return zero.
|
|
||||||
## You can query each individual parameter with `paramStr proc`_
|
|
||||||
## or retrieve all of them in one go with `commandLineParams proc`_.
|
|
||||||
##
|
|
||||||
## **Availability**: When generating a dynamic library (see `--app:lib`) on
|
|
||||||
## Posix this proc is not defined.
|
|
||||||
## Test for availability using `declared() <system.html#declared,untyped>`_.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `parseopt module <parseopt.html>`_
|
|
||||||
## * `parseCmdLine proc`_
|
|
||||||
## * `paramStr proc`_
|
|
||||||
## * `commandLineParams proc`_
|
|
||||||
##
|
|
||||||
## **Examples:**
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## when declared(paramCount):
|
|
||||||
## # Use paramCount() here
|
|
||||||
## else:
|
|
||||||
## # Do something else!
|
|
||||||
|
|
||||||
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
|
||||||
## Returns the `i`-th `command line argument`:idx: given to the application.
|
|
||||||
##
|
|
||||||
## `i` should be in the range `1..paramCount()`, the `IndexDefect`
|
|
||||||
## exception will be raised for invalid values. Instead of iterating
|
|
||||||
## over `paramCount()`_ with this proc you can
|
|
||||||
## call the convenience `commandLineParams()`_.
|
|
||||||
##
|
|
||||||
## Similarly to `argv`:idx: in C,
|
|
||||||
## it is possible to call `paramStr(0)` but this will return OS specific
|
|
||||||
## contents (usually the name of the invoked executable). You should avoid
|
|
||||||
## this and call `getAppFilename()`_ instead.
|
|
||||||
##
|
|
||||||
## **Availability**: When generating a dynamic library (see `--app:lib`) on
|
|
||||||
## Posix this proc is not defined.
|
|
||||||
## Test for availability using `declared() <system.html#declared,untyped>`_.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `parseopt module <parseopt.html>`_
|
|
||||||
## * `parseCmdLine proc`_
|
|
||||||
## * `paramCount proc`_
|
|
||||||
## * `commandLineParams proc`_
|
|
||||||
## * `getAppFilename proc`_
|
|
||||||
##
|
|
||||||
## **Examples:**
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## when declared(paramStr):
|
|
||||||
## # Use paramStr() here
|
|
||||||
## else:
|
|
||||||
## # Do something else!
|
|
||||||
|
|
||||||
elif defined(nimscript): discard
|
|
||||||
elif defined(nodejs):
|
|
||||||
type Argv = object of JsRoot
|
|
||||||
let argv {.importjs: "process.argv".} : Argv
|
|
||||||
proc len(argv: Argv): int {.importjs: "#.length".}
|
|
||||||
proc `[]`(argv: Argv, i: int): cstring {.importjs: "#[#]".}
|
|
||||||
|
|
||||||
proc paramCount*(): int {.tags: [ReadDirEffect].} =
|
|
||||||
result = argv.len - 2
|
|
||||||
|
|
||||||
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
|
||||||
let i = i + 1
|
|
||||||
if i < argv.len and i >= 0:
|
|
||||||
result = $argv[i]
|
|
||||||
else:
|
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i - 1, argv.len - 2))
|
|
||||||
elif defined(windows):
|
|
||||||
# Since we support GUI applications with Nim, we sometimes generate
|
|
||||||
# a WinMain entry proc. But a WinMain proc has no access to the parsed
|
|
||||||
# command line arguments. The way to get them differs. Thus we parse them
|
|
||||||
# ourselves. This has the additional benefit that the program's behaviour
|
|
||||||
# is always the same -- independent of the used C compiler.
|
|
||||||
var
|
|
||||||
ownArgv {.threadvar.}: seq[string]
|
|
||||||
ownParsedArgv {.threadvar.}: bool
|
|
||||||
|
|
||||||
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
|
|
||||||
# Docstring in nimdoc block.
|
|
||||||
if not ownParsedArgv:
|
|
||||||
ownArgv = parseCmdLine($getCommandLine())
|
|
||||||
ownParsedArgv = true
|
|
||||||
result = ownArgv.len-1
|
|
||||||
|
|
||||||
proc paramStr*(i: int): string {.rtl, extern: "nos$1",
|
|
||||||
tags: [ReadIOEffect].} =
|
|
||||||
# Docstring in nimdoc block.
|
|
||||||
if not ownParsedArgv:
|
|
||||||
ownArgv = parseCmdLine($getCommandLine())
|
|
||||||
ownParsedArgv = true
|
|
||||||
if i < ownArgv.len and i >= 0:
|
|
||||||
result = ownArgv[i]
|
|
||||||
else:
|
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i, ownArgv.len-1))
|
|
||||||
|
|
||||||
elif defined(genode):
|
|
||||||
proc paramStr*(i: int): string =
|
|
||||||
raise newException(OSError, "paramStr is not implemented on Genode")
|
|
||||||
|
|
||||||
proc paramCount*(): int =
|
|
||||||
raise newException(OSError, "paramCount is not implemented on Genode")
|
|
||||||
elif weirdTarget or (defined(posix) and appType == "lib"):
|
|
||||||
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
|
||||||
raise newException(OSError, "paramStr is not implemented on current platform")
|
|
||||||
|
|
||||||
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
|
||||||
raise newException(OSError, "paramCount is not implemented on current platform")
|
|
||||||
elif not defined(createNimRtl) and
|
|
||||||
not(defined(posix) and appType == "lib"):
|
|
||||||
# On Posix, there is no portable way to get the command line from a DLL.
|
|
||||||
var
|
|
||||||
cmdCount {.importc: "cmdCount".}: cint
|
|
||||||
cmdLine {.importc: "cmdLine".}: cstringArray
|
|
||||||
|
|
||||||
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
|
||||||
# Docstring in nimdoc block.
|
|
||||||
if i < cmdCount and i >= 0:
|
|
||||||
result = $cmdLine[i]
|
|
||||||
else:
|
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i, cmdCount-1))
|
|
||||||
|
|
||||||
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
|
||||||
# Docstring in nimdoc block.
|
|
||||||
result = cmdCount-1
|
|
||||||
|
|
||||||
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
|
|
||||||
## executable filename, call `getAppFilename()`_.
|
|
||||||
##
|
|
||||||
## **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()
|
|
||||||
## <system.html#declared,untyped>`_.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `parseopt module <parseopt.html>`_
|
|
||||||
## * `parseCmdLine proc`_
|
|
||||||
## * `paramCount proc`_
|
|
||||||
## * `paramStr proc`_
|
|
||||||
## * `getAppFilename proc`_
|
|
||||||
##
|
|
||||||
## **Examples:**
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## when declared(commandLineParams):
|
|
||||||
## # Use commandLineParams() here
|
|
||||||
## else:
|
|
||||||
## # Do something else!
|
|
||||||
result = @[]
|
|
||||||
for i in 1..paramCount():
|
|
||||||
result.add(paramStr(i))
|
|
||||||
else:
|
|
||||||
proc commandLineParams*(): seq[string] {.error:
|
|
||||||
"commandLineParams() unsupported by dynamic libraries".} =
|
|
||||||
discard
|
|
||||||
|
|
||||||
when not weirdTarget and (defined(freebsd) or defined(dragonfly) or defined(netbsd)):
|
when not weirdTarget and (defined(freebsd) or defined(dragonfly) or defined(netbsd)):
|
||||||
proc sysctl(name: ptr cint, namelen: cuint, oldp: pointer, oldplen: ptr csize_t,
|
proc sysctl(name: ptr cint, namelen: cuint, oldp: pointer, oldplen: ptr csize_t,
|
||||||
newp: pointer, newplen: csize_t): cint
|
newp: pointer, newplen: csize_t): cint
|
||||||
|
|
|
||||||
313
lib/std/cmdline.nim
Normal file
313
lib/std/cmdline.nim
Normal file
|
|
@ -0,0 +1,313 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nim's Runtime Library
|
||||||
|
# (c) Copyright 2022 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## This module contains system facilities for reading command
|
||||||
|
## line parameters.
|
||||||
|
|
||||||
|
## **See also:**
|
||||||
|
## * `parseopt module <parseopt.html>`_ for command-line parser beyond
|
||||||
|
## `parseCmdLine proc`_
|
||||||
|
|
||||||
|
|
||||||
|
include system/inclrtl
|
||||||
|
|
||||||
|
when defined(nimPreviewSlimSystem):
|
||||||
|
import std/widestrs
|
||||||
|
|
||||||
|
when defined(nodejs):
|
||||||
|
from std/private/oscommon import ReadDirEffect
|
||||||
|
|
||||||
|
|
||||||
|
const weirdTarget = defined(nimscript) or defined(js)
|
||||||
|
|
||||||
|
|
||||||
|
when weirdTarget:
|
||||||
|
discard
|
||||||
|
elif defined(windows):
|
||||||
|
import winlean
|
||||||
|
elif defined(posix):
|
||||||
|
import posix
|
||||||
|
else:
|
||||||
|
{.error: "cmdparam module not ported to your operating system!".}
|
||||||
|
|
||||||
|
|
||||||
|
# Needed by windows in order to obtain the command line for targets
|
||||||
|
# other than command line targets
|
||||||
|
when defined(windows) and not weirdTarget:
|
||||||
|
when useWinUnicode:
|
||||||
|
template getCommandLine*(): untyped = getCommandLineW()
|
||||||
|
else:
|
||||||
|
template getCommandLine*(): untyped = getCommandLineA()
|
||||||
|
|
||||||
|
|
||||||
|
proc parseCmdLine*(c: string): seq[string] {.
|
||||||
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
|
## Splits a `command line`:idx: into several components.
|
||||||
|
##
|
||||||
|
## **Note**: This proc is only occasionally useful, better use the
|
||||||
|
## `parseopt module <parseopt.html>`_.
|
||||||
|
##
|
||||||
|
## On Windows, it uses the `following parsing rules
|
||||||
|
## <http://msdn.microsoft.com/en-us/library/17w5ykft.aspx>`_:
|
||||||
|
##
|
||||||
|
## * Arguments are delimited by white space, which is either a space or a tab.
|
||||||
|
## * The caret character (^) is not recognized as an escape character or
|
||||||
|
## delimiter. The character is handled completely by the command-line parser
|
||||||
|
## in the operating system before being passed to the argv array in the
|
||||||
|
## program.
|
||||||
|
## * A string surrounded by double quotation marks ("string") is interpreted
|
||||||
|
## as a single argument, regardless of white space contained within. A
|
||||||
|
## quoted string can be embedded in an argument.
|
||||||
|
## * A double quotation mark preceded by a backslash (\") is interpreted as a
|
||||||
|
## literal double quotation mark character (").
|
||||||
|
## * Backslashes are interpreted literally, unless they immediately precede
|
||||||
|
## a double quotation mark.
|
||||||
|
## * If an even number of backslashes is followed by a double quotation mark,
|
||||||
|
## one backslash is placed in the argv array for every pair of backslashes,
|
||||||
|
## and the double quotation mark is interpreted as a string delimiter.
|
||||||
|
## * If an odd number of backslashes is followed by a double quotation mark,
|
||||||
|
## one backslash is placed in the argv array for every pair of backslashes,
|
||||||
|
## and the double quotation mark is "escaped" by the remaining backslash,
|
||||||
|
## causing a literal double quotation mark (") to be placed in argv.
|
||||||
|
##
|
||||||
|
## On Posix systems, it uses the following parsing rules:
|
||||||
|
## Components are separated by whitespace unless the whitespace
|
||||||
|
## occurs within ``"`` or ``'`` quotes.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `parseopt module <parseopt.html>`_
|
||||||
|
## * `paramCount proc`_
|
||||||
|
## * `paramStr proc`_
|
||||||
|
## * `commandLineParams proc`_
|
||||||
|
|
||||||
|
result = @[]
|
||||||
|
var i = 0
|
||||||
|
var a = ""
|
||||||
|
while true:
|
||||||
|
setLen(a, 0)
|
||||||
|
# eat all delimiting whitespace
|
||||||
|
while i < c.len and c[i] in {' ', '\t', '\l', '\r'}: inc(i)
|
||||||
|
if i >= c.len: break
|
||||||
|
when defined(windows):
|
||||||
|
# parse a single argument according to the above rules:
|
||||||
|
var inQuote = false
|
||||||
|
while i < c.len:
|
||||||
|
case c[i]
|
||||||
|
of '\\':
|
||||||
|
var j = i
|
||||||
|
while j < c.len and c[j] == '\\': inc(j)
|
||||||
|
if j < c.len and c[j] == '"':
|
||||||
|
for k in 1..(j-i) div 2: a.add('\\')
|
||||||
|
if (j-i) mod 2 == 0:
|
||||||
|
i = j
|
||||||
|
else:
|
||||||
|
a.add('"')
|
||||||
|
i = j+1
|
||||||
|
else:
|
||||||
|
a.add(c[i])
|
||||||
|
inc(i)
|
||||||
|
of '"':
|
||||||
|
inc(i)
|
||||||
|
if not inQuote: inQuote = true
|
||||||
|
elif i < c.len and c[i] == '"':
|
||||||
|
a.add(c[i])
|
||||||
|
inc(i)
|
||||||
|
else:
|
||||||
|
inQuote = false
|
||||||
|
break
|
||||||
|
of ' ', '\t':
|
||||||
|
if not inQuote: break
|
||||||
|
a.add(c[i])
|
||||||
|
inc(i)
|
||||||
|
else:
|
||||||
|
a.add(c[i])
|
||||||
|
inc(i)
|
||||||
|
else:
|
||||||
|
case c[i]
|
||||||
|
of '\'', '\"':
|
||||||
|
var delim = c[i]
|
||||||
|
inc(i) # skip ' or "
|
||||||
|
while i < c.len and c[i] != delim:
|
||||||
|
add a, c[i]
|
||||||
|
inc(i)
|
||||||
|
if i < c.len: inc(i)
|
||||||
|
else:
|
||||||
|
while i < c.len and c[i] > ' ':
|
||||||
|
add(a, c[i])
|
||||||
|
inc(i)
|
||||||
|
add(result, a)
|
||||||
|
|
||||||
|
when defined(nimdoc):
|
||||||
|
# Common forward declaration docstring block for parameter retrieval procs.
|
||||||
|
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
||||||
|
## Returns the number of `command line arguments`:idx: given to the
|
||||||
|
## application.
|
||||||
|
##
|
||||||
|
## Unlike `argc`:idx: in C, if your binary was called without parameters this
|
||||||
|
## will return zero.
|
||||||
|
## You can query each individual parameter with `paramStr proc`_
|
||||||
|
## or retrieve all of them in one go with `commandLineParams proc`_.
|
||||||
|
##
|
||||||
|
## **Availability**: When generating a dynamic library (see `--app:lib`) on
|
||||||
|
## Posix this proc is not defined.
|
||||||
|
## Test for availability using `declared() <system.html#declared,untyped>`_.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `parseopt module <parseopt.html>`_
|
||||||
|
## * `parseCmdLine proc`_
|
||||||
|
## * `paramStr proc`_
|
||||||
|
## * `commandLineParams proc`_
|
||||||
|
##
|
||||||
|
## **Examples:**
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## when declared(paramCount):
|
||||||
|
## # Use paramCount() here
|
||||||
|
## else:
|
||||||
|
## # Do something else!
|
||||||
|
|
||||||
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
|
## Returns the `i`-th `command line argument`:idx: given to the application.
|
||||||
|
##
|
||||||
|
## `i` should be in the range `1..paramCount()`, the `IndexDefect`
|
||||||
|
## exception will be raised for invalid values. Instead of iterating
|
||||||
|
## over `paramCount()`_ with this proc you can
|
||||||
|
## call the convenience `commandLineParams()`_.
|
||||||
|
##
|
||||||
|
## Similarly to `argv`:idx: in C,
|
||||||
|
## it is possible to call `paramStr(0)` but this will return OS specific
|
||||||
|
## contents (usually the name of the invoked executable). You should avoid
|
||||||
|
## this and call `getAppFilename()`_ instead.
|
||||||
|
##
|
||||||
|
## **Availability**: When generating a dynamic library (see `--app:lib`) on
|
||||||
|
## Posix this proc is not defined.
|
||||||
|
## Test for availability using `declared() <system.html#declared,untyped>`_.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `parseopt module <parseopt.html>`_
|
||||||
|
## * `parseCmdLine proc`_
|
||||||
|
## * `paramCount proc`_
|
||||||
|
## * `commandLineParams proc`_
|
||||||
|
## * `getAppFilename proc`_
|
||||||
|
##
|
||||||
|
## **Examples:**
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## when declared(paramStr):
|
||||||
|
## # Use paramStr() here
|
||||||
|
## else:
|
||||||
|
## # Do something else!
|
||||||
|
|
||||||
|
elif defined(nimscript): discard
|
||||||
|
elif defined(nodejs):
|
||||||
|
type Argv = object of JsRoot
|
||||||
|
let argv {.importjs: "process.argv".} : Argv
|
||||||
|
proc len(argv: Argv): int {.importjs: "#.length".}
|
||||||
|
proc `[]`(argv: Argv, i: int): cstring {.importjs: "#[#]".}
|
||||||
|
|
||||||
|
proc paramCount*(): int {.tags: [ReadDirEffect].} =
|
||||||
|
result = argv.len - 2
|
||||||
|
|
||||||
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
|
let i = i + 1
|
||||||
|
if i < argv.len and i >= 0:
|
||||||
|
result = $argv[i]
|
||||||
|
else:
|
||||||
|
raise newException(IndexDefect, formatErrorIndexBound(i - 1, argv.len - 2))
|
||||||
|
elif defined(windows):
|
||||||
|
# Since we support GUI applications with Nim, we sometimes generate
|
||||||
|
# a WinMain entry proc. But a WinMain proc has no access to the parsed
|
||||||
|
# command line arguments. The way to get them differs. Thus we parse them
|
||||||
|
# ourselves. This has the additional benefit that the program's behaviour
|
||||||
|
# is always the same -- independent of the used C compiler.
|
||||||
|
var
|
||||||
|
ownArgv {.threadvar.}: seq[string]
|
||||||
|
ownParsedArgv {.threadvar.}: bool
|
||||||
|
|
||||||
|
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
|
||||||
|
# Docstring in nimdoc block.
|
||||||
|
if not ownParsedArgv:
|
||||||
|
ownArgv = parseCmdLine($getCommandLine())
|
||||||
|
ownParsedArgv = true
|
||||||
|
result = ownArgv.len-1
|
||||||
|
|
||||||
|
proc paramStr*(i: int): string {.rtl, extern: "nos$1",
|
||||||
|
tags: [ReadIOEffect].} =
|
||||||
|
# Docstring in nimdoc block.
|
||||||
|
if not ownParsedArgv:
|
||||||
|
ownArgv = parseCmdLine($getCommandLine())
|
||||||
|
ownParsedArgv = true
|
||||||
|
if i < ownArgv.len and i >= 0:
|
||||||
|
result = ownArgv[i]
|
||||||
|
else:
|
||||||
|
raise newException(IndexDefect, formatErrorIndexBound(i, ownArgv.len-1))
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
proc paramStr*(i: int): string =
|
||||||
|
raise newException(OSError, "paramStr is not implemented on Genode")
|
||||||
|
|
||||||
|
proc paramCount*(): int =
|
||||||
|
raise newException(OSError, "paramCount is not implemented on Genode")
|
||||||
|
elif weirdTarget or (defined(posix) and appType == "lib"):
|
||||||
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
|
raise newException(OSError, "paramStr is not implemented on current platform")
|
||||||
|
|
||||||
|
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
||||||
|
raise newException(OSError, "paramCount is not implemented on current platform")
|
||||||
|
elif not defined(createNimRtl) and
|
||||||
|
not(defined(posix) and appType == "lib"):
|
||||||
|
# On Posix, there is no portable way to get the command line from a DLL.
|
||||||
|
var
|
||||||
|
cmdCount {.importc: "cmdCount".}: cint
|
||||||
|
cmdLine {.importc: "cmdLine".}: cstringArray
|
||||||
|
|
||||||
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
|
# Docstring in nimdoc block.
|
||||||
|
if i < cmdCount and i >= 0:
|
||||||
|
result = $cmdLine[i]
|
||||||
|
else:
|
||||||
|
raise newException(IndexDefect, formatErrorIndexBound(i, cmdCount-1))
|
||||||
|
|
||||||
|
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
||||||
|
# Docstring in nimdoc block.
|
||||||
|
result = cmdCount-1
|
||||||
|
|
||||||
|
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
|
||||||
|
## executable filename, call `getAppFilename()`_.
|
||||||
|
##
|
||||||
|
## **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()
|
||||||
|
## <system.html#declared,untyped>`_.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `parseopt module <parseopt.html>`_
|
||||||
|
## * `parseCmdLine proc`_
|
||||||
|
## * `paramCount proc`_
|
||||||
|
## * `paramStr proc`_
|
||||||
|
## * `getAppFilename proc`_
|
||||||
|
##
|
||||||
|
## **Examples:**
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## when declared(commandLineParams):
|
||||||
|
## # Use commandLineParams() here
|
||||||
|
## else:
|
||||||
|
## # Do something else!
|
||||||
|
result = @[]
|
||||||
|
for i in 1..paramCount():
|
||||||
|
result.add(paramStr(i))
|
||||||
|
else:
|
||||||
|
proc commandLineParams*(): seq[string] {.error:
|
||||||
|
"commandLineParams() unsupported by dynamic libraries".} =
|
||||||
|
discard
|
||||||
|
|
@ -54,14 +54,12 @@ when defined(windows) and not weirdTarget:
|
||||||
proc findFirstFile*(a: string, b: var WIN32_FIND_DATA): Handle =
|
proc findFirstFile*(a: string, b: var WIN32_FIND_DATA): Handle =
|
||||||
result = findFirstFileW(newWideCString(a), b)
|
result = findFirstFileW(newWideCString(a), b)
|
||||||
template findNextFile*(a, b: untyped): untyped = findNextFileW(a, b)
|
template findNextFile*(a, b: untyped): untyped = findNextFileW(a, b)
|
||||||
template getCommandLine*(): untyped = getCommandLineW()
|
|
||||||
|
|
||||||
template getFilename*(f: untyped): untyped =
|
template getFilename*(f: untyped): untyped =
|
||||||
$cast[WideCString](addr(f.cFileName[0]))
|
$cast[WideCString](addr(f.cFileName[0]))
|
||||||
else:
|
else:
|
||||||
template findFirstFile*(a, b: untyped): untyped = findFirstFileA(a, b)
|
template findFirstFile*(a, b: untyped): untyped = findFirstFileA(a, b)
|
||||||
template findNextFile*(a, b: untyped): untyped = findNextFileA(a, b)
|
template findNextFile*(a, b: untyped): untyped = findNextFileA(a, b)
|
||||||
template getCommandLine*(): untyped = getCommandLineA()
|
|
||||||
|
|
||||||
template getFilename*(f: untyped): untyped = $cast[cstring](addr f.cFileName)
|
template getFilename*(f: untyped): untyped = $cast[cstring](addr f.cFileName)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue