Reputation: 31491
I am trying to select an entire XML CDATA section with VIM. For those unfamiliar with XML, a CDATA section looks like this:
<someTag><![CDATA[
This text is escaped in a Character Data section!
Look, I can use < and > characters freely!
]]></someTag>
<anotherTag><![CDATA[More escaped text!]]></anotherTag>
I tried this mapping to visually select and yank the text inside the CDATA section, but it appears that the call function disables visual selection:
inoremap <F9> <Esc>:call searchpair('<!\[CDATA\[', '', ']]>', 'b')v:call searchpair('<!\[CDATA\[', '', ']]>')y
Is there any way to select the entire CDATA section? This is what I use to select methods in C-based languages, for reference:
inoremap <F7> <Esc><C-V>aBy
Thank you.
Upvotes: 2
Views: 155
Reputation: 393354
This fixed version works for me
:inoremap <F9> <Esc>:call searchpair('<!\[CDATA\[', '', ']]>', 'b')<CR>
v:<C-u>call searchpair('<!\[CDATA\[', '', ']]>')<CR>v`<o
(no linebreak in real life)
Tricks:
<CR>
for the necessary Enter keys<C-u>
to clear the range on the commandlinev`
to reselect to the start of the visual selectiono
to move cursor to end of visual selectionI'm surprised that this would be an insert mode mapping, I'm assuming you have normal mode mappings too.
By the way, perhaps you'd be interested in operator pending
mode mappings for 'proper' text-object semantics too:
Edit Update in response to comment:
The following appears to work (judicious use of \zs
and \ze
in the search pattern). You might want to back-track one position (add <BS>
to the end of the mapping). Also, by now, the operator-pending
type mapping seems to get more attractive.
:inoremap <F9> <Esc>:call searchpair('<!\[CDATA\[\zs', '', '\ze]]>', 'b')<CR>
v:<C-u>call searchpair('<!\[CDATA\[\zs', '', '\ze]]>')<CR>v`<o
PS.: You may want to apply an explicit magic-level (e.g. \V
) inside your search patterns as well
Upvotes: 3
Reputation: 4230
When you're making text objects it's important not to wrap around the file.
:call searchpair('<!\[CDATA\[', '', ']]>', 'bW')|call searchpair('<!\[CDATA\[', '', ']]>', 'sW')|norm v''o
Using the 's' flag sets the ' mark, which is nice.
Using the 'W' flag makes sure we don't do EOF wrapping, which is important.
Also, insert mode mappings generally benefit from <C-O>
, although in this case not so much. Still, it's a good habit to get into. So:
:inoremap <F9> <C-O>:<C-U>call searchpair('<!\[CDATA\[', '', ']]>', 'bW')|call searchpair('<!\[CDATA\[', '', ']]>', 'sW')|norm v''o
Upvotes: 1