Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add completion file for GNU Stow #36

Closed
wants to merge 21 commits into from

Conversation

orel1
Copy link
Contributor

@orel1 orel1 commented Jun 24, 2019

Hello,
Here you can find a new zsh completion script for GNU Stow.

Copy link
Member

@danielshahaf danielshahaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch. I skimmed through and found a few issues, but did not do a complete review.

Completion/Unix/Command/_stow Outdated Show resolved Hide resolved

__stow_complete_packages() {
local IFS=$'\n'
local basedir="${1/\~/$HOME}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it's going to DTWT on ~foo and foo~bar. Could you please make it more robust? For that matter, why isn't local basedir="$1" good enough?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know exactly why I had this, but with _values -C "packages from $basedir" $basedir/*(-/N:t), local basedir="$1" seems sufficient. So, I'm going to make a modification in that way.

arguments=(
'(- *)'{--help,-h}'[show help]'
'(- *)'{--version,-v}'[show version number]'
'(-d --dir)'{-d,--dir=-}'[set the stow dir (default is current dir)]:stow dir:_files -/'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is {-d,--dir=-} correct? GNU programs generally use {-d+,--dir=} (added plus, removed minus).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I'll fix that and do the same for -t,--target=-

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are still a few instances of --foo=- in _stow and _chkstow. Could you please confirm that they're correct, or change them if they aren't?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argh, good point.

Completion/Unix/Command/_stow Outdated Show resolved Hide resolved
@orel1
Copy link
Contributor Author

orel1 commented Jun 29, 2019

Following the previous discussions, I made some modifications/corrections.

it works, except on one point, if I use --dir=$HOME/somedir or --dir=~/somedir no completion results are found. For ~ this is really not a problem, but it seems that $HOME is not expand...

# if not provided from the command line, for the stow command, the stow
# directory is assumed to be the value of the "STOW_DIR" environment
# variable...
stow_dir="$STOW_DIR"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be worthwhile to check [[ ${(t)STOW_DIR} == *export* ]], in order to prevent mysterious behaviour for users who set the variable but forget to export it.

@danielshahaf
Copy link
Member

it works, except on one point, if I use --dir=$HOME/somedir or --dir=~/somedir no completion results are found. For ~ this is really not a problem, but it seems that $HOME is not expand...

A tilde would be expanded there if MAGIC_EQUAL_SUBST were set.

I'm afraid I don't remember how this is usually handled. You might try asking on the mailing list — it has more answerers than our github/gitlab presence.

@orel1
Copy link
Contributor Author

orel1 commented Jul 1, 2019

ok. Thanks you for the feedback.
I'll take my chances on that side.

option '-U' is recommended for the use of functions supplied with the
zsh distribution
use zsh's "glob qualifiers" instead for performance on cygwin and for
correctness (filenames with spaces, etc)
if defined, stow can use the value of the "STOW_DIR" environment
variable as stow directory
Without this, parameters like '$HOME' or '~/' were not evaluated and
therefore could not be used as a value for the '--dir|-d' option.
Thanks to the help from the zsh-users ML
(https://www.zsh.org/mla/users/2019/msg00315.html)
The problem whith evaluation is that it breaks the principle of least
surprise, and could lead to unexpected and undesired results.
# A zsh completion script for GNU stow (https://www.gnu.org/software/stow/)
#

__stow_complete_packages() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider guarding this with (( $+functions[__stow_complete_packages] )) ||, so that the function doesn't get re-defined if it already exists. Also, the complete in the function name feels a bit redundant

Copy link
Contributor Author

@orel1 orel1 Dec 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 3570f59

local -a stow_pkg_list=( $stow_dir/*(-/N:t) )

if [[ ${#stow_pkg_list} -gt 0 ]]; then
_values -C "packages from $stow_dir" ${stow_pkg_list[@]}
Copy link
Contributor

@okdana okdana Oct 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to escape special characters in the operands if you're going to use _values; something like: -- ${${stow_pkg_list//\\/\\\\}//:/\\:}

Alternatively you could replace all of this by _wanted and compadd, but you might have to change the way you call the function from _arguments

Also, descriptions should be singular (package, not packages)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 3c75ffc

arguments=(
'(- *)'{--help,-h}'[show help]'
'(- *)'{--version,-V}'[show version number]'
'(-d --dir)'{-d+,--dir=}'[set the stow dir (default is current dir)]:stow dir:_files -/'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be in the completion style guide, but either Oliver or Daniel once suggested to me to put defaults in square brackets at the end of the match description, as in stow directory [$PWD]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how to do that... could you give me an example please ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change :stow dir: to :stow dir [$PWD]:.

One of us will add this guidance to Etc/completion-style-guide (or you can do that, of course).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done by @okdana (thanks!) in workers/44969.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in a3e659b

'(- *)'{--version,-V}'[show version number]'
'(-d --dir)'{-d+,--dir=}'[set the stow dir (default is current dir)]:stow dir:_files -/'
'(-t --target)'{-t+,--target=}'[set the target dir (default is parent of stow dir)]:target dir:_files -/'
'*'{-S,--stow}'[stow the package names that follow]:stow package:->stow_package'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the stow man page, i don't think these specs are right:

https://www.gnu.org/software/stow/manual/stow.html#Mixing-Operations

Off the top of my head i'm not sure what would be the ideal way to do this. You could use the :*:... mechanism, but there's no way to return from it. idk. At the least, you might consider leaving a note here that it's not accurate

Also, the :stow package: in all of these is superfluous (and misleading)

Copy link
Contributor Author

@orel1 orel1 Dec 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I hadn't thought of this case. But after a few tests, this doesn't seem to be a problem for stow, even if it can lead to surprising results... I have added a note to explain that point (76c1504).

However, I do not understand the following comment:

Also, the :stow package: in all of these is superfluous (and misleading)

if I remove :stow package: it doesn't work anymore...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try just : :.

The description is ignored because it goes to the stow_package state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 0ebc963

'--no-folding[disable any further tree folding or tree refolding]'
'(-p --compat)'{-p,--compat}'[use legacy algorithm for unstowing]'
'(-n -no --simulate)'{-n,--no,--simulate}'[do not actually make any filesystem changes]'
'(-v --verbose)'{-v,--verbose}'[increase or set the level of verbosity (from 0 to 5)]'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like --verbose is supposed to take an optional verbosity level, and it should be possible to use them multiple times so they stack up (e.g., you can do either -vvv or --verbose=3)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, initially I used this (see my first commit 64fcfa8) :

'(-v --verbose)'{-v,--verbose}'[increase verbosity]'
'(-v --verbose)'--verbose=-'[set verbose level to n]:level:(0 1 2 3 4 5)'`

I don't know if there's a better way to do this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the argument to --verbose is optional, use two colons to indicate so. For example:

'*-v[increase verbosity]'
'*--verbose=-[increase verbosity]::level:(0 1 2 3 4 5)'

I'd be inclined to have the same description so the options are grouped together. Things like "to n" seem weird without more context for what "n" is anyway. And if options can be repeated, we want the initial * rather than exclusion lists.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 675da08

'*:stow package:->stow_package'
)

if (( ${+commands[stow]} )) ; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we don't worry about version checks like this, we just support whatever the latest options are. Especially since it's just this one option, i wouldn't bother with it personally. (If you did keep it, i'd try to use _pick_variant or something rather than making an external call every single time)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 8ae64ab

stow_dir="$opt_args[-d]"
elif (( $+opt_args[--dir] )) ; then
stow_dir="$opt_args[--dir]"
elif [[ ${(t)STOW_DIR} == *export* ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this maybe check for emptiness?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be sure, are you thinking about the case where the exported variable is empty ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't speak for okdana but I would assume so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's what i meant. I'm not sure how Stow actually handles that — i know some environment variables are only checked for set-ness — but intuitively i'd assume that STOW_DIR='' is treated as unset

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be treated as equivalent to cwd. For example, s=""; echo $s:P works this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in b1272e3

stow_dir="$PWD"
fi

__stow_complete_packages "$stow_dir"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not setting ret here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, the use of the ret variable is not very clear to me....
I should add && ret=0 at the end of the line ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completion functions should return 0 if they added matches or did something useful. and 1 if not. Returning 1 can mean that zsh goes on to try further "completers" - approximate completion and so on.

A common way to do this is to start the script by declaring ret=1, put && ret=0 after ever call to compadd or other completion functions and then put return ret at the end. If you use this approach, you need to remember the && ret=0 on every call that might add some completion candidates.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 414270e

fi
fi

_arguments -s -W -C $arguments && ret=0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure about the use of -W here. Genuine cases where -w or -W are needed are very rare so I tend not to believe it when I see it used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in b9c086f


case $service in
stow)
local context state line curcontext="$curcontext" ret=1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making context local is superfluous. It is nearly always fine to stick with curcontext abd pass -C to _arguments/_values wherever you use states. context is an array and is only applicable where multiple states could be active together (which only happens with things like optional arguments).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 6178a88

@okapia
Copy link
Contributor

okapia commented Nov 26, 2019

It'd be great to get this merged into zsh.

Thanks for addressing the initial points from Daniel's review. And sorry that it was then left for a couple of months before further review comments were added. It'd still be good to address these further points. Can we perhaps get this finalised? Thanks

@orel1
Copy link
Contributor Author

orel1 commented Nov 26, 2019

I agree with that, but time has gone by far too quickly in recent weeks....

I'm trying to respond to the last comments this weekend.

@orel1
Copy link
Contributor Author

orel1 commented Dec 7, 2019

Thank you for all your answers 😄

@okapia
Copy link
Contributor

okapia commented Dec 16, 2019

Merged in 058cc10.

Thanks for the contribution.

I'm not sure if any of the normal zsh developers use GNU stow at all. I certainly don't. So please help keep the completion current by sending us fixes as and when there are updates to stow. Thanks

@okapia okapia closed this Dec 16, 2019
okdana pushed a commit to okdana/zsh that referenced this pull request Dec 16, 2019
romkatv pushed a commit to romkatv/zsh that referenced this pull request Dec 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants