Vim paragraph motions { } not performing as expected - vim

Whilst editing a text file I found that the { and } (paragraph back / paragraph forward) motions navigated to two points in the file which were not paragraph breaks.
The file in question is identified in Notepad++ as ANSI as UTF-8 and contains some cyrillic looking characters.
The file was generated by creating a backup of a filter subscription list setting in the AdblockPlus Firefox extension.
I don't understand why the motion operators would suddenly stop in the middle of a paragraph.

From :help paragraph:
A paragraph begins after each empty line, and also at each of a set of
paragraph macros, specified by the pairs of characters in the 'paragraphs'
option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to
the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in
the first column). A section boundary is also a paragraph boundary.
A section begins after a form-feed (<C-L>) in the first column and at each of
a set of section macros, specified by the pairs of characters in the
'sections' option. The default is "SHNHH HUnhsh", which defines a section to
start at the nroff macros ".SH", ".NH", ".H", ".HU", ".nh" and ".sh".
So, it could be some strange characters starting with . in column 1, or a form-feed (^L).
The first one can be avoided with :set paragraphs= sections=.
Also, check that you don't have a mapping overload of } via :verbose nmap }.

Related

Why are paragraphs interpreted differently using "{" and "}" motions vs. "ap" and "ip"?

When using { or } to navigate between paragraphs, Vim appears to treat lines with white space characters as if they were part of the paragraph and skips past them. This behaviour has been discussed in a number of threads and the explanation given (based on :h paragraph) is that "a paragraph begins after each empty line", which is fine.
However, this does not appear to be consistent with the way Vim treats the ap and ip commands, which actually do treat lines with whitespace characters as paragraph breaks. For example, given the following text where the first two paragraphs are separated by a non-empty line (containing whitespace) and the second and third paragraphs are separated by an empty line (and assuming the cursor starts at the top of the buffer) the following occurs:
1 abc # next line contains spaces
2
3 def # next line is blank
4
5 jkl
}: moves the cursor to line 4 (i.e., treats lines 1-4 as a paragraph)
dap: deletes lines 1 and 2 (i.e., treats only lines 1-2 as a paragraph)
These two behaviours appear to be inconsistent with one another. Why do these two commands that operate on a paragraph object behave differently?
As mentioned in :help ap and :help ip:
Exception: a blank line (only containing white space) is also a paragraph boundary.
So the behaviour of ap was made voluntarily different from that of } and the difference is clearly documented. The exact reasoning behind that difference is explained nowhere, though, and may be lost in time. You might want to ask on Vim's official mailing list.
Anyway, we can extrapolate a little…
Vim's } is consistent with vi's }. This is expected since Vim's whole purpose is, after all, to be a convincing stand-in for vi.
ap (and the whole concept of text objects) is a Vim thing. It wasn't in vi so there is no existing behaviour to replicate and the person who added that feature decided to make it treat "paragraphs" in a slightly more intuitive fashion than }.

What Are the Differences Between the Vim Text Objects ip and ap?

The Vim Handbook gives them both the exact same description. From the Vim Handbook:
ap: "a paragraph", select [count] paragraphs. Exception: a blank line (only containing white space) is also a paragraph boundary. When used in Visual mode it is made linewise.
ip: "inner paragraph", select [count] paragraphs. Exception: a blank line (only containing white space) is also a paragraph boundary. When used in Visual mode it is made linewise.
Because of this, it is not entirely clear to me what the differences between these are. For example, say you had the commands gqap and gqip. How do they differ in behaviour?
Again, just reading :help ap because someone gave you the link, without proper background, will get you nowhere and only bring more confusion.
Text objects can be of two types: those that include their boundaries and those that exclude their boundaries.
By convention, text objects that include their boundaries start with a, like ap, and those that exclude their boundaries start with i, like ip.
What constitutes a "paragraph" is explained under :help paragraph, which is linked from both :help ip and :help ap. In concrete terms, the boundaries of a paragraph are:
a non-empty line preceded by an empty one, think of it as zero-width match,
the next empty line.
So you have ip, which excludes the empty line, and ap, which includes it:
[...] end of paragraph above.
Beginning of paragraph in the middle | |
with some boring filler text so that | ip | ap
it covers a few lines. | |
|
Beginning of paragraph below [...]
When doing gq over a paragraph, using ip or ap doesn't really matter because the extra empty line is unlikely to change anything to what is being done to the text. ip and ap are a bit of an exception, here, because the difference between the two types of text objects usually matters quite a lot:
it
----------------------
<h2>One day I will be a H1</h2>
-------------------------------
at
See :help text-objects for a reference on the subject and :help 04.8 for a more gentle introduction.
As alluded to in my other answer, proper learning lets you develop an intuition that is hard to build from random, disconnected, links and tweets and so on.

