Vimtex: Little help for implementing auto - adding "\item" in itemize and enumerate

Created on 15 Dec 2020  路  10Comments  路  Source: lervag/vimtex

Well as we already started in this issue: https://github.com/lervag/vimtex/issues/1863#issuecomment-743761892
I'm trying to implement a way to add \item automatically if I'm in an itemize environment. So currently I have this:

if vimtex#env#is_inside('itemize')
    imap <CR> i\item
else
    unmap <CR>
endif

But I'm getting this error message:

E745: Using a List as a Number

Do you have an idea how I can fix this?

enhancement

Most helpful comment

@lervag Your imap adds the item macro, but it doesn't add it in the new line: ...

Sorry, I forgot that you also wanted the newline. I see @j1-lee corrected my snippet. Thanks for pitching in, @j1-lee! For the custom function, I would rewrite it as follows:

function! ImapAutoItem()
  for l:env in ['itemize', 'enumerate']
    if vimtex#env#is_inside(l:env) != [0, 0]
      return "\<cr>\\item"
    endif
  endfor

  return "\<cr>"
endfunction

All 10 comments

I am not a vim expert, but how about putting the following in your vimrc?

inoremap <expr> <CR> (vimtex#env#is_inside('itemize') != [0, 0] ? "\<CR>\\item " : "\<CR>")

In your case, the error message seems to arise because vimtex#env#is_inside('itemize') returns a list, not a number (that can be interpreted as true/false).

@j1-lee proposes a relevant solution. I would add that such a map should be created either in a autocmd Filetype tex ... context or in a personal filetype plugin for tex, e.g. in ~/.vim/after/ftplugin/tex.vim. The latter is IMHO to be preferred. Further, I would suggest that you use the imaps feature (it is enabled by default), in which case you can add the mapping like this:

call vimtex#imaps#add_map({
      \ 'lhs' : '<cr>',
      \ 'rhs' : '\item ',
      \ 'leader'  : '',
      \ 'wrapper' : 'vimtex#imaps#wrap_environment',
      \ 'context' : [
      \   'itemize',
      \   'enumerate',
      \ ],
      \})

@j1-lee somehow your mapping doesn't work:
GIF

@lervag Your imap adds the \item macro, but it doesn't add it in the new line:
GIF

Do you have an idea how I can fix this?

For the inoremap command, I am not sure why that does not work. One reason might be the map is overwritten later somehow, e.g., by another plugin. Try putting that in nvim/after/ftplugin/tex, not nvim/ftplugin/tex, although I am not sure whether this would work.

Also, when you do so, insert <buffer> argument as follows:

inoremap <buffer> <expr> <CR> (vimtex#env#is_inside('itemize') != [0, 0] ? "\<CR>\\item " : "\<CR>")

As for the second solution involving vimtex#imaps#add_map(), i guess replacing a line to

      \ 'rhs' : "\r\\item ",

might work (or not hehe). Note we are using double quotes " here.

@j1-lee Yeah! It's working now! Adding the nvim/after/ftplugin/tex directory helped! that's coooooooool :D Thank you!
How do you know of this directory? Where can I read more about it?

Glad it worked! I heard of this directory when I was reading some stackexchange thread regarding setlocal formatoptions-=o. I don't remember the situation quite well, but the issue was something like putting that in nvim/ftplugin/ is overridden by some other plugins. The remedy was to put that in nvim/after/ftplugin/ instead. I am sorry I can't remember where exactly that came from, so I cannot provide a relevant reference...

@j1-lee new issue xD I want to have this feature as well if I'm in an enumerate environment. Currently I have this in my nvim/after/ftplugin/tex/mappings.vim:

inoremap <buffer> <expr> <CR> (vimtex#env#is_inside('itemize') != [0, 0] ? "\<CR>\\item " : "\<CR>")
imap <buffer> <expr> <CR> (vimtex#env#is_inside('enumerate') != [0, 0] ? "\<CR>\\item " : "\<CR>")

But now it doesn't add the \item automatically in an itemize environment. Do you have an idea how I can fix that?

I guess it is because the second line overrides the first line. In this case, we could think of something like the following:

function! ImapAutoItem()
  let l:in_itemize = vimtex#env#is_inside('itemize') != [0, 0]
  let l:in_enumerate = vimtex#env#is_inside('enumerate') != [0, 0]
  let l:return_imap = "\<CR>"
  if l:in_itemize || l:in_enumerate
    let l:return_imap .= '\item '
  endif
  return l:return_imap
endfunction

inoremap <expr> <buffer> <CR> ImapAutoItem()

But in this case I think the solution by @lervag:

call vimtex#imaps#add_map({
      \ 'lhs' : '<cr>',
      \ 'rhs' : "\r\\item ",
      \ 'leader'  : '',
      \ 'wrapper' : 'vimtex#imaps#wrap_environment',
      \ 'context' : [
      \   'itemize',
      \   'enumerate',
      \ ],
      \})

would be much better.

Edit: I changed s: to l:. This is not likely to change any behavior, but scoping with l: seems more accurate here.

@j1-lee woohoooo! The imap is working!!! Thank you!!!

@lervag Your imap adds the item macro, but it doesn't add it in the new line: ...

Sorry, I forgot that you also wanted the newline. I see @j1-lee corrected my snippet. Thanks for pitching in, @j1-lee! For the custom function, I would rewrite it as follows:

function! ImapAutoItem()
  for l:env in ['itemize', 'enumerate']
    if vimtex#env#is_inside(l:env) != [0, 0]
      return "\<cr>\\item"
    endif
  endfor

  return "\<cr>"
endfunction
Was this page helpful?
0 / 5 - 0 ratings

Related issues

benutzer193 picture benutzer193  路  4Comments

lervag picture lervag  路  5Comments

carloabelli picture carloabelli  路  3Comments

dsevero picture dsevero  路  4Comments

thomasahle picture thomasahle  路  4Comments