How to go back in vim to last cursor position - vim

To go down 17 lines of code, I can do:
17j
Is there a way to go back to the previous line of code (exactly where the cursor was) instead of having to do 17k? About half the time, if I do ctrl-o it will go back to the previous place, but often it does not if no editing takes place.

function Jump(jump)
execute "normal! m'" . v:count1 . a:jump
endfunction
nnoremap <silent> j :<C-U>call Jump('j')<CR>
nnoremap <silent> k :<C-U>call Jump('k')<CR>

Related

vim navigation for very long lines [duplicate]

This question already has answers here:
Vim: move around quickly inside of long line
(8 answers)
Closed 8 years ago.
I'm editing a text file with vim and I have wrap enabled using "set wrap". Suppose I have one very long line which has been wrapped to 10 lines. Lets say I'm on the 5th word(which is on the first line when wrapped) and I'd like to get to a word on the 7th line(when wrapped). Whats the fastest way I could get to that line. I'm not too keen on going w<a-number>l -- there is probably a better/easier way to do this, right?
gj to go to line below (same line, but wrapped)
gk to go to the above line.
I have a map in my .vimrc
map j gj
map k gk
There are several motions that specifically deal with :set wrap; mostly they are variants of the "normal" motions with g prefixed.
So there's gj and gk to move across screen lines, as well as g0, g^, g$, etc. Look them up with :help for more details.
When you know the word or see it. for example it's hello, you might search for it with /hello. That should jump there. If there is a hello before, you can use n to get to the next one.
As Paco says in his answer, you can navigate screen lines with gj and gk. If that is too much hassle, as it probably is, you can add these lines to your ~/.vimrc to have the normal arrow keys navigate in terms of screen lines instead of logical lines:
noremap <silent> <Up> gk
noremap <silent> <Down> gj
noremap <silent> <Home> g<Home>
noremap <silent> <End> g<End>
inoremap <silent> <Up> <C-o>gk
inoremap <silent> <Down> <C-o>gj
inoremap <silent> <Home> <C-o>g<Home>
inoremap <silent> <End> <C-o>g<End>

How to ignore error in VIM key mapping command series?

I'm editing key mappings for line movement as following:
vnoremap <silent> <C-j> :m '>+1<CR>gv
vnoremap <silent> <C-k> :m '<-2<CR>gv
They are supposed to move the line block up and down and work fine in most cases except at the top and bottom of a file.
When I select the line 1 2, and input ctrl-k, sure, it cannot move anymore upwards, while the expected behavior is that the line 1 2 are still highlight in visual mode.
The current appearance is that, the line 1 2 are not highlight anymore. I know that's because the ":m '<-1" failed, then gv will not be executed.
So my question is how to ignore this error to ensure gv executed anyway? Or some other solutions?
Please note, I know a solution linemovement.vim. It run these in two separated commands and some functions. While I suppose this should be a lightweight code.
You need :silent! to suppress the output and skip errors:
vnoremap <C-j> :<C-u>silent! '<,'>m '>+1<CR>gv
vnoremap <C-k> :<C-u>silent! '<,'>m '<-2<CR>gv
<C-u> removes the "selection range" inserted automatically by Vim because :silent doesn't accept a range.
we add '<,'> before :move so that it still works on the visual selection.
Here is that fix applied to my enhanced (adds autoindenting) version of those mappings:
nnoremap ,<Up> :<C-u>silent! move-2<CR>==
nnoremap ,<Down> :<C-u>silent! move+<CR>==
xnoremap ,<Up> :<C-u>silent! '<,'>move-2<CR>gv=gv
xnoremap ,<Down> :<C-u>silent! '<,'>move'>+<CR>gv=gv
Thanks for the idea.

Move current line (up/down) to one position in Vim

