Vim: how to jump to definition in a split window - vim

I would like to define a command, gv, which jumps to definition in a split window. I'm aware that gd is the command to jump to definition but in the existing window.
I tried this mapping:
nnoremap <silent> gv :vsplit<CR>gd
But it didn't work. It opened up the exactly same file in a split window, without actually jumping to definition. Seems like the gd command after <CR> was ignored. How do I fix this?
I saw some answers mentioning <C-]> but is there away to implement this without generating tags?
Hopefully this makes sense. Thanks in advance!

:help gd jumps to the local definition of the word under the cursor. That "local definition" is always in the same buffer no matter what so I hope you don't expect it to jump to some other buffer.
Your mapping:
nnoremap <silent> gv :vsplit<CR>gd
works as expected, here: the window is split and the cursor jumps to the local definition of the word under the cursor:
First jump is with gd, second jump is with your gv.
If you want a "jump to definition" that works across files, gd and gD are not what you want. See :help ctags, :help cscope and :help include-search. Note that those features are not particularly smart. If you want something that understands your code better than you do, look elsewhere.

You don't actually need to define a new mapping/command for this. If you press CTRL-W d (or type :dsp <word>), it will show you the definition in a new window. From the documentation:
CTRL-W CTRL-D *CTRL-W_CTRL-D* *CTRL-W_d*
CTRL-W d Open a new window, with the cursor on the first
macro definition line that contains the keyword
under the cursor. The search starts from the
beginning of the file. If a count is given, the
count'th matching line is jumped to.
However, if you really want to press gv and have the definition shown, an alternative to romainl's solution is the following:
nnoremap gv :vertical dsplit <C-R><C-w><cr>

Related

How to understand VIM configuration noremap <leader>M mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm

I find many results on internet using this confiuration to remove ^M. I can understand the substitute command :%s/<C-V><cr>//ge<cr>. But I cannot figure out why mmHmt and 'tzt'm is necessary.
noremap <leader>M mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm
mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm
^^................................ create mark m
^............................... move the cursor to the top of the window
^^............................. create mark t
^^...... move the cursor to mark t
^^.... position the current line at the top of the window
^^.. move the cursor to mark m
Creating those marks and jumping back to them after the substitution seems to be an attempt at keeping the cursor in place.
Hints:
The mapping is a normal mode mapping so the commands in the RHS are assumed to be normal command by default.
mmHmt is thus a sequence of normal mode commands, and so is 'tzt'm.
Doing :help m explains mm and mt. It also explains 't and 'm indirectly.
You are left with H: :help H, and zt: :help zt.
See :help m, :help H, :help ', :help zt.
Learning Vim is really easy. It not only allows one to understand random snippets found on the internet but, more importantly, to not need those in the first place.
See :help user-manual.

wrap paragraph in Vim

I would like to wrap a paragraph. I have tried the following in my .vimrc:
nnoremap [w vipga
But there are two problems:
It does not work for me (even though the key sequence works for me when I type it manually).
I would like my cursor position to stay the same.
The command to reformat is gq, not ga (you may have remapped that, but then would need to use :nmap for the mappings to apply).
To maintain the cursor position (as much as possible, as the reformat may make the current position invalid), you can set a mark and then jump back to it. Ergo:
:nnoremap [w m`vipgqg``

How to jump next tag when using tagbar in VIM

when using VIM with tagbar displayed.
I want to use the next command in .vimrc
nnoremap tn <C-w>h<cr>
to jump to the next tag in the tagbar. But the it takes no effect at all.
when i typed tn, the cusor is jumped to the next tag, but the main window keeps still
is there somebody can help me?
I don't use TagBar anymore so I can't test it for you but the doc seems to say that you can use:
:TagbarOpen fj
to jump to the TagBar window. I think it is a little more solid than <C-w>h which is pretty much tied to a specific layout.
Thus, a possible mapping would be:
nnoremap tn :TagbarOpen fj<CR>
But neither your mapping nor this one allow you to place the cursor on the next tag which is what you seem to want ("to jump to the next tag in the tagbar"). TagBar has a mapping, <C-n> to go to the next top-level tag which may or may be not what you want. You could add it to the mix or, maybe, use j:
nnoremap tn :TagbarOpen fj<CR><C-n>
nnoremap tn :TagbarOpen fj<CR>j
As a side note, after a month of usage, I found TagBar to be rather good at showing the structure of my code but rather bad at helping me navigate through it. Because I used it primarily for navigation, I ditched it for Vim's default ctags integration (<C-]>, :tag <Tab>, :tselect and so on…) and CtrlP's wonderful :CtrlPBufTag and :CtrlPTag.
Normally, <CR> in normal mode just moves the cursor to the beginning of the next line. To make that key jump to the tag on the current line, the tagbar plugin defines a buffer-local mapping in its tag window. Though it's generally recommended to use :nnoremap, this is one case where you have to allow remappings by using :nmap:
:nmap tn <C-w>h<cr>

move the text after the cursor to a new line

I am Vim newbie, and I'm using MacVim on OSX Snow Leopard. One of the most common actions I have to take is to move the cursor to a new line but also move the text after the cursor to the new line. I know that pressing 'o' in normal or visual mode moves the cursor to a new line and switches the mode to insert.
What I'd like to do is move the cursor to a new line, and move the text after the cursor to that new line as well, preferably staying in the normal mode? Is this possible? How can I accomplish this task?
If the cursor is on a <space> as in ([] marks the cursor):
lorem ipsum[ ]dolor sit amet
the simplest is to do r<CR>, that is "replace the current character with a linebreak".
Otherwise, use #knittl's solution.
So you want to move everything in the current line, which comes after the cursor to the next line? Read: insert a line break??
(move cursor)
i (or a)
<return>
<esc> (or ^C)
To map this sequence of keystrokes to a single key, follow #thb's suggestion and use the :map command:
:map <F2> i<CR><ESC>
:map <F2> i<CR>
This keeps vi in insert mode.
As I answered in this post, How do I insert a linebreak where the cursor is without entering into insert mode in Vim?.
Please try Control + j.
The code below achieves the same behavior as "normal" editors (for the lack of better terms on the top of my mind) except that you'd have to press "enter" twice instead of once.
I also wanted to get rid of the space if it's right before my current character.
There might be an easier way and I totally welcome edits :-)
" in ~/.vimrc or ~/.vimrc.after if you're using janus
nnoremap <cr><cr> :call ReturnToNewLine()<cr>
function ReturnToNewLine()
let previous_char = getline(".")[col(".")-2]
" if there's a space before our current position, get rid of it first
if previous_char == ' '
execute "normal! \<bs>\<esc>"
endif
execute "normal! i\<cr>\<esc>"
endfunction
This remaps pressing enter twice to going to insert mode, placing a carriage return and escaping.
The reason I'm using this mapping (enter twice) is because I was used to this functionality with other text editors by pressing a enter; also, typing enter twice is fast.
Another thing that I found useful in this context was allowing vim to move right after the last character (in case I wanted to move the last character to a new line). So I have the following in my ~/.vimrc as well.
set virtualedit=onemore
Note that I'm using nnoremap (normal mode non-recursive) instead of map (which is VERY dangerous) (check this out for more information on the differences http://learnvimscriptthehardway.stevelosh.com/chapters/05.html)
You need to map some keys to do a line break at the cursor,
I found the following mapping easy to use, just go to your vimrc and add this line:
:map <silent> bl i<CR><ESC>
to assign a line break at cursor to "bl" combo

How to paste in a new line with vim?

I often have to paste some stuff on a new line in vim. What I usually do is:
o<Esc>p
Which inserts a new line and puts me in insertion mode, than quits insertion mode, and finally pastes.
Three keystrokes. Not very efficient. Any better ideas?
Shortly after :help p it says:
:[line]pu[t] [x] Put the text [from register x] after [line] (default
current line). This always works |linewise|, thus
this command can be used to put a yanked block as
new lines.
:[line]pu[t]! [x] Put the text [from register x] before [line]
(default current line).
Unfortunately it’s not shorter than your current solution unless you combined it with some keyboard map as suggested in a different answer. For instance, you can map it to any key (even p):
:nmap p :pu<CR>
Options:
1) Use yy to yank the whole line (including the end of line character). p will then paste the line on a new line after the current one and P (Shift-P) will paste above the current line.
2) Make a mapping: then it's only one or two keys:
:nmap ,p o<ESC>p
:nmap <F4> o<ESC>p
3) The function version of the mapping (unnecessary really, but just for completeness):
:nmap <F4> :call append(line('.'), #")<CR>
" This one may be a little better (strip the ending new-line before pasting)
:nmap <F4> :call append(line('.'), substitute(#", '\n$', '', ''))<CR>
:help let-register
:help :call
:help append()
:help line()
:help nmap
You can paste a buffer in insert mode using <C-R> followed by the name of the buffer to paste. The default buffer is ", so you would do
o<C-R>"
I found that I use <C-R>" very often and bound that to <C-F> in my vimrc:
inoremap <C-F> <C-R>"
This still uses three keystrokes, but I find it easier than Esc:
o<Alt-p>
Since you're in insert mode after hitting o, the Alt modifier will allow you to use a command as if you weren't.
Using this plugin: https://github.com/tpope/vim-unimpaired
]p pastes on the line below
[p pastes on the line above
advantages:
works on all yanked text (word, line, character, etc)
indents the pasted text to match the indentation of the text
around it
2 keystrokes instead of 3 and much "easier" strokes
fast
Personally I've nmapped Enter (CR) like this:
nmap <CR> o<Esc>k
...based on this Vim Wikia article.
This way I can make newlines directly from normal mode, and combining this with wanting to paste to a newline below I'd do:
<CR>jp
You could also skip k in the nmap above, depending on what functionality you prefer from Enter, so it would just be <CR>p.
I've also imapped jj to Esc, which would also assist in this case. Esc is way too far away from the home row for how significant it is in vim.
Not shorter than the other solutions, but I do think it feels less clunky than some of them, and it has other uses too.
If you wanted to stay in the insert mode, you can do o ctrl+o p
o – insert mode and go to the new line
ctrl+o – run a single command
like in normal mode
p – paste
It's three keystrokes but you stay in insert mode and also o ctrl+o is quite fast so I personally treat it as 2.5 keystrokes.
If you're copying a whole line then pasting a whole line, use Y to yank the line or lines, including line break, in the first place, and p to paste. You can also use V, which is visual line mode, in contrast with plain v for visual mode.
I have mapping inoremap jj <ESC>. So it is easy to insert new line with ojj and Ojj and then p.
so ojjp paste new a newline. it have one more stroke then o<esc>p but ojjp is easy for me.
I found an elegant solution to this. If you are putting the yank register in your OS's clipboard (which is great anyway), with
set clipboard+=unnamed
than you can do o<Ctl-v>.
Besides being fewer strokes, this improves on both o<Esc>p and :pu because it preserves indenting: both of the other options start you at character zero on the new line.
Caveat is that this may or may not be OS dependent. All I know is that it works on recent version of OS X, but clipboard is just one of many ways to get yank in the OS clipboard.
If you want to paste in a new line and still keep indentation, create this mapping:
nnoremap <leader>p oq<BS><Esc>p
Prerequisite: you have leader mapped and you have set autoindent in your .vimrc.
Explanation: a new line is created with 'o', 'q' is typed and then back-spaced on (to keep indentation), and 'esc' brings you back to normal mode where you finally paste.
If you also want to end in insert mode, it is possible to paste while in insert mode using CTRL-R ". https://stackoverflow.com/a/2861909/461834
Still three keystrokes, but no escape, and you save a keystroke if you want to end in insert anyway.
I use the following mapping in my Neovim config:
nnoremap <leader>p m`o<ESC>p``
nnoremap <leader>P m`O<ESC>p``
A little explanation:
m`: set a mark in the current cursor position.
o<Esc>p: create a new line below and paste the text in this line
O<Esc>P: create a new line above and paste the text in this line
``: put the cursor in the original position
See :h mark for more information about marks in Vim.
This solution only seems to apply when the block of copied text starts on a new line (as opposed to grabbing a snippet of text somewhere within a line), but you can always start your copy on the last character you want to grab, then navigate to the last character at the end of line prior to the start of your desired copy block. Then when you want to paste it, place the cursor at the end of the line under which you want your text to be pasted and hit p. If I haven't screwed up the explanation, this should provide the effect you're looking for.

Resources