What are the "paragraph macros" in :help paragraphs

Running :help paragraph in vim gives:
A paragraph begins after each empty line, and also at each of a set of
paragraph macros, specified by the pairs of characters in the 'paragraphs'
option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to
the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in
the first column).
Most of the vim help I've seen has been super helpful, and I was beginning to feel I was getting a grip on it. Suddenly though:
IPLPPPQPP TPHPLIPpLpItpplpipbp
Aaand I'm lost.
Could someone explain to me what this sequence of characters is supposed to mean?
nroff(1) is a unix text-formatting utility. It's e.g. used for formatting the man pages.
In nroff, you got macros that do stuff: e.g. .PP means following is a paragraph with the first line indented. These macros are usually(1) 2-letter codes preceded by a dot.
The docs are saying how Vim detects paragraph boundaries: A paragraph boundary is either an empty new line or a dot in the first column followed by one of the 2-letter codes specified in the paragraphs option.
Example:
Hello
LP
World
If I put the cursor on World and enter vip in normal mode. Everything will be selected.
Hello
.LP
World
.LP is contained in the paragraphs option, thus vip will in this case not mark Hello as it's above the paragraph boundary.
(1) For 1-letter macros, you append a space. That's why there is a space in the default paragraphs value, it's for .P.

How to highlight long paragraphs?

I know how to highlight long lines. Either :
:match ErrorMsg '\%>140v.\+'
which I rather prefer to the "colorcolumn way" :
:set colorcolumn=140
So, for instance, the text :
Vim is a text editor written by B. Moolenaar and first released
publicly in 1991. It is based on the vi editor common to Unix-like
systems. Vim is free and open source software.
gets highlighted starting with "Vim is free, etc…"
But how can I achieve the same result for a paragraph (in this example, 3 lines) such as :
[Empty line]
Vim is a text editor written by B. Moolenaar and first released publicly in 1991.
It is based on the vi editor common to Unix-like systems.
Vim is free and open source software
[Empty line]
Thanks in advance
This is difficult, because you have to specify (in a single regular expression)
the condition of paragraphs (which I assume to be lines separated by at most a single newline; i.e. empty lines create new paragraphs)
the counting of characters (highlight after 140 characters)
Here's the best I've achieved; it still somehow matches "into" following paragraphs if the current one is too small:
:match ColorColumn /\%(\%^\|\n\n\)\%(\%(.\+\n\)*.*\)\&\_.\{140}\%(\zs.\|\n\zs.\)/
Explanation:
anchored at the beginning of the buffer or an empty line
match non-empty line(s)
and additional characters AND
match 140 characters and/or newlines
then start a match on the following character, or if that it a newline (which doesn't show up right), the next character after it
I'd be happy if someone improves on this.

vim select paragraph -- how to redefine paragraph boundaries?

In vim, vip selects "inner paragraph" :help v_ip,
however it is of limited use.
vim paragraph boundary is hard coded, a
paragraph is separated by 2 or more blank lines.
:help paragraph
Some archaic marcos like .IP, also seem to be supported as
paragraph separators, but it is all hard coded.
I want to specify my own paragraph separators to easily
select paragraphs of text in vim.
Like perl in paragraph mode using an regexp splitter.
I tried setting paragraphs to be delimited by blank lines or braces:
:set paragraph+={ cpoptions+={
but does NOT work as documented,
braces are ignored by 'vip' selection command.
The solution I want should work for all paragraphs commands
like vip, vap, dip, dap, {,}.
Note how you can map operators, so you won't have to remap vip or vap (you could map aH to your movement operation - and all of the following work magically using your selections:
daH
vaHy
d2aH
etc
I don't know if it's an option for you, but you can change paragraph delimiting in certain way by including the 'w' flag in 'formatoptions'. Check out help for 'fo-table' to read more. Basically it makes it so that lines ending in a space are like 'soft returns' and lines ending in a non-space character mark the end of paragraphs. Empty lines are not markers at all in this case. The 'w' formation flag does work with all vip, vap, etc., if I recall.
If that isn't going to do the trick for you, then I suggest remapping the vip, vap, etc. sequences to a custom function of your own. That way you can set it up to select things exactly as you want.
See :help paragraphs.
'paragraphs' 'para' string (default "IPLPPPQPP TPHPLIPpLpItpplpipbp")
global
Specifies the nroff macros that separate paragraphs. These are pairs
of two letters (see object-motions).

Resources