Is it possible to configure zsh (and/or oh my zsh) to perform autocompletion as follows?
I type soco and it expands to somecommand.sh.
Because this matches:
somecommand.sh
^^ ^^
That's the _approximate completer.
E.g.
zstyle ':completion:*' completer _extensions _complete _approximate
Related
With the following in an empty directory:
$ zsh -d -f -i
% autoload -Uz compinit && compinit
% zstyle ':completion:*:*:cd:*:*' ignored-patterns foo
% mkdir foo
% mkdir bar
% mkdir zsh
When I type cd <TAB> I get a menu with only bar and zsh. This is great.
When I remove zsh and I do cd <TAB>, bar is completed without showing a menu. Also great.
But when I remove bar as well and I do cd <TAB>, foo is completed. I don't want that to happen.
Starting again, but from the parent directory and doing cd <TAB> to complete the parent directory and then cd <TAB> I see foo or get it completed for all three cases.
Is there a way to ignore foo completely so I never see it and never get it completed in the same directory and any other directory?
Edit:
I found that using zstyle ':completion:*:*:cd:*:*' ignored-patterns '**/foo' the problem of seeing the ignored pattern from a parent directory goes away, but ignored patterns are still completed when there is not other choice. So with this:
$ zsh -d -f -i
% autoload -Uz compinit && compinit
% zstyle ':completion:*:*:cd:*:*' ignored-patterns '**/foo'
% mkdir foo
and typing cd <Tab> still completes foo. Is there a way of just not completing in this case?
Reason for this behavior
The zsh completion system has multiple completer functions. These are enabled via:
zstyle ':completion:*' completer <list of completers>
The default value for this is _complete _ignored (see).
This means that first regular completion is tried, and if it did not produce a completion, the special _ignored completer is tried instead. The _ignored completer ignores the ignored-patterns style you defined and therefore finds the foo match.
From the zsh documentationon on _ignored:
The ignored-patterns style can be set to a list of patterns which are compared against possible completions; matching ones are removed. With this completer those matches can be reinstated, as if no ignored-patterns style were set. [...] The single-ignored style is also available as described above.
A solution
Remove _ignored from the list of completers.
You can display the current list via zstyle -L '*' completer.
If this is empty, it still is at its default value and you can disable _ignored via:
zstyle ':completion:*' completer _complete
A sort-of solution
From the documentation entry on single-ignored (mentioned in the citation above):
This is used by the _ignored completer when there is only one match. If its value is ‘show’, the single match will be displayed but not inserted. If the value is ‘menu’, then the single match and the original string are both added as matches and menu completion is started, making it easy to select either of them.
So if you set it to show (or menu) (via zstyle ':completion:*' single-ignored show) then it won't immediately be completed and only show up in the tab completion menu.
This means you could just ignore it and continue typing.
Appendix
It is (as far as I can tell) not possible to disable a completer only for cd (say with zstyle ':completion:*:*:cd:*:*' completer ...), as they are determined at the very beginning of the completion process.
There is also a way of ignoring certain file/directory patterns using the file-patterns style and the ^ glob pattern, but the style does not seem to be used with cd completion. But e.g. for ls this should do the trick:
zstyle ':completion:*:*:ls:*:*' file-patterns '^foo|^**/foo:directories'
The zsh guide on completion is also a good resource for all this:
http://zsh.sourceforge.net/Guide/zshguide06.html
I think the simplest example is that if a command does not exist, then invalid-command <TAB> will present a list of files that you can tab complete on.
If the command (and completion) does exist, then on exhausting the completions, hitting <TAB> will either produce the bell sound e.g:
prompt > yarn test <TAB>
Or it will result in - no more arguments - e.g:
prompt > yarn run test <TAB>
- no more arguments -
To produce the above behaviours I currently have the following:
zstyle ':completion:*' completer _complete _correct _approximate _files
zstyle ':completion:*:descriptions' format "- %d -"
zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*:manuals.(^1*)' insert-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes
zstyle ':completion:*' rehash yes
zstyle -e ':completion:*:approximate:*' max-errors \
'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
I had hoped that adding _files to the end of :completion:* it would fallback to the current files if no other completion was available, but it appears I was naive in this assumption? :)
I think I'd be able to go into the _command completion definitions and add this to each one individually, but as a general fallback this seems quite appropriate (and matches prior experiences).
I would like to allow completion for --flags after other input in my gradle completion script, but _arguments seems to require that
specs that describe option flags must precede specs that describe non-option ("positional" or "normal") arguments of the analyzed line (from the zsh completion docs)
In other words: command foo --o[TAB] does nothing, but command --o[TAB] works fine. Is there any way to configure _arguments or do I need to use other control functions?
NOTE: Separate completion functions do not seem like an option in my case as the inputs are not in a fixed list (gradle tasks are arbitrary and multiple can be specified, gradle myfoo mybar --o[TAB] must work).
So you want to be able to type something like vim foo -[TAB] and have a list auto expand to show flags and switches, where currently you have to type vim -[TAB] to get your flags and switches and then type foo, yes?
Hopefully I am understanding your question correctly.
My current zsh completion options might be able to help with this, as I can do what I described, which seems to be what you are asking for? It has been quite a while sense I set these up so I don't remember precisely what each one does. What I belive you want though is the setopt COMPLETE_IN_WORD , unset LIST_AMBIGUOUS, as well as the zstyle ':completion::approximate*:*' prefix-needed false options. If I am wrong someone please correct me.
I have included what I use in my zsh as my completion section. I have tested this as standalone and it works on my zsh as is.
#{{{ Completion Stuff
zmodload -i zsh/complist
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
bindkey -M viins '\C-i' complete-word
# Faster! (?)
zstyle ':completion::complete:*' use-cache 1
# case insensitive completion
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' \
'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' verbose yes
zstyle ':completion:*:descriptions' format '%B%d%b'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:warnings' format 'No matches for: %d'
zstyle ':completion:*' group-name ''
# generate descriptions with magic.
zstyle ':completion:*' auto-description 'specify: %d'
# Don't prompt for a huge list, page it!
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
# Don't prompt for a huge list, menu it!
zstyle ':completion:*:default' menu 'select=0'
# Have the newer files last so I see them first
zstyle ':completion:*' file-sort modification reverse
# color code completion
zstyle ':completion:*' list-colors "=(#b) #([0-9]#)*=36=31"
unsetopt LIST_AMBIGUOUS
setopt COMPLETE_IN_WORD
# Separate man page sections.
zstyle ':completion:*:manuals' separate-sections true
#
zstyle ':completion:*' list-separator 'fREW'
# complete with a menu for xwindow ids
zstyle ':completion:*:windows' menu on=0
zstyle ':completion:*:expand:*' tag-order all-expansions
# more errors allowed for large words and fewer for small words
zstyle ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX+$#SUFFIX)/3 )) )'
# Errors format
zstyle ':completion:*:corrections' format '%B%d (errors %e)%b'
# Don't complete stuff already on the line
zstyle ':completion::*:(rm|vi):*' ignore-line true
# Don't complete directory we are already in (../here)
zstyle ':completion:*' ignore-parents parent pwd
zstyle ':completion::approximate*:*' prefix-needed false
I was able to solve this with this commit at least to allow options after 1 task is specified.
The trick is to set the state within _arguments with :->statename, reset the context to the next word, and provide a wildcard matcher that matches non-command words and use _arguments again.
There's almost certainly a way to allow options specified after an arbitrary number of words and avoid some duplication, but this is a workable start.
I am using zsh with oh-my-zsh's rc file and there is some behavior I find particularly annoying. By default, oh-my-zsh is configured to return case-insensitive matches when auto-completing. This behavior is sometimes good, but other times it really sucks. Is there a way I can configure zsh to only use case-insenstive matching when there are no case-sensitive matches?
For instance, this case would use case-sensitive matching:
> ls
LICENSE.txt lib/
> emacs l <-- should autocomplete to lib/
In this case, case-insensitive auto-completion would happen:
> ls
README lib/
> emacs r <-- should autocomplete to README
Thanks!
Just uncomment the following line in ~/.zshrc:
# Uncomment the following line to use case-sensitive completion.
# CASE_SENSITIVE="true"
It worked for me
Create a file ~/.oh-my-zsh/custom/better-completion.zsh (assuming you are using default paths for oh-my-zsh) with the following lines
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
Explanation:
Rules for matches in zsh completion in general are defined in the matcher-list style. For oh-my-zsh this is defined in ~/.oh-my-zsh/lib/completion.zsh (once for case-sensitive and once for case-insensitive). You could change it there but it would probably be gone if you updated your oh-my-zsh. ~/.oh-my-zsh/custom is specifially intended for customization and files with extension .zsh are loaded from there by .oh-my-zsh/oh-my-zsh.sh at the end of the configuration.
The default (case-insensitive) settings for matcher-list in oh-my-zsh are:
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
The first of which tells to handle upper and lower case interchangeable.
As it is the first rule, it will be invariably used for every match.
The only change needed is to prepend '' for simple completion (it is even the first example in zshcompsys(1) for matcher-list)
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
This tries first to complete the current word exactly as its written, before trying case-insensitive or other matches.
To be complete:
The second (original) rule allows for partial completion before ., _ or -, e.g. f.b -> foo.bar.
The third rule allows for completing on the left side of the written text, e.g. bar -> foobar)
For those not using oh-my-zsh, you can add the following two lines to ~/.zshrc
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*'
autoload -Uz compinit && compinit
If I have files "something1" and "something2" in a folder, how do I make ZSH's tab completion fill in only the common characters? For example, I would type:
som<Tab>
and I want it to fill in with "something", not "something1".
Current zstyles:
zstyle ':completion:*' special-dirs true
zstyle ':completion::complete:*' use-cache on
zstyle ':completion::complete:*' cache-path ~/.zsh/cache/$HOST
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*' list-prompt '%SAt %p: Hit TAB for more, or the character to insert%s'
zstyle ':completion:*' menu select=1 _complete _ignored _approximate
zstyle -e ':completion:*:approximate:*' max-errors \
zstyle ':completion:*' select-prompt '%SScrolling active: current selection at %p%s'
zstyle ':completion:*::::' completer _expand _complete _ignored _approximate
zstyle -e ':completion:*:approximate:*' max-errors \
zstyle ':completion:*:expand:*' tag-order all-expansions
zstyle ':completion:*' verbose yes
zstyle ':completion:*:descriptions' format '%B%d%b'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:warnings' format 'No matches for: %d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*' group-name ''
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters
# zstyle ':completion:*:processes' command 'ps -au$USER'
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
#zstyle ':completion:*:processes' command 'ps ax -o pid,s,nice,stime,args | sed "/ps/d"'
zstyle ':completion:*:*:kill:*:processes' command 'ps --forest -A -o pid,user,cmd'
zstyle ':completion:*:processes-names' command 'ps axho command'
#zstyle ':completion:*:urls' local 'www' '/var/www/htdocs' 'public_html'
zstyle ':completion:*' hosts $(awk '/^[^#]/ {print $2 $3" "$4" "$5}' /etc/hosts | grep -v ip6- && grep "^#%" /etc/hosts | awk -F% '{print $2}')
zstyle ':completion:*:*:(^rm):*:*files' ignored-patterns '*?.o' '*?.c~' \
zstyle ':completion:*:functions' ignored-patterns '_*'
zstyle ':completion:*:*:*:users' ignored-patterns \
zstyle ':completion:*:scp:*' tag-order \
zstyle ':completion:*:scp:*' group-order \
zstyle ':completion:*:ssh:*' tag-order \
zstyle ':completion:*:ssh:*' group-order \
zstyle '*' single-ignored show
Adding this to ~/.zshrc works for me:
setopt noautomenu
setopt nomenucomplete
https://serverfault.com/a/447549
remove line:
setopt menu_completion
from your .zshrc
and it should work fine with filling unambiguous part first.
It works like that out of the box if you use Zsh's new completion system. Add this to your ~/.zshrc file (or to try it out, just paste it into the command line):
autoload -Uz compinit && compinit
bindkey '^I' complete-word
After this, if you have two files something1 and something2 in your present working dir, and you type
% file s
and then press Tab, it will complete to
% file something
Press Tab again and it will display
something1 something2
under the command line.
You can then keep pressing Tab to cycle through these two.
In your zshrc file (at ~/.zshrc) paste this line
zstyle ':autocomplete:*' insert-unambiguous yes
if previously it was set to no it changing to the above line will work.
Check out man zshoptions. It's pretty well organized so that all of the completion options are in a "Completion" section. I think that the option you're looking for is list_ambiguous. if so, you just need to add in the line
setopt list_ambiguous
to your .zshrc
Good news: this is totally doable, and you won't need to worry about zstyles. (I believe.) Bad news: it's a bit tricky to answer.
A great explanation of specific zsh completion options related to the problem you're trying to solve can be found in this specific section of the User's Guide to zsh.
Also, you can do a 'man zshoptions' and look for completion-specific options. The answer above mentioning list_ambiguous is part of the answer, but I don't believe it addresses the whole picture. A key question you'll need to ask yourself is "What do I want to happen after I hit TAB the first time and zsh inserts only the common characters?" You can have zsh do a lot of different things on the second TAB press or even the third. Using various combinations of the ZSH completion options can yield a wide variety of useful results. It all depends on what you want.
Good luck!