Case insensitive commands in Vim [duplicate] - vim

The same goes for :q and :Q. I almost always don't let up on shift quick enough and seeing that :Q and :W aren't used anyway I thought it would be nice to just have them do the same as their lower-case counterparts.

The hack is via a :cmap or :cabb, but these have side effects (i.e. other instances will be inadvertently converted, too).
The cmdalias plugin does this better.
But I think for your use case it's best to define your own uppercase command-variants. The main challenge is to support all the options that the original one has:
command! -bang -range=% -complete=file -nargs=* W <line1>,<line2>write<bang> <args>
command! -bang Q quit<bang>

Yes, you can remap them in your .vimrc like so:
cabb W w
cabb Q q
or
cmap W w
cmap Q q
The downside is that it "W" will expand to "w" with both cases (cmap displays the change, cabb does not).
It's generally quite easy to remap keys to suit your needs in Vim. Try looking at the following tutorial: Mapping keys in Vim
edit:
As #IngoKarkat points out, this is a hackish solution. I'm leaving it here because it's fast and easy. However, the downside is clear; it interferes with other uses.

noremap works for me with no known side effects
noremap :W :w

Assuming you're looking for a quicker way to do :wq
Really this is a combo of ESC then : (which itself is Shift+;) then w then q then Enter. Five keystrokes, six if you count : as two.
Instead, try ESC then (holding) Shift press Z then Z again (no : at all). It will save and quit the file immediately. One less keystroke (or two, depending upon how you count it) plus much harder to mess up.

You can define W and Q by adding the following entries to your .vimrc:
command! W write
command! Q quit

This is not an answer to your question, but a solution to your problem — "I almost always don't let up on shift quick enough". Swap the meaning of the colon and semicolon. Then no shift is needed, as you will use ;w and ;q.
nnoremap ; :
nnoremap : ;
vnoremap ; :
vnoremap : ;

Related

Include all default binds in vimrc?

