3

With the code below, everything works as expected:

  • When I write c and hit the TAB key, I get the appropriate completions in correct order.

    Image

  • When I write ./ and hit the TAB key, I get the completion for the executables tag.

    Image


# Always use menu selection when using unambiguous completions.
zstyle ':completion:*:*:*:*:*' menu 'select'

# Show only completions.
zstyle ':completion:*:*:*:*:*' completer _complete

# Group name becomes the name of the matching tag.
zstyle ':completion:*:*:*:*:*' group-name ''

# Configure the order of tag matching as well as their descriptions.
zstyle -e ':completion:*:*:-command-:*:*' tag-order '
    reply=(
           "executables:Executables:Executables
            builtins:Builtins:Builtins
            commands:Commands:Commands
            aliases:Aliases:Aliases
            functions:Functions:Functions
            parameters:Variables:Variables
            reserved-words:Keywords:Keywords"
          )
'

# Configure the order in which completion groups will be shown.
zstyle ':completion:*:*:-command-:*:*' group-order 'Executables' 'Builtins' 'Commands' 'Aliases' 'Functions' 'Variables' 'Keywords'

# Configure the format for each group/tag description.
zstyle ':completion:*:*:*:*:descriptions' format $'%{\e[0;38;2;0;0;0;48;2;200;150;0m%} %d %{\e[0;38;2;200;150;0;48;2;0;0;0m%}%{\e[0m%}'

# Initialize completion system.
autoload -Uz compinit && compinit

However if the tags that I've specified do not produce any completion, other tags will be tried as well.

Easiest way to prove this is to exclude the functions tag from tag-order style:

zstyle -e ':completion:*:*:-command-:*:*' tag-order '
    reply=(
           "executables:Executables:Executables
            builtins:Builtins:Builtins
            commands:Commands:Commands
            aliases:Aliases:Aliases
            parameters:Variables:Variables
            reserved-words:Keywords:Keywords"
          )
'

and then create 2 functions with a unique prefix:

function unique_prefix_A() { }
function unique_prefix_B() { }

Now when I write unique_prefix_ and hit the TAB key, I don't expect to see anything since functions tag was removed from tag-order.
However, because Executables, Builtins, Commands, Aliases, Variables and Keywords didn't provide any completions, zsh will by default try to match other tags, namely the excluded functions tag, to try to give any completion.

Because of this, the functions unique_prefix_A and unique_prefix_B will be suggested:

Image

I don't like this behavior and want to limit the search only to tags that I have explicitly specified.

The manual for the tag-order style suggests a simple solution:

- If any value consists of only a hyphen, then only the tags specified in the other values are generated. Normally all tags not explicitly selected are tried last if the specified tags fail to generate any matches. This means that a single value consisting only of a single hyphen turns off completion.

Applying the solution:

# Configure the order of tag matching as well as their descriptions.
zstyle -e ':completion:*:*:-command-:*:*' tag-order '
    reply=(
           "executables:Executables:Executables
            builtins:Builtins:Builtins
            commands:Commands:Commands
            aliases:Aliases:Aliases
            functions:Functions:Functions
            parameters:Variables:Variables
            reserved-words:Keywords:Keywords"
           "-"
          )
'

Current behavior is:

  • When I write c and hit the TAB key, I get the appropriate completions in correct order.

    Image)

  • When I write ./ and hit the TAB key, I get nothing.

    Image


Why is now only executables tag not working?

How can I fix it and get the desired behavior?

closed as off-topic by Jeff Schaller, G-Man, sourcejedi, sebasth, Rui F Ribeiro May 20 '18 at 9:00

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question has been posted on multiple sites. Cross-posting is strongly discouraged; see the help center and community FAQ for more information." – Jeff Schaller, sourcejedi, sebasth, Rui F Ribeiro

  • 2
    I cannot reproduce this behavior. Please post a complete example that reproduces the problem. You are missing some settings from your .zshrc that influence the behavior. An obvious one is setopt menu_complete, which I added. A harmless one is the escape character missing from the description format (tip: write $'…\e[…' instead of a literal escape character which is unprintable). Something else must be missing, because with the - I do get directory and executable_file. Also please give an example for “other tags will be tried as well”. – Gilles May 17 '18 at 15:56
  • I don't use the menu_complete option as none of the completions were selected when I pressed the first TAB key(you probably meant the auto_menu, but that is specified by default). I am able to reproduce this while .zshrc contains only the code that I copied here. Maybe the distribution and zsh versions play a role? This is the output from uname -a: Linux Arch 4.16.4-1-ARCH #1 SMP PREEMPT Thu Apr 24 13:21:29 UTC 2018 x86_64 GNU/Linux. This is the output of zsh --version: zsh 5.5.1 (x86_64-unknown-linux-gnu. Thanks for the $'...', I'll update the question. – Iskustvo May 17 '18 at 21:39
  • 1
    Aha! The version does play a role. With the "-" version (and even without any setopt, the zstyle does seem to do the trick), I get Executables after ./ in zsh 5.0.7 but not in 5.1.1 or 5.4.2. I don't understand what's going on. With set -x, I do see a call to _files -J Executables -X … -g '*(-*)', but it calls _tags which sees that the tag-order style contains a - and so decides not to do completions. I don't understand what's going on there. That part of _tags is identical in 5.0.7. – Gilles May 18 '18 at 7:20
  • 2
    In 5.0.7, _command_names calls _path_files, whereas in later versions it calls _files. It's due to this commit, which is indeed between 5.0.7 and 5.1.1. I haven't confirmed that this commit makes the difference but it's plausible. I don't understand if the behavior you're observing is intended. – Gilles May 18 '18 at 7:43
  • I've answered the same question here: stackoverflow.com/questions/50185846/… – Miguel Ortiz May 18 '18 at 17:41
1
+150

The executable tag invokes _files -g '*(-*) in this case. Then _files calls more _tags, so it would be necessary to specify these implicitly specified tags in the completion functions, too.

zstyle -e ':completion:*:*:-command-:*:*' tag-order '
    reply=(
           "executables:Executables:Executables
            builtins:Builtins:Builtins
            commands:Commands:Commands
            aliases:Aliases:Aliases
            functions:Functions:Functions
            parameters:Variables:Variables
            reserved-words:Keywords:Keywords
            globbed-files directories"
           "-"
          )
'

It would be useful to add globbed-files and directories in this case:

% ls -al
total 80
drwxr-xr-x  3 t    t     4096 May 18 08:27 .
drwxrwxrwt 16 root root 69632 May 18 15:27 ..
drwxr-xr-x  2 t    t     4096 May 18 08:27 directory
-rwxr-xr-x  1 t    t        0 May 18 08:27 executable-file
-rw-r--r--  1 t    t        0 May 18 08:27 test
% ./<TAB>
Executables
directory/        executable-file*

But on the above setting, directories and local executable files will go into the same "Executable" group. If we would like to make "directories" go into other groups, we could specify the file-patterns directly and use it like this:

zstyle ':completion:*:*:-command-:*:*' file-patterns \
 '*(#q-*):executables:Executables *(-/):directories:Directories'

zstyle -e ':completion:*:*:-command-:*:*' tag-order '
    reply=(
           "executables:Executables:Executables
            builtins:Builtins:Builtins
            commands:Commands:Commands
            aliases:Aliases:Aliases
            functions:Functions:Functions
            parameters:Variables:Variables
            reserved-words:Keywords:Keywords
            directories:Directories"
            -
          )
'

In the below example, "directory" and "executable-file" are in the separated groups:

% ls -al
total 80
drwxr-xr-x  3 t    t     4096 May 18 08:27 .
drwxrwxrwt 15 root root 69632 May 18 15:24 ..
drwxr-xr-x  2 t    t     4096 May 18 08:27 directory
-rwxr-xr-x  1 t    t        0 May 18 08:27 executable-file
-rw-r--r--  1 t    t        0 May 18 08:27 test
% ./<TAB>
Executables
executable-file*
Directories
directory/

Below is the resulted smallest .zshrc example:

autoload -Uz compinit && compinit
zstyle ':completion:*:*:*:*:*' group-name ''
zstyle ':completion:*:descriptions' format '%B%F{black}%d%f%b'
zstyle ':completion:*:*:*:*:*' menu 'select'

# This comment out block is just for a reminder of my answer's first half.
# zstyle -e ':completion:*:*:-command-:*:*' tag-order '
#       reply=(
#                    "executables:Executables:Executables
#                       builtins:Builtins:Builtins
#                       commands:Commands:Commands
#                       aliases:Aliases:Aliases
#                       functions:Functions:Functions
#                       parameters:Variables:Variables
#                       reserved-words:Keywords:Keywords
#                       globbed-files directories"
#                    "-"
#                   )
# '

zstyle ':completion:*:*:-command-:*:*' file-patterns \
 '*(#q-*):executables:Executables *(-/):directories:Directories'

zstyle -e ':completion:*:*:-command-:*:*' tag-order '
    reply=(
           "executables:Executables:Executables
            builtins:Builtins:Builtins
            commands:Commands:Commands
            aliases:Aliases:Aliases
            functions:Functions:Functions
            parameters:Variables:Variables
            reserved-words:Keywords:Keywords
            directories:Directories"
            -
          )
'

Updated: comment out the unecessary block.

Not the answer you're looking for? Browse other questions tagged or ask your own question.