js -d:nodejs now supports osenv: getEnv, putEnv, envPairs, delEnv, existsEnv (v2) (#15826)
* js -d:nodejs now supports osenv: `getEnv`, `putEnv`, `envPairs`, `delEnv`, `existsEnv` * refactor to osenv * fix for js (without -d:nodejs) + VM Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
parent
bc007a3cd3
commit
cc882917fe
3 changed files with 272 additions and 208 deletions
|
|
@ -31,6 +31,8 @@
|
||||||
- Removed deprecated `iup` module from stdlib, it has already moved to
|
- Removed deprecated `iup` module from stdlib, it has already moved to
|
||||||
[nimble](https://github.com/nim-lang/iup).
|
[nimble](https://github.com/nim-lang/iup).
|
||||||
|
|
||||||
|
- Removed deprecated `iup` module from stdlib, it has already moved to [nimble](https://github.com/nim-lang/iup).
|
||||||
|
- nodejs now supports osenv: `getEnv`, `putEnv`, `envPairs`, `delEnv`, `existsEnv`
|
||||||
- `doAssertRaises` now correctly handles foreign exceptions.
|
- `doAssertRaises` now correctly handles foreign exceptions.
|
||||||
|
|
||||||
## Language changes
|
## Language changes
|
||||||
|
|
|
||||||
|
|
@ -3,228 +3,264 @@
|
||||||
when not declared(os) and not declared(ospaths):
|
when not declared(os) and not declared(ospaths):
|
||||||
{.error: "This is an include file for os.nim!".}
|
{.error: "This is an include file for os.nim!".}
|
||||||
|
|
||||||
when defined(windows):
|
when defined(nodejs):
|
||||||
from parseutils import skipIgnoreCase
|
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
||||||
|
var ret: cstring
|
||||||
|
let key2 = key.cstring
|
||||||
|
{.emit: "`ret` = process.env[`key2`];".}
|
||||||
|
result = $ret
|
||||||
|
|
||||||
proc c_getenv(env: cstring): cstring {.
|
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
||||||
importc: "getenv", header: "<stdlib.h>".}
|
var key2 = key.cstring
|
||||||
proc c_putenv(env: cstring): cint {.
|
var ret: bool
|
||||||
importc: "putenv", header: "<stdlib.h>".}
|
{.emit: "`ret` = `key2` in process.env;".}
|
||||||
proc c_unsetenv(env: cstring): cint {.
|
result = ret
|
||||||
importc: "unsetenv", header: "<stdlib.h>".}
|
|
||||||
|
|
||||||
# Environment handling cannot be put into RTL, because the ``envPairs``
|
proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||||
# iterator depends on ``environment``.
|
var key2 = key.cstring
|
||||||
|
var val2 = val.cstring
|
||||||
|
{.emit: "process.env[`key2`] = `val2`;".}
|
||||||
|
|
||||||
var
|
proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
||||||
envComputed {.threadvar.}: bool
|
var key2 = key.cstring
|
||||||
environment {.threadvar.}: seq[string]
|
{.emit: "delete process.env[`key2`];".}
|
||||||
|
|
||||||
when defined(nimV2):
|
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
||||||
proc unpairedEnvAllocs*(): int =
|
var num: int
|
||||||
result = environment.len
|
var keys: RootObj
|
||||||
if result > 0: inc result
|
{.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".}
|
||||||
|
for i in 0..<num:
|
||||||
|
var key, value: cstring
|
||||||
|
{.emit: "`key` = `keys`[`i`]; `value` = process.env[`key`];".}
|
||||||
|
yield ($key, $value)
|
||||||
|
|
||||||
when defined(windows) and not defined(nimscript):
|
# commented because it must keep working with js+VM
|
||||||
# because we support Windows GUI applications, things get really
|
# elif defined(js):
|
||||||
# messy here...
|
# {.error: "requires -d:nodejs".}
|
||||||
when useWinUnicode:
|
|
||||||
when defined(cpp):
|
|
||||||
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
|
||||||
importcpp: "(NI16*)wcschr((const wchar_t *)#, #)", header: "<string.h>".}
|
|
||||||
else:
|
|
||||||
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
|
||||||
importc: "wcschr", header: "<string.h>".}
|
|
||||||
else:
|
|
||||||
proc strEnd(cstr: cstring, c = 0'i32): cstring {.
|
|
||||||
importc: "strchr", header: "<string.h>".}
|
|
||||||
|
|
||||||
proc getEnvVarsC() =
|
|
||||||
if not envComputed:
|
|
||||||
environment = @[]
|
|
||||||
when useWinUnicode:
|
|
||||||
var
|
|
||||||
env = getEnvironmentStringsW()
|
|
||||||
e = env
|
|
||||||
if e == nil: return # an error occurred
|
|
||||||
while true:
|
|
||||||
var eend = strEnd(e)
|
|
||||||
add(environment, $e)
|
|
||||||
e = cast[WideCString](cast[ByteAddress](eend)+2)
|
|
||||||
if eend[1].int == 0: break
|
|
||||||
discard freeEnvironmentStringsW(env)
|
|
||||||
else:
|
|
||||||
var
|
|
||||||
env = getEnvironmentStringsA()
|
|
||||||
e = env
|
|
||||||
if e == nil: return # an error occurred
|
|
||||||
while true:
|
|
||||||
var eend = strEnd(e)
|
|
||||||
add(environment, $e)
|
|
||||||
e = cast[cstring](cast[ByteAddress](eend)+1)
|
|
||||||
if eend[1] == '\0': break
|
|
||||||
discard freeEnvironmentStringsA(env)
|
|
||||||
envComputed = true
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
const
|
when defined(windows):
|
||||||
useNSGetEnviron = (defined(macosx) and not defined(ios) and not defined(emscripten)) or defined(nimscript)
|
from parseutils import skipIgnoreCase
|
||||||
|
|
||||||
when useNSGetEnviron:
|
proc c_getenv(env: cstring): cstring {.
|
||||||
# From the manual:
|
importc: "getenv", header: "<stdlib.h>".}
|
||||||
# Shared libraries and bundles don't have direct access to environ,
|
proc c_putenv(env: cstring): cint {.
|
||||||
# which is only available to the loader ld(1) when a complete program
|
importc: "putenv", header: "<stdlib.h>".}
|
||||||
# is being linked.
|
proc c_unsetenv(env: cstring): cint {.
|
||||||
# The environment routines can still be used, but if direct access to
|
importc: "unsetenv", header: "<stdlib.h>".}
|
||||||
# environ is needed, the _NSGetEnviron() routine, defined in
|
|
||||||
# <crt_externs.h>, can be used to retrieve the address of environ
|
|
||||||
# at runtime.
|
|
||||||
proc NSGetEnviron(): ptr cstringArray {.
|
|
||||||
importc: "_NSGetEnviron", header: "<crt_externs.h>".}
|
|
||||||
elif defined(haiku):
|
|
||||||
var gEnv {.importc: "environ", header: "<stdlib.h>".}: cstringArray
|
|
||||||
else:
|
|
||||||
var gEnv {.importc: "environ".}: cstringArray
|
|
||||||
|
|
||||||
proc getEnvVarsC() =
|
# Environment handling cannot be put into RTL, because the ``envPairs``
|
||||||
# retrieves the variables of char** env of C's main proc
|
# iterator depends on ``environment``.
|
||||||
if not envComputed:
|
|
||||||
environment = @[]
|
|
||||||
when useNSGetEnviron:
|
|
||||||
var gEnv = NSGetEnviron()[]
|
|
||||||
var i = 0
|
|
||||||
while gEnv[i] != nil:
|
|
||||||
add environment, $gEnv[i]
|
|
||||||
inc(i)
|
|
||||||
envComputed = true
|
|
||||||
|
|
||||||
proc findEnvVar(key: string): int =
|
var
|
||||||
getEnvVarsC()
|
envComputed {.threadvar.}: bool
|
||||||
var temp = key & '='
|
environment {.threadvar.}: seq[string]
|
||||||
for i in 0..high(environment):
|
|
||||||
when defined(windows):
|
|
||||||
if skipIgnoreCase(environment[i], temp) == len(temp): return i
|
|
||||||
else:
|
|
||||||
if startsWith(environment[i], temp): return i
|
|
||||||
return -1
|
|
||||||
|
|
||||||
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
when defined(nimV2):
|
||||||
## Returns the value of the `environment variable`:idx: named `key`.
|
proc unpairedEnvAllocs*(): int =
|
||||||
##
|
result = environment.len
|
||||||
## If the variable does not exist, `""` is returned. To distinguish
|
if result > 0: inc result
|
||||||
## whether a variable exists or it's value is just `""`, call
|
|
||||||
## `existsEnv(key) proc <#existsEnv,string>`_.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `existsEnv proc <#existsEnv,string>`_
|
|
||||||
## * `putEnv proc <#putEnv,string,string>`_
|
|
||||||
## * `delEnv proc <#delEnv,string>`_
|
|
||||||
## * `envPairs iterator <#envPairs.i>`_
|
|
||||||
runnableExamples:
|
|
||||||
assert getEnv("unknownEnv") == ""
|
|
||||||
assert getEnv("unknownEnv", "doesn't exist") == "doesn't exist"
|
|
||||||
|
|
||||||
when nimvm:
|
when defined(windows) and not defined(nimscript):
|
||||||
discard "built into the compiler"
|
# because we support Windows GUI applications, things get really
|
||||||
else:
|
# messy here...
|
||||||
var i = findEnvVar(key)
|
when useWinUnicode:
|
||||||
if i >= 0:
|
when defined(cpp):
|
||||||
return TaintedString(substr(environment[i], find(environment[i], '=')+1))
|
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
||||||
else:
|
importcpp: "(NI16*)wcschr((const wchar_t *)#, #)", header: "<string.h>".}
|
||||||
var env = c_getenv(key)
|
|
||||||
if env == nil: return TaintedString(default)
|
|
||||||
result = TaintedString($env)
|
|
||||||
|
|
||||||
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
|
||||||
## Checks whether the environment variable named `key` exists.
|
|
||||||
## Returns true if it exists, false otherwise.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `getEnv proc <#getEnv,string,string>`_
|
|
||||||
## * `putEnv proc <#putEnv,string,string>`_
|
|
||||||
## * `delEnv proc <#delEnv,string>`_
|
|
||||||
## * `envPairs iterator <#envPairs.i>`_
|
|
||||||
runnableExamples:
|
|
||||||
assert not existsEnv("unknownEnv")
|
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
discard "built into the compiler"
|
|
||||||
else:
|
|
||||||
if c_getenv(key) != nil: return true
|
|
||||||
else: return findEnvVar(key) >= 0
|
|
||||||
|
|
||||||
proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
|
||||||
## Sets the value of the `environment variable`:idx: named `key` to `val`.
|
|
||||||
## If an error occurs, `OSError` is raised.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `getEnv proc <#getEnv,string,string>`_
|
|
||||||
## * `existsEnv proc <#existsEnv,string>`_
|
|
||||||
## * `delEnv proc <#delEnv,string>`_
|
|
||||||
## * `envPairs iterator <#envPairs.i>`_
|
|
||||||
|
|
||||||
# Note: by storing the string in the environment sequence,
|
|
||||||
# we guarantee that we don't free the memory before the program
|
|
||||||
# ends (this is needed for POSIX compliance). It is also needed so that
|
|
||||||
# the process itself may access its modified environment variables!
|
|
||||||
when nimvm:
|
|
||||||
discard "built into the compiler"
|
|
||||||
else:
|
|
||||||
var indx = findEnvVar(key)
|
|
||||||
if indx >= 0:
|
|
||||||
environment[indx] = key & '=' & val
|
|
||||||
else:
|
|
||||||
add environment, (key & '=' & val)
|
|
||||||
indx = high(environment)
|
|
||||||
when defined(windows) and not defined(nimscript):
|
|
||||||
when useWinUnicode:
|
|
||||||
var k = newWideCString(key)
|
|
||||||
var v = newWideCString(val)
|
|
||||||
if setEnvironmentVariableW(k, v) == 0'i32: raiseOSError(osLastError())
|
|
||||||
else:
|
else:
|
||||||
if setEnvironmentVariableA(key, val) == 0'i32: raiseOSError(osLastError())
|
proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
|
||||||
|
importc: "wcschr", header: "<string.h>".}
|
||||||
else:
|
else:
|
||||||
if c_putenv(environment[indx]) != 0'i32:
|
proc strEnd(cstr: cstring, c = 0'i32): cstring {.
|
||||||
raiseOSError(osLastError())
|
importc: "strchr", header: "<string.h>".}
|
||||||
|
|
||||||
|
proc getEnvVarsC() =
|
||||||
|
if not envComputed:
|
||||||
|
environment = @[]
|
||||||
|
when useWinUnicode:
|
||||||
|
var
|
||||||
|
env = getEnvironmentStringsW()
|
||||||
|
e = env
|
||||||
|
if e == nil: return # an error occurred
|
||||||
|
while true:
|
||||||
|
var eend = strEnd(e)
|
||||||
|
add(environment, $e)
|
||||||
|
e = cast[WideCString](cast[ByteAddress](eend)+2)
|
||||||
|
if eend[1].int == 0: break
|
||||||
|
discard freeEnvironmentStringsW(env)
|
||||||
|
else:
|
||||||
|
var
|
||||||
|
env = getEnvironmentStringsA()
|
||||||
|
e = env
|
||||||
|
if e == nil: return # an error occurred
|
||||||
|
while true:
|
||||||
|
var eend = strEnd(e)
|
||||||
|
add(environment, $e)
|
||||||
|
e = cast[cstring](cast[ByteAddress](eend)+1)
|
||||||
|
if eend[1] == '\0': break
|
||||||
|
discard freeEnvironmentStringsA(env)
|
||||||
|
envComputed = true
|
||||||
|
|
||||||
proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
|
||||||
## Deletes the `environment variable`:idx: named `key`.
|
|
||||||
## If an error occurs, `OSError` is raised.
|
|
||||||
##
|
|
||||||
## See also:ven
|
|
||||||
## * `getEnv proc <#getEnv,string,string>`_
|
|
||||||
## * `existsEnv proc <#existsEnv,string>`_
|
|
||||||
## * `putEnv proc <#putEnv,string,string>`_
|
|
||||||
## * `envPairs iterator <#envPairs.i>`_
|
|
||||||
when nimvm:
|
|
||||||
discard "built into the compiler"
|
|
||||||
else:
|
else:
|
||||||
var indx = findEnvVar(key)
|
const
|
||||||
if indx < 0: return # Do nothing if the env var is not already set
|
useNSGetEnviron = (defined(macosx) and not defined(ios) and not defined(emscripten)) or defined(nimscript)
|
||||||
when defined(windows) and not defined(nimscript):
|
|
||||||
when useWinUnicode:
|
|
||||||
var k = newWideCString(key)
|
|
||||||
if setEnvironmentVariableW(k, nil) == 0'i32: raiseOSError(osLastError())
|
|
||||||
else:
|
|
||||||
if setEnvironmentVariableA(key, nil) == 0'i32: raiseOSError(osLastError())
|
|
||||||
else:
|
|
||||||
if c_unsetenv(key) != 0'i32:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
environment.delete(indx)
|
|
||||||
|
|
||||||
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
when useNSGetEnviron:
|
||||||
## Iterate over all `environments variables`:idx:.
|
# From the manual:
|
||||||
##
|
# Shared libraries and bundles don't have direct access to environ,
|
||||||
## In the first component of the tuple is the name of the current variable stored,
|
# which is only available to the loader ld(1) when a complete program
|
||||||
## in the second its value.
|
# is being linked.
|
||||||
##
|
# The environment routines can still be used, but if direct access to
|
||||||
## See also:
|
# environ is needed, the _NSGetEnviron() routine, defined in
|
||||||
## * `getEnv proc <#getEnv,string,string>`_
|
# <crt_externs.h>, can be used to retrieve the address of environ
|
||||||
## * `existsEnv proc <#existsEnv,string>`_
|
# at runtime.
|
||||||
## * `putEnv proc <#putEnv,string,string>`_
|
proc NSGetEnviron(): ptr cstringArray {.
|
||||||
## * `delEnv proc <#delEnv,string>`_
|
importc: "_NSGetEnviron", header: "<crt_externs.h>".}
|
||||||
getEnvVarsC()
|
elif defined(haiku):
|
||||||
for i in 0..high(environment):
|
var gEnv {.importc: "environ", header: "<stdlib.h>".}: cstringArray
|
||||||
var p = find(environment[i], '=')
|
else:
|
||||||
yield (TaintedString(substr(environment[i], 0, p-1)),
|
var gEnv {.importc: "environ".}: cstringArray
|
||||||
TaintedString(substr(environment[i], p+1)))
|
|
||||||
|
proc getEnvVarsC() =
|
||||||
|
# retrieves the variables of char** env of C's main proc
|
||||||
|
if not envComputed:
|
||||||
|
environment = @[]
|
||||||
|
when useNSGetEnviron:
|
||||||
|
var gEnv = NSGetEnviron()[]
|
||||||
|
var i = 0
|
||||||
|
while gEnv[i] != nil:
|
||||||
|
add environment, $gEnv[i]
|
||||||
|
inc(i)
|
||||||
|
envComputed = true
|
||||||
|
|
||||||
|
proc findEnvVar(key: string): int =
|
||||||
|
getEnvVarsC()
|
||||||
|
var temp = key & '='
|
||||||
|
for i in 0..high(environment):
|
||||||
|
when defined(windows):
|
||||||
|
if skipIgnoreCase(environment[i], temp) == len(temp): return i
|
||||||
|
else:
|
||||||
|
if startsWith(environment[i], temp): return i
|
||||||
|
return -1
|
||||||
|
|
||||||
|
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
||||||
|
## Returns the value of the `environment variable`:idx: named `key`.
|
||||||
|
##
|
||||||
|
## If the variable does not exist, `""` is returned. To distinguish
|
||||||
|
## whether a variable exists or it's value is just `""`, call
|
||||||
|
## `existsEnv(key) proc <#existsEnv,string>`_.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `existsEnv proc <#existsEnv,string>`_
|
||||||
|
## * `putEnv proc <#putEnv,string,string>`_
|
||||||
|
## * `delEnv proc <#delEnv,string>`_
|
||||||
|
## * `envPairs iterator <#envPairs.i>`_
|
||||||
|
runnableExamples:
|
||||||
|
assert getEnv("unknownEnv") == ""
|
||||||
|
assert getEnv("unknownEnv", "doesn't exist") == "doesn't exist"
|
||||||
|
|
||||||
|
when nimvm:
|
||||||
|
discard "built into the compiler"
|
||||||
|
else:
|
||||||
|
var i = findEnvVar(key)
|
||||||
|
if i >= 0:
|
||||||
|
return TaintedString(substr(environment[i], find(environment[i], '=')+1))
|
||||||
|
else:
|
||||||
|
var env = c_getenv(key)
|
||||||
|
if env == nil: return TaintedString(default)
|
||||||
|
result = TaintedString($env)
|
||||||
|
|
||||||
|
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
||||||
|
## Checks whether the environment variable named `key` exists.
|
||||||
|
## Returns true if it exists, false otherwise.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `getEnv proc <#getEnv,string,string>`_
|
||||||
|
## * `putEnv proc <#putEnv,string,string>`_
|
||||||
|
## * `delEnv proc <#delEnv,string>`_
|
||||||
|
## * `envPairs iterator <#envPairs.i>`_
|
||||||
|
runnableExamples:
|
||||||
|
assert not existsEnv("unknownEnv")
|
||||||
|
|
||||||
|
when nimvm:
|
||||||
|
discard "built into the compiler"
|
||||||
|
else:
|
||||||
|
if c_getenv(key) != nil: return true
|
||||||
|
else: return findEnvVar(key) >= 0
|
||||||
|
|
||||||
|
proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||||
|
## Sets the value of the `environment variable`:idx: named `key` to `val`.
|
||||||
|
## If an error occurs, `OSError` is raised.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `getEnv proc <#getEnv,string,string>`_
|
||||||
|
## * `existsEnv proc <#existsEnv,string>`_
|
||||||
|
## * `delEnv proc <#delEnv,string>`_
|
||||||
|
## * `envPairs iterator <#envPairs.i>`_
|
||||||
|
|
||||||
|
# Note: by storing the string in the environment sequence,
|
||||||
|
# we guarantee that we don't free the memory before the program
|
||||||
|
# ends (this is needed for POSIX compliance). It is also needed so that
|
||||||
|
# the process itself may access its modified environment variables!
|
||||||
|
when nimvm:
|
||||||
|
discard "built into the compiler"
|
||||||
|
else:
|
||||||
|
var indx = findEnvVar(key)
|
||||||
|
if indx >= 0:
|
||||||
|
environment[indx] = key & '=' & val
|
||||||
|
else:
|
||||||
|
add environment, (key & '=' & val)
|
||||||
|
indx = high(environment)
|
||||||
|
when defined(windows) and not defined(nimscript):
|
||||||
|
when useWinUnicode:
|
||||||
|
var k = newWideCString(key)
|
||||||
|
var v = newWideCString(val)
|
||||||
|
if setEnvironmentVariableW(k, v) == 0'i32: raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if setEnvironmentVariableA(key, val) == 0'i32: raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if c_putenv(environment[indx]) != 0'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
|
proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
||||||
|
## Deletes the `environment variable`:idx: named `key`.
|
||||||
|
## If an error occurs, `OSError` is raised.
|
||||||
|
##
|
||||||
|
## See also:ven
|
||||||
|
## * `getEnv proc <#getEnv,string,string>`_
|
||||||
|
## * `existsEnv proc <#existsEnv,string>`_
|
||||||
|
## * `putEnv proc <#putEnv,string,string>`_
|
||||||
|
## * `envPairs iterator <#envPairs.i>`_
|
||||||
|
when nimvm:
|
||||||
|
discard "built into the compiler"
|
||||||
|
else:
|
||||||
|
var indx = findEnvVar(key)
|
||||||
|
if indx < 0: return # Do nothing if the env var is not already set
|
||||||
|
when defined(windows) and not defined(nimscript):
|
||||||
|
when useWinUnicode:
|
||||||
|
var k = newWideCString(key)
|
||||||
|
if setEnvironmentVariableW(k, nil) == 0'i32: raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if setEnvironmentVariableA(key, nil) == 0'i32: raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if c_unsetenv(key) != 0'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
environment.delete(indx)
|
||||||
|
|
||||||
|
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
||||||
|
## Iterate over all `environments variables`:idx:.
|
||||||
|
##
|
||||||
|
## In the first component of the tuple is the name of the current variable stored,
|
||||||
|
## in the second its value.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `getEnv proc <#getEnv,string,string>`_
|
||||||
|
## * `existsEnv proc <#existsEnv,string>`_
|
||||||
|
## * `putEnv proc <#putEnv,string,string>`_
|
||||||
|
## * `delEnv proc <#delEnv,string>`_
|
||||||
|
getEnvVarsC()
|
||||||
|
for i in 0..high(environment):
|
||||||
|
var p = find(environment[i], '=')
|
||||||
|
yield (TaintedString(substr(environment[i], 0, p-1)),
|
||||||
|
TaintedString(substr(environment[i], p+1)))
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,29 @@ block:
|
||||||
if not isWindows:
|
if not isWindows:
|
||||||
doAssert cwd.isAbsolute
|
doAssert cwd.isAbsolute
|
||||||
doAssert relativePath(getCurrentDir() / "foo", "bar") == "../foo"
|
doAssert relativePath(getCurrentDir() / "foo", "bar") == "../foo"
|
||||||
|
|
||||||
|
import std/sequtils
|
||||||
|
|
||||||
|
template main =
|
||||||
|
putEnv("foo", "bar")
|
||||||
|
doAssert getEnv("foo") == "bar"
|
||||||
|
doAssert existsEnv("foo")
|
||||||
|
|
||||||
|
putEnv("foo", "")
|
||||||
|
doAssert existsEnv("foo")
|
||||||
|
putEnv("foo", "bar2")
|
||||||
|
doAssert getEnv("foo") == "bar2"
|
||||||
|
|
||||||
|
when nimvm:
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
# need support in vmops: envPairs, delEnv
|
||||||
|
let s = toSeq(envPairs())
|
||||||
|
doAssert ("foo", "bar2") in s
|
||||||
|
doAssert ("foo", "bar") notin s
|
||||||
|
|
||||||
|
delEnv("foo")
|
||||||
|
doAssert not existsEnv("foo")
|
||||||
|
|
||||||
|
static: main()
|
||||||
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue