vim: delete all blank space until next non-blank character - vim

Say I have the following code:
<p>
Hello
</p>
And I want to make it
<p>Hello</p>
I would like to put the cursor in normal mode at the end of line 1, so on the ' > ' and have a command to delete all spaces until the next character. The closest I can think of is the motion
d/Hello
which deletes everything until Hello but the issue is that it deletes also the character under the cursor (the ' > ') so I end up with
<pHello
</p>
How would you do that?

One way when you won't need to repeat this action many times.
JxJx
Explanation:
J # Join current line with next one but substitute end of line with a space.
x # Remove the space.
Jx # Repeat same process for last line.

There's a tag text-object in vim:
put cursor within tag, press vat to select entire tag
press :, it becomes :'<,'>
type j, it becomes :'<,'>j
press Enter to join lines
:help v_at
at "a tag block", select [count] tag blocks, from the
[count]'th unmatched "<aaa>" backwards to the matching
"</aaa>", including the "<aaa>" and "</aaa>".
See |tag-blocks| about the details.
When used in Visual mode it is made characterwise.

When standing anywhere in the second line (the one that says Hello), press the following keys: ^d0vatgJ. Simply explained:
^ will go to the first non-whitespace character, H
d0 will delete to the beginning of the line
vat will select the entire tag
gJ will join all the lines without inserting spaces
If you start on the H, you can skip the ^ part.

Related

How can I paste to next line and enter insert mode on current line?

I'm brand new to vim. A common pattern I am dealing with looks like this
myFunction :: some code
myFunction = some more code
how could I create a command where after executing I look like this
myFunction
myFunction
and am in insert mode with my cursor on the end of the first 'myFunction' ?
If you are copying the first line to the down then maybe try yy for yanking the whole (first) line, P for pasting the line before the cursor and A to go in insert mode at the end of first line.
And you can use :map to do whole thing at one. Like :map 'l yyPA
I have found an almost perfect solution "using ultisnips plugin", the only thing missing is the cursor position. I am considering an already typed text:
You must select the target lines (use vip in normal mode) and use your defined trigger on ultisnips
snippet trigger "Description" w
`!p
import re
snip.rv = re.sub("(^\w+).*", r"\1", snip.v.text, flags=re.MULTILINE)
`
endsnippet

Sublime Text 3: How to do multi-line selection that excludes blank lines?