Sometimes I want to swap current line with line up or below in vim. I can do it with commands :m+1 or :m-1. However it is too wordy. Is there shorter way doing the same?
give this a try:
ddp and ddkP
if it gives what you want. ;)
Both Tim Pope's unimpaired.vim - Pairs of handy bracket mappings and my own LineJuggler plugin provide (among others; my plugin has a focus on line moves and copies, whereas Tim's has a mixture of useful stuff) [e and ]e mappings to move the current line / selection above or below. These don't clobber the default register, as ddp et al. would do.
Give mappings a chance:
nnoremap <leader>k :move-2<CR>==
nnoremap <leader>j :move+<CR>==
xnoremap <leader>k :move-2<CR>gv=gv
xnoremap <leader>j :move'>+<CR>gv=gv
Vim has the :move command that allows you to move one line.
For instance, :m +1 will move the current line down.
I have these mappings in my .vimrc :
" move the lines of visual mode up or down
" JK to move and keep a correct indentation (with =)
" <up><down> to move keeping the correct indentation
vnoremap <silent> J :m '>+1<cr>gv=gv
vnoremap <silent> <down> :m '>+1<cr>gv
vnoremap <silent> K :m '<-2<cr>gv=gv
vnoremap <silent> <up> :m '<-2<cr>gv
With these lines, if you select a bunch of lines in visual mode, and then press <up> or <down> arrows, the lines will be moved up or down (and you will stay in the same visual selection thanks to the gv at the end).
J and K are almost the same, but they keep and autoindentation, using the = operator (gv= autoindents the last visual selection).
For sure, i encourage you to do modify the keys that are mapped to your own preferences. These are just mine. Also, copy-pasting without understanding is probably a bad idea. If you understand that mapping, you could check help pages for :m, gv and =.

how can i intuitively move cursor in vim?(not by line)

