VIsual select to a specific character - vim

I am working in vim. I have a piece text that looks like :
one = 24
two = 52
three = 56
four = 74
Is there a way to use visual select to yank and paste up to the equal to sign in each line ? I want an operation that leaves me with the following result :
one = 24
two = 52
three = 56
four = 74
one =
two =
three =
four =
My current solution is to copy the whole thing, then jump to the one = 24 line in what I copied and then record this macro : 0f=ld$j to #w and then repeat it three times with 3#w. Is there a way to do this using visual select and yank and paste ?

I tend to use :substitute for these things
" First I yank and paste, in normal mode
yapP
" Then I transform
gv " to reselect, while in normal mode
:s/=.*/=/ " that will actual display :'<,'>s/.....
The actual reselection part may need a little work depending on where the cleared snippet shall appear. May be something like yapo<esc>p:'[,']s/=.*/=/ + enter

You can visually select the lines to apply normal commands to them with :norm.
Thus, you could do:
ggVG:norm f=ld$

How about
:global /=/ copy $ | substitute /=\zs.*//
We use global to select the original lines, then copy them to the end $ and remove the parts after = with substitute.

You could use a mapping like this
vnoremap ,s y:let #"=system('sed -nE "s/=.*/=/p"',#")<cr>
When selecting now some lines in in visual mode, type ,s. This will put the desired modification into the " register and you can paste them now using p wherever you want.

Related

I have text in separate lines inside same box, How to make it all in one line

