nushell
nushell copied to clipboard
How to passtrough any kind of argument / disable parsing
Question
I used fish to source a script to help me find my remote targets with avahi. It would wrap the ssh and rsync commands and if there is a certain keyword scan and cache the results for a little time so I can connect without any parameters.
I have converted most of my script to nushell and it is working much better and looking nicer, but I can't wrap a command silently / without any parsing.
I'd like to pass every argument and flag, and also disable the help page for the command if possible (so the original one shows).
I read about pre_execute hooks, and that seemed viable, but I need to access the command to parse it. So far I haven't found out if I can access the cli command from the hook.
Additional context and details
My working fish functions:
function wrap_ssh_based_command
set bin $argv[1]
set regex $argv[2]
set args $argv[3..-1]
function contains_keyword_arg --no-scope-shadowing
for arg in $argv
if echo $arg | string escape | string match -r "$regex" > /dev/null
return 0
end
end
return 1
end
contains_keyword_arg $args
if [ $status -eq 0 ]
cached_probe
if [ $status -eq 0 ]
eval "$bin $args"
touch $DEVELOPMENT_CONFIG_PATH
end
else
eval "$bin $args"
end
end
alias ssh="wrap_ssh_based_command /usr/bin/ssh \"$KEYWORD\" $argv"
alias rsync="wrap_ssh_based_command /usr/bin/rsync \"$KEYWORD(?=:)\" $argv"
My current function works, but if I add any flags like -v for verbose it fails, because that flag is not defined for the function.
def wrap_ssh_based_command [bin, regex_pattern, ...args] {
let cmd = ($args | prepend $bin | str collect " ")
if not ($args | find --regex $regex_pattern | is-empty) {
let scanned = cached_avahi_probe
nu -c $cmd
touch $target.config_path
} else {
nu -c $cmd
}
}
alias ssh = wrap_ssh_based_command /usr/bin/ssh $keyword
alias rsync = wrap_ssh_based_command /usr/bin/rsync $"($keyword)\(?=:)"
I'm thinking you're going to have to add flags to your custom command signature, like:
> def test [name, ...args, --verbose(-v)] { echo $"name=($name) args=($args) verbose=($verbose)" }
> test abc
name=abc args=[] verbose=false
> test abc def ghi
name=abc args=[def, ghi] verbose=false
> test abc def ghi -v
name=abc args=[def, ghi] verbose=true
> test abc def ghi -v -a
Error: nu::parser::unknown_flag (link)
× The `test` command doesn't have flag `-a`.
╭─[entry #6:1:1]
1 │ test abc def ghi -v -a
· ┬
· ╰── unknown flag
╰────
help: use test --help for a list of flags
There may be other ways but I'm not sure exactly. You might look around in our nu_scripts repo to see if anyone else has solved this problem.
There may be other ways but I'm not sure exactly. You might look around in our nu_scripts repo to see if anyone else has solved this problem.
Good idea, I missed that. I don't use arguments with ssh
much, but rsync
has the useful archive and recursive arguments. I guess at that amount of flags there's no problem just hard coding it.
This issue has come up often before, see the issues linked in this PR: https://github.com/nushell/nushell/pull/6567
We need to find a good solution to being able to relax the signature parsing.