mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-08-01 06:37:46 +00:00
RFC: add a command to help parsing arguments in scripts (#875)
the other day, i was writing a script and wanted to pass a `list<int>` to it which is not possible because there is no such things as _types_ for externals 🤔 i ended up writing an "arg parsing" command to help in that task and thought it could be useful to people 😇 in this MR, i add `std-rfc parse-arg` in the `script-parsing.nu` module and add associated tests which all pass. i invite the reader to have a look at the docstring of `parse-arg` which should contain a full example explaining the usage of this new command 😉 --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
parent
6aa2700730
commit
71f5736d93
4 changed files with 100 additions and 0 deletions
|
@ -6,3 +6,4 @@ export module math/
|
||||||
export use bulk-rename.nu *
|
export use bulk-rename.nu *
|
||||||
export use set-env.nu *
|
export use set-env.nu *
|
||||||
export use bench.nu
|
export use bench.nu
|
||||||
|
export use script-parsing.nu [ parse-arg ]
|
||||||
|
|
61
stdlib-candidate/std-rfc/script-parsing.nu
Normal file
61
stdlib-candidate/std-rfc/script-parsing.nu
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# helps parsing CLI arguments for Nushell scripts
|
||||||
|
#
|
||||||
|
# the following Nushell script does not make sense to be used as an external
|
||||||
|
# command because there is no such thing as a `list<string>` in Bash for
|
||||||
|
# instance.
|
||||||
|
# ```nushell
|
||||||
|
# def main [x: list<int>] {
|
||||||
|
# print $x
|
||||||
|
# }
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# one needs to write something less strict at parse-time and thus looses type
|
||||||
|
# information...
|
||||||
|
# ```nushell
|
||||||
|
# def main [
|
||||||
|
# x: string, # list<int>
|
||||||
|
# ] {
|
||||||
|
# print $x
|
||||||
|
# }
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# it's possible to write a much stronger script whith `parse-arg`
|
||||||
|
# ```nushell
|
||||||
|
# def main [
|
||||||
|
# x: string, # list<int>
|
||||||
|
# ] {
|
||||||
|
# let x = $x | parse-arg (metadata $x).span "list<int>" # the script would crash if either
|
||||||
|
# # `$x: string` is not valid NUON or if
|
||||||
|
# # the resulting value is not a `list<int>`
|
||||||
|
# print $x # here, `$x` is a `list<int>` as intended
|
||||||
|
# }
|
||||||
|
# ```
|
||||||
|
export def parse-arg [
|
||||||
|
span: record<start: int, end: int>, # the span of the input variable
|
||||||
|
expected_type: string, # the expected type for the input variable
|
||||||
|
]: [ string -> any ] {
|
||||||
|
let val = try {
|
||||||
|
$in | from nuon
|
||||||
|
} catch {
|
||||||
|
error make {
|
||||||
|
msg: $"(ansi red_bold)invalid NUON(ansi reset)",
|
||||||
|
label: {
|
||||||
|
text: "invalid NUON",
|
||||||
|
span: $span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($val | describe) != $expected_type {
|
||||||
|
error make {
|
||||||
|
msg: $"(ansi red_bold)bad type(ansi reset)",
|
||||||
|
label: {
|
||||||
|
text: $"type: ($val | describe)",
|
||||||
|
span: $span,
|
||||||
|
},
|
||||||
|
help: $"expected ($expected_type)",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$val
|
||||||
|
}
|
|
@ -3,4 +3,5 @@ export module record.nu
|
||||||
export module str_xpend.nu
|
export module str_xpend.nu
|
||||||
export module math.nu
|
export module math.nu
|
||||||
export module bench.nu
|
export module bench.nu
|
||||||
|
export module script-parsing.nu
|
||||||
export module str_dedent.nu
|
export module str_dedent.nu
|
||||||
|
|
37
stdlib-candidate/tests/script-parsing.nu
Normal file
37
stdlib-candidate/tests/script-parsing.nu
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use std assert
|
||||||
|
use ../std-rfc parse-arg
|
||||||
|
|
||||||
|
const SPAN = { start: 0, end: 0 }
|
||||||
|
|
||||||
|
export def "test parse-arg ok" [] {
|
||||||
|
const TEST_CASES = [
|
||||||
|
[ input, type, expected ];
|
||||||
|
|
||||||
|
[ "123", "int", 123 ],
|
||||||
|
[ "[1, 2, 3]", "list<int>", [1, 2, 3] ],
|
||||||
|
[ "'spam'", "string", "spam" ],
|
||||||
|
[
|
||||||
|
"{ a: 1, b: 'egg', c: false }",
|
||||||
|
"record<a: int, b: string, c: bool>",
|
||||||
|
{ a: 1, b: 'egg', c: false },
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
for t in $TEST_CASES {
|
||||||
|
assert equal ($t.input | parse-arg $SPAN $t.type) $t.expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export def "test parse-arg err" [] {
|
||||||
|
const TEST_CASES = [
|
||||||
|
[ input, type ];
|
||||||
|
|
||||||
|
[ "{ invalid NUON", "" ],
|
||||||
|
[ "[1, 2, 3]", "string" ],
|
||||||
|
]
|
||||||
|
|
||||||
|
for t in $TEST_CASES {
|
||||||
|
let msg = $"test case: input: '($t.input)', type: ($t.type)"
|
||||||
|
assert error { $t.input | parse-arg $SPAN $t.type } $msg
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue