VIM equivalent for (something like) 6xi? - vim

There's a command in VIM where you can say how many chars to replace, and VIM will put a "$" at that many characters out, and you can type in the replacement for those characters. The original and new text can be different lengths. What's the command for this?

The nearest I can think of is '6s'; that deletes the next 6 characters and leaves you in insert mode, but it doesn't show a '$' at the end - it just removes the material.

It is the behavior of c command when 'cpoptions' contains $ (so it is a default behavior for vi and some configurations of Vim).

The command is s. In your example, it would be 6s.

Related

Writing whole alphabet in Vim

I sometimes need to write the whole alphabet abcd…z and I hate typing it letter by letter in Vim's insert mode. Does there exist any method to do this more efficiently?
I know about the ga command which gives me the ascii code of the character where the cursor is … but don't know anything about how to mix it with my standard solution to type numbers from 1 to (for example) 5000: a1ESCqqyyp^Aq4998#q …
Using set nrformats+=alpha:
ia<Esc>qqylp<C-a>q24#q
Step by step:
ia<Esc> " Start with 'a'
qqylp<C-a>q " #q will duplicate the last character and increment it
24#q " Append c..z
If your shell does brace expansion this is a pretty elegant solution:
:r !printf '\%s' {a..z}
:read! reads the output of an external command into the current buffer. In this case, it reads the output of the shell's printf applied to {a..z} after it's been expanded by the shell.
How about this command:
:put =join(map(range(char2nr('a'),char2nr('z')),'nr2char(v:val)'),'')
Collect the ASCII values of the characters in the range from a to z, then map them over the nr2char() function and insert the result into the current buffer with :put =.
When you leave out the enclosing join( … ,'') you get the characters on a separate line each.
See
:h nr2char(),
:h char2nr(),
:h :put,
and look up range(), map(), join() and friends in the list-functions table.
First, set nrformats+=alpha.
Then:
ia<ESC>Y25p<CTRL-V>}g<CTRL-A>k26gJ
Which means:
ia insert the initial a
Y25p yank the a and duplicate it on 25 lines
<CTRL-V> go into visual block mode
} go to the last character at the end of the current paragraph
g<CTRL-A> incrementally increase each alphabetic character (see help v_g_CTRL-A)
k go up one line
26gJ join 26 lines without inserting or removing any spaces
Which leads to:
abcdefghijklmnopqrstuvwxyz
I have found a shorter solution (you don't need to change nrformats beforehand) while solving http://www.vimgolf.com/challenges/5ebe8a63d8085e000c2f5bd5
iabcdefghijklm<Esc>yiwg??P
which means:
iabcdefghijklm<Esc> insert first half of the alphabet
yiw copy it
g?? ROT13 encode (shift by 13 letters) to get the second half
P paste the first half
You might try using Vim abbreviations or a full-fledged snippet manager plugin like UltiSnips. It might take a few moments to set up, and you'd have to type that alphabet one more time to define it as an abbreviation or snippet, but after that you'd be able to insert the alphabet or any other common chunk of text much more easily.

How do I remove the last six characters of every line in Vim?

I have the following characters being repeated at the end of every line:
^[[00m
How can I remove them from each line using the Vim editor?
When I give the command :%s/^[[00m//g, it doesn't work.
You could use :%s/.\{6}$// to literally delete 6 characters off the end of each line.
The : starts ex mode which lets you execute a command. % is a range that specifies that this command should operate on the whole file. The s stands for substitute and is followed by a pattern and replace string in the format s/pattern/replacement/. Our pattern in this case is .\{6}$ which means match any character (.) exactly 6 times (\{6}) followed by the end of the line ($) and replace it with our replacement string, which is nothing. Therefore, as I said above, this matches the last 6 characters of every line and replaces them with nothing.
I would use the global command.
Try this:
:g/$/norm $xxxxxx
or even:
:g/$/norm $5Xx
I think the key to this problem is to keep it generic and not specific to the characters you are trying to delete. That way the technique you learn will be applicable to many other situations.
Assuming this is an ANSI escape sequence, the ^[ stands for a single <Esc> character. You have to enter it by pressing Ctrl + V (or Ctrl + Q) on many Windows Vim installations), followed by Esc. Notice how this is then highlighted in a slightly different color, too.
It's easy enough to replace the last six characters of every line being agnostic to what those characters are, but it leaves considerable room for error so I wouldn't recommend it. Also, if ^[ is an escape character, you're really looking for five characters.
Escape code
Using ga on the character ^[ you can determine whether it's an escape code, in which case the status bar would display
<^[> 27, Hex 1b, Octal 033
Assuming it is, you can replace everything using
:%s/\%x1b\[00m$//gc
With \%x1b coming from the hex value above. Note also that you have to escape the bracket ([) because it's a reserved character in Vim regex. $ makes sure it occurs at the end of a line, and the /gc flags will make it global and confirm each replacement (you can press a to replace all).
Not escape code
It's a simple matter of escaping then. You can use either of the two below:
:%s/\^\[\[00m$//gc
:%s/\V^[[00m\$//gc
If they are all aligning, you can do a visual-block selection and delete it then.
Otherwise, if you have a sequence unknown how to input, you can visually select it by pressing v, then mark and yank it y (per default into register "). Then you type :%s/<C-R>"//g to delete it.
Note:
<C-R>" puts the content of register " at the cursor position.
If you yanked it into another register, say "ay (yank to register a - the piglatin yank, as I call it) and forgot where you put it, you can look at the contents of your registers with :reg.
<C-R> is Vim speak for Ctrl+R
This seems to work fine when the line is more than 5 chars long:
:perldo $_ = substr $_, 0, -5
but when the line is 5 or less chars long it does nothing.
Maybe there is a easy way in perl to delete the last 5 chars of a string, but I don't really know it:)
Use this to delete:
:%s/^[[00m//gc

Highlight positions of the marks in Vim?

I am practising '[ and '], and I cannot see the difference.
How can you highlight the positions of the marks?
Use the showmarks plugin for VIM. It does just that.
vim-signature worked well for showing marks.
showmarks didn't work for me. It also hasn't been updated in nearly a decade.
I find several marks related plugins on GitHub, which shows marks on the signcolumn and provide commands to manage your marks:
vim-signature
vim-markology
vim-markbar
Currently, I am using vim-signature and it works great. You may try these plugins and choose what suits you best.
Your problem may be that the previously changed or yanked text was all on one line. If you use ' with a mark it just takes you to the line, not to the exact character. Use ` instead to get the exact character.
One way to temporarily highlight the region would be to type this:
`[v`]
This will jump to the start change/yank mark, start a visual block and then jump to the end change/yank mark.
Normally you can "blink" the matching delimiter ([{}]) ... using the % (percent sign) command in vi.
(That's not even unique to vim ... it works in other versions of vi as well).
The '[ and '] (single quote, square brackets) are unique to vim as far as I know. They move to the first non-blank character on the first or last line where most recently modified or "put" any text. If your most recent change only only affected a single line then the commands would both move to the same place (as you described).
Note that the ' command (in normal vi as well as vim) is a movement. 'letter (single quote followed by any lower case letter) is a command to move to the locate where a mark was most recently set (using the m command, of course). '' (repeating the single quote command twice) moves to "most recent" cursor location (think of there being a implicit mark there). That's the most recent location from which you initiated a movement or made a change ('[ and '] are ONLY about where you made changes).
For example if I'm on line 100 and I use n to search for the next occurrence of my current search pattern, then '' will get me back to line 100. From there if I type '' again then it will toggle me back to whatever the search (n) command found.
Personally I never use '[ and '] ... I drop a mark using ma (or b, or c or whatever) and then make my changes or pastes before or after the mark I've set, as appropriate.
This command will show the marks:
:match Error /\%'[\|\%']/

Unable to replace a space with a new line in Vim

I know the thread.
I run
:%s/ /s/\n/g
I get
E488: Trailing characters
2nd example
I run
:%s/ /\n/g
I get
text^#text
I run the same codes also with the following settings separetaly
set fileformat=unix
and
set fileformat=dos
How can you replace with a new line in Vim?
:%s/ /Ctrl vReturn/g
Where Ctrl v is Control-key plus key v and Return is the return key (the one on the main keyboard, not the enter key on the numpad). The other characters are typed as usual.
If this is entered correctly, the sequence Ctrl vReturn will display as the characters ^M, typically in a different color, to indicate that they are special. Note that actually typing ^M will not work.
Also note that in Vim for windows, it's Control-q instead of Control-v (as that is paste).
Ctrl-v also allows entering other "special" keys via the keyboard. It is also useful for e.g. Tab or Backspace.
Try
%s/ /\r/g
Enter the following:
:s/ /
and now type Ctrl-V or Ctrl-Q (depends on your configuration) and hit the Enter key. You should now have:
:s/ /^M
Finish it off:
:s/ /^M/g
and you are good to go.
Specifically to answer your problem with trailing characters, this is the regex you specified:
:%s/ /s/\n/g
You have too many /. What happens is that you replace ' ' with s, and then you tag on this after the substitution: \n/g
I think you meant this:
:%s/ \s/\n/g
Note that your /s was changed to \s. Now the substitution will replace one space followed by one whitespace of any kind (space or tab) with \n. I doubt if this solve the problem or replacing space with a newline, but it should explain the error message.
Try either
For Unix:
:1,$s/\ /\n/g
For Windows:
:1,$s/\ /\r/g
This contains an escape character for the space.

How to repeat a command with substitution in Vim?

In Unix the ^ allows you to repeat a command with some text substituted for new text. For example:
csh% grep "stuff" file1 >> Results
grep "stuff" file1
csh% ^file1^file2^
grep "stuff" file2
csh%
Is there a Vim equivalent? There are a lot of times I find myself editing minor things on the command line over and over again.
Specifically for subsitutions: use & to repeat your last substitution on the current line from normal mode.
To repeat for all lines, type :%&
q: to enter the command-line window (:help cmdwin).
You can edit and reuse previously entered ex-style commands in this window.
Once you hit :, you can type a couple characters and up-arrow, and it will character-match what you typed. e.g. type :set and it will climb back through your "sets". This also works for search - just type / and up-arrow. And /abc up-arrow will feed you matching search strings counterchronologically.
There are 2 ways.
You simply hit the . key to perform an exact replay of the very last command (other than movement). For example, I type cw then hello to change a word to "hello". After moving my cursor to a different word, I hit . to do it again.
For more advanced commands like a replace, after you have performed the substition, simply hit the : key then the ↑ up arrow key, and it fills your command line with the same command.
To repeat the previous substition on all lines with all of the same flags you can use the mapping g&.
If you have made a substitution in either normal mode :s/A/B/g (the current line) or visual mode :'<,>'s/A/B/g (lines included in the current selection) and you want to repeat that last substitution, you can:
Move to another line (normal mode) and simply press &, or if you like, :-&-<CR> (looks like :&), to affect the current line without highlighting, or
Highlight a range (visual mode) and press :-&-<CR> (looks like :'<,'>&) to affect the range of lines in the selection.
With my limited knowledge of Vim, this solves several problems. For one, the last visual substitution :'<,'>s/A/B/g is available as the last command (:-<UP>) from both normal and visual mode, but always produces an error from normal mode. (It still refers to the last selection from visual mode - not to the empty selection at the cursor like I assumed - and my example substitution exhausts every match in one pass.) Meanwhile, the last normal mode substitution starts with :s, not :'<,'>s, so you would need to modify it to use in visual mode. Finally, & is available directly from normal mode and so it accepts repetitions and other alternatives to selections, like 2& for the next two lines, and as user ruohola said, g& for the entire file.
In both versions, pressing : then & works as if you had pressed : and then retyped s/A/B/, so the mode you were in last time is irrelevant and only the current cursor line or selection determines the line(s) to be affected. (Note that the trailing flags like g are cleared too, but come next in this syntax too, as in :&g/: '<,'>&g. This is a mixed blessing in my opinion, as you can/must re-specify flags here, and standalone & doesn't seem to take flags at all. I must be missing something.)
I welcome suggestions and corrections. Most of this comes from experimentation just now so I'm sure there's a lot more to it, but hopefully it helps anyway.
Take a look at this: http://vim.wikia.com/wiki/Using_command-line_history for explanation.

Resources