if some lines are too long, it will be forced to be newlined.
for example, normally a long line will looks like this
1 first line
2 this is the long second line of the file
3 third line.
but, if the window of a vim are too narrow, it will looks like this
1 first line
2 this is the long
second line of the file
3 third line
the problem arise from this.
let's assume the vim cursor are located at before 't' in 'third line'. if i type 'k', cursor will move to before 's' in 'second line of the file'. after that, if i type 'k' again, cursor will move to 'f' in 'first line'!, not 't' in 'this is the long'. what i want is that the cursor move to 't' in 'this is the long', it is more intuitive process for me. how can set my vim to works like this?
In Vim, the gj and gk commands move by line on the screen rather than by line in the file. This sounds like it probably matches your description.
You can modify your keys like this:
:map j gj
:map k gk
No, if some lines are too long and you have set wrap on they will be shown on "two lines", so to say, but there won't be a newline character between them. If you turn off wrap with set nowrap you'll see the effect.
Normally, k and j move you up and down. If you want to navigate wrapped lines use gk or gj, or just as some like it, map it to for example, the cursor keys.
nmap <up> gk
nmap <down> gj
To move in vim in a natural way is possible.
What I did was, and I suggest you, to modify (or create) your "~/.vimrc" and add these two lines:
map <C-Up> g<Up>
map <C-Down> g<Down>
This will map you control-up and control-down to the movements commands (this is coherent with control-right and control-left to move around long lines)
If you add these other two lines, you can use the same command to move in insertmode:
imap <C-Up> <C-[> g<Up> i
imap <C-Down> <C-[> g<Down> i
(VIM is great !)
Greg Ruo
This answer is derived from #mario-rossi 's answer (Kudo to him), with minor midification.
I use the normal UP and DOWN arrow key, rather than CTRL+up and CTRL+down. And somehow I need to remove one excess space in the INSERT mode mapping to avoid an off-by-one behavior.
Put the following into your ~/.vimrc:
" When a long line is wrapped, the "gk" and "gj" allow you to move up and down
" a visual line, while normal "k" and "j" move a physical line.
" The following settings map "gk" and "gj" to cursor <up> and <down>.
map <up> gk
map <down> gj
" And the following lines enables same <up> and <down> behavior in INSERT mode
imap <up> <C-[> <up>i
imap <down> <C-[> <down>i
Took this from vim.fandom.com:
There are several cases to remap up and down movements. First, you probably should remap both k/j and / arrows. Second, you should coose vim modes that requires remap. Basic modes are Normal (nmap), Insert (as after i command, imap) and Select (as after v command, vmap). To remap all three:
nnoremap j gj
nnoremap k gk
vnoremap j gj
vnoremap k gk
nnoremap <Down> gj
nnoremap <Up> gk
vnoremap <Down> gj
vnoremap <Up> gk
inoremap <Down> <C-o>gj
inoremap <Up> <C-o>gk
There's also one significant Operator mode (as in dj or, to say, y4k), remapping operator (omap) breaks vim experience/habits dramatically and not recommended.
Personally I prefer to remap Insert mode only, to keep my editorial habits intact.

Vim: search and highlight but do not jump

The super star (*) key in Vim will search for the word under the cursor and jump forward to the next match. The user can jump to the next matches with the n key. If hlsearch is enabled, it will also highlight the matches.
I want to be able to press * and get the highlighted matches and be able to navigate the matches using the n key. However, I do not want Vim to jump to the next match when * is pressed, it should remain on the current word. Is there a way to do this?
I would map:
nnoremap * *``
Works exactly like you want, except that it adds a jump in the jump list. To prevent that you need:
nnoremap * :keepjumps normal! mi*`i<CR>
I found this works pretty well, there's no blink and it doesn't need an intermediate register.
nnoremap <silent> * :let #/= '\<' . expand('<cword>') . '\>' <bar> set hls <cr>
Or if you want the g* behavior:
nnoremap <silent> g* :let #/=expand('<cword>') <bar> set hls <cr>
The best solution:
don't add a jump to the jump list
the behavior of the star key is not be changed
so, try the plugin:
http://www.vim.org/scripts/script.php?script_id=4335
Much better than:
" a jump adds to the jump list
nnoremap * *``
" I got a dead loop on macvim
nnoremap * :keepjumps normal *``<cr>
" the behavior is changed
nnoremap <silent> <Leader>* :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
I haven't seen this one yet:
nmap <silent> * "syiw<Esc>: let #/ = #s<CR>
It's very short and does not involve jumping around which can result in blinking.
Explanation: copy the word under cursor to s register and then set the search register (/) to the content of s register. The search register is not writeable directly, that's why the let is necessary and hence the silent to keep vim's command line clean.
I have the following in my .vimrc, which I think works better than the other alternatives:
" Put word under cursor into search register and highlight
nnoremap <silent> <Leader>* :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
vnoremap <silent> <Leader>* :<C-U>
\let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
\gvy:let #/=substitute(
\escape(#", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR>
\gV:call setreg('"', old_reg, old_regtype)<CR>:set hls<CR>
If you want to keep the current view and add the search to the history, try this [not so efficient] solution:
noremap * msHmt`s*`tzt`s
It is using the marks s (save) and t (top).
A simple solution came to my mind: put map * *# in .vimrc file (it will blink though).
Many answers here outline rather simple mappings that work well for common cases, but may have side effects (like flickering by jumping back and forth) or lack robustness (may break if some regexp characters are defined as keyword characters).
If you're looking for a robust implementation and don't mind installing a plugin, you can choose from a plethora of alternatives, many of which also offer additional search-related improvements:
My SearchHighlighting plugin changes the * command, extends it to visual selections, and offers optional auto-searching of the word under the cursor.
star search changes the behavior of * to not jump to the next match, and includes the visual search from the next plugin
vim-visual-star-search provides searching of the visual selection
visualstar.vim provides searching of the visual selection
select & search can use either n/N or * in the visual selection, and can avoid jumping.
vim-asterisk provides a z* mapping that also doesn't jump, visual *, more intuitive smartcase handling, and can keep the cursor position when jumping (like ,*)
searchant.vim hooks into the built-in search commands and provides a separate highlighting for the match last jumped to.
The other answers here are good, particularly #rodrigo's, but I wanted to write a solution that preserves scroll position and does so without affecting any of the marks.
This works for me:
function! StarPositionSave()
let g:star_position_cursor = getpos('.')
normal! H
let g:star_position_top = getpos('.')
call setpos('.', g:star_position_cursor)
endfunction
function! StarPositionRestore()
call setpos('.', g:star_position_top)
normal! zt
call setpos('.', g:star_position_cursor)
endfunction
nnoremap <silent> * :call StarPositionSave()<CR>*:call StarPositionRestore()<CR>
Putting normal! * in the function directly doesn't seem to work, as (at least in neovim) it suppresses search highlighting from being triggered (as if :nohlsearch was run).
My solution:
nnoremap <silent><expr> * v:count ? '*'
\ : ':silent execute "keepjumps normal! *" <Bar> call winrestview(' . string(winsaveview()) . ')<CR>'
nnoremap <silent><expr> g* v:count ? 'g*'
\ : ':silent execute "keepjumps normal! g*" <Bar> call winrestview(' . string(winsaveview()) . ')<CR>'
Edit: Recent Vim has <Cmd> mapping, so you can use below to avoid CmdlineEnter/Leave to be fired.
nnoremap <expr> * v:count ? '*'
\ : '<Cmd>silent keepjumps normal! *<CR><Cmd>call winrestview(' .. string(winsaveview()) .. ')<CR>'
nnoremap <expr> g* v:count ? 'g*'
\ : '<Cmd>silent keepjumps normal! g*<CR><Cmd>call winrestview(' .. string(winsaveview()) .. ')<CR>'
Pros:
No flickering.
Jump list remains unchanged.
With a count, it invokes original *; you can use 1* if you miss the original *.
Marks and registers are untouched.
Using original *, its behavior is almost identical with * (except for jumping).
This means 'smartcase' is ignored as * do.
No need to install plugins.
Similar to * we have
[I ..................... it shows where the word under the cursor appears
I also have some useful lines on my vimrc that can, maybe, help you
" When double click a word vim will hightlight all other ocurences
" see CountWordFunction()
" [I shows lines with word under the cursor
nnoremap <silent> <2-LeftMouse> :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>
nnoremap <Leader>* :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>
if !exists('*CountWordFunction')
fun! CountWordFunction()
try
let l:win_view = winsaveview()
exec "%s/" . expand("<cword>") . "//gn"
finally
call winrestview(l:win_view)
endtry
endfun
endif
command! -nargs=0 CountWord :call CountWordFunction()
cnoreabbrev cw CountWord
nnoremap <F3> :CountWord<CR>
I'm adding this answer because I found the other answers either, centered the line in the view (which I found distracting), or seemed overly complicated.
The following command works well for me:
noremap * :let #/ = "\\<<C-r><C-w>\\>"<cr>:set hlsearch<cr>
It simply sets the pattern to the whole word under the cursor and then turns on (or updates) the highlighting for the search pattern.
NOTE: It doesn't modify the search history (which I prefer but might not be quite what you want).
just do
nnoremap * *N
nnoremap # #n
works with this http://www.vim.org/scripts/script.php?script_id=4335 too like so:
vnoremap * :<C-u>call VisualStarSearchSet('/')<CR>/<C-R>=#/<CR><CR>N
vnoremap # :<C-u>call VisualStarSearchSet('?')<CR>?<C-R>=#/<CR><CR>n
nnoremap <silent> ml :<c-u>let #/ = '\<'.expand('<cword>').'\>'\|set hlsearch<CR>wb
and if you want a visual mode one:
function SetSearchVisualSelection()
let clipboard_original_content=#"
normal gvy " this overwrites clipboard
let raw_search=#"
let #/=substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g")
let #"=clipboard_original_content
endfunction
vnoremap ml :call SetSearchVisualSelection()<CR>:set hlsearch<CR>

Resources