I often use commands like ci( and di{ when editing source code.
Parameters in Ruby blocks are contained inside pipe characters, like |a, b|
Is it possible to extend this behavior to add support for |, so that commands like ci|, da| and yi| work properly?
I have the following in my vimrc (I have added the va| and vi| commands for completeness):
nnoremap di\| T\|d,
nnoremap da\| F\|d,
nnoremap ci\| T\|c,
nnoremap ca\| F\|c,
nnoremap yi\| T\|y,
nnoremap ya\| F\|y,
nnoremap vi\| T\|v,
nnoremap va\| F\|v,
The , operator repeats the previous F,f,T or t but in the opposite direction. A very useful key!
These mappings can be easily modified to support other delimiters; I use the $ versions all the time when editing LaTeX.
This is what I would use:
vnoremap <silent> a<bar> :<c-u>silent! normal! vF<bar>of<bar><cr>
vnoremap <silent> i<bar> :<c-u>silent! normal! vT<bar>ot<bar><cr>
onoremap <silent> a<bar> :normal va<bar><cr>
onoremap <silent> i<bar> :normal vi<bar><cr>
Basically setup a operator pending mode (that is the onoremap) which will call the appropriate visual mode mapping. The visual mode mappings will search backwards to find a | with F| then go to the other side of the visual selection via the o command, then search forwards with f| to select the other end of the piped area. The inner mappings are the same but instead of using the F and f commands you use T and t.
Sadly these mappings do not work correctly with the ., redo command as they inherently rely visual mode mappings which means the . command will execute the same command again but only for an area that take up the same amount of space.
Related
I know that I can use ctrl+w to shift between different Vim windows. But how do I remap the CMD-key to replace ctrl+w in various way? I'm specifically looking to bind cmd with the arrow keys, so that I can shift to NERDTree easily with CMD+LeftArrow. Appreciate the assistance.
I've tried to add the following to $MYVIMRC...
nmap <silent> <D-h> :wincmd h<CR> // For going to NERDTree
nmap <silent> <D-l> :wincmd l<CR> // For going back to file I'm working on.
In the left-hand side of a mapping, Command+Left is written <D-Left>. With this and other issues fixed (see below), your mappings should look like this:
nnoremap <D-Left> <Cmd>wincmd h<CR>
nnoremap <D-Right> <Cmd>wincmd l<CR>
or, simply, like this:
nnoremap <D-Left> <C-w>h
nnoremap <D-Right> <C-w>l
Other issues:
Recursive mappings (nmap) should be reserved to the rare situations where you want to use another mapping in your mapping. This is not the case, here, so nnoremap is the best choice.
The mapped commands don't echo anything so <silent> is useless.
Vim's comment leader is ", not //.
You can't have comments on the same line as a mapping anyway, see :help map-comments.
The newish :help <Cmd> is cleaner than using : in the right-hand side of a mapping.
Note that these mappings only work in the MacVim GUI.
I would like to use a slash (/) for a search during a vimscript, but I don't want to overwrite the "/ register. How do I do this?
In my particular example, I am working on a custom vim text object for LaTeX, a$, to specify the region between and including the previous and next dollar signs ($ characters, which delimit math mode in LaTeX). I'm following a guide found here which suggests using a vnoremap and an omap command, which is a simple enough approach. What I would like to write is:
vnoremap a$ :<C-U> execute "normal! ?\\$\rvN"<CR>
omap a$ :normal va$<CR>
However, this implementation has a fatal flaw: the "/ register becomes overwritten with the search for the dollar sign character, clearing any previous search and causing confusion and inefficiencies when trying to use n or N next.
Save #/. Search. Restore #/. You might not be able to squeeze all that into a mapping so I'd recommend a function instead:
function! VisualAroundDollar()
let search = #/
execute "normal! ?\\$\rvN"
let #/ = search
endfunction
vnoremap a$ :<C-U>call VisualAroundDollar()<CR>
omap a$ :normal va$<CR>
May I suggest to consider the command keeppatterns
As :h keeppatterns says "Execute {command}, without adding anything to the search history" it may help you to build you mapping
If $ are always on the same line then it is often best to use f & t to make your custom text-objects.
xnoremap a$ :<c-u>normal! F$vf$"<cr>
onoremap a$ :normal va$<cr>
If your text-object goes over multiple lines then you need to do some kind of searching. Here is an example using search() which does not change the search register.
xnoremap a$ :<c-u>call search('\$', 'bcW')<cr>m<:call search('\$', 'W')<cr>m>gv
onoremap a$ :normal va$<cr>
As #ViVeteran stated you can also use :keeppatterns with / or ? to avoid changes to the search register and history.
xnoremap :<c-u>execute "keeppatterns normal! ?\\$\<cr>v/\\$"<cr>
onoremap a$ :normal va$<cr>
Note: :keeppatterns requires Vim 7.4.083+
For more complicated custom text-objects there is vim-textobj-user. You may want to look into vim-textobj-latex which use vim-textobject-user to create an assortment of Latex specific text-objects.
For more help see:
:h Operator-pending
:h :map-modes
:h c_CTRL-U
:h search()
:h :keeppatterns
My SearchAsQuickJump plugin provides an implementation of this. You can use the normal search (/{pattern}), but conclude it (in GVIM) via <S-CR> instead of <CR>. That will search but keep the original search pattern. It also has commands that correspond to the built-in * and # searches.
I want to remap <PageUp> to <C-u> and PageDown to <C-d> per the Vim scrolling documentation.
As it stands right now, my /etc/vim/vimrc looks like this:
nnoremap <PageUp> <C-u>
nnoremap <PageDown> <C-d>
I've tried a lot of different combinations and nothing I've done has worked.
My goal is to make the cursor move to the Start Of File or EOF when holding down PageUp/PageDown. As it is right now, the cursor stops before it gets all the way to the top (and PageDown scrolls past the EOF). Just annoyances I'm trying to fix.
EDIT: The above settings work fine. I was placing my mappings too early in the file.
What about the following mappings?
nnoremap <PageUp> gg
nnoremap <PageDown> G
Or simply using gg and G?
Instead of placing the mappings into the system-wide /etc/vim/vimrc, you should put user customizations into the ~/.vimrc file. Nonetheless, the global configuration (if that's what you want) should work, too. That it doesn't means that the mappings get cleared or redefined. You can check with
:verbose nmap <PageDown>
If it didn't get redefined, you have to hunt for :nunmap commands in all loaded scripts (:scriptnames), or capture a log with vim -V20vimlog.
You can do this with
map <silent> <PageUp> 1000<C-U>
map <silent> <PageDown> 1000<C-D>
imap <silent> <PageUp> <C-O>1000<C-U>
imap <silent> <PageDown> <C-O>1000<C-D>
from fixing-pageup-and-pagedown
I use mappings to normal mode commands that I'd also like to work in insert mode. This can be done by adding <C-o> to insert mode mapping:
nmap <C-Up> 10<Up>
imap <C-Up> <C-o>10<Up>
But this means repeating each mapping twice.
To avoid repetition, I've tried to "overload" some other key, then use it for mode-specific part:
" F12 selects prefix suitable for current mode
nmap <F12> <Nop>
imap <F12> <C-o>
" single mapping relying on "overloaded" F12
map <C-Up> <F12>10<Up>
For some reason, it doesn't work. F2 in insert mode just inserts <F2> as text.
Any idea what's wrong and how to fix it?
Bonus points if you can extend the solution to visual mode.
As ZyX has already pointed out, there is no single :map command for all modes, because it mostly doesn't make sense. If you really want to define a mapping for all modes, use both :map and :map!; see :help map-modes.
As you typically define mappings only once in your .vimrc, I would not worry too much about the little duplication, but if you do, you can use a wrapper function to avoid this:
function! MapBoth(keys, rhs)
execute 'nmap' a:keys a:rhs
execute 'imap' a:keys '<C-o>' . a:rhs
endfunction
call MapBoth('<C-Up>', '10<Up>')
Original
nnoremap <F2> :w<CR>
inoremap <F2> <Esc>:w<CR>a
map sometimes does not set it for all modes. I don't know the exact reason, so to be sure I like to explicitly set all mapping in my configuration file. I suggest that you do the same as there are cases where you can get something unexpected due to different modes. That's why it is important to consider every remapping that you do for each particular mode with care.
In addition, favor *noremap command instead of just *map everywhere you can as recursive mapping is a known source of errors, especially for beginners.
Lastly, I don't know what are you trying to achieve by binding writing of a file in visual mode. Are you aiming for partial buffer writing (it's when you selected something in visual mode, then hit this file-writing shortcut and only selected text is written)? Or do you want the whole file to be written when you are in visual mode, regardless of whether you selected anything or not when you hit the file-writing shortcut? Provide more information on that. Personally, in either case it is weird mapping for visual mode, as it is really not indented for that. It's rather better to keep such stuff in normal mode.
Update
As others have already given exhaustive answers on your question, I just thought that it would be helpful if add my 2 cents, but in slightly different direction. By looking on what you are trying to do, namely mapping navigation features involving arrow keys in insert mode, I can infer that you are very new to Vim. As you probably already know, the philosophy behind Vim is that you should never ever touch mouse during your work inside Vim - call it a kind of golden rule.
What I want to point out now, is what I call a silver rule, and it basically looks like this:
noremap <Up> <Nop>
noremap <Down> <Nop>
noremap <Left> <Nop>
noremap <Right> <Nop>
inoremap <Up> <Nop>
inoremap <Down> <Nop>
inoremap <Left> <Nop>
inoremap <Right> <Nop>
In other words, prevent yourself from using arrow keys (everywhere except command-line mode). Your fingers should always be only in the region of character keys. Vim is all about modes. Insert mode is not for navigation - it is intended for bursts of typing. When you work with code or just text (doesn't matter) you spend most of your time in normal mode - navigating - looking through the file, seeking where to land next in order to edit something, add something, i.e. to do your next input burst for which you switch to insert mode, and when you are finished you switch back to normal mode to look for some more meat - like a predator. :)
So what is it all about? I just want to head you to the right direction right from the beginning. This way you can become intermediate Vim user very quickly - just a few days. In order to get better feeling of all the aforementioned I suggest that you should definitely watch Vim Novice Video Tutorials by Derek Wyatt where he talks about all that stuff in more detail and shows it in action in the screencasts. There are also Intermediate and Advanced tutorials by him which you might also look when you are comfortable with the basics.
I wish you happy vimming! :)
There are no commands to define mappings for all modes: :map maps for normal, operator-pending and visual modes (really visual and select at once) which is clearly stated in documentation. It does not make any sense to have same mapping for all modes, though unlike movement ones saving may be done in all modes with exactly the same rhs:
function s:Save()
update
return ''
endfunction
noremap <expr> <F2> <SID>Save()
noremap! <expr> <F2> <SID>Save()
. noremap! is another multi-mode mapping command, it covers insert and command mode now. You can’t move the cursor from <SID>Save() function (textlock) thus this method is not applicable for cursor movement commands, but you can use variables in order not to repeat the same thing twice:
let s:tendownlhs='10j'
execute ' noremap <C-Down> '.s:tendownlhs
execute 'inoremap <C-Down> <C-o>'.s:tendownlhs
. Now without command mode as this is tricky and likely useless.
If it is okay for the mapping to end up in normal mode, you could combine a for loop with <C-\><C-n> mappings. <C-\><C-n> switches from any mode to normal mode.
For example, this allows switching panes with Alt-{h,j,k,l} from any mode:
for map_command in ['noremap', 'noremap!', 'tnoremap']
execute map_command . ' <silent> <M-h> <C-\><C-n><C-w>h'
execute map_command . ' <silent> <M-j> <C-\><C-n><C-w>j'
execute map_command . ' <silent> <M-k> <C-\><C-n><C-w>k'
execute map_command . ' <silent> <M-l> <C-\><C-n><C-w>l'
endfor
noremap maps in Normal, Visual, and Operator-pending mode
noremap! maps in Insert and Command mode
tnoremap maps in Neovim's Terminal mode
I mapped key F2 to refresh (:edit) currently opened file. I'm using this when watching a log file to update the screen when file has been updated outside (new lines added at the end of a log file).
nnoremap <silent> <F2> :edit<CR>
I would like to jump to the end of the file after it has been refreshed.
How do I create key mapping which does :edit and jump to end of the file (shortcut G) at the same time?
An idiomatic way to position the cursor in the just opened (or reopened) file
is to use the +-argument of the :edit command (see :help +cmd).
Although the general syntax allows to execute any command, there are special
cases for navigating to a certain line by a pattern matching text on that line
(+/ followed by the pattern), or by a line number (+ followed by the
number). If the number is omitted in the latter form, it is assumed to be the
last line of the file.
In such a way, to reload the current file positioning the cursor on the last
line, one can use the command
:edit +$
or
:edit + %
It is possible to shorten these commands by using :e instead of :edit and
leaving out an optional space before the +-argument.
:e+$
or
:e+ %
The corresponding mappings would take the form
:nnoremap <silent> <F2> :edit +$<CR>
and
:nnoremap <silent> <F2> :edit + %<CR>
Note that this +-argument syntax is also valid for opening a file from the
command line, so
$ vim + filename
works as well.
This is what I'd use:
nnoremap <silent><F2> :edit<bar>$<CR>
You can chain commands in a map by using <bar>. This mapping does what you want:
:nnoremap <silent> <F2> :edit <bar> :normal! G<enter>
It's important to use normal! instead of normal in mappings/scripts because the prior will not take user defined mappings into account. Even if there is a mapping for G in this case, vim will treat G as if it were not mapped at all.
You can use :normal to use the normal-mode G motion:
:nnoremap <silent> <F2> :edit<CR>:norm! G<CR>
Perhaps better would be to use the :$ command to go to the end of the file:
:nnoremap <silent> <F2> :edit<CR>:$<CR>
In Vim '|' can be used to separate commands, much like many flavors of Linux/Unix. For more information about the use of the bar check out :help bar
Example:
:edit | normal! G
If you wish to use this in a key mapping You may find that your ~/.vimrc doesn't like maps utilizing |, or \|. In order to make this work use the equivalent <bar> instead.