vim macro replacing \n with ',' - vim

I am trying to save a macro which replaces \n with ,
Input:
978818
978818
900298
900272
Output:
'978818','978818','900298','900272'
When I saved the macro using CTRL+R CTRL+R,B in vimrc it looks like below:
let #b = ":%s/\n/','/g^MI'^[A~#kb~#kb^["
But now when I run this macro it give the output as:
978818978818900298900272
and error:
E486: Pattern not found: ','
Don't know why it is trying to match ,

You probably need to escape the \n. vim thinks you want a new line character at that point in the string and replaces it with a literal new line. So the fixed macro should be.
let #b = ":%s/\\n/','/g^MI'^[A~#kb~#kb^["
Edit: If you want something that you can copy and paste-able I believe the macro below is equivalent to what you want.
let #b = ":%s/\\n/','/g\nI'\e$xx"

Related

Vim delete parent parenthesis and reindent child

I'm trying to go from here:
const f = function() {
if (exists) { // delete this
const a = 'apple'
}
}
to:
const f = function() {
const a = 'apple'
}
What's the fastest way to delete and reindent everything in between?
Assuming that cursor is inside the braces; any number of lines and nested operators; "else"-branch is not supported:
[{"_dd<]}']"_dd
Explanation:
[{ go to previous unmatched brace
"_dd delete the "{"-line (now the cursor is in the first line of the block)
<]} decrease identation until the next unmatched "}"
'] go to the last changed line (i.e. "}"-line)
"_dd and delete it
If the cursor is initially set on the "{"-line and you don't care for 1-9 registers, the command can be simplified to dd<]}']dd
Assuming your cursor is somewhere on the line containing const a
?{^M%dd^Odd== (where ^M is you hitting the Enter key and ^O is you hitting Ctrl+O).
Broken down this is:
?{^M - search backwards/upwards for the opening brace
% - jump to the corresponding brace (closing brace)
dd - delete the current line
^O - jump to previous location (the opening brace)
dd - delete the line
== - indent current line
You don't need a special macro or function or anything to do this since vim gives you all the powerful text manipulation tools to do the task. If you find yourself doing this an awful lot then you could always map it to a key combination if you want.
The above only works for single lines inside curly braces, but the one below will work for multiple lines (again assuming you are on some line inside the curly braces)
<i{0f{%dd^Odd I'll leave you to figure out how this one works. Type the command slowly and see what happens.
Great answers all around, and, as pointed out, you can always map these keys to a shortcut. If you'd like to try a slightly more generic solution, you could check my "deleft" plugin: https://github.com/AndrewRadev/deleft.vim

insert n characters before pattern

I have a text file where I want to insert 20 spaces before the string 'LABEL'. I'd like to do this in vim.
I was hoping something like s/LABEL/ {20}LABEL/ would work. It doesn't.
This SO question is close to what I want to do, but I can't put 'LABEL' after the '=repeat()'. Vim regex replace with n characters
%s/LABEL/\=repeat(' ',20)/g works.
%s/LABEL/\=repeat(' ',20)LABEL/g gives me E15: Invalid expression: repeat(' ',20)LABEL
How do I get vim to evaluate =repeat() but not =repeat()LABEL?
After \=, a string is expect. And LABEL isn't a valid string
%s/LABEL/\=repeat(' ',20).'LABEL'/g
BTW thanks to \ze, you don't need to repeat what is searched.
%s/\zeLABEL/\=repeat(' ',20)/g
Note that if you need to align various stuff, you could use printf() instead
%s#label1\|other label#\=printf('%20s', submatch(0))#

Position cursor when asking a user for input in Vim?

I'm writing a custom function in Vim which asks the user what they would like to rename the current file to:
let b:newname = input('Rename to: ', expand('%'))
It prepopulates the input field with the filename such as ExampleFile.php. However I would like to position the cursor just before the . as more often than not, users will be renaming the file as opposed to the extension.
However, I cannot figure out a way to move the cursor. Even <Left><Left><Left> would suffice if I could get it to work
You can insert special keys in a double quote string with \<xxx>. Check the help for expr-quote. So just concatenate that to your string:
let b:newname = input('Rename to: ', expand('%') . "\<left>\<left>\<left>\<left>")

How to find and replace the first line word with vim

I have a file like this:
foo
bar
And I'm trying to get something like:
foo: foo,
bar: bar,
I've tried :%s/^\w/\0: \0,/g where ^\w matches the first word in line but I'm getting
f: f,foo
b: b,bar
Someone can explain to me what I'm doing wrong?
You are missing two characters (\+) which extend the match to the entire word, because \w only matches one character of a word and not the whole word.
The following should do what you want.
%s/^\w\+/\0: \0,/g
Instead of replacing you could (globally) copy, paste and append:
:g/\v^.+$/normal! yEPa: ^[A,
(where ^[ is escape, entered as <c-v><esc>)
or use (lower-case) e if that is the kind of "word" you want

Substituting everything from = to end of the line in VIM

Let's say I have several lines like:
$repeat_on = $_REQUEST['repeat_on'];
$opt_days = $_REQUEST['opt_day'];
$opt_days = explode(",", $opt_days);
... and so on.
Let's say I use visual mode to select all the lines: how can I replace everything from = to the end of the line so it looks like:
$repeat_on = NULL;
$opt_days = NULL;
$opt_days = NULL;
With the block selected, use this substitute:
s/=.*$/= NULL;
The substitution regex changes each line by replacing anything between = and the end of the line, including the =, with = NULL;.
The first part of the command is the regex matching what is to be replaced: =.*$.
The = is taken literally.
The dot . means any character.
So .* means: 0 or more of any character.
This is terminated by $ for end of line, but this actually isn't necessary here: try it also without the $.
So the regex will match the region after the first = in each line, and replace that region with the replacement, which is = NULL;. We need to include the = in the replacement to add it back, since it's part of the match to be replaced.
When you have a block selected, and you hit : to enter a command, the command line will be automatically prefixed with a range for the visual selection that looks like this:
:'<,'>
Continue typing the command above, and your command-line will be:
:'<,'>s/=.*$/= NULL;
Which will apply the replacement to the selected visual block.
If you'll need to have multiple replacements on a single line, you'll need to add the g flag:
:'<,'>s/=.*$/= NULL;/g
Some alternatives:
Visual Block (fast)
On the first line/character do... Wl<C-v>jjCNULL;<Esc>bi<Space><Esc>
Macro (faster)
On the first line/character do... qqWllCNULL;<esc>+q2#q
:norm (fastest)
On the first line do... 3:no<S-tab> WllCNULL;<Enter>
Or if you've visually selected the lines leave the 3 off the beginning.

Resources