29

Quotation marks in LaTeX are different than in normal text, in that they're formatted ``like this'' (or `like this' for single quotes). This makes it difficult to navigate through them in Vim.

I usually use something like T`ct' (backwards until `, change until '). However, this is clunky and unnatural. I would prefer to be able to use something along the lines of ciq ("change in quotes"), just like I can do ciw, ca), ci", ca', etc.

Is there any way to tell Vim to treat ``LaTeX'' `quotes' as text objects? (As a plus, is there any way to only trigger this while editing a .tex file?)

10

I don't know LaTeX but this seems to work:

vnoremap iq :<C-U>silent! normal! t'vT`<CR>
omap iq :normal viq<CR>

I based this off the information over here: http://vim.wikia.com/wiki/Creating_new_text_objects

You can add support for aq as well:

vnoremap aq :<C-U>silent! normal! f'vF`<CR>
omap aq :normal vaq<CR>
  • This works for iq, but doesn't seem to work with, for example, daq. – Doorknob Feb 13 '15 at 22:13
  • Right. You can make it work with aq as well with an additional similar mapping. I edited the answer. I also swapped T` with t' in the mapping so that it searches forward first, which seems more natural to me. – superjer Feb 16 '15 at 23:21
  • This works for single quotes, but daq on ``foo'' just results in `foo'. – Doorknob Feb 16 '15 at 23:57
  • I don't think this method can work for more than single quotes. You would need to do deeper inspection of the text than the f and t operators allow, which would require writing a whole function with variables and everything. I don't have time to do so right now. – superjer Feb 17 '15 at 1:49
7

Edit: I just discovered the vim-textobject-latex plugin, which adds the exact functionality you're looking for (in addition to a few other things). From the plugin's README:

Currently supported text objects are:

a   i   Description
a\\ i\\ Inline math surrounded by ``\\(`` and ``\\)``.
a$  i$  Inline math surrounded by dollar signs.
aq  iq  Single-quoted text ``\`like this'``.
aQ  iQ  Double-quoted text ``\``like this''``.
ae  ie  Environment ``\begin{...}–\end{...}``

So you can use caq and the like as you wanted. I tested it, and it works as advertised, but note that it is dependent on the vim-textobject-user plugin. Also note you must make sure that the textobject-user plugin loads first, otherwise things won't work.


If you don't want to mess with plugins, however, my original answer remains useful:

Adding these two lines to your .vimrc will cover most of what you want.

onoremap aq :<c-u>normal! F`vf'<cr>
onoremap iq :<c-u>normal! T`vt'<cr>

These create new text objects (aq and iq) which go back to the previous `, enter visual selection mode, then select up to the next '.

This will work for ciq, caq, yiq, and diq. However, yaq and daq will not yank/delete the outer quotes, so I created another text object, a", to handle that (i" is not needed, but I added to keep things consistent:

onoremap a" :<c-u>normal! 2F`v2f'<cr>
onoremap i" :<c-u>normal! 2T`v2t'<cr>

The major downside here is that this will break normal ca", etc. use. If you preface them with au FileType tex, you'll only have that issue in .tex files, but it still might occasionally be an annoyance. You could also name the object something like ad/id ('d' for 'double' quote), but that seemed less intuitive to me (I was aiming for the least difference from normal operation).

The only way I can think of to wrap these up into just two text objects would be to write a function that checks for another quote outside of the first set and set the aq text objects to call that.

Note: There are a couple other minor issues with these:

  1. Yanking might leave your cursor in an unexpected place (this could be fixed by adding using a mark in the commands (e.g. ma2F`v2f'<cr>`a), just make sure not to use one you frequently use manually)
  2. The cursor must be inside the quotes; weird things happen if it is on the quotes.

To wrap all of that up, this is what I personally would add to my .vimrc for this issue:

augroup filetype_latex
    au!
    au FileType tex,plaintex onoremap a' :<c-u>normal! muF`vf'<cr>`u
    au FileType tex,plaintex onoremap i' :<c-u>normal! muT`vt'<cr>`u
    au FileType tex,plaintex onoremap a" :<c-u>normal! mu2F`v2f'<cr>`u
    au FileType tex,plaintex onoremap i" :<c-u>normal! mu2T`v2t'<cr>`u
end augroup

As you can see, I opted for breaking normal ca'/ya"/etc functionality so I wouldn't have to learn new commands for them since I wouldn't be using the normal functionality as much within LaTeX anyways. That's just a personal preference; not hard to switch the object names. I also added in the filetype detection and marks.

2

This is an old question but for the benefit of future visitors: I find its easier to change the latex quotes with:

\usepackage{csquotes} % change " " into nice double quotes  
\MakeOuterQuote{"}

And then This thing is "Foobar"! will work fine in vim and latex.

0

Plugin vim-sandwich

Another useful plugin for this is vim-sandwich which has defined ft-specific surroundings

  • l` or l' for `text',
  • l" for ``text'' and
  • textobjects to easily operate on them.

With the default mappings following work

  • textobject: replace inner text of `text' with cisl' or if auto detection of nearest surrounding is fine cib (e.g. cursor on h in `a (phony) text' requires to press vibibc). However, you can define following additional textobject iq (OP example) omap <unique> iq <Plug>(textobj-sandwich-query-i)l' xmap <unique> iq <Plug>(textobj-sandwich-query-i)l' omap <unique> aq <Plug>(textobj-sandwich-query-a)l' xmap <unique> aq <Plug>(textobj-sandwich-query-a)l' omap <unique> iQ <Plug>(textobj-sandwich-query-i)l" xmap <unique> iQ <Plug>(textobj-sandwich-query-i)l" omap <unique> aQ <Plug>(textobj-sandwich-query-a)l" xmap <unique> aQ <Plug>(textobj-sandwich-query-a)l" Now simply pressing ciq or ciQ works.
  • add to text with saiwl' single apostrophes to get `text'
    The pattern of the command is sa{motion/textobject}{surrounding} and means invoke operator add surrounding on inner word and surround type is latex single quote.
  • delete with sdl' or with sdb
  • change with srl'l" or with srbl"

It supports

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.