What is the meaning of the % character in vim? - vim

The vim wikia page provides the following description for search and replace:
:%s/foo/bar/g
Find each occurrence of 'foo' (in all lines), and replace it with 'bar'.
:s/foo/bar/g
Find each occurrence of 'foo' (in the current line only), and replace it with 'bar'.
...
I can see that the the % character causes the whole buffer to be searched.
What is the meaning of the % character in vim? Is it a variable that refers to the current buffer?

Learn how to look up commands and navigate the built-in :help; it is comprehensive and offers many tips. You won't learn Vim as fast as other editors, but if you commit to continuous learning, it'll prove a very powerful and efficient editor.
Here's how you would have found the information:
Look up the command: :help :substitute
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
Ah, the stuff in front is called range. Further down, there's a link to it:
Also see |cmdline-ranges|.
(:help [range] would have also taken you to it.) And that explains the meaning of %, as well as the help keyword for direct access.
% equal to 1,$ (the entire file) *:%*

Related

the difference between : and / in s/vi/VIM/g and s:^vi$:VIM:

I read vim regex example
s/vi/VIM/g
and
s:^vi$:VIM:
What' the difference between / and :,
Search but found few helpful materials.
Vim lets you change the character you use to start and end the search pattern arbitrarily. This is useful if you're going to have to escape the slash a lot in a particular expression.
For example, these two commands are equivalent:
s/\/\//ss/g
s://:ss:g
but the second one is much easier to type and read.
The two :s commands are different.
s/vi/VIM/g replace all vi by VIM no matter where vi is and how many times it occurred.
However, s:^vi$:VIM: replace lines containing only vi two characters by line: VIM
Regarding the / and : they are just separators of :s command. They make no difference in your command. If you want to read this part explanation, do :h E146 in your vim.

Vim Mode Plus Mark Occurrence for search

When I type /foo and then enter, is there a way to mark occurrence for all highlighted words? Right now, the /search seems pretty useless compared to the regular atom search, since it only highlights but doesn't let you replace.
The key / is used for searching, whereas :s for substitutions (i.e. replacements). So to replace foo with bar you can do:
:%s/foo/bar/gc
Here % means look for replacements in the entire file, and the last gc are replacement flags. The Vim documentation provides a great explanation of the topic and it can be accessed by typing :help subs. To learn more about replacement flags: :h flags.
Some more suggestions for a good workflow (at least in Vim itself):
After using /foo to locate a match, and you only want to replace that one: As the cursor is at the start of the match, you can use ce, cE or more generally cgn (gn selects the current / next match; it's a recent addition in version 8.0).
If you want to replace all matches, you don't need to repeat the search pattern in the :substitute command; an empty {pattern} there will recall the search pattern. So, you can briefly write :%s//bar/g (+ c to interactively influence replacements).
It seems I can't mark occurrence if I press enter. However, I can do some things if I haven't pressed enter.
cmd-o marks all search occurrences
ctr-cmd-c waits for you to specify a range, and then changes all search occurrences

Can I calculate the length of each line in vim?

I have a file below.
My
first
name
is
Kim.
And I wanna find the way(vim plugin, regular expression or vim function) that make this file below.
My 2
first 5
name 4
is 2
Kim. 4
Is there any method to calculate the length of each line in vim?
I don't want to achieve this via perl/ruby script or script development.
One way to do it:
:%s/\v(.*)\zs/\="\t".strlen(submatch(1))/
To understand how is this supposed to work: :help \v, :help \zs, :help s/\=, :help strlen(), and :help submatch().
Depending on what you use this for, if you work with wide characters you might need to replace strlen() with strwidth() or strdisplaywidth(). They might make more sense as "line length".

Vim Search/Replace, meaning of %s

In Vim you can search/replace text in the following way.
:%s/old/new
What does the %s mean?
% is the range over which the :s command (short for :substitute) will be run. % itself is short for the range :1,$, which means Line 1 to the last line in the buffer.
The Vim help has a couple topics (user manual - :help 10.3, reference manual - :help cmdline-ranges) describing the forms that ranges can take.
The syntax for :s (which is short for :substitute) is:
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
The % range means "the whole file".
This is very powerful; if you would want to do substitutions on just line 1, you would use:
:1s/a/b/
Or, for just lines 1 to 3:
:1,3s/a/b/
A very useful (related) trick, is to highlight lines with visual mode (V), and then use :s to substitute just on the lines you highlighted.
See: :help [range]
:%s/old/new/
This will search the entire document for "old" and replace the first instance on each line with "new". You can use :%s/old/new/g to replace all instances of "old" with "new".
(Updated based answer on jamessan's comment).
%s stands for the whole document. See here:
http://vim.wikia.com/wiki/Ranges

Matching backticks using matchit --- possible?

I'm writing a lot of RST lately and I would like the % keystroke to match between grave accent (i.e. backtick) characters.
`The cursor is at the |vertical line`
and then hitting % moves the cursor as shown
`The cursor is at the vertical line|`
I have tried setting the b:match_words for the matchit plugin but that doesn't help.
Any tips appreciated.
Forgive me for tooting my own horn, but I am an expert on the matchit plugin.
Although it is designed to extend the built-in matching functionality, matchit extends it in several ways. For one, it allows you to match regular expressions, not just single characters. You can get very good results by using vim's start-of-word and end-of-word patterns:
:let b:match_words='`\<:\>`'
This certainly works on the one-line example you gave. Similarly, you might decide that the starting ` usually does not have a non-whitespace character before it, and the closing one is not followed by a non-whitespace character. (If that is too many negatives, then "This is markup" usually starts a new line or follows a space or tab; and it is usually followed by the end of a line or a space or tab.) Then you could use
:let b:match_words='\S\#<!`:`\S\#!'
The matchit plugin tries to live up to vim's design goals, including :help design-documented. The standard vim distribution includes both matchit.vim (the script) and matchit.txt in $VIMRUNTIME/macros/. You can either read the documentation there or follow the instructions at :help matchit-install and browse the documentation with :help.
Under :help b:match_words, it says,
Tips: Be careful that your initial pattern does not match your final pattern.
This is because, when you bang on the % key, the script has to be able to figure out whether it is on the starting pattern or the ending pattern. The only information it has to make this decision is what you have told it in b:match_words.
The matchit plugin is designed to work similar to the built-in % command and as such suffers some of the same limitations. In particular, from :help 'matchpairs':
Only character pairs are allowed that are different, thus you cannot
jump between two double quotes.
Thus, this works as expected (but not as you want):
:let b:match_words="`:'"
But this does not work:
:let b:match_words="`:`"
For some suggestions how to pair identical delimiters with matchit in common prose or markup files, such as rst, see my repository.

Resources