-
-
Save romainl/5b2cfb2b81f02d44e1d90b74ef555e31 to your computer and use it in GitHub Desktop.
" Background here: https://gist.github.com/romainl/047aca21e338df7ccf771f96858edb86 | |
" with help from https://github.com/teoljungberg | |
function! CCR() | |
let cmdline = getcmdline() | |
let filter_stub = '\v\C^((filt|filte|filter) .+ )*' | |
command! -bar Z silent set more|delcommand Z | |
if getcmdtype() !~ ':' | |
return "\<CR>" | |
endif | |
if cmdline =~ filter_stub . '(ls|files|buffers)$' | |
" like :ls but prompts for a buffer command | |
return "\<CR>:b" | |
elseif cmdline =~ '\v\C/(#|nu|num|numb|numbe|number|l|li|lis|list)$' | |
" like :g//# but prompts for a command | |
return "\<CR>:" | |
elseif cmdline =~ filter_stub . '(\%)*(#|nu|num|numb|numbe|number|l|li|lis|list)$' | |
" like :g//# but prompts for a command | |
return "\<CR>:" | |
elseif cmdline =~ '\v\C^(dli|il)' | |
" like :dlist or :ilist but prompts for a count for :djump or :ijump | |
return "\<CR>:" . cmdline[0] . "j " . split(cmdline, " ")[1] . "\<S-Left>\<Left>" | |
elseif cmdline =~ filter_stub . '(cli)' | |
" like :clist or :llist but prompts for an error/location number | |
return "\<CR>:sil cc\<Space>" | |
elseif cmdline =~ filter_stub . '(lli)' | |
" like :clist or :llist but prompts for an error/location number | |
return "\<CR>:sil ll\<Space>" | |
elseif cmdline =~ filter_stub . 'old' | |
" like :oldfiles but prompts for an old file to edit | |
set nomore | |
return "\<CR>:Z|e #<" | |
elseif cmdline =~ filter_stub . 'changes' | |
" like :changes but prompts for a change to jump to | |
set nomore | |
return "\<CR>:Z|norm! g;\<S-Left>" | |
elseif cmdline =~ filter_stub . 'ju' | |
" like :jumps but prompts for a position to jump to | |
set nomore | |
return "\<CR>:Z|norm! \<C-o>\<S-Left>" | |
elseif cmdline =~ filter_stub . 'marks' | |
" like :marks but prompts for a mark to jump to | |
return "\<CR>:norm! `" | |
elseif cmdline =~ '\v\C^undol' | |
" like :undolist but prompts for a change to undo | |
return "\<CR>:u " | |
elseif cmdline =~ '\v\C^tabs' | |
set nomore | |
return "\<CR>:Z| tabnext\<S-Left>" | |
elseif cmdline =~ '^\k\+$' | |
" handle cabbrevs gracefully | |
" https://www.reddit.com/r/vim/comments/jgyqhl/nightly_hack_for_vimmers/ | |
return "\<C-]>\<CR>" | |
else | |
return "\<CR>" | |
endif | |
endfunction | |
cnoremap <expr> <CR> CCR() |
Looks like I've never had to search for any of those words. Thank you.
This is really neat, thanks!
I have found a caveat with this in relation to cnoreabbrev
. I have one set up like so cnoreabbrev w update
, which only writes the buffer if modified. So if I :w<CR>
works just like :write<CR>
. The above snippet forces you to :w<space><CR>
which is just extra <space>
and not a big deal but I was hoping if you have some advice to achieve the previous effect where an extra <space>
won't be necessary.
That trailing space is part of how abbreviations work: you press <Space>
to expand your abbreviation and you get that annoying trailing <Space>
. You can use <C-]>
as an alternative trigger if you don't want that pesky <Space>
:
Example:
:ab hh hello
"hh<Space>" is expanded to "hello<Space>"
"hh<C-]>" is expanded to "hello"
Apologies if I have not explained myself very well.
With the abbreviation cnoreabbrev w update
set, If I type :w<CR>
, it executes :update
immediately without any additional <space>
/<C-]>
. No need for expansion in this case.
Are you sure :w<CR>
actually executes :update
? :write
and :update
are exactly equivalent if the buffer is changed.
Does the update time change on the file even if there was no change?
I tried your abbreviation on my end and :w<CR>
is just :write<CR>
: the abbreviation is never expanded.
Yes, in my case :w<CR>
just executes :update
and as the :h :update
suggest it only writes if the buffer is modified.
- If the buffer is modified,
:w<CR>
expands to:update
and writes the buffer,:ls
shows accurate update time. - If the buffer is not modified,
:w<CR>
expands to:update
does not write the buffer,:ls
shows accurate update time.
I tried this with vim -u NONE
and can reproduce.
I am running 8.2.400
.
I can't reproduce your issue (8.2.319
and 8.0.503
).
w
is never expanded when I press <CR>
so :w<CR>
is just regular :w<CR>
. Could there be a trailing/leading <Space>
somewhere?
If you've got your <CR>
mapped to the snippet from this gist, try disabling it. Because that's what causes this small issue with cnoreabbrev
.
Nope, no spaces involved. I tried wiping my entire vimrc
as well as vim -u NONE
, to the same effect. Auto expansion on <CR>
.
That's okay, perhaps, I am missing something on my part. I'll spend some time figuring this out and report back once I find out what the hell is going on.
I changed line 40 to return "\<C-]>\<CR>"
to get around my issue. Tested it for a while, haven't noticed any issues.
Also added space on line 15 '\v\C^(dli|il)\ '
so that if I accidentally don't input a search term after li
/dli
, it won't be stuck in an error loop.
Thank you for a very nice ccr.vim command line consolidation!
I have just found that the latest changes:
if getcmdtype() != ':' return "\<CR>" endif
caused a conflict with this insert mode mapping:
inoremap <expr> <cr> pumvisible() ? "\<C-y>\<cr>" : "\<cr>"
Comment this out will work fine, except that now it will have same issue with /ls .
Change to the following seems fix both issues:
if getcmdtype() != ':' return "\<Esc>" endif
To list tabpages and then setup the command line to jump to a tabpagenr add another elseif condition with:
elseif cmdline=~# '\C^tabs | set nomore | return "\<CR>:Z| tabnext\<S-Left>"
@craigmac added, thank you.
I also added support for :list
to that silly n|nu|…
pattern that I love and is getting sillier and sillier.
FWIW, my local version also supports :filter
for most cases and also deals with abbreviations more gracefully. I should update the gist to reflect those changes.
Latest update:
- handles
:filter
for supported commands, think:filt rb old
, :clist
and:llist
are now on separate branches to make handling:filter
easier,- command-line abbreviations are now handled properly.
Thank you all for your comments.
Another little annoyance: if you use alternate file #
in, for example, :buffer #<CR>
it switches the buffer then puts :
on the command-line, which is not what we want. Same thing happens with :edit #<CR>
. I see that the issue is one condition which checks for #|num|...
and returns "\<CR>:"
. I'm trying to think why the #
is checked for there, and if it breaks any cases if I remove it. On further examination, is that line missing a ^
so that it wouldn't pick up a #
in the case of :buffer #<CR>
?
@craigmac :#
is a synonym of :number
so it has to be taken into account. As of now, line 14 is triggered by commands like :g/foo/#
, which I use quite often.
The pattern could definitely be improved or I could !!
a second pattern.
@craigmac looking at it again, :buffer #<CR>
and :edit #<CR>
seem to work fine on my end.
- The pattern on line 14 has a
/
before the#
so it shouldn't match against:<command> #
. - The pattern on line 17 starts with
\v\C^((filt|filte|filter) .+ )*
so it shouldn't match either.
Do you use the latest version of this gist?
@romainl I re-copied and tried it out, only to realize I had my own version of the command overriding this one (which had a syntax error causing my bug). Apologies, it works fine as is!
@craigmac No problem!
Not sure if I am missing somthing but you may want to add somthing like
To avoid using the mappings in
/
or?
commands. e.g. searching forls
in a file