how to move a block or column of text - vim

I have the following text as a simple case:
...
abc xxx 123 456
wer xxx 345 678676
...
what I need to move a block of text xxx to another location:
...
abc 123 xxx 456
wer 345 xxx 678676
...
I think I use visual mode to block a column of text, what are the other commands to move the block to another location?

You should use blockwise visual mode (Ctrl+v).
Then d to delete block, p or P to paste block.

Try the link.
Marking text (visual mode)
v - start visual mode, mark lines, then do command (such as y-yank)
V - start Linewise visual mode
o - move to other end of marked area
Ctrl+v - start visual block mode
O - move to Other corner of block
aw - mark a word
ab - a () block (with braces)
aB - a {} block (with brackets)
ib - inner () block
iB - inner {} block
Esc - exit visual mode
Visual commands
> - shift right
< - shift left
y - yank (copy) marked text
d - delete marked text
~ - switch case
Cut and Paste
yy - yank (copy) a line
2yy - yank 2 lines
yw - yank word
y$ - yank to end of line
p - put (paste) the clipboard after cursor
P - put (paste) before cursor
dd - delete (cut) a line
dw - delete (cut) the current word
x - delete (cut) current character

One of the few useful command I learned at the beginning of learning VIM is
:1,3 mo 5
This means move text line 1 through 3 to line 5.

In VIM, press Ctrl+V to go in Visual Block mode
Select the required columns with your arrow keys and press x to cut them in the buffer.
Move cursor to row 1 column 9 and press P (thats capital P) in command mode.
Press Ctrl+Shift+b to get in and out of it.
(source)

Using an external command "awk".
%!awk '{print $1,$3,$2,$4}' test.txt
With pure vim
:%s,\v(\w+) (\w+) (\w+) (\w+),\1 \3 \2 \4,g
Another vim solution using global command
:g/./normal wdwwP

Related

Vim: unindent multiple lines to the beginning

Suppose I have something like this:
line 1 with text
line 2 with text
line 3 with text
line 4 with text
I want to unindent all of these lines to the beginning, like this:
line 1 with text
line 2 with text
line 3 with text
line 4 with text
Shift + V < gives me ONE level of un-indentation. How can I get them all to the beginning? Sorry, I'm having trouble phrasing this...
There are two different ways you could do this:
Visually select all of the lines, press <, and then press . as many times as you need until there is no indent left. Or if there are a specific number of lines you would like this on, you could do something like
5<< (unindent 5 lines)
<j (unindent this line and the next)
<ip (unindent inside this paragraph)
followed by as many . as you need.
Select all of the lines, and then type either :norm d^ or :s/^\s*
Also, Shift-V + V + < is basically the same as <<.

How to wrap each line in quotes in SublimeText?

Input:
boston beach summer figural yellow blue
boston floral flowers still still-life food pink figural
boston horse pink purple house flowers floral figural
Expected output:
"boston beach summer figural yellow blue"
"boston floral flowers still still-life food pink figural"
"boston horse pink purple house flowers floral figural"
The actual input file has 600+ lines, and I'm looking at a quick way to wrap each line in quotes? Does the method involve using multiple cursors? How about macros?
I would use a multiple cursors approach like this:
Windows
Ctrl + A (Select everything)
Ctrl + Shift + L (Split into lines)
End (Put the cursor at the end of the line)
" (Add the quote at the end of the line)
Home (Go to the first character of the line)
Home (Go to the beginning of the line... like if you have tabs or spaces)
" (Add the quote at the beginning of the line)
Mac
Cmd + A (Select everything)
Cmd + Shift + L (Split into lines)
Cmd + → (Put the cursor at the end of the line)
" (Add the quote at the end of the line)
Cmd + ← (Go to the first character of the line)
Cmd + ← (Go to the beginning of the line... like if you have tabs or spaces)
" (Add the quote at the beginning of the line)
Method 1:
no multiple cursors
+ best performance (use for large files)
- slightly clumsy
Replace (.*) with "\1"
Method 2:
multiple cursors
+ best in regards to usability/comfort
- slower for bigger files
- wont work if the file has empty lines
Ctrl+a, Ctrl+Shift+l, "
Method 3:
multiple cursors
+ close to #2 as usability, but works always
- slower for bigger files
Ctrl+a, Ctrl+Shift+l, End, ", Home, "
None of these worked in Sublime Text 3 for a multi-column TSV file with tab spacing.
I found this worked for column 1:
Find: ^\s*\S+
Replace: "$0"

Writing text blocks using nested iteration in Vim

