How to select multiple lines until a determinate character? - vim

I would like to select multiple line until a determinate character, like in the image below where the special character is for this example is =.
I've tried with VIM ctrl+v/ but doesn't work.This is the example:
global Tint=spettro.readlines()[3].split(",")[1]
global Average=spettro.readlines()[4].split(",")[1]
global Sensor_Mode=spettro.readlines()[6].split(",")[1]
global Case_Temperature=spettro.readlines()[7].split(",")[1]
global Sensor_Temperature=spettro.readlines()[8].split(",")[1]

You can't in Vim. There's blockwise visual selection (via <C-V>), but this is restricted to rectangular blocks, expect for a selection (with $) that goes to the end of all covered lines, where a "jagged right edge" is possible.
Since selection in itself is of little value, you probably want to do something with it. There are alternatives, e.g. :substitute or :global commands with a pattern that selects up to the first =: /^[^=]*/
To yank the text, I'd use this (there are different approaches, too; note that you need to adapt the range inside the getline()):
:let ## = join(map(getline(1, '$'), 'matchstr(v:val,"^[^=]*")'), "\n")

Try the vim-multiple-cursors plug-in.
Then, to select in those three lines:
/=<cr> go to the first '='
<c-n> start multiple cursors mode
<c-n> create a new cursor and jump to the second '='
<c-n> create a new cursor and jump to the third '='
ho0 select everything before the '='
Deleting and changing the selection seems to work fine. I do not know whether or not yanking is possible, too.

https://github.com/magnars/multiple-cursors.el
I haven't played with it much, but it can probably do what you want. Look at the video.
You can probably achieve your end goal with regex replacement (and maybe a keyboard macro), but you haven't stated what the end goal is. It's generally better to ask how to change one chunk of code into another, and not assume some technique (e.g. multiple selections).

Related

Vim: recognize character sequences as part of "whole word"

This has been bugging me for a while: I'm writing code that uses verilog-auto which means I'm editing in a verilog file with perl snippets injected into comment sections. One very useful thing that I like to do in Vim is to search for the whole word under the cursor with * and #. However, with perl syntax that contains variable names such as ${w} and $w, these shortcuts don't work.
I don't want to add $, { and } to my "keywords" list as there are many instances where I don't want these to count as part of a whole word. For instance, in verilog concatenation: {sig1,sig2[1:0]}, I wouldn't want {sig1 to be searched for as a whole word.
Is there a way to get "whole word" to recognize sequences via a regex or something? So only ${[a-z]+} or $[a-z]+ gets recognized as "keywords".
Either that or a separate keyboard shortcut that can let me search for the pattern under the cursor.
Here's a really ugly hack, but it works:
nnoremap * viW:s/\%V\$*{*\a*}*/\=setreg('a', submatch(0))/n<cr>/<C-r>a<cr>n
nnoremap # viW:s/\%V\$*{*\a*}*/\=setreg('a', submatch(0))/n<cr>/<C-r>a<cr>N
The only downside is that this will overwrite your last visual selection, so if you use gv a lot, this isn't the best solution. It also overwrites the a register, although you could pick a different one if you want.

vim: replace block

Let's say I have this text:
something "something else"
something here "just another quoted block"
I want to substitute "something else" with "just another quoted block", so I do:
/quot<enter> (to jump to second quoted block searching for the string "quot")
yi" (to yank inner text for current quoted block)
?else<enter> (to jump back to the first quoted block wich contains "else")
vi" (to visually select the quoted block)
p (to paste yanked text)
This works, but I would like to know if the two last steps can be replaced by a single one, to avoid visual mode. I know it's not a huge gain keystroke-wise, but I think that the Vim philosophy would encourage what I'm trying to do, and every time I do this my mind keeps asking for this command. :-P
What I tried so far:
r (replace) replaces just one character
c (change) throws me into Insert mode and does not let me paste the text.
"_di"P
Delete inside quotes to the blackhole register; paste last yanked before cursor.
Or
ci"<Ctrl-R>0<ESC>
Change inside quotes to retrieve last yank; leave insert mode.
With my ReplaceWithRegister plugin, the last two steps would be gri". It also offers grr (replace current / [count] lines); though it only saves a little typing, I find this indispensable.
Key stroke wise, j$yi"k then vi"p is actually probably the fastest. However, if you absolutely must go into insert mode you can j$yi"k then "_ci"<C-r>" or ci"<C-r>0. The :help i_CTRL-R operator allows you to put the contents of a register into insert mode.
I usually try to keep it simple, using what I feel is more intuitive with every day commands:
j
yi"
k
ci"
<ESC>
p

