How to add a word at the beginning of multiple lines in vim? - vim

In Vim,
How do i add a word at the beginning of all lines?
Also how do i add it at end?
Eg..
If i have
A
B
C
D
I want to make it to
int A =
int B =
etc..

use visual block mode (Ctrl-v) to select the column you want, and then hit I, type the characters you want, and then hit Esc
So in this case, you'd put your cursor on A, hit Ctrl-v, go down to D, hit I and type int (it'll only appear on the first line while you type it), and then hit Esc at which point it'll apply that insert to all visually selected portions.
This works for anywhere in the document, beginning of line or end of line.
:he v_b_I for more info on Visual Block Insert

You can do this:
:%s/^/at the beginning/
:%s/$/at the end/

:%s/.\+/int & =
+ won't match on empty lines

If you need to copy just the first word, then do:
:%s/^\w\+/int & =/g
If you want to preserve indentation, then do:
:%s/^\(\s*\)\(\w\+\)/\1int \2 =/g

A global substitute should do i:
:%s/.\+/int & =/
This is how it works: in the second part of the substitution (ie in the int & =) the ampersand is replaced with what machted in the first part (the .*). Since .* matches the entire line, each line is subsituted as wanted.
If you have empty lines (in which you don't want to have any replacements), you could go with a
:%s/^\S\+$/int & =/

Related

In Vim, paste over text between two parenthesis?

Something that I find myself doing often is yanking the text between two parenthesis and pasting that over another pair of parenthesis. For example:
foo(int a, int b, int c)
bar(int d, int e)
becomes
foo(int a, int b, int c)
bar(int a, int b, int c)
Is there a quick way in Vim to yank the text from foo and paste it over the text in bar?
Yank the content of the first pair of parentheses:
yib
Visually select the content of the second pair of parentheses and put:
vibp
One way would be yi) inside foo's arguments and "_di)P within bar's arguments.
yi) yanks the text inside the parentheses
"_di)P uses the null register to delete the text inside the parentheses and pastes the text, vi)p also works and avoids the null register
The only thing changing is the function name though, so you could also just yank the line and use cw (change word) to change foo to bar.
Cursor over the first paren of foo, then use y% to yank all the text until the matching paren. (You can also use v%y if you prefer to visually see the text you're yanking.)
Then cursor over the first paren of bar, then use v%p. It selects the text up until the matching paren then pastes over it.
Use this to go to last parenthesis shift + 5.
Press 5 twice for the first parentheses.
I use vim-scripts/ReplaceWithRegister.
Copy as usual with
yi(
Paste with gri(

Quickest way to switch order of comma-sparated list in Vim

Supose I have a function such as
myfunc(arg1 = whatever, arg2 = different)
I would like to transform it to
myfunc(arg2 = different, arg1 = whatever)
What is the quickest command sequence to achieve this? suppose the cursor is on the first "m". My best attempt is fadt,lpldt)%p.
There is a vim plugin: vim-exchange
visual select arg1 = whatever
press Shiftx
visual select arg2 = different
press Shiftx
I would recommend you change it a bit so it will work from wherever the cursor is and so that it will work on any arguments:
0f(ldt,lpldt)%p
All I changed from your method was I added 0 to move the cursor to the beginning and I changed fa to f(l so that it will work regardless of argument name.
Now you can either put this into a macro, or, if you use it a lot, you can make it a mapping:
nnoremap <C-k> 0f(ldt,lpldt)%p
I arbitrarily chose Ctrl-k here put you can use whatever you like.
I wrote a plugin for manipulating function arguments called Argumentative. With it you just execute >, and the argument your cursor is on will shift to the right. It also provides argument text object in the form of i, and a,.
With pure vim, with your cursor at the start of the line:
%3dB%pldt,lp
This is the quickest I could think of on the spot (12 strokes).
This should work for all names as long as there is always a space around the equal signs.
% " Jump to closing brace
3dB " Delete to the beginning of 3 WORDS, backwards
% " Jump to the beginning brace
p " Paste the deleted text from the default register
l " Move right one character
dt, " Delete until the next comma
l " Move right one character
p " paste the deleted text from the default register
You could also turn this into a Macro to use at any time.

Vim - delete until (inclusive) character in multiple lines

I have this code:
def foo(c: Char) = c match {
case 'a': 'B'
}
My cursor is on the space after =. I want to delete everything until, including, the }. How can I do that?
Can I do the same where the cursor is anywhere on the first line? Anywhere in the block (and place the cursor after the =)?
d/}/e
does the job.
d/} deletes until the } but adding the /e flag moves the cursor on the last char of the match, effectively deleting everything between the cursor and the }, inclusive.
Using visual selection works too, in a slightly more intuitive way:
v/}<CR>d
Try with this: d%.
The d is for delete and the % moves between braces.
This should work:
d}
This deletes one paragraph forward.
You can achieve something like this with the EasyMotion plugin.

How can I quickly add something to a few lines in vim?