Some of my text are in different lines inside same cell. I want them in single line. How do I bring them in single line ?
Example:
first cell contains:
Hi Ram, I want to go to movie today.
Are you willing to join?
If yes, let me know early.
Example:
Expected output:
Hi Ram, I want to go to movie today.Are you willing to join?If yes, let me know early.
New line in a cell A1 caused by alt+Enter for example, may be removed using a formula such as:
=SUBSTITUTE(A1,CHAR(10)," ")
Where A1 is the cell containing the text to be changed. You can enter the formula above in a different cell of course.
The parameter " " indicates 1 space to replace the line break. You could use any other character.
Another type of line break is CHAR(13). You can remove CHAR(13) using the same function again:
=SUBSTITUTE(SUBSTITUTE(A1, CHAR(13)," "), CHAR(10), " ")
In case you had some spaces already before the new-line character, you need to wrap the above formula in a TRIM function like so:
=TRIM(SUBSTITUTE(A1,CHAR(10)," "))
OR
=TRIM(SUBSTITUTE(SUBSTITUTE(A1,CHAR(13)," "),CHAR(10)," "))
Always make a copy of your file before you apply formulas that could change the data.
Note-1:
char(13) is officially called "carriage return" and char(10) is called "line feed".
CHAR(10) returns a line break on Windows, and CHAR(13) returns a line break on the Mac. This answer is for Windows. You can't visually see it but you can see its effect.
Note-2:
As #kojow7 answered, a text wrap can cause the text to appear on more than 1 line depending on the cell width and the text length. This answer does not resolve this case.
Related discussion can be found here: Remove line breaks from cell.
Two things you may need to fix here: 1) Line breaks and 2) Text Wrapping
To fix line breaks:
Select the cells that need to be changed
Press CTRL+H to open Search and Replace
In the Find box type CTRL+J to insert the line break character (it may look like nothing was inserted in the field, but it does insert a line break)
Decide whether to replace the line breaks with a space or with nothing
Press Replace All
To turn off text wrapping:
Select the cells that need to be changed
Go to the Home Tab
In the Alignment Group check to see if the Wrap Text button is clicked.
If it is, click on it again to deselect it.
Depending on your situation, you may need to fix either one or both of these.
Depending on your document it might contain linefeeds or carriage returns or BOTH.
Alexander Frolov (https://www.ablebits.com/office-addins-blog/2013/12/03/remove-carriage-returns-excel/) has written a very good blog post about different technics of finding and removing linebreaks in an Excel file. We will use the “macro way” of doing that – as it is the one that works either on Windows AND Mac. The search replace method offered here too will not work on Mac but on windows.
Add the below Macro to your document (slighlty modified from the original)
Change the value of “ReplaceWith” from ” ” (space) to anything you like a linebreak to be replaced with.
E.g. ReplaceWith = “-” will result in “Line1-Line2-Line3”
Run the Macro (Extras > Macro) while all cells are selected.
Sub RemoveCarriageReturns()
ReplaceWith = " "
LinefeedChar = Chr(10)
Dim recordRange As Range
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
For Each recordRange In ActiveSheet.UsedRange
If 0 < InStr(recordRange, LinefeedChar) Then
recordRange = Replace(recordRange, LinefeedChar, ReplaceWith)
End If
Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
If your separate lines are not gone by now please change "LinefeedChar" from "Chr(10)" to "Chr(13)" and run it again

Delete from cursor to end of line under visual selection in vim

I have a code segment like below.
type Account struct {
Id int
UserId int
Name string
Address string
City string
State string
CountryId string
}
I want to delete all the data types. Is there a key combination to this?
I tried <C-V> and select the first letter of all data types in a vertical line, hoping d + $ would work post that, however vim only takes the first input d and deletes the first letter.
Use <C-v> to enter visual block mode, select the lines you want to change and then D to delete until the end of those.
From :h v_D :
{Visual}["x]X or *v_X* *v_D* *v_b_D*
{Visual}["x]D Delete the highlighted lines [into register x] (for
{Visual} see |Visual-mode|). In Visual block mode,
"D" deletes the highlighted text plus all text until
the end of the line. {not in Vi}
Note that, as mentioned in the help, X and D are not equivalent in visual block mode (X only deletes the current selection, not until the end of the line).
You can move to the left brace, press the % key and issue:
s/ \+[^ ]* *$/
to get:
type Account struct
Id
UserId
Name
Address
City
State
CountryId
}
The substitution removes all non-white-space characters at the end of the line.
You can use C-V and select the first column of all data type, then do $ to select until the end of the line, followed by x or d to delete.
Visually select all those lines with v6j.
Remove the extra stuff with :'<,'>norm ElD ('<,'> is added automatically for you).
Also, watch out for trailing space!
Not the shortest possible sequence but following is more natural to me
vi{ - Visually select the inner paragraph
'<,'>norm weld$ (typed as :norm weld$)
witch breaks down to
'<,'>norm - Apply normal commands over the selection
wel - jump to the end of the first word
d$ - delete until the end of the line

Paste yanked text in several sequential lines

If I have multi-line line snippet:
length = 1;
keys = NewKey(value);
gt_backref = NULL;
ls_backref = NULL;
And I need to paste yanked (<ctrl>-V+y) node-> between every line of snippet:
node->length = 1;
node->keys = NewKey(value);
node->gt_backref = NULL;
node->ls_backref = NULL;
How do I paste yanked text in several sequential lines? Something like <ctrl>-V+<shift>-I but for paste, not for typed text.
<C-v>{motion}I<C-r>"<Esc>
Enter visual block mode with <C-v>.
Extend your selection.
Hit I to enter insert mode.
Do <C-r>" to insert the content of the unnamed register.
Hit <Esc> to apply the change to all the selected lines.
Or with :normal:
:[range]norm I<C-r>"<CR>
Well, if you select the text with Shift-V, then do a regex
:'<,'>s/.*/node->&/
that would add node-> to the selected lines.
or I guess even simpiler
:'<,'>s/^/node->/
If it's more complicated, maybe you would create some kind of macro with a search to find the type of lines you want to replace and run the same regex replace on each of those lines
This answer based on #Shaun's answer. This really needs a macro. But the correct regexp is
:'<,'>s/\(^\s\+\)/\1node->/
Because I need to take into account indentation.
But this approach does not universal. For every particular case we need new regexp.

Use VIM Visual Block to concatenate blocks

I try to use VIM build my SQL query by concatenate block of strings. For example, I have the following strings in three tabs in VIM:
# block one
where c = '123'
where c = '2345'
...
# block two
set b = 12
set b = 345
...
# block three
update myTable set a = 'abc',
update myTable set a = '23423',
...
each block contains 100 lines (fragments of SQL query). I would like to concatenate those blocks in to one complete SQL query: block one + block two + block three (100 lines) like this:
# sql queries
update myTable set a = 'abc', set b = 12 where c = '123'
update myTable set a = '23423', set b = 345 where c = '2345'
...
Just ignore the first line #..., it is just for explanation. I think that Visual Block can be used do that:
Yank all the lines in tab "block two";
Paste buffer to tab "block three" at the beginning;
Yank all the lines in tab "block one";
Paste the buffer to tab "block three" at the beginning.
However, I tried to the tip in Visual Block Mode(first two y and p examples), I could not get my expected result. The paste does not concatenate the buffer strings to the block. Not sure what I did wrong. Or any other alternative ways?
I recently ran across a VimCasts episode that describes how to do editing in visual block mode. Check out the video, I believe he describes what you want.
Did you try Visual-blockwise (ctrl-v)? They have to be the same width lines, but it works.
# Yank the lines from the other file
gg V G
# Add whitespace to the end
:%s/$/ /
# Select the whitespace at the end of the other file, and paste it
gg $ ctrl-v $ p
You may have to make a few changes, but hopefully it gave you some ideas at least.

vim how to create a debug message fast

I am using ruby on rails but that does not matter much for this question. Let's say that i have a statement like this
error = 'this is an error message'
I have noticed that I end up doing this a lot
error = 'this is an error message'
puts "error = #{error.inspect}"
I am sure a macro can be written which would take the work on the left hand side of left most = and then create another line along with template shown above.
I am using mvim on mac. Any pointer in terms of where I should start to look for developing what I want.
Try snipmate:
http://www.vim.org/scripts/script.php?script_id=2540
I recorded a simple macro that does your sample. To record a macro type q followed by what register you want the macro to be put in (convention calls for qq). To play the macro type # then the macro register. You can view this at :help recording
To write the macro, use the following commands (and here is how is should look in the register)
^yEoputs "error = #{^Op.inspect}"^[
^ moves to the first non whitespace character of the line
yE yanks to the end of the space separated word.
o Puts you in insert mode on the next line
puts "error = #{ is the text that you type out
^O is ctrl+O (capital letter o) - this allows the next, and only the next command to be run in command mode, which is...
p Puts the yanked word, after this command is run you're still in insert mode
.inspect}" is the text that you type and finally...
^[ is Esc
I would go for:
nnoremap µ :s/^\s*\(\k\+\)\s*=.*/&\rputs "\1 = #{\1.inspect}"/<cr>
:s presents the advantage of doing the job plus matching the assigned variable if any. Doing the same thing with classical commands like yw, p, etc would be more cumbersome.
If the template become more complex, we can rely on template-file expanders as long as they easily permit to call viml function like matchstr(). Of course, in that case I would use mu-template with the following template-file:
VimL:" $Id: {rtp}/template/ruby/inspect.template
VimL: let s:value_start = '¡'
VimL: let s:value_end = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:varname = matchstr(getline(line('.')-1), '^\s*\zs\k\+\ze\s*=')
VimL: if empty(s:varname) |throw "the previous line don't assign any variable" |endif
puts "¡s:varname¡ = #{¡s:varname¡.inspect}"<++>
VimL:"vim: encoding=utf-8
If you're doing these on the fly, a snipmate snippet could look like this:
${1:error} = '${2:error message here}'
puts "error = #{$1.inspect}"
If, on the other hand you're just wanting to output pre-existing variables for debugging purposes. Nick-Canzoneri's macro may be more useful.

Resources