Vim Tips Wiki
(Fix a typo in a link.)
(consolidate bug list, create related scipts section for link)
Line 37: Line 37:
 
==See also==
 
==See also==
 
*[[VimTip1516|Mapping keys in Vim tutorial]]
 
*[[VimTip1516|Mapping keys in Vim tutorial]]
  +
  +
==Related scripts==
  +
*{{script|id=2100|text=textobj-user}} is a library that assists in writing text objects. With a patch to the Vim source, it can even handle things such as {{help|o_v}}.
   
 
==Comments==
 
==Comments==
 
{{todo}}
 
{{todo}}
   
  +
Bugs:
Fix bug: will select containing fold for nested folds if cursor is on first line of fold.
+
*Will select containing fold for nested folds if cursor is on first line of fold.
 
  +
*Cannot handle characterwise selection with o_v {{help|o_v}}
There is [http://www.vim.org/scripts/script.php?script_id=2100 textobj-user],a library to easily write text objects. It's not easy to write text objects which behabe the same as the built-in ones. For example, the above example cannot support characterwise selection with o_v (see :help o_v), and it must use onoremap not omap. textobj-user takes care of many troubles such as these.
 
  +
*Subsequent repetitions of the text-object do nothing. Should probably select next fold level for consistency with other text objects like aB.
----
 

Revision as of 14:35, 27 April 2009

Tip 1555 Printable Monobook Previous Next

created April 19, 2008 · complexity intermediate · 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.

See also

Related scripts

  • textobj-user is a library that assists in writing text objects. With a patch to the Vim source, it can even handle things such as :help o_v.

Comments

 TO DO 

Bugs:

  • Will select containing fold for nested folds if cursor is on first line of fold.
  • Cannot handle characterwise selection with o_v :help o_v
  • Subsequent repetitions of the text-object do nothing. Should probably select next fold level for consistency with other text objects like aB.