mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-07-31 14:17:45 +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 set-env.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 math.nu
|
||||
export module bench.nu
|
||||
export module script-parsing.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