zsh-users / zsh-completions

Additional completion definitions for Zsh.
Other
6.87k stars 712 forks source link

Inconsistent "group-name" style resolution: "description" seems to override some tags but not others #1070

Open detly opened 6 months ago

detly commented 6 months ago

Firstly, I'm not sure whether this issue relates to zsh itself, completions, or zle. I'll start by raising it here, but if I should ask elsewhere please feel free to let me know.

The basic context is this:

I would like to configure things so that (a) completions are grouped by kind and (b) I can customise the group titles. I am actually using Nerdfont icons for this, but for demonstration I've used some terrible ASCII art.

My reading of the docs is that I can start with this to force the group-by-kind behaviour:

zstyle ':completion:*' group-name ''

From here I can add styles like:

# For eg. ls first arg completion
zstyle ":completion:*:globbed-files" format '.~* globbed files *~.'
# For eg. git add arg completion
zstyle ":completion:*:modified-files" format ".~* modified files *~."

This works! Here's a docker session on zshusers/zsh:master where the last part shows the tab behaviour:

e585e6c8ae90# zstyle ':completion:*' group-name ''
zstyle ":completion:*:globbed-files" format '.~* globbed files *~.'

autoload -Uz compinit
zmodload zsh/complist
compinit

e585e6c8ae90# ls # <tab>
.~* globbed files *~.
bin/    dev/    home/   lib64/  mnt/    proc/   run/    srv/    tmp/    var/                
boot/   etc/    lib/    media/  opt/    root/   sbin/   sys/    usr/   

The problem arises when I want to add a "catch-all" group heading via ':completion:*:descriptions':

f4a37443f595# zstyle ':completion:*' group-name ''
zstyle ":completion:*:globbed-files" format '.~* globbed files *~.'
zstyle ':completion:*:descriptions' format '%d'

autoload -Uz compinit
zmodload zsh/complist
compinit

f4a37443f595# ls # <tab>
file
bin/    dev/    home/   lib64/  mnt/    proc/   run/    srv/    tmp/    var/                
boot/   etc/    lib/    media/  opt/    root/   sbin/   sys/    usr/                      

The group header is now back to file, a result of %d substitution (which can be confirmed by using non-template text). I'm confused because the docs say:

The style is tested with each tag valid for the current completion before it is tested for the descriptions tag. Hence different format strings can be defined for different types of match.

I would not expect that adding a style for ':completion:*:descriptions' would override the more specific globbed-files tag. Even more confusingly, if I trigger completions for git add, the descriptions style does not override the modified-files style.

38630c3df2b0# apt-get -q update
apt-get -yq install git

# Output not shown

38630c3df2b0# zstyle ':completion:*' group-name ''
zstyle ":completion:*:globbed-files" format '.~* globbed files *~.'
zstyle ":completion:*:untracked-files" format ".~* untracked files *~."
zstyle ':completion:*:descriptions' format '%d'

autoload -Uz compinit
zmodload zsh/complist
compinit

mkdir ~/git-test
cd ~/git-test
git init .
touch magic more-magic

Initialized empty Git repository in /root/git-test/.git/
38630c3df2b0# git add # <tab> x2
.~* untracked files *~.
magic       more-magic

38630c3df2b0# ls # <tab> x2
file
magic       more-magic

I've tried looking for any differences in the tags, by using ctrl+x, h:

38630c3df2b0# git add # <tab> x2 <c-x> <h>
tags in context :completion::complete:git-add::
    argument-rest options  (_arguments _git-add _git)
tags in context :completion::complete:git-add:argument-rest:
    modified-files other-files  (_git-add _git) 
    modified-files              (__git_files __git_modified_files __git_ignore_line __git_ignore_line_inside_arguments _git-add _git) 
    untracked-files             (__git_files __git_other_files __git_ignore_line __git_ignore_line_inside_arguments _git-add _git)
tags in context :completion::complete:git::
    argument-rest  (_arguments _git)

38630c3df2b0# ls # <tab> x2 <c-x> <h>
tags in context :completion::complete:ls::
    argument-rest options  (_arguments _ls)
tags in context :completion::complete:ls:argument-rest:
    globbed-files  (_files _arguments _ls)

I also tried adding a style for argument-rest, but this overrides pretty much any other group name I might care about, and it's also still unclear as to why that would work but not more specific ones.

I tried this on Zsh 5.9 on Ubuntu 23.10 and the Docker images zshusers/zsh:master and zshusers/zsh:5.9 with identical results. The output I've posted above has been a little bit modified to try to show the workflow and debugging info, but the commands themselves should work as they are posted.