replace a region with whitespace - vim

is there a keystroke to replace a region (series of characters, whatever) with a another character (for example whitespace)?
I am not searching for c, because it deletes the existing characters and lets me enter new ones, which may be less or more characters. I want to replace exactly the deleted characters with another char as with R.
For example I have this:
one two three four
and want to replace it with:
one two ----- four
If the cursor is on the beginning of three, I'd like to enter a keystroke, a region (for a example w for end-of-word) and a replacing char (in this case -) to let vim replace all characters in that region with the given replacing char.

you could try:
ver-
to replace selected part with -
same, if you want to replace / fill the "region" with space, you do:
verspace

Related

Replace a word (or many words) with spaces of same length?

In a general sense, my question is how do I do something like "dw" or "dd", but instead of deleting characters, I want to over-write with spaces?
E.g. lets say I have text:
first second third
if the cursor is on the "s" in second, I can hit "dw" to get:
first third
but what if I want:
first third
Is there a simple way to do that? An ideal solution would be to use the "d" style syntax (e.g. dw, daw, d$, etc.) but with whitespace replacement instead of deletion.
From the start of the word,
Ctrl-v to enter visual block mode,
e to move to the end of the word (highlighting the word in the process),
r[SPACE] to replace the highlighted characters with spaces.
Because of their very nature (the next character must be consumed), r and R can't work like operators. If you want to replace a motion, visually select it first, and then do r<Space> or r_ or whatever.
In this very specific case:
ver<Space>
or:
viwr<Space>
NOTE: I used ve and viw because the semantics of w are inconsistent so I prefer to avoid it when possible.

Is there a way to use the Find and Replace function in Excel to replace the first and last entry in a string of text?

I have a sequence of a letters, in my case part of a gene. I want to change the first and the last letter in this string of text, but keep the internal characters the same.
For example, if I have the the sequence:
ATCGAATCCATGACG
And I want to change the first letter, in this case A to the word START and change the last letter, G, to STOP all while keeping the internal A's and G's the same. Is this possible to do with the Find and Replace function, or will I have to write a script?
It is easy to do when I have a handful of sequences, I do it by hand. When I get into the hundreds, it can be very difficult.
Thank you.
The function LEN(text) returns the number of characters within a string of letters. MID(text, start, num_chars) returns the middle section of a string. CONCATENATE(text1, text2, ...) pieces together different strings. We can use these in combination to get what you want:
=CONCATENATE("START", MID(A1,2,LEN(A1)-2), "STOP")
You could use replace, and focus on the left and right side independently, then combine, or you can use left/right to add string of text to the available string minus a character, like:
="START"&LEFT(RIGHT(A1,LEN(A1)-1),LEN(A1)-2)&"STOP"
I used left/right, but mid would also work
just another option:
=REPLACE(REPLACE(A1,LEN(A1),1,"STOP"),1,1,"START")

How do I put several characters after the first letter and the last letter by use of Vim?

How do I put several characters after the first letter and the last letter in the whole text by use of Vim?
E.g. I need to put {{c1:: after the first letter and }} after the last letter. Also, I want to ignore two-letter words.
You mean in every word? Try this:
:%s/\<\(\w\)\(\w\w\+\)\>/\1{{c1::\2}}/g
That will replace every first character in a word with the first character followed by {{c1:: and add }} at the end of it. Words shorter than three characters are ignored.
If your words contain more than just [a-zA-Z0-9], then replace \w by a more appropriate character class.

Tell vim to add commas to a number, e.g. change 31415926 to 31,415,926

