Here is my completion function:
f()
{
reply=('ok')
}
compctl -K f c
Then I do
c
tab
c ok
Something works. Then I do tab after b
c ok "a b"
and nothing happens. I expect a b to be replaced with ok (as it does in bash).
How could I achieve it?
I really need to do completions inside quotes. Typical launch of my program looks like this: c 'a, &b, c[d]' 'a < 1 and b == "2013"'
This has nothing to do with the use of quotes. zsh doesn't offer ok as a completion in your second case because it isn't anywhere close to what was already entered for that argument. The completion wouldn't be offered after c a either.
zsh generally assumes that what is to be completed will be somewhat related to what has already been entered, relieving the author of a completion function from needing to check for matches. You can add the -U option to your compctl command to tell it that the entire $reply list should be used, even entries which don't match.
I should also note that compctl belongs to the old zsh completion system. The new completion system is described in the zshcompsys manpage
Related
Fish shell is awesome, and its completions is one of the reasons I love it so much.
But, every once in a while, when I type I get a completion that's not useful for me. The problem is the completion replaces what I wrote, and so I don't know how to continue.
Here's an example:
$ touch HELLO
$ echo goodbye > h
When I type the last letter, h, fish shell replaces it with HELLO where the capital H is already typed, and the ELLO part is grayed out, meaning that it will be replaced by future typing.
But I just wanted to create a file named h with the content goodbye - fish gives me a hard time :(
Anyone has any suggestions?
It does not replace what you typed. The effective string is still "h", so just pressing enter will create a file called "h".
(yes, this could be shown better, there is an open issue about it)
Many times I end up writting wrapper function around existing ones, for instance:
function gl {
some_computed_stuff=...
git --no-pager log --reverse $some_computed_stuff "$#"
}
function m {
make "$#" && notify-send success || notify-send failed
}
I know that aliases keep autocompletion but sometimes functions are required and in that case autocompletion is lost.
For instance here I would like to keep git log completion for my function gl or make completion for m.
I tried to add compctl -K _git gl but no suggestions are made. It won't work anyway since I must somehow find how to provide log argument to _git autocompletion script as well, so my question is:
Is there a way to make ZSH (but also bash) understand that typing gl is the exact equivalent of git log? Something like (for ZSH only):
compctl 'git log' gl
compctl 'make' m
For zsh, you can create a new completion with compdef function.
In its basic form it associates a completion function with a word. Provided that zsh comes with lots of completions already built-in, one can just reuse those. For example, for m function from the question:
$ compdef _make m
As per documentation, you can also define a completion for a specific service, if the one is defined in the completion function. Again, as zsh comes with _git completion and it already defines git-log service, a gl function from the question may be autocompleted with:
$ compdef _git gl=git-log
On Linux, you can see existing completion implementations in /usr/share/zsh/functions/Completion/Unix/. You can read the completion implementations to see what services they define.
I am working on porting Google Cloud SDK command line auto completion feature to fish shell. When I have an unambiguous reply with multiple arguments:
A) Either the command is completed with all those arguments BUT spaces gets escaped (\ ) when I specify the function call in the complete command inside ''s or ""s, like: > complete ... -a '(__fun)'
B) or if I don't do that (just: -a (__fun)), then only the first argument of the reply gets into the completion and all the other arguments "get lost"
Is it possible to reply with multiple arguments at once in fish completion?
Could be done in a number of ways. You will have to hack it a bit, though, since as ridiculous_fish says it's not designed for this.
Easiest would be to ship your own wrapper function that can take the escaped output and pass it on in a way that works. Not very pretty, though, and would screw with autosuggestions unless you also go back and modify the history lines.
Here's something semi-hacky/semi-elegant I would propose:
If you have looked up a "sequence" of args you'd want to complete at once, at first invocation put the trailing args as the description to the first one. Once that one has been locked in, remove all other options but the first in this "description queue", keep going through it and it will simply be a matter of quickly pressing tab-tab-tab-tab.
Completions don't have to be perfect, they're mostly a lil help on the way until you have enough history lines that autosuggestions take over, imo.
I wonder if there's a way to use ipython-like completion in zsh?
What I mean is in ipython you could type several characters and then loop through your command history, but this will only affect those commands which start with characters you've typed in the first place.
If your history look like this:
token = 'something blah blah'
import os
token.split()
..and then you type token and loop through history in ipython you will get only 1st and 3rd lines.
So is there any way to make zsh work this way?
You can use the widgets history-beginning-search-backward and history-beginning-search-forward for that. By default they are not bound to any keys so you'll have to do that with bindkey.
bindkey "^[[5~" history-beginning-search-backward
bindkey "^[[6~" history-beginning-search-forward
Where ^[[5~ is the code for page up and [[6~ for page down. These codes may be different for your terminal.
You can either use cat -v to show the codes for the non-printing characters. Or you can use the associative array terminfo from the zsh/terminfo module (which may already be loaded; see zshmodules(1) and zshbuiltins(1) for more infos on zsh modules) which should contain the correct codes in the keys knp (next-page key) and kpp (previous-page key):
if (( ${+terminfo[knp]} )) && (( ${+terminfo[kpp]} )); then
bindkey "${terminfo[kpp]}" history-beginning-search-backward
bindkey "${terminfo[knp]}" history-beginning-search-forward
fi
To be honest these widgets will not loop when they reach the beginning or end of history, but as you can go both directions (and considering that ipython does not loop either) that should not be a real problem.
I know there is a way to list mappings via :map (or :imap, :cmap, etc.), but I can't find a way to list macros I have stored in my vimrc file (as in let #a = 'blahblah').
Is there a way to do this without having to manually looking inside it (via :split [myvimrcfile] or whatever way)?
Also, if it is possible, is there a way to attach some sort of documentation that would display with the macro to explain what it is for? I have a handful that I use quite a bit, but about 6 weeks apart. It would be nice to just quickly list them along with a comment that tells me what the macro does (or even just a name so I make sure I use the right one).
Thanks
In vim, the macros are just stored in registers. You can recall the content of any register and execute it as a macro (which is what the # does). To see a list of what is in your registers, use :reg.
You can see the contents of all the registers using the
:reg
command. Or an argument string like this
:reg ahx
will show you the contents of registers a, h, and x.
That way you can at least see what sequence of commands will be run and hopefully that will be clear enough for you to tell one from another.
The registers simply contain text. You can paste the command sequence in as text or you can copy text into a register and then run it as a command, depending on how you access the register.
I have not found any direct way to edit the contents of a register, but you can paste it into the file, edit it, and then save it back to the same register.
IHTH.
As /u/jheddings wrote the macros are stored as registers and what counts is the assignment of the code to the register (usually done in the vimrc files with let #a=blahblah
To ease the way to display the macros you defined in your vimrc file (in my case it is in the ~/.vimrc path) you can use this vim function:
function! ShowMacros()
10new
exe 'r!' . 'grep -B 1 -E "^\s*let #" ~/.vimrc'
call cursor(1,1)
endfunction
What it does:
10new - open a new vim window with ten lines size
exe ... - execute a command and put in the window
call ... - go to the first line first column
You can execute this function by tipping in the normal mode
:call ShowMacros
You could additionally create a key mapping or a command to fasten the way to call the function:
:cnoremap sm call ShowMacros()<CR>
command! sm call ShowMacros()`
This is the original post where I wrote the function similar to the above.
The OP asked, "is there a way to attach some sort of documentation that would display with the macro to explain what it is for?"
I have found VI / VIM macros extremely obtuse to understand even a week after I've written them, so I heartily support the idea of documentation. I have a suggestion for that, in two parts.
First is the process of documenting the macro in your .vimrc. I've developed the following .vimrc comment format that helps me understand, a week or a year or more later, what a macro is supposed to be doing. E.g.:
"
"= GENERIC CLIPBOARD YANK <F2>y (Y for Yank)
"= Yank the entire contents of the file into the clipboard; quit without saving.
"
"define F2 followed by y to be:
"| Go to line 1.
"| | From there, into the * buffer (system clipboard),
"| | | yank to the end of the file.
"| | | | Go to sleep for 1 second (to allow the clipboard to be updated).
"| | | | | Quit without saving the file.
"| | | | | |
map #2y 1G"*yG1gs:q!<CR>
"-------"-"-"-"--"------
Second, I am imagining that Jakub's ShowMacros() function above could be modified to grep a specific set of Help lines for each macro that would be in the file along with the definition, much the way the above command-line breakdown is attached to the definition, that would provide the needed User Help.
I've flagged two lines above with "= at the beginning of each, so that they can become the User Help. Then Jakub's grep command would search for "^\"= ". Here's the command I used. I'm not sure if the -E for Extended Regular Expressions is needed and the -B 1 is a nice touch to include one line previous to a matching sequence, so here I have an explicitly empty comment line.
In my vimrc, I only needed one backslash, for the initial parsing of the definitions. Here's the line, replacing the one in Jakub's function definition above:
exe 'r!' . 'grep -B 1 -E "^\"= " ~/.vimrc'
Thanks to Jakub's hint, I now can generate help from my .vimrc in pretty much exactly the way the OP is asking for. I've been using vi since 1983, so I'm pretty stoked.
Thanks Jakub!
IHTH,
August