cledoux
cledoux

Reputation: 4947

Join two lines in Vim without moving the cursor

How can I join two lines in Vim and leave the cursor in its original position instead of it jumping to the merge point?

For example, take the the following two lines with the cursor at the position indicated by the caret:

this is ^line one
this is line two

Merging by J produces:

this is line one ^this is line two

How can I produce:

this is ^line one this is line two

I have tried things like Ctrl + O and variations of ''. None of these seem to work. They go to the beginning of the line, not to the original cursor position.

Upvotes: 6

Views: 865

Answers (3)

SergioAraujo
SergioAraujo

Reputation: 11790

Utility function that you can use for other purposes:

" Utility function that save last search and cursor position
" http://technotales.wordpress.com/2010/03/31/preserve-a-vim-function-that-keeps-your-state/
" video from vimcasts.org: http://vimcasts.org/episodes/tidying-whitespace
if !exists('*Preserve')
    function! Preserve(command)
        try
            " Preparation: save last search, and cursor position.
            let l:win_view = winsaveview()
            let l:old_query = getreg('/')
            silent! execute 'keepjumps ' . a:command
         finally
            " Clean up: restore previous search history, and cursor position
            call winrestview(l:win_view)
            call setreg('/', l:old_query)
         endtry
    endfunction
endif

The advantage of the solution using the above function is: Does not occupy any register

" Join lines without moving the cursor (gJ prevent adding spaces between lines joined)
nnoremap J :call Preserve("exec 'normal! J'")<cr>
nnoremap gJ :call Preserve("exec 'normal! gJ'")<cr>

BTW: Two more examples on how you can use the Preserve function -

" Remove extra spaces at the end of the line

    fun! CleanExtraSpaces()
        call Preserve('%s/\s\+$//ge')
    endfun
    com! Cls :call CleanExtraSpaces()
    au! BufwritePre * :call CleanExtraSpaces()

" Reident the whole file

    call Preserve('exec "normal! gg=G"')

Upvotes: 0

Zsolt Botykai
Zsolt Botykai

Reputation: 51593

You can do it like:

:nnoremap <F2> mbJ`b

This assigns the following actions to the F2 key:

  1. That is, create a mark (mb, but NOTE if you had set previously the b mark, than it gets overwritten!)
  2. Join the lines
  3. Jump back to the previous mark (`b)

Upvotes: 4

Randy Morris
Randy Morris

Reputation: 40927

Another approach that wouldn't stomp on marks would be this:

:nnoremap <silent> J :let p=getpos('.')<bar>join<bar>call setpos('.', p)<cr>

Much more verbose but it prevents you from losing a mark.

  • :nnoremap - Non-recursive map
  • <silent> - Do not echo anything when the mapping is pressed
  • J - Key to map
  • :let p=getpos('.') - Store cursor position
  • <bar> - Command separator (| for maps, see :help map_bar)
  • join - The ex command for normal's J
  • <bar> - ...
  • call setpos('.', p) - Restore cursor position
  • <cr> - Run the commands

Upvotes: 13

Related Questions