Let's say I'd like to write a 5x5 text block, such as
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
And I want to do it using nested iteration.
In pseudocode it would look like
do five times ((do five times (type 'a')) change line)
So my first guess was to simply convert that as
5 ((5 (i a esc)) enter)
But I can't do that, because Vim doesn't support use of parentheses for specifying execution order. And simply typing
5 5 i a esc enter
will of course not work, since that will just produce a single line with 55 'a's and a newline.
So my question is: Is there a way to write text blocks using nested iteration in Vim? I know that there are other ways to write text blocks, but I want to know if this is possible, just out of curiosity.
You cannot do this directly, you need to use a register, expression, or macro:
qq5aa<Esc>a<CR><Esc>q4#q
qq - record macro
5aa<Esc> - insert 5 a's
a<CR><Esc> - insert line break
q4#q - stop recording, repeat 4 more times
I do not normally like one-liners, but this seems to work:
:for i in range(5) | for j in range(5) | execute 'normal ia' | endfor | execute "normal A\<CR>" | endfor
and this is a lot shorter:
:for i in range(5) | execute 'normal 5aa' | put='' | endfor
<esc> i a <esc> x 5p dd 5P
esc - switch to normal mode
i - switch to insert mode
a - print "a"
esc - switch to normal mode
x - deleta "a"
5p - paste a 5 times ("aaaaa")
dd - delete line "aaaaa"
5P - paste line "aaaaa" 5 times
:norm 5oaaaaa
is the simplest way I could think of to obtain a 5x5 matrix of a's but I don't think it satisfies your curiosity.
One could also do:
:norm Oaaaaa
5#:
but that's not really recursive either.
So… I don't know!

Vim: paste multiple lines after multiple lines

In vim, how can I paste multiple lines of code after every line of a visual block?
What I have is:
foo
bar
1
2
3
What I am trying to do is:
1
foo
bar
2
foo
bar
3
foo
bar
Is there a way to easily accomplish this?
You can cut it to the default register and do a global replacement for the rest of lines, like this:
Go to first column of first line of the file:
gg0
Cut data:
3dd
Do a global repeat for every line of the file and paste it:
:g/^/put
It yields:
1
foo
bar
2
foo
bar
3
foo
bar
assume that you want to copy and paste line number 1 2 3, run this command:
:g/^\S/1,3t.
then the text foo bar would be copied to right place. then you can remove the two lines.
You can also change the 1,3 to other range.
Not fully automated but almost there:
Visually highlight desired rows to copy with Shift+V
Delete with d
Move to first line ("1") and start recording with q followed by some letter, i.e., a.
Paste with p and then move down to the next line ("2"). Stop recording with q.
Now just repeat the last recorded command with ##, or + the designated letter, i.e., #a.

Vim: Quickly select rectangular blocks of text in visual-block mode

I'm looking for a fast way to select a block of text in visual-block mode. I deal with files of this nature:
aaaa bbbb cccc
aaaa bbbb cccc
aaaa bbbb cccc
dddd Xeee ffff
dddd eeee ffff
dddd eeee ffff
gggg hhhh iiii
gggg hhhh iiii
gggg hhhh iiii
My goal is to select the middle block in visual-block mode. I would do:
Navigate to the corner (where the X is)
Ctrl-V
'e' to extend selection to the end of block
'jj' or '2j' to extend the selection downward to the bottom of the block.
I'm looking for an alternative to (4) that, similar to 'e', would move to the last row of the block. In this simple example 'jj' is not too inconvenient, but sometimes these are large blocks.
There's a similar question here , but that involves jumping a pre-determined number of lines. Is there a way to do this, again an analog to 'e', but moving row-wise instead of column-wise? Thanks!
Starting on the X, you could do this with <C-v>}kee:
<C-v> – start blockwise visual mode
} – go to the end of the paragraph (that motion supposedly provides the benefit of this rather involved combo)
k – one above to exclude the empty line
ee – move the cursor from the first column to the end of the inner block.
I had some fun trying to make a function "select Visual block around cursor".
function! ContiguousVBlock()
let [lnum, vcol] = [line('.'), virtcol('.')]
let [top, bottom] = [lnum, lnum]
while matchstr(getline(top-1), '\%'.vcol.'v.') =~# '\S'
let top -= 1
endwhile
while matchstr(getline(bottom+1), '\%'.vcol.'v.') =~# '\S'
let bottom += 1
endwhile
let lines = getline(top, bottom)
let [left, right] = [vcol, vcol]
while len(filter(map(copy(lines), 'matchstr(v:val,"\\%".(left-1)."v.")'),'v:val=~#"\\S"')) == len(lines)
let left -= 1
endwhile
while len(filter(map(copy(lines), 'matchstr(v:val,"\\%".(right+1)."v.")'),'v:val=~#"\\S"')) == len(lines)
let right += 1
endwhile
call setpos('.', [0, top, strlen(matchstr(lines[0], '^.*\%'.left.'v.')), 0])
execute "normal! \<C-V>"
call setpos('.', [0, bottom, strlen(matchstr(lines[-1], '^.*\%'.right.'v.')), 0])
endfunction
nnoremap <Leader>vb :<C-U>call ContiguousVBlock()<CR>
You can try it with <Leader>vb: It should select any contiguous non-whitespace rectangular block around the cursor. The vertical axis is preferred.
Maybe I'll improve it later, but for now you can try if it solves your problem, if you like.
As an alternative to my homegrown attempt, you could try the popular plugin textobj-word-column. It gives you text objects ac ic aC iC to select a column of words or WORDs.
Start visual mode with v. Then select inner paragraph with ip. Enter visual block mode with <C-v>. Now just go to the end of the block with es as required.
Starting from the bottom right of the block is the same thing, but instead of e, use w.

Resources