What are the "paragraph macros" in :help paragraphs - vim

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.

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.

Vim paragraph motions { } not performing as expected

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

Remove Various Whitespaces While Editing in Vim

So oftentimes, while editing with Vim, I'll get into a variety of situations where whitespace gives me hassle. For example, say I have a comment like this:
#This program was featured on the Today show, it is an algorithm for promoting world peace in third-world countries
#given the name of that country and the name of a celebrity to endorse its cause
If I want to, for example, trim the lines so they go to X characters, I end up putting a newline somewhere in the middle of the top line to get this (after hitting the newline and auto-indenting):
#This program was featured on the Today show, it is an algorithm for promoting
world peace in third-world countries
#given the name of that country and the name of a celebrity to endorse its cause
I then add a # to the beginning of the line, and that's all well and good, but then I want that line to line up, too. To do so, I have to delete the newline, all the whitespace for the indent on the next line, and then the commenting # mark. It doesn't take an awfully long amount of time to do that, but this and similar situations all add up over a day's worth of coding.
Now the example above is pretty specific, but my question isn't. What's a good way in Vim to delete all whitespace INCLUDING NEWLINES up until the next non-whitespace character? If Vim already has movements that do that, that would be awesome, but if not, does anyone have a favorite Vim function they use to do the above that could be mapped to a key? At the very least, am I missing some Vim usage idiom that prevents me from even having to worry about this case?
EDIT: Formatting to width, while useful and applicable to the case above, isn't the focus of this question. I'm concerned more with whitespace removal that doesn't stop at the end of a line, but instead carries on to the first non-whitespace character of the next line.
You really just want to reformat that comment to fit the current 'textwidth'. If the comment is a paragraph (i.e., separated by a line of whitespace above and below), then you can just use gqip (gq is the reformat command, ip is the "inner-paragraph" text object) to reformat it. If it's not a standalone paragraph, you can visually select those lines and then use gq.
This likely also relies on having 'formatoptions' set correctly to make sure the comment characters are handled properly, but in many cases the ftplugin has already done that.
This is a while later, but I found that there is a command that does what I need to in 90% of circumstances:
J -- join line below to the current one
This command seems to work:
:.s/\W*$\n\W*//g
it uses a replace to remove whitespace up to end of line and the new line at the end.
In this example:
testting aad $
asdjkasdjsdaksddjk$
(to see meta characters in vim use the command :set list)
if you place the cursor on the first line and use the first command it will delete everything from aad to $ (not including aad but including $ and a newline.)
Also, note for what you are doing it is far more efficient to use an external program to format comments for you. In particular, par is a great small C program that edits text and wraps it to desired lengths.
If you have par in your path, to do what you are trying to do is as easy as selecting the block of comment with Shift+v and running the command
:!par 40pgr
where 40 is the desired width in columns.
If you are feeling hackish, write your own program in C/perl/C++/python that edits comments however you like, then put it in path and use the external filter command :! to process blocks of text through it.

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