z -h tries to cd into the help output
sdemos opened this issue · comments
I ran z -h
to see what I could do and hit some confusing output -
$ z -h
pazi_cd:cd:7: file name too long: pazi 0.0.2\nEuan Kemp <euank@euank.com>\nA fast autojump tool\n\nUSAGE:\n pazi [FLAGS] [OPTIONS] [dir_target] [SUBCOMMAND]\n\nFLAGS:\n -d, --dir print a directory matching a pattern; should be used via the 'z' function 'init' creates\n -h, --help Prints help information\n -i, --interactive interactively search directory matches\n -V, --version Prints version information\n\nOPTIONS:\n --add-dir <directory> add a directory to the frecency index\n --debug <debug> print debug information to stderr [env: PAZI_DEBUG=]\n\nARGS:\n <dir_target> \n\nSUBCOMMANDS:\n help Prints this message or the help of the given subcommand(s)\n import Import from another autojump program\n init Prints intialization logic for the given shell to eval
I noticed that z --help
does the thing I expect. I dug into it a little bit and it looks like the zsh function pazi_cd
only checks for the --help
explicitly. That also means that z --version
has a similar issue
$ z --version
pazi_cd:cd:7: no such file or directory: pazi 0.0.2
I don't know if the best solution is to just add checks for all possible help and version flags, or if there is some more general solution I didn't think of immediately.
After thinking about this a little, I think there may be a somewhat elegant solution possible.
The real problem here is that pazi
needs to be run and then the output acted upon from shell based on the flags given.
Right now, I'm using shell to try and guess what the output will be by duplicating a tiny subset of flag parsing.
An alternate solution would be to duplicate no flag parsing, but to pass more information back up to the caller, that is for pazi_cd
to call pazi --dir
and get back enough information to know whether it can safely cd or not. On pazi's side, we can easily include type information (e.g. enum Result { CdResult(Dir), OutputResult((Output, ExitCode)) }
).
This seems like a much better approach on the shell end of things. One way to accomplish this could be to have a first line of output with a well known set of possible values (e.g. it could be cd | print | error
each of which would then do a well-defined thing with the remainder). This is still better than the eval
that fasd does here.
However, since we have so few possible modes of operation, I think we can just overload exit-codes. Since pazi --dir
may be called directly, it might make sense to have an opt in flag for this so the alias can have the extra information and other callers don't necessarily get it, but it might make sense to just always leave it on.
Concretely, what I'm suggesting is that pazi_cd
turns into something like the following:
pazi_cd() {
output="$(pazi --meta-exit-codes --dir -- "$@")"
case $? in
0) cd "${output}";; # success
1) exit 1;; # error no output
2) echo "${output}";; # success, print output (e.g. 'pazi')
3) echo "${output}" && exit 1;; # error, output
esac
}
Pazi would then be modified to interpret --meta-exit-codes
as "re-parse the trailing args as the real args, and wrap output with more exit-code stuff".
Apologies for being so verbose in describing this; I know you probably have long-since got the point and it's really not all that complicated. I think it even could work to fix this problem :)
@LinuxMercedes what do you think?
Also, since it might give you a laugh @sdemos, the idea I thought about before the one in the above comment was to write a library that converts a clap-rs
App
into a posix-sh getopt parsing structure, use that to generate even more pazi init
code, and go from there... I hope I'm not missing something obvious in the above because I really don't want to have to implement this backup idea.
It seems like either of the solutions you mentioned in the first comment would fix the issue.
The second comment seems like it would...work?
@euank I particularly like the exit-code-parsing option, although I think you could collapse your error handling into
1) [ "$output" != "" ] && echo "${output}"; exit 1;;
I can't see anything that would stop this from working with either bash
or zsh
.
Also, if we wanted to eventually be able to return multiple error codes, it might make sense for us to make 0
correspond to a path being output, 1
correspond to non-path OK output, and everything greater correspond to error codes. Basically, something like this:
pazi_cd() {
output="$(pazi --meta-exit-codes --dir -- "$@")"
ret=$?
case $ret in
0) cd "${output}";; # success, cd somewhere
1) echo "${output}";; # success, print output (e.g. 'pazi')
*) [ "$output" != "" ] && echo "${output}"; exit $ret;; # error
esac
}
Or, if you really care about returning 1
in the case of an error, we could map "print output" to 127
or something.
I implemented my idea from above, which I believe resolves this issue; I'll ping this issue again once a pazi release includes that change as well.
awesome! thanks.