How can I move a selection of lines 1 line down? [duplicate] - vim

This question already has answers here:
Move entire line up and down in Vim
(21 answers)
Closed 8 years ago.
I'm trying to create maps for moving the selection up or down. Moving all selected lines 1 line up is easy:
vnoremap <silent> <M-k> :m--<CR>gv
But moving the lines downwards isn't as easy. The move command requires the same amount of "+" as the amount of lines moved. If I have 10 lines selected, I have to write :m++++++++++ to move them down once.
Alternatively I could write :m line("'>")+1 or in other words, "move selection to the line below the last line in the selection". Unfortunately it just results in "E14: Invalid address" for some reason.
I can't use :exec ... to build a command because I just get "E481: No range allowed" because Vim automatically inserts :'<,'> when I hit colon and I don't know how to prevent that.
Any ideas? I just want a map to move the selected lines down once.
Edit: Thanks to the :<C-u> trick in the accepted answer, I now have these 4 key binds that appear to work perfectly:
" Move lines
nnoremap <silent> <M-j> :m+<CR>
nnoremap <silent> <M-k> :m--<CR>
vnoremap <silent> <M-j> :<C-u>exec "'<,'>m " . (line("'>") + 1)<CR>gv
vnoremap <silent> <M-k> :m--<CR>gv

First of all, you don't need to implement this yourself, the Transposing page on the Vim Tips Wiki covers this and also has links to several plugins that provide such mappings.
The key to handling the move down in visual mode is indeed to use the '> mark. However, you indeed need to use :execute to get that result to the :move command.
The '<,'> added range in the visual mode mappings can be cleared by starting the right-hand side with :<C-u>execute ...; this is a well-known idiom.
If you want to learn more, have a look at some of the plugins' implementations.

Related

Is there a way to copy a selected area up or down in vim?

