Move current line (up/down) to one position in Vim - 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 =.

Related

Is there a native way to shift text vertically in Vim while exchanging with an adjacent line?

Consider the following text file:
--> Foobar
Barfoo
I would like to transform this text to
Foobar
--> Barfoo
There are several ways to do this. One possibility is to use REPLACE mode to overwrite the first line with three spaces, and then use REPLACE mode.
However, I'm wondering if there's a native way to select the array text (maybe in visual block mode) and pull it down to an adjacent line.
After learning about visual re-selection (gv), I figured out how to do this in a way that generalizes to any kind of visual selection (the first step is different depending on what one wants to select and move).
Select the block visually: 0vf>
Yank the block into a register: y
Re-select the block: gv
Replace all the text with a space character: r[Space]
Move down a line: j
Enter Replacement mode with [Shift]R.
Paste the register contents [Control]R"
I recorded this as a macro and it works reasonably well.
While sticking to native vim has it merits, sometimes it's not worth being such a purist. Visual blocks are one area worth enhancing with plugins. In your case, I recommend vim-schlepp based on Damian Conway's dragvisuals.vim plugin which makes dragging and duplication of visual blocks a joy. For more ideas on visual block plugins, just watch Conway's demo here.
You could use a binding:
nnoremap <silent> <A-j> :m .+1<CR>==
nnoremap <silent> <A-k> :m .-2<CR>==
inoremap <silent> <A-j> <Esc>:m .+1<CR>==gi
inoremap <silent> <A-k> <Esc>:m .-2<CR>==gi
vnoremap <silent> <A-j> :m '>+1<CR>gv=gv
vnoremap <silent> <A-k> :m '<-2<CR>gv=gv
With this bind, you can use Alt + j and Alt + k to move a line up or down in normal and visual mode(for multiple lines).
This binding was taken from the Vim Wiki.

Navigate in gvim like in most

I'd like to use gvim to view files with long lines. It's a table, so I'm not wrapping the lines.
Is this possible to configure gvim so arrows navigation will be like in "most" tool? Arrow key will move the whole screen 1 character lef/right/top/bottom?
Thanks a lot.
I think this should do what you want.
set nocompatible
set nowrap
set virtualedit=all
nnoremap <Left> zh
nnoremap <Right> zl
nnoremap <Up> <C-y>
nnoremap <Down> <C-e>
If you want the same behavior in insert mode, add the same mappings again as a second set, but use inoremap instead of nnoremap.
The virtualedit setting will allow the cursor to move beyond the end of the line and continue on as if the line had infinite whitespace to the right.
NOTE: virtualedit is only available if Vim was compiled with that feature. You can check with :version. If this feature is available, you should see a + next to it, e.g. +virtualedit.

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.

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.

Best of both worlds: arrow keys for cursor movement or flipping through buffers

I really like this vim trick to use the left and right arrows to flip between buffers:
"left/right arrows to switch buffers in normal mode
map <right> :bn<cr>
map <left> :bp<cr>
(Put that in ~/.vimrc)
But sometimes I'm munching on a sandwich or something when scrolling around a file and I really want the arrow keys to work normally.
I think what would make most sense is for the arrow keys to have the above buffer-flipping functionality only if there are actually multiple buffers open.
Is there a way to extend the above to accomplish that?
I'd rather have a completely different mapping because:
cursors are really useful, and not having them because you have a hidden buffer will annoy you a lot
some plugins use <left> and <right> because they are less obfuscated than l and h; those plugins are likely to break with such mappings
Anyway, you can try this:
nnoremap <expr> <right> (len(filter(range(0, bufnr('$')), 'buflisted(v:val)')) > 1 ? ":bn\<cr>" : "\<right>")
nnoremap <expr> <left> (len(filter(range(0, bufnr('$')), 'buflisted(v:val)')) > 1 ? ":bp\<cr>" : "\<left>")
To see documentation on the pieces above:
:h :map-<expr>
:h len()
:h filter()
:h range()
:h bufnr()
:h buflisted()
I use alt-direction to switch between buffers.
nmap <A-Left> :bp<CR>
nmap <A-Right> :bn<CR>
If you modifying hl's defaults, then the arrows would feel more useful. (Like changing whichwrap to allow hl to go past the end of line.)
I do something similar with jk to make them different from my arrows:
" work more logically with wrapped lines
set wrap
set linebreak
noremap j gj
noremap k gk
noremap gj j
noremap gk k
That will wrap long lines and jk will move to what looks like the line below. (If you have one long line, then you'll move to the part of that line below the cursor.) Great for editing prose or long comments.
See also
help showbreak
I map Tab and Shift+Tab to switch buffers when in normal mode (makes sense to my brain and the keys are not doing anything useful otherwise).
Add this to your .vimrc
" Use Tab and Shift-Tab to cycle through buffers
nnoremap <Tab> bnext<CR>
nnoremap <S-Tab> :bprevious<CR>

Resources