I have some scripts in Stata written as follows:
* 1. count of firms in each bin
grouplabs Inear_dist_km_0_10 Inear_dist_km_10_30 Inear_dist_km_30_60 Inear_dist_km_60_100 Inear_dist_km_100_150 Inear_dist_km_morethan150, groupvar(Inear_dist_km_gr) emptylabel(empty)
graph hbar (count) if Inear_dist_km_gr !=1, over(Inear_dist_km_gr) name(n1)
* 2. count of firms in each bin (bigger bins)
grouplabs Inear_dist_km_0_20_v2 Inear_dist_km_20_40_v2 Inear_dist_km_40_60_v2 Inear_dist_km_morethan60_v2, groupvar(Inear_dist_km_v2_gr) emptylabel(empty)
graph hbar (count) if Inear_dist_km_v2_gr !=1, over(Inear_dist_km_v2_gr) name(n2)
* 3. GGK firm level bins
grouplabs Inear_dist_km_GGK_0_10 Inear_dist_km_GGK_10_50 Inear_dist_km_GGK_morethan50, groupvar(Inear_dist_km_GGK_gr) emptylabel(empty)
graph hbar (count) if Inear_dist_km_GGK_gr !=1, over(Inear_dist_km_GGK_gr) name(n3)
I need to add the character ; at the end of each line, but not in the blank lines between each script. I have tried the Split into Lines trick to get multiple cursors at the end of each line, but the selection also includes the empty lines in between. This results in
* 1. count of firms in each bin;
grouplabs Inear_dist_km_0_10 Inear_dist_km_10_30 Inear_dist_km_30_60 Inear_dist_km_60_100 Inear_dist_km_100_150 Inear_dist_km_morethan150, groupvar(Inear_dist_km_gr) emptylabel(empty);
graph hbar (count) if Inear_dist_km_gr !=1, over(Inear_dist_km_gr) name(n1);
;
* 2. count of firms in each bin (bigger bins);
grouplabs Inear_dist_km_0_20_v2 Inear_dist_km_20_40_v2 Inear_dist_km_40_60_v2 Inear_dist_km_morethan60_v2, groupvar(Inear_dist_km_v2_gr) emptylabel(empty);
graph hbar (count) if Inear_dist_km_v2_gr !=1, over(Inear_dist_km_v2_gr) name(n2);
;
* 3. GGK firm level bins;
grouplabs Inear_dist_km_GGK_0_10 Inear_dist_km_GGK_10_50 Inear_dist_km_GGK_morethan50, groupvar(Inear_dist_km_GGK_gr) emptylabel(empty);
graph hbar (count) if Inear_dist_km_GGK_gr !=1, over(Inear_dist_km_GGK_gr) name(n3);
How can I exclude the empty lines from the selection so that only lines with characters in it will have ; at the end? I appreciate your help.
If you're sure that your blank lines are really blank and not filled with whitespace characters use regex substitution by pressing ctrl+H, search for (?<!^)$ and replace with ;.
The regex says: find an end of line ($) not directly after ((?<!…)) the beginning (^).
Else search for (?<=\S)$ but make sure you don't havy any trailing spaces or tabs.
How to 'make sure': find them with [^\S\n]+$ and delete.
The first regex says: find an end of line directly after ((?<=…)) a non-whitespace character, including linebreak.
The second regex says: find a sequence (…+) of characters that are not any of ([^…]) non-whitespace characters or linebreak -- i.e. a sequence of whitespace characters excluding the linebreak -- and then the end of line.
The most visual and friendly way might be to
find your blank lines with ctrl+F, search for ^\s*$,
select all with alt+enter,
menu > Selection > Invert Selection (now you've highlighted inly the non-blank lines),
go on with the original Split into Lines trick.

vim how to paste multiple lines insert into another multiple lines?

For example, copy multiple lines A:
'fjalkfjljfllfs'
'dasldkjlasdjla'
'jlfajldjaflajl'
they are random string with same length.
I have multiple lines text B and want to insert A into B's same position (not begin or end):
'xxxx fjalkfjljfllfs xxxxx'
'xxxx dasldkjlasdjla xxxxx'
'xxxx jlfajldjaflajl xxxxx'
in vim, is there a way to do this?
If you mark you lines A via blockwise visual mode (ctrl + V) and copy them with y you can just put them back with p.

Append to top and bottom of selected text in vim

So I have the following text (==== delimiters denotes selected text):
This is some text
I'm not interested in.
This is indented text
not important.
=====================
This text portion is
selected.
=====================
Also not important
indented text
Other text i'm not
interested in.
Now I want to create a vim function so that when called, it appends at the top and at the bottom some default text. For example I would like to end with:
This is some text
I'm not interested in.
This is indented text
not important.
THIS TEXT WAS APPENDED
AFTER FUNCTION CALL
This text portion is
selected.
THIS OTHER TEXT WAS
APPENDED AFTER THE SAME
FUNCTION CALL
Also not important
indented text
Other text i'm not
interested in.
Please note that indentation should be preserved (thanks benjifisher)
How can I do this?
This is a little sloppy, but it works:
function! Frame() range
'<put!=\"THIS OTHER TEXT WAS\nAPPENDED AFTER\nFUNCTION CALL\"
'>put=\"THIS OTHER TEXT WAS\nAPPENDED AFTER THE SAME\nFUNCTION CALL\"
endfun
Select your lines in Visual mode, and type
:'<,'>call Frame()
(The range '<,'> is inserted automatically.) There are some advantages to using :execute with a:firstline and a:lastlineas in :help function-range-example, instead of the Visual marks '< and '>, but that gets a little complicated. You could also prefix each command with :silent if you do not care to be told that 3 lines have been added (twice).
Here is a version that copies the indentation from the first and last selected lines, as requested in the updated question. This version uses :call append() instead of :put, which makes it more convenient to use a:firstline and a:lastline; possibly, this will be useful if you ever want to call the function with a range other than the Visual one.
" Add lines at the bottom before adding at the top, since the line numbers
" will change when you add lines.
function! Frame() range
" Define a list of lines and prepend the desired indentation.
let botlines = ['THIS OTHER TEXT WAS', 'APPENDED AFTER THE SAME', 'FUNCTION CALL']
let botspaces = matchstr(getline(a:lastline), '\s*')
let lines = []
for line in botlines
call add(lines, botspaces . line)
endfor
" Now add those lines at the bottom.
call append(a:lastline, lines)
" Now do the same thing at the top.
let toplines = ['THIS OTHER TEXT WAS', 'APPENDED AFTER', 'FUNCTION CALL']
let topspaces = matchstr(getline(a:firstline), '\s*')
let lines = []
for line in toplines
call add(lines, topspaces . line)
endfor
call append(a:firstline - 1, lines)
endfun

Remove new lines inside a div using vim

I have some data like this
<div>
This
is
some text
</div>
and i want to end up with this
<div>
This is some text
</div>
I know I can search and replace for \n, but I want to limit that search for only the lines inside the <div> tag.
I have a very long HTML file with thousands of Divs, no class or ID.
How can I do this with Vim?
Move your cursor into the <div> block, try this:
vitojJ
To join all non-overlapped <div> blocks, try this:
:g/<div>/+1,/<\/div>/-1 join
Start recording a macro (in register d) with qd
Search for an opening DIV tag with /<div (then press return)
Use visual mode to select everything inside the DIV with vit
Change the visual selection so that it doesn't include the line with the opening tag with oj
Join the lines with J
Stop recording with q
Now you can play back the macro as many times as you need to with #d (or, for a fixed number of repetitions you can prefix it with a number, e.g. 20#d)
(This solution assumes that, as in your example, the open and close tags are always on their own lines. Also, if there is only one line of content in the DIV then the closing tag will end up on the same line as the content.)
You can do one of these:
Select the tree lines with V, and use J to put them in the same line.
Put the cursor on the second line and use 3J.
Put your cursor on the second line, and do J two times.
If you are on "This", VjjJ (select whole lines, down twice, join rows with ' ' as separator.)
--
If you want the end result to be <div>This is some text</div>: place cursor anywhere in tag and do vatJ (visual mode, select inclusive, select tag, join rows.)
:g/<div>/norm! jVjjJ
:................... command
g................... global
/<div> ............. search for <div>
norm! .............. in normal mode
j................... down one line 'j',
V .................. visual by line 'V'
jj ................. down more two lines
J .................. upper 'J' join lines
For variable number of lines try
:g/<div>/norm! jV/\/div^MkJ
:............. command
g ............ global
/<div> ....... search div
norm! ....... execute in normal mode
j ............ down one line
V ............ start visual mode
/\/div ....... search div close
^M ........... type <ctrl-v> in linux or <ctrl-k> on windows, after that <enter>
k ............ up one line
J ............ joine all selected lines
On linux to insert <Enter> press <ctrl-v><enter>
On windows try <ctrl-k><enter>

Resources