In VSCode you can copy and paste selected lines of text up or down using Alt+Shift + Up or Down.
I switched to vim a few months ago, and I really miss this feature.
I found out you can move selected lines in visual mode up or down using these visual mode bindings,
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
but it'd be great if you could copy and paste up and down as well without using yy and p because when you're done yanking, the cursor is placed at the initial position, exiting visual mode and reducing productivity.
Well, that, here, is the problem with copying and pasting random snippets from the internet without understanding what they do: they are little black boxes that one can't modify or extend at will by lack of knowledge.
Let's deconstruct the first mapping:
vnoremap J :m '>+1<CR>gv=gv
:[range]m {address} moves the lines covered by [range] to below line {address}. Here, the range is automatically injected by Vim: '<,'> which means "from the first line of the latest visual selection to its last line", and the address is '>+1, meaning "the last line of the latest visual selection + 1 line". So :'<,'>m '>+1<CR> effectively moves the selected lines below themselves,
gv reselects the latest visual selection,
= indents it,
gv reselects it again for further Js or Ks.
Now, we want a similar mapping but for copying the given lines. Maybe we can start with :help :m and scroll around?
Sure enough we find :help :copy right above :help :move, which we can try right away:
xnoremap <key> :co '>+1<CR>gv=gv
Hmm, it doesn't really work the way we want but that was rather predictable:
the address is one line below the last line of the selection,
the selection is reselected and indented, which is pointless.
We can fix the first issue by removing the +1:
xnoremap <key> :co '><CR>gv=gv
and fix the second one by selecting the copied lines instead of reselecting the latest selection:
xnoremap <key> :co '><CR>V'[=gv
See :help :copy and :help '[.

vim move a block of selected code up or down

There is a way to move highlighted code up or down with arrow keys. Even the indentation would be correct on dropping the block.
For the life of me I do not remember how to do it.
Can someone please tell me how to do it.( suitably embarrassed asking this).
Here's the link that'll help you
link
You can move a line, or a block of lines, with the :m command. Examples:
:m 12 move current line to after line 12
To move a block of lines, use the same command but visually select the lines before entering the move command. You can also use arbitrary ranges with the move command. Examples:
:5,7m 21 move lines 5, 6 and 7 to after line 21
why not use d+p if you had chosen the block code
If you want to do it with arrow keys, you can try Tim Pope's vim-unimpaired plugin, which you can find on Github.
Then you can use mappings similar to these (except map them to whatever keys you like).
" ^U moves lines up, ^D moves lines down.
" Works in normal or visual select modes.
nmap <C-u> [e
nmap <C-d> ]e
vmap <C-u> [egv
vmap <C-d> ]egv
Cutting a block of text in visual mode and then pasting:
Go to command mode by pressing Esc if you're not already in it
Move to the start or end of where you want to go
Press V to switch to visual mode
Move with arrows or H,J,K,L to the other end of the block you want to move
Press D to cut it, it will switch back into command mode
Move to where you want to put it and press P to paste what you cut
It seems like a lot of steps but it's just a verbose explanation.
Here is my configurations, There is a nice configuration that I am using to map Ctrl+J to move a block of code up and Ctrl+K to move a block down. I am using currently NVIM but I think the same configuration setting is applicable for VIM as well.
Setting on NVIM
The location that I am using on macOS Catalina for the NVIM is located at:
.config/nvim/init.vim
nnoremap K :m .-2<CR>==
nnoremap J :m .+1<CR>==
vnoremap K :m '<-2<CR>gv==gv
vnoremap J :m '>+1<CR>gv=gv
for vim I think you can change the setting on
.vimrc located under the home directory.

How do I swap two lines in vim?

I have this:
pick 887b66f add 222 Dziewiecsil to flowers new title
pick dc331cb new name of beginning commit
And I want to get this:
pick dc331cb new name of beginning commit
pick 887b66f add 222 Dziewiecsil to flowers new title
Is there a way to do this in a quick way using keyboard shortcuts?
To swap the current line with the next one, type ddp while in command mode.
dd - delete line (actually called cut in other editors) and save it in register
p - paste line from register
dd deletes the current line, then you can paste the removed line using p. There's another way though using m. With m you can move lines around i.e.
:m 1 will move the current line after line 1
:m 0 will move the current line to top
:m $ will move the current line to bottom
In your example, place the cursor in the first line and type :m $
More info: http://vim.wikia.com/wiki/Moving_lines_up_or_down
Example:
1. one
> 2. two
with :m-2, switch (current line - 2)
> 2. two
1. one
with :m+1 switch (current line + 1)
1. one
> 2. two
You could map this if you want.
Despite the fact that question is quite old and marked as answered, I'd like to extend the answer by saying that you can use normal mode commands, which were provided by Sven Marnach with nnoremap like so:
:nnoremap <C-Up> <Up>ddp<Up>
:nnoremap <C-Down> ddp
This will allow you to move lines with Ctrl + Up and Ctrl + Down within your file. However this will overwrite #" register, which stores your last copied string/word/letter/etc. So by adding "(reg) before dd and p commands we can fix this:
:nnoremap <C-Up> <Up>"add"ap<Up>
:nnoremap <C-Down> "add"ap
Here we add "a before delete and paste commands to store our line in #a register, so your default copy register will not be overwritten. However it may overwrite contents of #a register (who knows, but you may use it for something important in your use-case, but this step bit paranoid, you can skip it if you want to), let's fix that too:
:nnoremap <silent><C-Up> :let save_a=#a<Cr><Up>"add"ap<Up>:let #a=save_a<Cr>
:nnoremap <silent><C-Down> :let save_a=#a<Cr>"add"ap:let #a=save_a<Cr>
(<silent> needed to prevent echoing our commands to message-line at the bottom.)
Now we have two mappings which allow us to move lines within the file with keyboard shortcuts. You can redefine buttons, I use Alt + j/k, which would be <A-j> and <A-k> for those commands. However not all terminal emulators support Alt key mappings AFAIK.
The mappings proposed in the Vim wikia page are actually the best way to map key combinations that emulate the way Sublime and other editors implement this feature.
This includes an indentation action after the move, which is also great (that's the double equal == signs, in case you don't want that).
It also supports visual and insert modes, so that you can move lines while editing or with fulblocks.
nnoremap <A-j> :m .+1<CR>==
nnoremap <A-k> :m .-2<CR>==
inoremap <A-j> <Esc>:m .+1<CR>==gi
inoremap <A-k> <Esc>:m .-2<CR>==gi
vnoremap <A-j> :m '>+1<CR>gv=gv
vnoremap <A-k> :m '<-2<CR>gv=gv
I personally mapped them to <D-J> and <D-K> on my Mac, instead of <A- which maps to the Alt key. That way I use Cmd + Shift + j/k, which feels more natural to my fingertips.

What are the must have vim commands to place in my vimrc file for general editing [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is in your .vimrc?
I am fairly confident with vim having used it on and off for the past 3 years but I keep finding new simple suggestions for my vimrc for general editing which, after I use them seem blatantly obvious.
An example being:
noremap p "+p
noremap y "+y
For OS clipboard use (on my linux box anyway)
Another example being:
imap jj <ESC>
So in an attempt to collect together a definitive set of simple vimrc entries I will ask the questions, which do you find most useful?
Edit:
I am looking for the most basic vim commands, not functions and stringed commands
This will save you a lot of pinky strain over the years
nnoremap ; :
This remaps ; to :, as it is a relatively unused key and you don't have to press shift for the :. The : still works, just in case you still press shift from muscle memory.
Personally, I've also found these to be helpful:
1) Use first person shooter (FPS) games' movement keys for window movements (not a good idea if you use A or D often. I don't.)
map <W> <C-w><Up>
map <S> <C-w><Down>
map <A> <C-w><Left>
map <D> <C-w><Right>
2) Use <space> as a leader
nnoremap <space> <Nop>
let mapleader = " "
3) Disable middle mouse, especially on a mac, where inadvertently using the mouse (to switch applications) pastes content if middle click is accidentally pressed
map <MiddleMouse> <Nop>
imap <MiddleMouse> <Nop>
4) Movement between tabs (kind of similar to Firefox)
map <T> :tabnew<Space>
map <Q> :tabclose<cr>
map <Leader>[ gT
map <Leader>] gt
I forgot to add that for the above, I use it as T <filename><enter>, which is a nice and quick way of opening a file in the current directory in a new tab.

vim: how to select pasted block

Is there a vim command to directly select a block of text which has just been pasted?
ps. I know about gv to reselect a block after exiting visual mode. It doesn't apply to this case.
If you want to select it just after paste (before you change anything else), use
nnoremap <expr> gV "`[".getregtype(v:register)[0]."`]"
. [ and ] marks point to start and end of the last change, v:register is set to the last register used (which is register used for the paste command unless you, for example, yank something), [0] selects only first byte of register type (it is required because for blockwise register it returns <C-v>{width}) and register type is one byte which is just the same as the keystroke you should use in normal mode to invoke visual mode.
I saw this solution somewhere on SO, you may want to search for it in order to get some alternatives.
In my case I have this map:
:nnoremap gp `[v`]
After more research I think the better solution is:
" https://vim.fandom.com/wiki/Selecting_your_pasted_text
nnoremap <expr> gp '`[' . strpart(getregtype(), 0, 1) . '`]'
I have had the following maps in my vimrc forever:
nnoremap <leader>p `[V`]
nnoremap <leader>[ `[V`]<
nnoremap <leader>] `[V`]>
They do the following:
visually select the recently pasted block
de-indent the recently pasted block
indent the recently pasted block
I probably use the indent ones even more than the selection one.

Resources