[-- Attachment #1: Type: text/plain, Size: 685 bytes --] Test case: alias -g tail="multitail -Cs --follow-all" f() { setopt localoptions no_aliases local tail tail=1 echo $tail } g() { setopt localoptions no_aliases local tail=1 echo $tail } $ type -f f f () { setopt localoptions no_aliases local multitail -Cs --follow-all tail=1 echo $tail } $ type -f g g () { setopt localoptions no_aliases local tail=1 echo $tail } As you can see, `setopt noaliases` works as expected in function `g` where `local tail=1` is used, but not in function `f` where `local tail` is used without an assignment statement. See https://github.com/junegunn/fzf/issues/1938 for more info.
On Thu, Mar 26, 2020 at 10:55 AM Marlon Richert <marlon.richert@gmail.com> wrote: > > Test case: > > alias -g tail="multitail -Cs --follow-all" > f() { > setopt localoptions no_aliases > local tail > tail=1 > echo $tail > } Alias expansion happens when functions get parsed. If you don't want `tail` to be alias-expanded within function `f`, you need to add `setopt no_aliases` before the function of `f`. > g() { > setopt localoptions no_aliases > local tail=1 > echo $tail > } `tail` within `local tail=1` is not subject to global alias expansion. Roman.
[-- Attachment #1: Type: text/plain, Size: 1148 bytes --] Aha. So, if I want that aliases don't get expanded in the functions in https://github.com/junegunn/fzf/blob/master/shell/completion.zsh, then where should I put the `setopt noaliases` statement? Does it suffice to just put `emulate -L zsh; setopt localoptions noaliases;` at the top of the file? I don't want the noaliases option to leak into my own shell environment. Or is there a better solution possible here than using noaliases? On Thu, 26 Mar 2020 at 11:59, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > On Thu, Mar 26, 2020 at 10:55 AM Marlon Richert > <marlon.richert@gmail.com> wrote: > > > > Test case: > > > > alias -g tail="multitail -Cs --follow-all" > > f() { > > setopt localoptions no_aliases > > local tail > > tail=1 > > echo $tail > > } > > Alias expansion happens when functions get parsed. If you don't want > `tail` to be alias-expanded within function `f`, you need to add > `setopt no_aliases` before the function of `f`. > > > g() { > > setopt localoptions no_aliases > > local tail=1 > > echo $tail > > } > > `tail` within `local tail=1` is not subject to global alias expansion. > > Roman. >
On Thu, Mar 26, 2020 at 11:27 AM Marlon Richert <marlon.richert@gmail.com> wrote: > > Aha. So, if I want that aliases don't get expanded in the functions in https://github.com/junegunn/fzf/blob/master/shell/completion.zsh, then where should I put the `setopt noaliases` statement? Does it suffice to just put `emulate -L zsh; setopt localoptions noaliases;` at the top of the file? I don't want the noaliases option to leak into my own shell environment. > > Or is there a better solution possible here than using noaliases? The official solution to this problem is to use autoloadable functions instead of sourcing zsh scripts with function definitions. One practical alternative is to add a bit of code at the top and at the bottom of completion.zsh. Like this: 'builtin' 'local' '-a' '_fzf_completion_opts' [[ ! -o 'aliases' ]] || _fzf_completion_opts+=('aliases') [[ ! -o 'sh_glob' ]] || _fzf_completion_opts+=('sh_glob') [[ ! -o 'no_brace_expand' ]] || _fzf_completion_opts+=('no_brace_expand') 'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' # the meat of completion.zsh goes here (( ${#_fzf_completion_opts} )) && setopt ${_fzf_completion_opts[@]} 'builtin' 'unset' '_fzf_completion_opts' Note that this doesn't just disable aliases but also changes a couple other options that similarly affect parsing of functions. (You could also wrap the whole script in try-always to make sure options are restored even if evaluation of the script stops prematurely.) Another alternative is to rename completion.zsh to internal-completion.zsh and place this shim in place of the original completion.zsh: 'builtin' 'emulate' 'zsh' '-o' 'no_aliases' '-c' 'builtin source ${${(%):-%x}:h}/internal-completion.zsh' Roman. > On Thu, 26 Mar 2020 at 11:59, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: >> >> On Thu, Mar 26, 2020 at 10:55 AM Marlon Richert >> <marlon.richert@gmail.com> wrote: >> > >> > Test case: >> > >> > alias -g tail="multitail -Cs --follow-all" >> > f() { >> > setopt localoptions no_aliases >> > local tail >> > tail=1 >> > echo $tail >> > } >> >> Alias expansion happens when functions get parsed. If you don't want >> `tail` to be alias-expanded within function `f`, you need to add >> `setopt no_aliases` before the function of `f`. >> >> > g() { >> > setopt localoptions no_aliases >> > local tail=1 >> > echo $tail >> > } >> >> `tail` within `local tail=1` is not subject to global alias expansion. >> >> Roman.
Roman Perepelitsa wrote on Thu, 26 Mar 2020 11:38 +0100: > On Thu, Mar 26, 2020 at 11:27 AM Marlon Richert > <marlon.richert@gmail.com> wrote: > > > > Aha. So, if I want that aliases don't get expanded in the functions in https://github.com/junegunn/fzf/blob/master/shell/completion.zsh, then where should I put the `setopt noaliases` statement? Does it suffice to just put `emulate -L zsh; setopt localoptions noaliases;` at the top of the file? I don't want the noaliases option to leak into my own shell environment. > > > > Or is there a better solution possible here than using noaliases? > > The official solution to this problem is to use autoloadable functions > instead of sourcing zsh scripts with function definitions. > Note that the -U flag should be passed to «autoload» in that case. > One practical alternative is to add a bit of code at the top and at > the bottom of completion.zsh. Like this: > > 'builtin' 'local' '-a' '_fzf_completion_opts' > [[ ! -o 'aliases' ]] || _fzf_completion_opts+=('aliases') > [[ ! -o 'sh_glob' ]] || _fzf_completion_opts+=('sh_glob') > [[ ! -o 'no_brace_expand' ]] || _fzf_completion_opts+=('no_brace_expand') > 'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' > > # the meat of completion.zsh goes here > > (( ${#_fzf_completion_opts} )) && setopt ${_fzf_completion_opts[@]} > 'builtin' 'unset' '_fzf_completion_opts' > z-sy-h does something similar with aliases: https://github.com/zsh-users/zsh-syntax-highlighting/blob/d1802e388e94aca25380a3a9aeb4a2b7ba661b41/zsh-syntax-highlighting.zsh#L30-L36 ⋮ https://github.com/zsh-users/zsh-syntax-highlighting/blob/d1802e388e94aca25380a3a9aeb4a2b7ba661b41/zsh-syntax-highlighting.zsh#L442-L444 For options, z-sy-h uses «emulate -L» for the vast majority of its code. It's on our todo list (issue #688) to add a «emulate zsh -o … -c 'source …'» shim around the entry point script, as Roman proposes below. > Note that this doesn't just disable aliases but also changes a couple > other options that similarly affect parsing of functions. (You could > also wrap the whole script in try-always to make sure options are > restored even if evaluation of the script stops prematurely.) > There are a few other options to worry about, e.g., KSH_ARRAYS, IGNORE_CLOES_BRACES. > Another alternative is to rename completion.zsh to > internal-completion.zsh and place this shim in place of the original > completion.zsh: > > 'builtin' 'emulate' 'zsh' '-o' 'no_aliases' '-c' 'builtin source > ${${(%):-%x}:h}/internal-completion.zsh' > > Roman. > Cheers, Daniel > > > > > On Thu, 26 Mar 2020 at 11:59, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > >> > >> On Thu, Mar 26, 2020 at 10:55 AM Marlon Richert > >> <marlon.richert@gmail.com> wrote: > >> > > >> > Test case: > >> > > >> > alias -g tail="multitail -Cs --follow-all" > >> > f() { > >> > setopt localoptions no_aliases > >> > local tail > >> > tail=1 > >> > echo $tail > >> > } > >> > >> Alias expansion happens when functions get parsed. If you don't want > >> `tail` to be alias-expanded within function `f`, you need to add > >> `setopt no_aliases` before the function of `f`. > >> > >> > g() { > >> > setopt localoptions no_aliases > >> > local tail=1 > >> > echo $tail > >> > } > >> > >> `tail` within `local tail=1` is not subject to global alias expansion. > >> > >> Roman.
On Thu, Mar 26, 2020 at 11:34 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> There are a few other options to worry about, e.g., KSH_ARRAYS,
> IGNORE_CLOES_BRACES.
Good point.
I also should've mentioned that `emulate zsh -o no_aliases -c "..."`
shouldn't be used if some of the functions you define must run with
user-defined options. E.g., if you want to respect user's
dot_glob/no_dot_glob (fzf does) or
interactive_comments/no_interactive_comments (f-sy-h does), then this
approach is out.
Here's another option that doesn't require one to create a new file:
() { 'emulate' '-L' 'zsh' '-o' 'no_aliases' && 'eval' "$(<<\END
# original file content goes here
END
)"; }
Downsides:
- one fork (increases loading time)
- breaks syntax highlighting in code editors
- zcompile won't be effective at speeding up loading time
- some aliases can still break this; for example: alias -g '()'=nope
Roman.
Roman Perepelitsa wrote on Sun, 29 Mar 2020 12:24 +0200: > On Thu, Mar 26, 2020 at 11:34 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote: > > > > There are a few other options to worry about, e.g., KSH_ARRAYS, > > IGNORE_CLOES_BRACES. > > Good point. > > I also should've mentioned that `emulate zsh -o no_aliases -c "..."` > shouldn't be used if some of the functions you define must run with > user-defined options. E.g., if you want to respect user's > dot_glob/no_dot_glob (fzf does) or > interactive_comments/no_interactive_comments (f-sy-h does), then this > approach is out. z-sy-h handles this by saving ${options} to an associative array before resetting the options so it can execute: 86 # Before we 'emulate -L', save the user's options 87 local -A zsyh_user_options 88 if zmodload -e zsh/parameter; then 89 zsyh_user_options=("${(kv)options[@]}") 90 else 91 local canonical_options onoff option raw_options 92 raw_options=(${(f)"$(emulate -R zsh; set -o)"}) 93 canonical_options=(${${${(M)raw_options:#*off}%% *}#no} ${${(M)raw_options:#*on}%% *}) 94 for option in "${canonical_options[@]}"; do 95 [[ -o $option ]] 96 # This variable cannot be eliminated c.f. workers/42101. 97 onoff=${${=:-off on}[2-$?]} 98 zsyh_user_options+=($option $onoff) 99 done 100 fi 101 typeset -r zsyh_user_options 102 103 emulate -L zsh (I'll fix lines 95-98 in a minute, though.) Cheers, Daniel > Here's another option that doesn't require one to create a new file: > > () { 'emulate' '-L' 'zsh' '-o' 'no_aliases' && 'eval' "$(<<\END > > # original file content goes here > > END > )"; } > > Downsides: > > - one fork (increases loading time) > - breaks syntax highlighting in code editors > - zcompile won't be effective at speeding up loading time > - some aliases can still break this; for example: alias -g '()'=nope
On Sun, Mar 29, 2020 at 10:47 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> z-sy-h handles this by saving ${options} to an associative array before
> resetting the options so it can execute:
Right. This is done in function _zsh_highlight in
zsh-syntax-highlighting.zsh. My point is that you cannot rename
zsh-syntax-highlighting.zsh to zsh-syntax-highlighting-impl.zsh and
replace the original zsh-syntax-highlighting.zsh with `emulate zsh -o
no_aliases -c 'source zsh-syntax-highlighting-impl.zsh'` because
you'll no longer be able to access user options from _zsh_highlight.
Sticky emulation mode is cool but in this case it provides too much
insulation.
Roman.
Roman Perepelitsa wrote on Sun, 29 Mar 2020 21:03 +00:00:
> On Sun, Mar 29, 2020 at 10:47 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> > z-sy-h handles this by saving ${options} to an associative array before
> > resetting the options so it can execute:
>
> Right. This is done in function _zsh_highlight in
> zsh-syntax-highlighting.zsh. My point is that you cannot rename
> zsh-syntax-highlighting.zsh to zsh-syntax-highlighting-impl.zsh and
> replace the original zsh-syntax-highlighting.zsh with `emulate zsh -o
> no_aliases -c 'source zsh-syntax-highlighting-impl.zsh'` because
> you'll no longer be able to access user options from _zsh_highlight.
> Sticky emulation mode is cool but in this case it provides too much
> insulation.
Yeah, the code I quoted needs to run before options are changed —
i.e., in the outer script, before the 'emulate' call. That's precisely
why that code's written in a KSH_ARRAYS-compatible way. (It wasn't
at first, but people opened bug reports…)