I'm trying to get away from my arrow use but there is one thing I've yet to solve without using the arrow keys. Take this example:
var1 = "1"
var2 = "2"
var3 = "3"
var4 = "4"
Now I want this to be:
var_1 = "1"
var_2 = "2"
var_3 = "3"
var_4 = "4"
Using arrows I would just goto the var1, insert and add the underscore and then arrow down and do the same thing. The problem with using hjkl is I can't be in insert mode so I have to esc out, move down, insert...rinse repeat which required more work. Is there another way to accomplish this?
You can also use a visual block insert:
go to the "1" in "var1"
press CTRL+V
go down with j to select all the rows you wish to affect
I (that's capital i)
_
<ESC>
The underscore should now be inserted at the correct place in all the rows selected (for some reason it takes a second for it to happen on my machine)
There are many ways to do this. Using movement commands for example:
1G0 → Go to the start of the first line
f1 → go to the first occurence of "1"
i_<ESC> → insert "_" and go back to normal mode
j. → go down a line and repeat the insert command
j. → go down a line and repeat the insert command
...
Or, better yet, use an "ex" command:
:%s/var/var_/
Or even with the visual block command, as johusman notes.
Assuming you're at line 1, character 1...
Using a macro:
qqfra_<Esc>+q3#q
q Record macro
q Into register q
f find
r 'r'
a append
_ underscore
Esc Normal mode
+ Start of next line
3 Three times
# Play macro
q from register q
Par 11.
Or (better) using substitute:
:%s!r!&_<CR>
Par 9!
[Sorry... too much VimGolf!]
I tend to prefer :substitute over the visual block mode.
%s/var\zs\ze\d/_/
I always have line numbers turned on, so I'd do e.g.
1,4 s/var/var_/
This is similar to the
% s/var/var_/
answer, but it only functions on the named lines. You can use visual mode to mark the lines, if you don't like typing the range (the 1,4 prefix) in your command.

Vim: creating a C string literal around a block of text with vertically aligned quotes?

I would like to create a macro or a script in Vim that does the following:
wrap a block of text in double quotes
escaping any quotes that appear in the text itself
have the quotes on the right side in vertical alignment
For example:
<html>
<head></head>
<body>
<h1>High Score Server</h1>
<table>
ROWS
</table>
</body>
</html>
would become:
"<html> "
"<head></head> "
"<body> "
"<h1>High Score Server</h1>"
"<table> "
"ROWS "
"</table> "
"</body> "
"</html> ";
I am able to achieve this with a macro, but without the vertical alignment of the quotes on the right side. Can anyone help me with this one?
What I'd do :
With "surround" and "Align" plugins :
1) with cursor on first line (0,0), type <C-V>)$s"
2) then <S-V>):Align " and <Enter>.
Another solution without plugins :
1) set virtual mode
:set ve=all
2) <C-V> to go in block-wise selection, with cursor at the position 0,0
3) go down to the bottom of the text, then Shift-I, type " and Esc. This should prepend the quotes.
4) now go on the left end (since ve=all, you can go where there is no text)
5) <C-V>, go down to bottom, type r"
This is long to explain, but easy to do and reproduce. Also useful in lots of case.
function Enquote()
let [startline, endline]=sort([line("'<"), line("'>")])
let lines=getline(startline, endline)
let lengths=map(copy(lines), 'len(split(v:val, ''\zs''))')
let maxlen=max(lengths)
call map(lines, '''"''.v:val.repeat(" ", maxlen-lengths[v:key]).''"''')
return setline(startline, lines)
endfunction
Explanation:
line("'<") and line("'>") get the line numbers of start and end of last visual selection.
sort([...]) sorts this line numbers since you may have started selecting lines from the end of the selection.
let [a, b]=[c, d] is a parallel assignment: sort will produce a sorted list of two items, where first item is lesser or equal to second item. Obviously, lesser is a first selected line.
len(split(v:val, '\zs')) is an advanced strlen() which supports unicode.
max(list) finds a maximum value. Obvious.
So, map(copy(lines), 'len(split(v:val, ''\zs''))') applies this strlen to all items in list. copy() is required since we do not want our list to be modified.
map(lines, '''"''.v:val.repeat(" ", maxlen-lengths[v:key]).''"''') modifies an lines in a way you require. I switched from printf to repeat because printf does not handle multibyte characters correctly (by «correctly» I mean that «¥» is one character long, while printf considers it two bytes long).
setlines(linenumber, listoflines) actually modifies buffer.
Making use of the unix program "par" to do this may well solve your problem. There's a Vimcast showing how to integrate it into vim over at http://vimcasts.org/episodes/formatting-text-with-par/
Is it possible to make two passes over the list of lines in vim script? Then you can do something like this (pseudocode):
let N = length of longest line
for each line L:
insert a " character at the beginning
append N - len(L) spaces
append a " character
best i got is a 3-pass regex.
select block in visual mode, then use:
:'<,'>s#^#"#
:'<,'>s#$# #
:'<,'>s#\(.\{28\}\).*#\1"
with the 28 being the length of your longest line.
By all means heed the previous answers and get your vim-fu in shape. Or install/modify/poke-the-author of this plugin:
http://www.vim.org/scripts/script.php?script_id=4727
From the plugin's page:
This script converts multi-line text in a C++ file to a multi-line
string literal, escaping the quote and tab characters. It also does
the reverse conversion, un-escaping some characters. It's not too
complete for now, but it will be someday if needs come.
If you need to make changes use the source-code repository:
https://bitbucket.org/dsign/stringliteral.vim
In two passes:
let l = max(map(getline("'<", "'>"), 'strwidth(v:val)'))
'<,'>s/.*/\=('"'.submatch(0).repeat(' ', l-strwidth(submatch(0)) )).'"'

Resources