Matching backticks using matchit --- possible? - vim

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.

Related

Why does this regular expression not work in Vim syntax highlighting?

I am attempting to create my own Python syntax highlighting file for Vim.
I'm trying to highlight the class inheritance object and the regex I've created
works in various regex testers, but doesn;t work in Vim. I've read that Vim's regex is close to Perl style
so that is what I've been using.
I'm trying to highlight the word 'Subscribers' in the following text:
class Divisions(Subscribers):
The regex I've composed is:
(?!:class\s\w+)(?<=\()\w+(?=\):)
I'll be honest here, I stumbled into this while I was struggling to make a negative lookbehind work with quantifiers,
which I now understand isn't possible. I was experimenting with the non-capturing group (?:class\s\w+) and accidentally
inserted the exclamation mark which 'magically' solved the problem. At least in the multiple regex testers I was using.
Just for clarity, then follows a look behind (?<=() to caputre but not include the '('
and then a look ahead after the word (?=):) to capture but not include the closing '):'
I've added it to my Vim syntax file as:
syn match pythonClassInherit "(?!:class\s\w+)(?<=\()\w+(?=\):)"
Is this a valid regular expression in Vim? If not, can anybody offer a working solution for Vim?
EDIT: I realized that I've had overcomplicated the issue; you just need a right Vim regex. Try
syntax match pythonClassInherit "\%(class\s\+\h\w*\s*(\s*\)\#<=\h\w*\%(\s*):\)\#="
highlight link pythonClassInherit pythonImport
Then you'll see the result:
You may replace pythonImport by another predefined highlight group.
For highlighting, I found https://learnvimscriptthehardway.stevelosh.com/ (highlighting starts from Chap. 45) helpful. As for regex, romainl's suggestion is awesome.
My first attempt was to use regex \zs. This, unlike \#<=, requires that the syntax group cover the part that comes before \zs, which cannot be satisfied because some other groups have already occupied that part. This led me a complicated solution, by overriding the default highlight groups to include a new group (for Subscribers). But it turns out we really don't have to.
If interested, see Vim syntax file not matching with \zs.
Online regular expression playgrounds don't support Vim's syntax so using them is pointless, here.
See vimregex.com for an overview, :help usr_27 for a gentle tutorial, :help pattern for the definitive reference, and :help perl-patterns for the differences between the Vim syntax and the Perl syntax.

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: 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.

What is the meaning of the % character in 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) *:%*

Delete surrounding whitespace in vim

I'm using the awesome https://github.com/tpope/vim-surround plugin to surround words with parenthesis, for example I often use: viws<space><space> to surround a word with spaces.
What I'm missing is the opposite of this, that is, deleting surrounding spaces around a word.
The most common use for me is function arguments like
foo(bar) vs foo( bar ) depending on code style.
Does anyone know a nice way to do this?
Note: This solution requires the surround plugin referenced in the question.
For your specific situation you could do the following:
cs()
This changes foo( bar ) to foo(bar), however, it is not a general solution to your problem.
I often productively procrastinate in search of vim plugins too, when I could just define a mapping for this.
nnoremap <leader>dd F<space>xf<space>x
EDIT more information
<leader> common key for user defined mappings (, is a good one)
dd combination to use (any other mnemonic one will suffice)
F<space>x search backwards for a space, then remove it
f<space>x search forwards for a space, then remove it
Maybe just BXElx in normal mode.
In fact, perfect solution for me is the mapping provided by #puk, but using the keys #sarnold expected in the first place (what one would expect from surround plugin if it implemented this).
This is:
nnoremap ds<space> F<space>xf<space>x

Resources