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

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.

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

c, i and s commands combined in VIM

I've been using VIM for a while and it surprises me each time. Under "Building Sentences" section in this tutorial, I saw the combination of commands cis and yip. I have used Vim quite a while and I am familiar with most commands in Normal Mode. I also know combining the commands in a meaningful way to produce combined actions.
However, the examples I showed above (cis and yip) totally broke my understanding of VIM command system in normal mode. "c" stands for change, "i" stands for insert and "s" stands for substitute but combined action is different than I would expect. I also went through VIM help files but never saw an example illustrating given usage.
Could someone clarify what's going on ?
cis
In vim help it is described as follows
:help c
"Delete {motion} text [into register x] and start insert …"
The next part of the command cis refer to the "motion" part. These commands are for text object selection. An explanation on the different types of text object selections can you get here:
:help text-objects
e.g. for
is – "inner sentence", select [count] sentences …
Analog to the explanation above its the same with yip
:help y
"Yank {motion} text [into register x] … "
And the text selection part yip
ip – "inner paragraph", select [count] paragraphs (see paragraph) …
In this case i does not stand for Insert and s not for substitute.
cis = change inner sentence.
This is completly logic once you understand the basic principle. Each command is like a sentence, it needs an Verb(Action) and an Noun(Object) and there are modifiers.
So the first button is your action C (Change). Now the following keystrokes will not be actions, until the c action ended (Until an Object is provided, or an invalid sequence is inserted). I (inner) is a modifier here and S the Object (Sentence).
I find this especially usefull for Changing words. if you only press cw on a word, you have to have the cursor on the beginning of the word.
With ciw you can change the whole word regardless of the cursor position (Note if you have / or some other seperators in the word, you maybe need ciW)
same letter can have different meanings. E.g. (/{ move to sentences/paragraph back, but ci( or ci{ means change in (...)/{...}.
Same as your s case, s in normal mode alone, does delete & start insert, however in cis, das means sentence.
p case: in normal mode alone, means paste, however in cip, yap ... means paragraph.
:h text-objects
will show you the concept of text-objects. It is a must skill for vim user. ;-)

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.

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

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