VIM column operation - vim

Intro
In gVim under Windows i have to replace insert and mod in each string of file some character in a specifics position.
Example
QWAER;PA 0X000055;123WAAAA
TYUIO;PA 0Y000056;123VAAAA
need to become
QWAE#;PAX000055;123;WAAAA
TYUI#;PAY000056;123;VAAAA
modify char 5 in #
delete char 9,10
insert ; in original pos 22 or after delete in pos 20
More Info
Usually I do
Put cursor and beginning of text to select
Press CTRL-V (CTRL-Q in gVim) to begin select of the column
keep press SHIFT and selecte the interested area
the go at the end of file
then do the replace insert or modification.
(This is where I learn about Keyboard-only column block selection in GVim Win32, or why does Ctrl-Q not emulate Ctrl-V when mswin.vim is included?
and here i learn how to do the insert(http://pivotallabs.com/column-edit-mode-in-vi/)
It's not a correct way to do the things.
In vim i can do the replaceof a fange of rows, and so on using commands.
I think that should be possible to use commands to replace a portion of each string but i have no Knoledge about those command.
this is the main idea
Replacing alternate line in vi text file with a particular string
Question
Is there a way to do the operations using commands with absolute position and not selection.
Thanks

:{range}normal 5|r#9|2x20|i;
Does what you want on the lines covered by {range}:
5|r# " go to column 5 and replace the character with #
9|2x " go to column 9 and cut 2 characters
20|i; " go to column 20 and insert a ; to the right
So…
:5,25norm 5|r#9|2x20|i; would apply that transformation to lines 5 to 25,
:.,$norm 5|r#9|2x20|i; would apply that transformation from the current line to the last,
:'<,'>norm 5|r#9|2x20|i; would apply that transformation to the current (or last) visual selection,
:'{,'}norm 5|r#9|2x20|i; would apply that transformation to the current "paragraph",
:%norm 5|r#9|2x20|i; would apply that transformation to the whole buffer,
and so on…
You could also record it, let's say in register q:
qq
5|r#
9|2x
20|i;<Esc>
q
and play it back on {range}:
:{range}#q
Or spend 30 minutes trying to come up with the right :s// command…
Reference:
:help range
:help :normal
:help |
:help r
:help x
:help i
:h recording

Related

Difference between cutting lines with 10dd and d9 in vim?

If I understand correctly both commands cut 10 lines and allow you to paste them anywhere.
Are they both the same as (n-1)dd and dn+enter where n is the number of lines to be cut?
The two relevant help section are copied below.
d
["x]d{motion} Delete text that {motion} moves over [into register
x]. See below for exceptions.
dd
["x]dd Delete [count] lines [into register x] linewise.
10dd is the second one which deletes 10 lines from you current position.
d9 does nothing. d9j (or d9<CR>) is delete from the cursor to where the cursor ends up (which is9j) is nine lines below the current one. However the j or <CR> makes it linewise so the same thing is deleted.
Both of these commands delete 10 lines. so ndd is equivalent to d(n-1)j.
d9j might be easier to type than 10dd if you have set relativenumber turned on because the difference between the line you are on and the line you want to delete to are on the left hand side of your screen.
You can use d9k to delete 10 lines up from your cursor line which you can't do with dd. Or you can use dfa to delete upto and including the next a. d{motion} is more powerful than dd because it isn't restricted to only linewise deletions.
Which one you use is up to you but certain combinations are easier depending on where your cursor is.

How to insert a block of white spaces starting at the cursor position in vi?

Suppose I have the piece of text below with the cursor staying at the first A currently,
AAAA
BBB
CC
D
How can I add spaces in front of each line to make it like, and it would be great if the number of columns of spaces can be specified on-the-fly, e.g., two here.
AAAA
BBB
CC
D
I would imagine there is a way to do it quickly in visual mode, but any ideas?
Currently I'm copying the first column of text in visual mode twice, and replace the entire two column to spaces, which involves > 5 keystrokes, too cumbersome.
Constraint:
Sorry that I didn't state the question clearly and might create some confusions.
The target is only part of a larger file, so it would be great if the number of rows and columns starting from the first A can be specified.
Edit:
Thank both #DeepYellow and #Johnsyweb, apparently >} and >ap are all great tips that I was not aware of, and they both could be valid answers before I clarified on the specific requirement for the answer to my question, but in any case, #luser droog 's answer stands out as the only viable answer. Thank you everyone!
I'd use :%s/^/ /
You could also specify a range of lines :10,15s/^/ /
Or a relative range :.,+5s/^/ /
Or use regular expressions for the locations :/A/,/D/>.
For copying code to paste on SO, I usually use sed from the terminal sed 's/^/ /' filename
Shortcut
I just learned a new trick for this. You enter visual mode v, select the region (with regular movement commands), then hit : which gives you this:
:'<,'>
ready for you to type just the command part of the above commands, the marks '< and '> being automatically set to the bounds of the visual selection.
To select and indent the current paragraph:
vip>
or
vip:>
followed by enter.
Edit:
As requested in the comments, you can also add spaces to the middle of a line using a regex quantifier \{n} on the any meta-character ..
:%s/^.\{14}/& /
This adds a space 14 chars from the left on each line. Of course % could be replaced by any of the above options for specifying the range of an ex command.
When on the first A, I'd go in block visual mode ctrl-v, select the lines you want to modify, press I (insert mode with capital i), and apply any changes I want for the first line. Leaving visual mode esc will apply all changes on the first line to all lines.
Probably not the most efficient on number of key-strokes, but gives you all the freedom you want before leaving visual mode. I don't like it when I have to specify by hand the line and column range in a regex command.
I'd use >}.
Where...
>: Shifts right and
}: means until the end of the paragraph
Hope this helps.
Ctrl + v (to enter in visual mode)
Use the arrow keys to select the lines
Shift + i (takes you to insert mode)
Hit space keys or whatever you want to type in front of the selected lines.
Save the changes (Use :w) and now you will see the changes in all the selected lines.
I would do like Nigu. Another solution is to use :normal:
<S-v> to enter VISUAL-LINE mode
3j or jjj or /D<CR> to select the lines
:norm I<Space><Space>, the correct range ('<,'>) being inserted automatically
:normal is probably a bit overkill for this specific case but sometimes you may want to perform a bunch of complex operations on a range of lines.
You can select the lines in visual mode, and type >. This assumes that you've set your tabs up to insert spaces, e.g.:
setl expandtab
setl shiftwidth=4
setl tabstop=4
(replace 4 with your preference in indentation)
If the lines form a paragraph, >ap in normal mode will shift the whole paragraph above and below the current position.
Let's assume you want to shift a block of code:
setup the count of spaces used by each shift command, :set shiftwidth=1, default is 8.
press Ctrl+v in appropriate place and move cursor up k or down j to select some area.
press > to shift the block and . to repeat the action until desired position (if cursor is missed, turn back with h or b).
Another thing you could try is a macro. If you do not know already, you start a macro with q and select the register to save the macro... so to save your macro in register a you would type qa in normal mode.
At the bottom there should be something that says recording. Now just do your movement as you would like.
So in this case you wanted 2 spaces in front of every line, so with your cursor already at the beginning of the first line, go into insert mode, and hit space twice. Now hit escape to go to normal mode, then down to the next line, then to the beginning of that line, and press q. This ends and saves the macro
(so that it is all in one place, this is the full list of key combinations you would do, where <esc> is when you press the escape key, and <space> is where you hit the space bar: qai<space><space><esc>j0q This saves the macro in register a )
Now to play the macro back you do # followed by the register you saved it in... so in this example #a. Now the second line will also have 2 spaces in front of them.
Macros can also run multiple times, so if I did 3#a the macro would run 3 times, and you would be done with this.
I like using macros for this like this because it is more intuitive to me, because I can do exactly what I want it to do, and just replay it multiple times.
I was looking for similar solution, and use this variation
VG:norm[N]I
N = numbers of spaces to insert.
V=Crtl-V
*** Notice *** put space immediate after I.

Vim: faster way to select blocks of text in visual mode

I have been using vim for quite some time and am aware that selecting blocks of text in visual mode is as simple as SHIFT+V and moving the arrow key up or down line-by-line until I reach the end of the block of text that I want selected.
My question is - is there a faster way in visual mode to select a block of text for example by SHIFT+V followed by specifying the line number in which I want the selection to stop? (via :35 for example, where 35 is the line number I want to select up to - this obviously does not work so my question is to find how if something similar to this can be done...)
In addition to what others have said, you can also expand your selection using pattern searches.
For example, v/foo will select from your current position to the next instance of "foo." If you actually wanted to expand to the next instance of "foo," on line 35, for example, just press n to expand selection to the next instance, and so on.
update
I don't often do it, but I know that some people use marks extensively to make visual selections. For example, if I'm on line 5 and I want to select to line 35, I might press ma to place mark a on line 5, then :35 to move to line 35. Shift + v to enter linewise visual mode, and finally `a to select back to mark a.
G Goto line [count], default last line, on the first
non-blank character linewise. If 'startofline' not
set, keep the same column.
G is a one of jump-motions.
V35G achieves what you want
Vim is a language. To really understand Vim, you have to know the language. Many commands are verbs, and vim also has objects and prepositions.
V100G
V100gg
This means "select the current line up to and including line 100."
Text objects are where a lot of the power is at. They introduce more objects with prepositions.
Vap
This means "select around the current paragraph", that is select the current paragraph and the blank line following it.
V2ap
This means "select around the current paragraph and the next paragraph."
}V-2ap
This means "go to the end of the current paragraph and then visually select it and the preceding paragraph."
Understanding Vim as a language will help you to get the best mileage out of it.
After you have selecting down, then you can combine with other commands:
Vapd
With the above command, you can select around a paragraph and delete it. Change the d to a y to copy or to a c to change or to a p to paste over.
Once you get the hang of how all these commands work together, then you will eventually not need to visually select anything. Instead of visually selecting and then deleting a paragraph, you can just delete the paragraph with the dap command.
v35G will select everything from the cursor up to line 35.
v puts you in select mode, 35 specifies the line number that you want to G go to.
You could also use v} which will select everything up to the beginning of the next paragraph.
For selecting number of lines:
shift+v 9j - select 10 lines
simple just press Shift v line number gg
example: your current line to line 41
Just press Shift v 41 gg
Shift+V n j or Shift+V n k
This selects the current line and the next/previous n lines. I find it very useful.
You can press vi} to select the block surrounded with {} brackets where your cursor is currently located.
It doesn't really matter where you are inside that block (just make sure you are in the outermost one). Also you can change { to anything that has a pair like ) or ].
v%
will select the whole block.
Play with also:
v}, vp, vs, etc.
See help:
:help text-objects
which lists the different ways to select letters, words, sentences, paragraphs, blocks, and so on.
v 35 j
text added for 30 character minimum
Text objects: http://vim.wikia.com/wiki/Creating_new_text_objects
http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objects
You can always just use antecedent numbers to repeat actions:
In visual mode, type 35&downarrow; and the cursor will move down 35 times, selecting the next 35 lines
In normal mode:
delete 35 lines 35dd
paste 35 times 35p
undo 35 changes 35u
etc.
} means move cursor to next paragraph. so, use v} to select entire paragraph.
It could come in handy to know:
In order to select the same ammount of lines for example use 1v
You should have done some modification to be able to use 1v, blockwise or linewise.
Today I saw this amazing tip from here:
:5mark < | 10mark > | normal gvV
:5mark < | 10mark > | normal gv
You can also reset the visual block boundaries doing so:
m< .......... sets the visual mode start point
m> .......... sets the visual mode end point
I use this with fold in indent mode :
v open Visual mode anywhere on the block
zaza toogle it twice
For selecting all in visual:
Type Esc to be sure yor are in normal mode
:0
type ENTER to go to the beginning of file
vG
Presss V to select the current line and enter the line number on keyboard and the press G.

How to fill a line with character x up to column y using Vim

How can I fill the remainder of a line with the specified character up to a certain column using Vim? For example, imagine that the cursor is on column four and I want to fill the remainder of the current line with dashes up to column 80. How would I do that?
You can do 80Ax<Esc>d80| for a simpler solution.
Here's a function to implement what you ask, and slightly more.
It fills the line from its current end of line, rather than the cursor position
It forces a single space between what's currently on the line and the repeated chars
It allows you to specify any string to fill the rest of the line with
It uses vim's textwidth setting to decide how long the line should be
(rather than just assuming 80 chars)
The function is defined as follows:
" fill rest of line with characters
function! FillLine( str )
" set tw to the desired total length
let tw = &textwidth
if tw==0 | let tw = 80 | endif
" strip trailing spaces first
.s/[[:space:]]*$//
" calculate total number of 'str's to insert
let reps = (tw - col("$")) / len(a:str)
" insert them, if there's room, removing trailing spaces (though forcing
" there to be one)
if reps > 0
.s/$/\=(' '.repeat(a:str, reps))/
endif
endfunction
Insert that into your .vimrc, and make a mapping to it, e.g.
map <F12> :call FillLine( '-' )
Then you can press F12 to apply the hyphens to the current line
Note: this could probably be easily extended to act on a selection in VISUAL mode, but currently works for single lines only.*
If I understand the question correctly, this can be accomplished like this: in normal mode subtract the cursor's current column position from the desired ending column, then type the result followed by 'i' to enter insert mode, then the character you want to fill the space with. End by returning to normal mode. For example, with the cursor at column four in normal mode, if you wanted to fill the rest of the line up to column 80 with dashes, type 76i- then Esc or Ctrl-[ to return to normal mode. This should result in 76 dashes starting in column 4 and ending in column 79.
If you have the virtualedit option set to block or all, you can create a visual selection (even over empty space) up to the desired column:
v80| (if virtualedit=all) or
<c-v>80| (if virtualedit=block)
Then replace the selected area with dashes:
r-
It's probably helpful to start visual mode after the last character in the line by hitting l to avoid overwriting the last character in the line. If you are not using virtualedit=all, then you need to set virtualedit+=onemore so you can move one character beyond the end of line in normal mode.
One of the other answers here is: 80Ax<Esc>d80|. I initially started using it as a key mapping like this:
nnoremap <leader>- 80A-<Esc>d80<bar>
...but I didn't like how it leaves the cursor at the end of the line. Also, for narrow windows (e.g. just a little wider than 80 cells), it causes the entire window to scroll horizontally because the cursor briefly jumps to the end of the long line before it's trimmed back to 80. This is partially resolved by returning to the beginning of the line:
nnoremap <leader>- 80A-<Esc>d80<bar>0
...but then the screen will "flash" briefly while the cursor jumps offscreen and back (thus scrolling the window briefly to the right and back). To prevent this, we can temporarily use reverse insert mode (:h revins or :h ri) to keep the cursor onscreen while appending. Here's the full command as a key mapping:
nnoremap <leader>- :set ri<cr>80A-<esc>81<bar>d$0:set nori<cr>
This answer answers your question. Just replace len computation with your desired column number (+/- 1 may be, I never remember), and remove the enclosing double-quotes added by the substitution.
Using the textwidth value is also possible. It allows for different maximum line widths depending on filetype (check :h 'tw'). Here is what I now use, it appends a space after existing line content if present and will prompt for the string to use for the pattern:
function! FillLine() abort
if &textwidth
let l:str = input('FillLine>')
.s/\m\(\S\+\)$/\1 /e " Add space after content (if present).
" Calculate how many repetitions will fit.
let l:lastcol = col('$')-1 " See :h col().
if l:lastcol > 1
let l:numstr = float2nr(floor((&textwidth-l:lastcol)/len(l:str)))
else
let l:numstr = float2nr(floor(&textwidth/len(l:str)))
endif
if l:numstr > 0
.s/\m$/\=(repeat(l:str, l:numstr))/ " Append repeated pattern.
endif
else
echohl WarningMsg
echom "FillLine requires nonzero textwidth setting"
echohl None
endif
endfunction
You can map it for quick access of course. I like:
nnoremap <Leader>' :call FillLine()<Cr>
Note that the calculation assumes simple ASCII characters are being inserted. For more complicated strings, len(l:str) might not work. From :h strlen():
If you want to count the number of multi-byte characters use strchars().
Also see len(), strdisplaywidth() and strwidth().
You can insert first your dashes and then go to the first character and enter your text in replace mode: 80i-Esc0R
if you don't want to type the text, first delete the line with 0D, use 80i-Esc to insert the dashes and 0RCTRL+r " to paste the contents of the unamed register in replace mode.
I actually stumbled across this looking to align columns. Just in case anyone else does the same, this thread might be useful: How to insert spaces up to column X to line up things in columns?

How do I select a chunk of text and paste it to the current cursor position w/o using mouse in vim?

I want to give up using mouse for selecting and pasting chunks of text within a buffer. Whats the most efficient way to do this with just kb? I mean navigate to arbitrary line, copy the substring, return to the previous position and paste.
Very simple method:
Select the lines with Shift-V
"Yank" (=copy) the text with y
Paste the text with p at the position you want to.
There are of course many other ways to copy and paste, yy copies the current line for example.
Do the some VIM tutorials, it is better than learning everything bit by bit.
If you want to go quickly to a line use the search by typing
/SUBSTRING and then Enter after you have found the correct substring.
Make sure to use hlsearch and incsearch
:set incsearch and :set hlsearch
When you are at the correct line, yank the whole line with yy or the whole word with yaw.
Then go back to where you started the search by typing two backticks ``
Then you can paste your yanked line/string with p
Mark your current position by typing ma (you can use any other letter instead of a, this is just a "named position register".
navigate to the line and substring for example by using a / search
yank text with y<movement> or mark it with shift/ctrl-v and then y
move back to your previously marked position with ```a`` (backtick)
paste your buffer with p or P
My normal method would be:
Use visual mode to select the text with v, V, or Ctrl+v
Yank using y
Go to the line you want to be on using 123G or :123
Navigate where I want to be within that line with t or f
Put the text with p or P
If you need to jump back and forth between the spots, I'd cycle through jumps using g, and g;.
Use "p" to paste after the current line, and "P" to paste above the current line.
Not sure what you mean by 'the substring'. If you want to copy line 50 to the current position, use:
:50t.
If you want to move line 50 to the current cursor position, use:
:50m.

Resources