Remove command with matching braces

I'm using (mac)vim with tex-suite and would like to have a single regex command (or any other way) to do the following thing:
Change
\textcolor{green}{some random text}
into
some random text
This should be done for all occurrences of \textcolor{green}{} in my tex file...
Any idea?
EDIT: I need it to recognize matching braces. Here an example :
\textcolor{green}{
with $v_\text{F}\sim10^6$m.s$^{-1}$ the massless Dirac fermions
velocity in pristine graphene}.
In my experience, things like this most often crop up during editing, and you might have the search for \textcolor{green}{ already highlighted.
In such a scenario, :global is usually my weapon of choice:
:g//norm d%diBvaBp
diBvaBp: diB (delete inner block), vaB (select block), p (put)
If you have surround.vim installed (recommend it!) you could remove the pair of braces simply doing dsB (delete surrounding {})
:g//norm d%dsB
Of course, you can combine it like
:g/\\textcolor{green}{/norm d%dsB
I just noted a potential issue when the target patterns don't start at the beginning of a line. The simplest way to get around that is
:g//norm nNd%diBvaBp
A more involved way (possibly less efficient) would be using a macro:
/\\textcolor{green}{
gg
qqd%diBvaBpnq
Followed by something like 100#q to repeat the macro
:%s,\\textcolor{green}{\([^}]\+\)},\1,g
Updated as per your updated question:
:%s,\\textcolor{green},\r-HUUHAA-&,g
:g/\\textcolor{green}/normal 0f\df}lvi{xhP$xx
:%s/\n-HUUHAA-//
Quick explanation of how it works:
Put all \textcolor{green} lines onto a line of their own, with 'special' marker -HUUHAA-
Use visual selection vi{ to select everything in between the {}, paste it outside and delete the now empty {}.
Delete leftover stuff including the marker.

Command to surround a character with spaces in vim

I am trying to use vim properly - to aid me I've mapped my arrow keys to "" so that I am forced to use {hjlk} to move around.
This is causing me a problem when I want to just surround a character with spaces, eg:
"2+3" is better formatted "2 + 3"
Previously I would have put my cursor over the + and typed:
i[space][arrow-right][space][Esc]
That's 5 presses.
To do this without the arrow I seem to need to put the cursor over the + and go:
i[space][Esc]lli[space][Esc]
That's 8 presses.
I can convert the "li" into an "a" which reduces it to 7 presses:
i[space][Esc]la[space][Esc]
Short of writing this into a macro is there a better way of doing it? Is there some magic vim command which will allow me to do it in less than even 5 presses - and some way to generalise it so that I can do it to entire words or symbols, eg if I want to convert 3==4 to 3 == 4?
Personally, I think it makes most sense to destroy what you want to surround, and then repaste it.
c w "" ESC P
Obviously, you can replace both the object and the quotes with whatever you like. To change just one character + to be [space]+[space], you would do
s [space] [space] ESC P
on the +
The first thing that jumps to mind after reading just the title is surround.vim which is an excellent script to do all kinds of useful things along the lines of what you've described.
To solve your specific problem, I would probably position the cursor on the + and:
s[space]+[space][esc]
To change 3==4 into 3 == 4, I might position the cursor on the first =, and:
i[space][esc]ww.
i have been wondering about this as well. i tried with surround.vim, but the naive approach
S<space>
(after making a visual selection) does not work since the space is already taken up as a modifier for adding space to other surrounding character pairs. S<space><cr> adds a ^M in the output. Ss almost works but inserts a space only before.
after asking at tpope/surround.vim on github:
S<space><space>
in visual mode works. alternatively, from normal mode, ysl<space><space> works for a single character
Hah! I've been trying to figure out how to surround a block in spaces for quite a while and I finally found the right combination.
Using surround.vim you say surround selector space space.
So for this specific case I would use visual mode (a good trick for operating on single characters under the cursor BTW) thus: "vs " <- four key presses!
I also have a habit of typing things like argument lists without spaces. With this technique you can just navigate to the second argument using w and say "vws " to visually select a word and surround with spaces.
I prefer visual select mode generally. Also the alternate surround syntax "ysw " excludes the word final comma that is caught by "vw".
You could create a macro with one of the described actions and call it everytime you need it (Like amphetamachine proposed while I was writing) or you could simply search & replace:
:%s/\(\d\)\(+\|-\)\(\d\)/\1 \2 \3/g
You probably have to execute this command two times because it will only find every second occurence of +/-.
EDIT:
This will replace everything without the need to be called twice:
:%s/\d\#<=+\|-\d\#=/ \0 /g
Try positioning your cursor over the '+' and typing this:
q1i[space][right arrow][space][left arrow][esc]q
This will record a quick macro in slot 1 that you can re-use whenever you feel like it, that will surround the character under the cursor with spaces. You can re-call it with #1.
There is also the more versatile one:
q1ea[space][esc]bi[space][right arrow][esc]q
Which will surround the word under the cursor ("==" counts as a word) with spaces when you hit #1.
You could set up a mapping like this (press enter in visual mode to wrap spaces):
:vnoremap <CR> <ESC>`<i<SPACE><ESC>`>la<SPACE><ESC>h
This method allows you to use . to repeat the command at the next +.
Put your cursor over the + and type:
s[SPACE][CTRL-R]"[SPACE][ESC]
I know this is and old thread, but this might be useful to someone. I've found that the map (map it to anything else you want!)
noremap <leader>ss diwi<SPACE><C-R>"<SPACE><ESC>B
works ok both for turning 'a+b' into 'a + b' (when used over the '+' char) and for turning 'a==b' into 'a == b' (when used over either the first or the second '=' sign).
I hope it's useful to someone.

Why does Vim add spaces when joining lines?

I want to unwrap text in Vim. When I join lines I get an additional space between sentences.
Why is that?
I have a feeling this is what you really want: gJ
From :h gJ:
gJ Join [count] lines, with a minimum of two lines.
Don't insert or remove any spaces. {not in Vi}
This is handy if you've copied something from a terminal and it's pasted it as a big rectangular block into vim, rather than a single line.
I usually use it in visual mode. Hilight stuff, gJ.
Formatting destroys information. There are many different blocks of text which will result in the same one once formatted. Therefore, there's no way to reverse the operation without prior knowledge (i.e. undo).
Unformatted:
Unformatted text could start out as either all one line, or several, yet look the same when formatted.
Unformatted text could start out as either all one line, or several,
yet look the same when formatted.
Formatted:
Unformatted text could start out as
either all one line, or several,
yet look the same when formatted.
If you want your paragraph all on one line, or if you're okay with a little manual fiddling, you can use J to join lines back together. You can use visual mode to apply the J command to several lines at once, perhaps combined with ap or ip to select a paragraph, e.g. vipJ. Again, you'll still lose some information - multiple spaces at line breaks before formatting will end up collapsed to single spaces. (You can actually join without modifying spaces by using gJ instead of J, but you'll already have lost them when you formatted)
If you're bothered by the extra spaces after sentences (lines ending in !, ?, or .), turn off joinspaces: set nojoinspaces
I guess the simple solution to join the lines without spaces between is:
:j!
With ! the join does not insert or delete any spaces. For the whole file, use :%j!.
See: :help :join.
This is the answer that ended up working for me, none of the above worked in my use case.
Essentially, use gJ like multiple others have said, but highlight all of file, so in command mode typing ggVGgJ.
I still got the extra one space after join, if the line we work on does not end with space. Usually this is the desired behaviour. Example
first line without space
second line
after joining with J, become
first line without space second line
Although in some case, we do not wish to apply it,
myInstance->methodA()
->methodB()
And we would want the join to become myInstance->methodA()->methodB() without any space in between!
Here the helpers mapping i use
nmap <leader>jj Jx
<leader> key can be checked with :let mapleader, default to key \ i believe.
so in normal mode, just \jj to perform join without any extra space!

Resources