Vim Tips Wiki
(Insert TipProposed template + minor manual clean)
(tweak for consistency and first-line functionality)
Line 17: Line 17:
 
A text object has two behaviors that need to be defined: visual mode, where it will select the appropriate text, and as a motion for an operator. So, you will need to use both a vmap and an omap to get the full text-object behavior. As a simple example, we will use a text object for operating on "a fold".
 
A text object has two behaviors that need to be defined: visual mode, where it will select the appropriate text, and as a motion for an operator. So, you will need to use both a vmap and an omap to get the full text-object behavior. As a simple example, we will use a text object for operating on "a fold".
   
We will start with visual mode, because it is simpler. We want to set the start of visual mode to the start of the fold, so we will first need to leave visual mode with <ESC> (because <ESC> will work no matter what the visual mode is) and then move the cursor to the start of the fold with z[. Next, we need to re-enter visual mode. The first inclination would be to use v to enter visual mode, but to get it to work in all modes, we should instead look at the specific visual mode we are in using the mode() function. Finally, we need to set the end of the visual selection to the end of the fold with z]. The entire mapping looks like this (vnoremap is used to ensure we get the built-in functionality of all commands, especially CTRL-V for visual block mode):
+
We will start with visual mode, because it is simpler. We want to set the start of visual mode to the start of the fold, so we will first need to leave visual mode with <ESC> (because <ESC> will work no matter what the visual mode is) and then move the cursor to the start of the fold with z[. This command will fail if performed when already on the first line in a fold, so we need to wrap the command in <tt>:silent! normal!</tt> in order to continue the mapping even in the case of an error. Next, we need to re-enter visual mode. Folds are based on lines, so it makes most sense to enter visual line selection with V. The other option would be to use an <expr> mapping, and use the 'mode()' function to discover the visual mode, but this is inconsistent with the behavior of other text objects. Finally, we need to set the end of the visual selection to the end of the fold with z]. The entire mapping looks like this (vnoremap is used to ensure we get the built-in functionality of all commands):
   
 
<pre>
 
<pre>
vnoremap <expr> af '<ESC>z['.mode().'z]'
+
vnoremap af :<C-U>silent! normal! [zV]z<CR>
 
</pre>
 
</pre>
   
Line 34: Line 34:
   
 
==Comments==
 
==Comments==
  +
{{todo}}
  +
  +
Fix bug: will select containing fold for nested folds if cursor is on first line of fold.
  +
  +
----
 
I'm not entirely sure if this merits a new tip, or if it should be merged with [[Indent text object]]. I do think this title is superior, and that we need a more general tip that uses examples, such as this one. That's why I placed it in [[:Category:Map]] because I think it demonstrates a good ''method'' to map something, rather than a good ''application'' of a mapping. The two tips may be dissimilar enough in focus that we could use two separate tips (the indent text object is much more complex and requires a function, so I feel it detracts from any general message).
 
I'm not entirely sure if this merits a new tip, or if it should be merged with [[Indent text object]]. I do think this title is superior, and that we need a more general tip that uses examples, such as this one. That's why I placed it in [[:Category:Map]] because I think it demonstrates a good ''method'' to map something, rather than a good ''application'' of a mapping. The two tips may be dissimilar enough in focus that we could use two separate tips (the indent text object is much more complex and requires a function, so I feel it detracts from any general message).
   

Revision as of 18:16, 21 April 2008

Proposed tip Please edit this page to improve it, or add your comments below (do not use the discussion page).

Please use new tips to discuss whether this page should be a permanent tip, or whether it should be merged to an existing tip.
created April 19, 2008 · complexity basic · author Fritzophrenic · version 7.0

A very useful feature of Vim is the ability to operate on "text objects", allowing you to delete a word with the cursor anywhere on the word, visually select a block of code from anywhere within the code, etc. with very little typing and no movement.

For example, to visually select a quoted string (with the quotes), type va". To change the entire contents of a () group (without changing the parentheses themselves), type ci(. See :help text-objects for more details.

Occasionally, however, you will come across a situation where what you want to act on is a well-defined object, but is not a Vim-defined text object. Examples of this include all text of the same indent level, or all text within a fold. Vim's excellent mapping tools allow you to simulate the behavior of text objects for behavior you define.

A text object has two behaviors that need to be defined: visual mode, where it will select the appropriate text, and as a motion for an operator. So, you will need to use both a vmap and an omap to get the full text-object behavior. As a simple example, we will use a text object for operating on "a fold".

We will start with visual mode, because it is simpler. We want to set the start of visual mode to the start of the fold, so we will first need to leave visual mode with <ESC> (because <ESC> will work no matter what the visual mode is) and then move the cursor to the start of the fold with z[. This command will fail if performed when already on the first line in a fold, so we need to wrap the command in :silent! normal! in order to continue the mapping even in the case of an error. Next, we need to re-enter visual mode. Folds are based on lines, so it makes most sense to enter visual line selection with V. The other option would be to use an <expr> mapping, and use the 'mode()' function to discover the visual mode, but this is inconsistent with the behavior of other text objects. Finally, we need to set the end of the visual selection to the end of the fold with z]. The entire mapping looks like this (vnoremap is used to ensure we get the built-in functionality of all commands):

vnoremap af :<C-U>silent! normal! [zV]z<CR>

Now that we have the visual mode mapping, we can actually use it to make our operator-pending mode mapping easier. Since a fold acts on entire lines, "a fold" should probably act on the entire fold (an "inner fold" is more open to interpretation...if it even makes sense). So, an easy way to accomplish an operation would be to visual line select the fold, then apply the operator. This can be done with:

omap af :normal Vaf<CR>

Here, we use omap and :normal without a bang (!) in order to make sure we use the remapped version of visual selection.

With these two simple mappings, you will now be able to use af just like a normal text object to act on folded text! More complex applications such as an indent-level text object may require a function call to accomplish, but the concept is the same. Map an appropriate visual mapping, and if possible, use it to simplify the operator mapping.

Comments

 TO DO 

Fix bug: will select containing fold for nested folds if cursor is on first line of fold.


I'm not entirely sure if this merits a new tip, or if it should be merged with Indent text object. I do think this title is superior, and that we need a more general tip that uses examples, such as this one. That's why I placed it in Category:Map because I think it demonstrates a good method to map something, rather than a good application of a mapping. The two tips may be dissimilar enough in focus that we could use two separate tips (the indent text object is much more complex and requires a function, so I feel it detracts from any general message).

--Fritzophrenic 17:11, 19 April 2008 (UTC)


Well, one is about the theory, the other is an applictation. A quite complete, and complex, one actually. Hence, I kind of like having two tips.

By the way, this aspect is also addressed into Yegappan's tutorial: VimTip1516.

Last thing, I'd also put this tip into Category:Scripting

--Luc Hermitte 18:05, 19 April 2008 (UTC)