Maybe this goes against the traditional zen of VI, but I get very overwhelmed when it comes to working with rebinding keys in Vi, in particular what can/cannot be bound. I've had a particular headache since moving to nvim with selecting/copying/pasting using visual mode, as well as no longer having access to Home/End to jump to beginning/end of a line while in insert mode.
I was thinking that a way around this, much like I do with my tmux config, is issue a command to unbind all keys in my vimrc, then rebind them all. That way, there's no confusion to what a binding is, and I can easy change and reference a change anytime. Am I going about this all wrong?
You can't really do this. Vim treats "built-in mappings" different from "user-defined mappings". You can't really "unmap" a built-in mapping.
Technically, it stores built-in mappings in a different C struct than user-defined mappings defined with :map. When you do :unmap, it just removes it from the user-defined struct (incidentally, I gave a brief − but incomplete − overview of how this works last week in How to find out what a key is mapped to? at vi.SE).
The only thing you can do is something like:
" Remap all ascii characters; everything below 33 is a control character
for i in range(33, 127)
" | needs some extra love
if i == 124 | continue | endif
execute 'nnoremap ' . nr2char(i) . ' <Nop>'
execute 'nnoremap <C-' . nr2char(i) . '> <Nop>'
endfor
" The above won't remap stuff like `<F1>`, `<Up>`
nnoremap <Bar> <Nop>
nnoremap <F1> <Nop>
nnoremap <Up> <Nop>
" ... etc ... You can use a loop for this as well...
" Now make our own mappings
nnoremap : :
" ...etc...
And the same for vnoremap, etc. but this won't remap <C-w><C-w>, gJ, etc. so you'll need to add even more exceptions for that (the "second key" for these mappings isn't even in a struct, but is a switch/case!)
However. don't do this. Because now rely on your vimrc that you and only you can understand. Just learn the default mappings. This will mean you can use any Vim installation out-of-the-box, and your mappings won't be somehow "better" than the default mappings.
You can put this line near the top of your vimrc to reset all options to their default value:
set all&
But you can't realistically hope to "unbind" the "default bindings" with a single command because:
they are not "bindings", they are "commands",
there's no such command anyway.
You could remap every default command to <nop> (:help <nop>) but that sounds like a lot of work for very little benefit.

Setting mouse=a and mapping <esc> to :noh breaks mouse working on vim? [duplicate]

I am a happy VIM user, although I admit I'm quite far from being fluent. I found this nice post:
Vim clear last search highlighting and I thought I'd become a better person if I didn't have to hammer away a random character sequence every time I did a search. Now, I'm also using the vimrc config from here:
http://amix.dk/vim/vimrc.html
and the problem I have is that when I add the line nnoremap <esc> :noh<return><esc> to it (it doesn't seem to make a difference where I put it) I get awkward behaviour when I use arrows in command mode, namely letters from A to D appear in a newline and I get switched to insert mode.
There has to be some mapping conflict but for the life of me I can't figure out where it is.
EDIT: As it follows from the answers it turns out the Ultimate vimrc part is not relevant, the mentioned nnoremap command will cause altered arrow behaviour even if it's the only vimrc entry. Changing title to a more informative one.
PS. I know I shouldn't use arrows, hopefully I'll get there one day.
The mapping
nnoremap <esc> :noh<return><esc>
will conflict with so called "grey keys" and I believe that it should be used either in GVim only or in terminal Vim by someone who does not use special keys like arrows.
From what I know (and guess) how Vim processes keys, I would say that it's impossible to do anything with this. For Vim to recognize special key all its components should go in a row, so when you press Arrow Left Vim gets the following sequence of codes:
<esc> [ D
But after your mapping Arrow Left becomes:
: n o h l <cr> <esc>
[ D
Vim sees two separate sequences and treats <esc> as a single press of Escape key, thus next two codes of Left Arrow key lose their special meaning.
So I suggest you to map :noh to some other key sequence (e.g. to one starting with <leader>, see :help mapleader; I don't recommend you to use F-keys, using them is as bad as using of arrow keys).
The cause had been explained well, but solution was not mentioned. However there is a straight one.
If you’ll tell to Vim explicitly that there are key sequences starting from <esc>[
:nnoremap <silent><esc> :noh<CR>
:nnoremap <esc>[ <esc>[
than when single <esc> will be pressed Vim will wait for a second (or different time, see :h 'timeoutlen') or for a next key (second <esc> for example) and only then replace it with :noh<CR>.
This solution preserves the ESC mapping to :nohlsearch.
The comment on this answer explaining why this is happening tells us that the root cause is the TermResponse behavior of vim. This can be compensated for by wrapping the mapping in an autocommand for the TermResponse event.
This ensures that the binding doesn't happen until after the term response is set, which prevents Esc from also sending a string like ]>1;3201;0c to vim.
Change your line in vimrc to this:
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
The augroup commands are not strictly necessary, but they prevent multiple mappings when you reload your vimrc without quitting vim.
EDIT: If you also use a graphical vim like Gvim or Macvim, the TermResponse event will not fire. Assuming you use a single vimrc, you'll need some additional code like
if has('gui_running')
nnoremap <silent> <esc> :nohlsearch<return><esc>
else
" code from above
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
end
Problem is that when you press an arrow terminal emits something like <Esc>OA. Vim part that supports terminal seems to use the same mapping mechanism to do the job as you are using: while nmap <Esc>OA will tell you nothing, call feedkeys("\eOA") will move one line up and call feedkeys("\eOA", 'n') will add letter A beyond current line. With your mapping being noremappable you forbid vim to use <Esc> as a part of the key. The problem is that you need remappable mapping here, but can have remappable mapping without it being recursive as well only if it starts with {lhs}, but <Esc>:noh<CR>OA is not going to work. I thought the following code will (it uses <expr> and function with side effect to make <Esc> be the first character of the actual {rhs} and still launch :noh), but in fact it does not:
function s:NoHlSearch()
nohlsearch
return "\e"
endfunction
nmap <expr> <Esc> <SID>NoHlSearch()
. I have no other idea how to solve the problem of having non-recursive remappable mapping which includes {lhs} but not at the start.
I have had good luck with this
if $TERM =~ 'xterm'
set noek
endif
nnoremap <silent> <esc> <esc>:noh<cr>
The disadvantage is that function keys can not be used in insert mode.
:h ek

Vim open file with h and l

So I have the following lines in my vimrc to scroll through autocompletion using jk.
" Making autocompletion work with jk
inoremap <expr> j ((pumvisible())?("\<C-n>"):("j"))
inoremap <expr> k ((pumvisible())?("\<C-p>"):("k"))
I was wondering if there would be a way to scroll through :tabe<Tab> suggestions using hand l? That's what would seem the most natural to me, however I haven't been able to find anything on how to do that.
When using command line completion, whether you use wildmenu or not and whatever value you have set for wildmode, your cursor stays in the command line and whatever printable character you hit is inserted including, of course, h and l.
With that in mind, do you really think it would be wise to abandon the ability to insert h and l in the command line?
If you don't like <Tab> you could try the wildchar option but you won't be able to get rid of or replace <C-n>/<C-p> and the arrows.
Also, command line completion is a generic feature that is not limited to :tabe. :tabe is a red herring, here.
To remap h and l looks weird to me. They are really usefull, at least you need it to write, type commands etc...
If you want an easy autocompletion tips you should add these lines in your vimrc :
set wildmenu
set wildmode =list:longest,list:full
And then add the SuperTab function, it allows you to autocomplete with Tab and navigate into the menu with Tab also. Here is the code :
imap <Tab> <C-R>=SuperTab()<CR>
function! SuperTab()
if (strpart(getline('.'),col('.')-2,1)=~'^\W\?$')
return "\<Tab>"
else
return "\<C-n>"
endif
endfunction
Hope it helps !

How to make an horizontal ruler with vimscript?

i'm trying to do a command that fills up the current line with # , then goes to the begining and rewrites with the date and time, then o, this is my attempt:
:nnoremap <F6><Home>
set count = 0
normal i
while count <= columns
normal #
set count += 1
endwhile
<Home>R =strftime("%c")<CR>
normal o
the result of pressing F6 should be somehting like:
Date and time######################################################################
but yeah this is my first attempt at extending vim so please help me understand how to make this allright.
The right-hand side of a mapping is basically the same as if you typed the commands. This allows you to gradually move from repeatedly typing something to recording a macro (#q), to finally making a permanent mapping.
Here's a somewhat literal translation of your attempt:
:nnoremap <F6> 80I#<Esc>0R<C-r>=strftime("%c")<CR><Esc>o
It uses a fixed width of 80. If you want something more dynamic (like the value of 'textwidth' when it's > 0), you have to move from direct execution to programmatic interpolation via :execute, like this:
:nnoremap <F6> :execute 'normal' (&textwidth > 0 ? &textwidth : 80) . "I#\<lt>Esc>"<CR>0R<C-r>=strftime("%c")<CR><Esc>o
As you can see, this is already way more cryptic, with a mixture of Ex commands and :normal mode, quoting, etc.
The final step is a fully configurable and reusable plugin. Only for those, with elaborate error handling and stuff, you'd typically use separate :function definitions, which are then just called from your mapping:
function! s:InsertSeparator()
...
endfunction
nnoremap <silent> <F6> :call <SID>InsertSeparator()<CR>
You can use printf in vimscript.
:nnoremap <F6> I<C-r>=substitute(printf("%-80s", strftime("%c")), '\(\s\)\#<=\s', '#', 'g')<CR><Esc>o

Mapping <esc> in vimrc causes bizarre arrow behaviour

I am a happy VIM user, although I admit I'm quite far from being fluent. I found this nice post:
Vim clear last search highlighting and I thought I'd become a better person if I didn't have to hammer away a random character sequence every time I did a search. Now, I'm also using the vimrc config from here:
http://amix.dk/vim/vimrc.html
and the problem I have is that when I add the line nnoremap <esc> :noh<return><esc> to it (it doesn't seem to make a difference where I put it) I get awkward behaviour when I use arrows in command mode, namely letters from A to D appear in a newline and I get switched to insert mode.
There has to be some mapping conflict but for the life of me I can't figure out where it is.
EDIT: As it follows from the answers it turns out the Ultimate vimrc part is not relevant, the mentioned nnoremap command will cause altered arrow behaviour even if it's the only vimrc entry. Changing title to a more informative one.
PS. I know I shouldn't use arrows, hopefully I'll get there one day.
The mapping
nnoremap <esc> :noh<return><esc>
will conflict with so called "grey keys" and I believe that it should be used either in GVim only or in terminal Vim by someone who does not use special keys like arrows.
From what I know (and guess) how Vim processes keys, I would say that it's impossible to do anything with this. For Vim to recognize special key all its components should go in a row, so when you press Arrow Left Vim gets the following sequence of codes:
<esc> [ D
But after your mapping Arrow Left becomes:
: n o h l <cr> <esc>
[ D
Vim sees two separate sequences and treats <esc> as a single press of Escape key, thus next two codes of Left Arrow key lose their special meaning.
So I suggest you to map :noh to some other key sequence (e.g. to one starting with <leader>, see :help mapleader; I don't recommend you to use F-keys, using them is as bad as using of arrow keys).
The cause had been explained well, but solution was not mentioned. However there is a straight one.
If you’ll tell to Vim explicitly that there are key sequences starting from <esc>[
:nnoremap <silent><esc> :noh<CR>
:nnoremap <esc>[ <esc>[
than when single <esc> will be pressed Vim will wait for a second (or different time, see :h 'timeoutlen') or for a next key (second <esc> for example) and only then replace it with :noh<CR>.
This solution preserves the ESC mapping to :nohlsearch.
The comment on this answer explaining why this is happening tells us that the root cause is the TermResponse behavior of vim. This can be compensated for by wrapping the mapping in an autocommand for the TermResponse event.
This ensures that the binding doesn't happen until after the term response is set, which prevents Esc from also sending a string like ]>1;3201;0c to vim.
Change your line in vimrc to this:
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
The augroup commands are not strictly necessary, but they prevent multiple mappings when you reload your vimrc without quitting vim.
EDIT: If you also use a graphical vim like Gvim or Macvim, the TermResponse event will not fire. Assuming you use a single vimrc, you'll need some additional code like
if has('gui_running')
nnoremap <silent> <esc> :nohlsearch<return><esc>
else
" code from above
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
end
Problem is that when you press an arrow terminal emits something like <Esc>OA. Vim part that supports terminal seems to use the same mapping mechanism to do the job as you are using: while nmap <Esc>OA will tell you nothing, call feedkeys("\eOA") will move one line up and call feedkeys("\eOA", 'n') will add letter A beyond current line. With your mapping being noremappable you forbid vim to use <Esc> as a part of the key. The problem is that you need remappable mapping here, but can have remappable mapping without it being recursive as well only if it starts with {lhs}, but <Esc>:noh<CR>OA is not going to work. I thought the following code will (it uses <expr> and function with side effect to make <Esc> be the first character of the actual {rhs} and still launch :noh), but in fact it does not:
function s:NoHlSearch()
nohlsearch
return "\e"
endfunction
nmap <expr> <Esc> <SID>NoHlSearch()
. I have no other idea how to solve the problem of having non-recursive remappable mapping which includes {lhs} but not at the start.
I have had good luck with this
if $TERM =~ 'xterm'
set noek
endif
nnoremap <silent> <esc> <esc>:noh<cr>
The disadvantage is that function keys can not be used in insert mode.
:h ek

Resources