Hello, I started working on a completion script for GNU Stow. The work in progress version is visible on github (https://github.com/zsh-users/zsh/pull/36/files). It works, but I'm stuck on the evaluation of a variable like "$HOME".... Context: GNU Stow is a symbolic link manager, which is based on packages stored in a directory (the '--dir' option). The completion allows to propose the packages present in this directory. From the command line, when I try to complete something like this: % stow --dir=$HOME/.dotfiles/ I get: 'no packages found in $HOME/.dotfiles/' It seems that "$HOME" is not evaluated, and it is the same with "~". Is there a way to evaluate these elements? Thank's -- Aur??lien
On 6 Aug 2019, at 12:04, Aurélien <orel_jf@yahoo.fr> wrote:
> From the command line, when I try to complete something like this:
>
> % stow --dir=$HOME/.dotfiles/
>
> I get: 'no packages found in $HOME/.dotfiles/'
>
> It seems that "$HOME" is not evaluated, and it is the same with "~". Is
> there a way to evaluate these elements?
Sorry for the late reply (haven't been paying attention to the ML much
recently), but if you still need help with this:
Completion functions get arguments on the command line in a 'raw' form,
exactly as they're given, including unexpanded parameters, leading tildes,
quotes, &c. That's why you get a literal $HOME instead of its value.
You can use the (Q) expansion flag to strip quotes, which is a semi-common
thing in completion functions when they need to take user input from the
command line, but there's no flag for anything fancier, and most functions
don't seem to bother with it. But if you wanted to, something like this is
probably the best way...?
local -a stow_pkg_list
eval set -A stow_pkg_list $1
[[ -n $stow_pkg_list ]] && stow_pkg_list=( $stow_pkg_list/*(-/N:t) )
It's not perfectly accurate, though; for example, because of how _arguments
breaks up optargs, this would treat `--dir=~/foo` and `--dir ~/foo` the same,
even though the tilde would not actually be expanded before passing it to stow
in the former case (unless magic_equal_subst was enabled)
dana
dana wrote on Fri, 16 Aug 2019 01:12 +00:00: > something like this is probably the best way...? > > local -a stow_pkg_list > eval set -A stow_pkg_list $1 This would run the code being typed on the command line in cases such as «--dir *(+f)» and «--dir $(sudo pwd)», wouldn't it? > [[ -n $stow_pkg_list ]] && stow_pkg_list=( $stow_pkg_list/*(-/N:t) ) I think you want ${^stow_pkg_list} in the second instance, don't you?
On 15 Aug 2019, at 20:28, Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > This would run the code being typed on the command line in cases > such as «--dir *(+f)» and «--dir $(sudo pwd)», wouldn't it? Yeah, i guess it would. On 15 Aug 2019, at 20:28, Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > I think you want ${^stow_pkg_list} in the second instance, don't you? I was assuming that you'd only ever expect a single argument. If the user did something like `stow --dir=$arr` or `stow --dir=$( print a b c)`, only the first element of the expansion would be the optarg; any others would probably be operands. But then of course it's possible for someone to do like `--dir={a,b,c}` or `--dir=$^foo`, and at that point i don't think there's *anything* sane you could do from inside that helper function. Stuff like that is probably why most functions don't try to do this dana
Le 16/08/2019 ?? 01:36, dana a ??crit??:
> You can use the (Q) expansion flag to strip quotes, which is a semi-common
> thing in completion functions when they need to take user input from the
> command line, but there's no flag for anything fancier, and most functions
> don't seem to bother with it. But if you wanted to, something like this is
> probably the best way...?
>
> local -a stow_pkg_list
> eval set -A stow_pkg_list $1
> [[ -n $stow_pkg_list ]] && stow_pkg_list=( $stow_pkg_list/*(-/N:t) )
>
> It's not perfectly accurate, though; for example, because of how _arguments
> breaks up optargs, this would treat `--dir=~/foo` and `--dir ~/foo` the same,
> even though the tilde would not actually be expanded before passing it to stow
> in the former case (unless magic_equal_subst was enabled)
>
Knowing that this option only accepts one value and after a few tests,
it seems that 'eval' is the right solution, . My function now looks like
this:
local stow_dir
local -a stow_pkg_list
eval set -A stow_dir $1
[[ -n $stow_dir ]] && stow_pkg_list=( $stow_dir/*(-/N:t) )
if [[ ${#stow_pkg_list} -gt 0 ]]; then
_values -C "packages from $stow_dir" ${stow_pkg_list[@]}
else
_message "no packages found in $stow_dir"
fi
and the completion of parameters such as'$HOME' or'~/' works well !
I pushed my modifications on github. Thank you for the answers :-)
--
Aur??lien