On a single line I am looking to turn this:
"".format(...)
into this:
"{0}, {1}, {2}, ..... {n}".format(...)
where n is the number of elements I wish to repeate. Without the need to manually insert each argument.
I don't know if this way is ok for you:
"I(cursor here)
".format(...)
execute command:
:r! seq -s, -f "{\%g}" 0 20
then join (J) the 3 lines. 20 is n in your case.
or "I".format(...)
to insert mode, ctrl-R then type =system("seq -s, -f '{%g}' 0 20")
With the cursor between the empty double quotes, I would do (for n = 5):
i<C-R>=join(map(range(5), 'printf("{%d}", v:val)'), ', ')<CR>
Some vimgolf enthusiasts can probably condense this further. But I would probably either write a mapping for it (if the need occurs so frequently), or do it manually like this:
5i{0}, <Esc>^f0;<C-A>;2<C-A>;3<C-A>;4<C-A>
I would use a macro, like:
0a{0}, <esc>lqqyF{f"PB<C-a>;q
Then just use whatever n-1 is with #q. E.g. 4#qXX would give:
"{0}, {1}, {2}, {3}, {4}, {5}".format(...)
There is no "seq" command in Windows, so I prefer this:
:call append(".", map(range(6), '"{".v:val."},"'))
and then join these lines use '6J'.
Related
Say I have the following python array literal:
def f():
arr = [
1,
2,
3
]
I want to delete everything in the brackets so that it becomes this:
def f():
arr = []
How can I do that with minimal commands in vim?
These are some of my attempts:
Using di] will delete the text, but not the empty newlines, leaving a lot of whitespace I'd have to delete:
def f():
arr = [
]
Using da] will delete the newlines, but also the brackets:
def f():
arr =
You can simply do:
ca[[]<Esc>
or:
ca][]<Esc>
See :help text-objects.
With your cursor on the first opening bracket ([), press V, followed by %. This will select the block which you then can join J, followed by di[.
Select the lines in visual mode (v) and use J to remove newlines. Then use di[.
Or if there are many lines, di[ first, after which you move the cursor to top line and then J. This will potentially leave a space between the brackets which has to be removed with x.
I find using a code formatter shortcut saves a lot of time
If you install vim prettier, you could do di[ <leader>p
Using the formatter in JS for example means I don't have to remove extra spacing, jump to end of line to insert ;, or fix indenting etc
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.
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.
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)) )).'"'
I have 2 methods in a source file:
def Foo
puts "hello"
puts "bar"
end
def Bar
puts "hello"
puts "bar"
end
I would like to swap the order of the methods, so Bar is first.
Assuming the cursor is on the d in def Foo, the simple way is to:
shift v -> jjjj -> d -> jjj -> p -> O -> esc
But that feels a little long winded and does not account well for arbitrarily long methods:
What is the most efficient way to do this in Vim, keystroke wise?
EDIT
Keep in mind, I would like the solution to account for a situation where the methods are in a context of a big class, so G is probably best avoided
Assuming the cursor is somewhere in the first method, press dap}p and they should be swapped.
What dap does is simply "delete a paragraph". Try :help object-select to learn other way of deleting/selecting text objects in VIM.
EDIT: Replaced G with } in the command.
Similar to Spatz's
d}}p
delete to the next blank line (below Foo), skip to the next blank line (below Bar), paste.
Found another method ( from godlygeek on #vim ):
with:
def function():
first
first
first
def lol():
second
second
second
From line 1, count up until the 'def lol', which is 5. Then:
:1,5m$
A couple of ways off the top of my head. You could say
5dd/end[enter key]pO
Deletes five lines, searches for end, places the lines underneath, adds a space.
If you have VimRuby installed, I believe you can use % to jump between def and end. In that case, you could say
v%x5jpO
Edit: I defer to spatz on this :P
From line 1, 5ddGp , or 5dd:5p is the most concise/shortest I can think of.
personally, I would go '4dd' then down under bar and press 'p', but I'm not a vim guru