Search code examples
xmlvimcdata

VIM: Scripting a selection of the entire CDATA section


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.


Solution

  • 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 commandline
    • v` to reselect to the start of the visual selection
    • o to move cursor to end of visual selection

    I'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