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,29 +3,65 @@
|
||||||
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):
|
||||||
|
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
||||||
|
var ret: cstring
|
||||||
|
let key2 = key.cstring
|
||||||
|
{.emit: "`ret` = process.env[`key2`];".}
|
||||||
|
result = $ret
|
||||||
|
|
||||||
|
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
||||||
|
var key2 = key.cstring
|
||||||
|
var ret: bool
|
||||||
|
{.emit: "`ret` = `key2` in process.env;".}
|
||||||
|
result = ret
|
||||||
|
|
||||||
|
proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||||
|
var key2 = key.cstring
|
||||||
|
var val2 = val.cstring
|
||||||
|
{.emit: "process.env[`key2`] = `val2`;".}
|
||||||
|
|
||||||
|
proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
||||||
|
var key2 = key.cstring
|
||||||
|
{.emit: "delete process.env[`key2`];".}
|
||||||
|
|
||||||
|
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
||||||
|
var num: int
|
||||||
|
var keys: RootObj
|
||||||
|
{.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)
|
||||||
|
|
||||||
|
# commented because it must keep working with js+VM
|
||||||
|
# elif defined(js):
|
||||||
|
# {.error: "requires -d:nodejs".}
|
||||||
|
|
||||||
|
else:
|
||||||
|
when defined(windows):
|
||||||
from parseutils import skipIgnoreCase
|
from parseutils import skipIgnoreCase
|
||||||
|
|
||||||
proc c_getenv(env: cstring): cstring {.
|
proc c_getenv(env: cstring): cstring {.
|
||||||
importc: "getenv", header: "<stdlib.h>".}
|
importc: "getenv", header: "<stdlib.h>".}
|
||||||
proc c_putenv(env: cstring): cint {.
|
proc c_putenv(env: cstring): cint {.
|
||||||
importc: "putenv", header: "<stdlib.h>".}
|
importc: "putenv", header: "<stdlib.h>".}
|
||||||
proc c_unsetenv(env: cstring): cint {.
|
proc c_unsetenv(env: cstring): cint {.
|
||||||
importc: "unsetenv", header: "<stdlib.h>".}
|
importc: "unsetenv", header: "<stdlib.h>".}
|
||||||
|
|
||||||
# Environment handling cannot be put into RTL, because the ``envPairs``
|
# Environment handling cannot be put into RTL, because the ``envPairs``
|
||||||
# iterator depends on ``environment``.
|
# iterator depends on ``environment``.
|
||||||
|
|
||||||
var
|
var
|
||||||
envComputed {.threadvar.}: bool
|
envComputed {.threadvar.}: bool
|
||||||
environment {.threadvar.}: seq[string]
|
environment {.threadvar.}: seq[string]
|
||||||
|
|
||||||
when defined(nimV2):
|
when defined(nimV2):
|
||||||
proc unpairedEnvAllocs*(): int =
|
proc unpairedEnvAllocs*(): int =
|
||||||
result = environment.len
|
result = environment.len
|
||||||
if result > 0: inc result
|
if result > 0: inc result
|
||||||
|
|
||||||
when defined(windows) and not defined(nimscript):
|
when defined(windows) and not defined(nimscript):
|
||||||
# because we support Windows GUI applications, things get really
|
# because we support Windows GUI applications, things get really
|
||||||
# messy here...
|
# messy here...
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
|
|
@ -66,7 +102,7 @@ when defined(windows) and not defined(nimscript):
|
||||||
discard freeEnvironmentStringsA(env)
|
discard freeEnvironmentStringsA(env)
|
||||||
envComputed = true
|
envComputed = true
|
||||||
|
|
||||||
else:
|
else:
|
||||||
const
|
const
|
||||||
useNSGetEnviron = (defined(macosx) and not defined(ios) and not defined(emscripten)) or defined(nimscript)
|
useNSGetEnviron = (defined(macosx) and not defined(ios) and not defined(emscripten)) or defined(nimscript)
|
||||||
|
|
||||||
|
|
@ -98,7 +134,7 @@ else:
|
||||||
inc(i)
|
inc(i)
|
||||||
envComputed = true
|
envComputed = true
|
||||||
|
|
||||||
proc findEnvVar(key: string): int =
|
proc findEnvVar(key: string): int =
|
||||||
getEnvVarsC()
|
getEnvVarsC()
|
||||||
var temp = key & '='
|
var temp = key & '='
|
||||||
for i in 0..high(environment):
|
for i in 0..high(environment):
|
||||||
|
|
@ -108,7 +144,7 @@ proc findEnvVar(key: string): int =
|
||||||
if startsWith(environment[i], temp): return i
|
if startsWith(environment[i], temp): return i
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
||||||
## Returns the value of the `environment variable`:idx: named `key`.
|
## Returns the value of the `environment variable`:idx: named `key`.
|
||||||
##
|
##
|
||||||
## If the variable does not exist, `""` is returned. To distinguish
|
## If the variable does not exist, `""` is returned. To distinguish
|
||||||
|
|
@ -135,7 +171,7 @@ proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].}
|
||||||
if env == nil: return TaintedString(default)
|
if env == nil: return TaintedString(default)
|
||||||
result = TaintedString($env)
|
result = TaintedString($env)
|
||||||
|
|
||||||
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
||||||
## Checks whether the environment variable named `key` exists.
|
## Checks whether the environment variable named `key` exists.
|
||||||
## Returns true if it exists, false otherwise.
|
## Returns true if it exists, false otherwise.
|
||||||
##
|
##
|
||||||
|
|
@ -153,7 +189,7 @@ proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
||||||
if c_getenv(key) != nil: return true
|
if c_getenv(key) != nil: return true
|
||||||
else: return findEnvVar(key) >= 0
|
else: return findEnvVar(key) >= 0
|
||||||
|
|
||||||
proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||||
## Sets the value of the `environment variable`:idx: named `key` to `val`.
|
## Sets the value of the `environment variable`:idx: named `key` to `val`.
|
||||||
## If an error occurs, `OSError` is raised.
|
## If an error occurs, `OSError` is raised.
|
||||||
##
|
##
|
||||||
|
|
@ -187,7 +223,7 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||||
if c_putenv(environment[indx]) != 0'i32:
|
if c_putenv(environment[indx]) != 0'i32:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
||||||
## Deletes the `environment variable`:idx: named `key`.
|
## Deletes the `environment variable`:idx: named `key`.
|
||||||
## If an error occurs, `OSError` is raised.
|
## If an error occurs, `OSError` is raised.
|
||||||
##
|
##
|
||||||
|
|
@ -212,7 +248,7 @@ proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
environment.delete(indx)
|
environment.delete(indx)
|
||||||
|
|
||||||
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
||||||
## Iterate over all `environments variables`:idx:.
|
## Iterate over all `environments variables`:idx:.
|
||||||
##
|
##
|
||||||
## In the first component of the tuple is the name of the current variable stored,
|
## In the first component of the tuple is the name of the current variable stored,
|
||||||
|
|
|
||||||
|
|
@ -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