I have a very large number (a couple hundred digits long), and I'd like to use vim to add commas to the number in the appropriate manner, i.e. after each group of three digits, moving from right to left. How can I do this efficiently?
Taken from here
Substitue command that adds commas in the right spot.
:%s/\(\d\)\(\(\d\d\d\)\+\d\#!\)\#=/\1,/g
This uses a zero width lookahead to match any number that isn't followed by groups of three numbers followed by one number. (or 3n+1 numbers)
So the numbers that match in are marked with ^. These are then replaced with a comma after it the match.
31415926
^ ^
Which replaces to
31,415,926
A friend of mine suggests using the printf program: ciw<C-r>=system("printf \"%'d\" ".shellescape(#"))<CR>.
This is one way of doing it:
s/\d\{-1,}\ze\(\d\{3}\)\+\s/&,/g
Notes:
\{-1,} is saying match at least 1 but in a non-greedy way (Vim doesn't seem to support the usual \+\? syntax; also, for quantifiers, you just need to escape the opening curly brace)
\ze is saying match the pattern behind this but don't store the match in & (equivalent to positive look-ahead)
\(\d\{3}\)\+\> matches groups of 3 digits that ends with word-nonword boundary (word in this sense means alphanumerical + underscore).
Alternatively, you can use \s for space/tab, or \D for non-digit instead of \>, whichever fits your needs better
The way that I used is to create a macro that adds one single comma, and then invoke the macro a whole bunch of times, like qahhi,<ESC>hq#a#a#a#a…

How to insert variable number of spaces necessary to align textual columns in Vim?

I’m a fan of Visual mode in Vim, as it allows to insert text before any given column.
For example, insertion of spaces after the quotation leaders below:
> one
> two
> three
can be done via <Ctrl-V>jjI <Esc>:
> one
> two
> three
as follows:
Start Visual mode with Ctrl-V.
Extend visual selection with jj.
Insert some spaces with I__.
Propagate the change to all the lines of the block selection with Esc.
Now I have a text file that needs some formatting. This is what it looks like:
start() -- xxx
initialize() -- xxx
go() -- xxx
Now I want to align part of this text to arrange it into columns like this:
start() -- xxx
initialize() -- xxx
go() -- xxx
The problem I have is that I cannot insert a different amount of indentation into each line and merely indenting a fixed amount of spaces/tabs is insufficient.
How can you do an indentation where all indented text will have to be aligned at the same column?
Update
I only figured out a rather verbose and unwieldy method:
Find the string position to indent from: \--.
Insert n (let's say 20) spaces before that: 20i <Esc>.
Delete a part of those spaces back to a certain column (let's say 15): d|15.
Save those steps as a macro and repeat the macro as often as necessary.
But this approach is very ugly, though!
I'm much better off without any vim plugins.
Here is my solution:
<Shift-V>jj:!column -ts --
Then insert -- into multiple lines just as you wrote in the question.
You can also append a number of comments at insertion time.
:set virtualedit=all
<Ctrl-V>jjA-- xxx<Esc>
You have to use a specific plugin, you can use either Tabular or Align plugin in this case.
They both allow you to align text on specific characters, like -- in your example. Their syntax is a bit different though. Pick the one that suit you the most.
Without plugin and if you have already entered your comments without emix's solution:
:,+2 s/--/ &
This will ensure all comments are to be shifted leftwise in order to align them properly.
Then blockwise select the column to which you want to align the text, and : 100<
An easy way to align text in columns is to use the Tabular or
Align plugin. If neither of these is ready at hand, one can use
the following somewhat tricky (and a little cumbersome looking) yet
perfectly working (for the case in question) commands.1,2
:let m=0|g/\ze -- /let m=max([m,searchpos(#/,'c')[1]])
:%s//\=repeat(' ',m-col('.'))
The purpose of the first command is to determine the width of the
column to the left of the separator (which I assume to be --
here). The width is calculated as a maximum of the lengths of the text
in the first column among all the lines. The :global command is used
to enumerate the lines containing the separator (the other lines do
not require aligning). The \ze atom located just after the beginning
of the pattern, sets the end of the match at the same position where
it starts (see :help \ze). Changing the borders of the match does
not affect the way :global command works, the pattern is written in
such a manner just to match the needs of the next substitution
command: Since these two commands could share the same pattern, it can
be omitted in the second one.
The command that is run on the matched lines,
:let m=max([m,searchpos(#/,'c')[1]])
calls the searchpos() function to search for the pattern used in the
parent :global command, and to get the column position of the match.
The pattern is referred to as #/ using the last search pattern
register (see :help "/). This takes advantage of the fact that the
:global command updates the / register as soon as it starts
executing. The c flag passed as the second argument in the
searchpos() call allows the match at the first character of a line
(:global positions the cursor at the very beginning of the line to
execute a command on), because it could be that there is no text to
the left of the separator. The searchpos() function returns a list,
the first element of which is the line number of the matched position,
and the second one is the column position. If the command is run on
a line, the line matches the pattern of the containing :global
command. As searchpos() is to look for the same pattern, there is
definitely a match on that line. Therefore, only the column starting
the match is in interest, so it gets extracted from the returning list
by the [1] subscript. This very position equals to the width of the
text in the first column of the line, plus one. Hence, the m variable
is set to the maximum of its current value and that column position.
The second command,
:%s//\=repeat(' ',m-col('.'))
pads the first occurrence of the separator on all of the lines that
contain it, with the number of spaces that is missing to make the text
before the separator to take m characters, minus one. This command
is a global substitution replacing an empty interval just before the
separator (see the comment about the :global command above) with the
result of evaluation of the expression (see :help sub-replace-\=)
repeat(' ',m-col('.'))
The repeat() function repeats its first argument (as string) the
number of times given in the second argument. Since on every
substitution the cursor is moved to the start of the pattern match,
m-col('.') equals exactly to the number of spaces needed to shift
the separator to the right to align columns (col('.') returns the
current column position of the cursor).
1 Below is a one-line version of this pair of commands.
:let m=0|exe'g/\ze -- /let m=max([m,searchpos(#/,"c")[1]])'|%s//\=repeat(' ',m-col('.'))
2 In previous revisions of the answer the commands used
to be as follows.
:let p=[0]|%s/^\ze\(.*\) -- /\=map(p,'max([v:val,len(submatch(1))+1])')[1:0]/
:exe'%s/\ze\%<'.p[0].'c -- /\=repeat(" ",'.p[0].'-col("."))'
Those who are interested in these particular commands can find their
detailed description in this answer’s edit history.
This is a modification on Benoit's answer that has two steps.
First step, block select text search and replace -- with lots of spaces.
'<,'>s/--/ --/
Now all the comments should have lots of spaces, but still be uneven.
Second step, block select the text again and use another regex to match all the characters you want to keep (say the first 20 characters or so) plus all the spaces following, and to replace it with a copy of those first 20 characters:
'<,'>s/\(.\{20}\)\s*/\1/
Not quite as easy as Benoit's, but I couldn't figure out how to make his second step work.

Resources