3

I use Vim to write longer sequences of body text. It does automatic formatting, which generally works nicely. If I have a sentence that ends in a number, say a date or a year, and that number happens to be placed at the beginning of a line, Vim will indent the next line, as if it is part of a numbered list.

I am editing an .rst file.

I have looked at formatoptions and suspected the n flag of being the problem, but set fo-=n made no difference.

I think I am missing some obvious setting that could solve this, but I am unsure where to start looking. Obviously I looked at formatoptions, fo-table, autoindent et. al., but as I see it I already unset the relevant option. What am I missing?

0

1 Answer 1

2

It looks like the rst filetype has some custom indentation rules which add this indentation. This works by setting the indentexpr setting to GetRSTIndent in /usr/share/vim/vim80/indent/rst.vim.

To completely disable the rst indentation you can use something like:

augroup ftype_rst
    autocmd!
    autocmd Filetype rst setlocal indentexpr=
augroup end

This will disable all indent rules, which may not be what you want. To disable just these rules you can override the GetRSTIndent() function in ~/.vim/after/indent/rst.vim (I've commented out the five lines that add indentation for lists):

let s:itemization_pattern = '^\s*[-*+]\s'
let s:enumeration_pattern = '^\s*\%(\d\+\|#\)\.\s\+'

function! GetRSTIndent()
  let lnum = prevnonblank(v:lnum - 1)
  if lnum == 0
    return 0
  endif

  let ind = indent(lnum)
  let line = getline(lnum)

  " if line =~ s:itemization_pattern
  "   let ind += 2
  " elseif line =~ s:enumeration_pattern
  "   let ind += matchend(line, s:enumeration_pattern)
  " endif

  let line = getline(v:lnum - 1)

  " Indent :FIELD: lines.  Don’t match if there is no text after the field or
  " if the text ends with a sent-ender.
   if line =~ '^:.\+:\s\{-1,\}\S.\+[^.!?:]$'
     return matchend(line, '^:.\{-1,}:\s\+')
   endif

  if line =~ '^\s*$'
    execute lnum
    call search('^\s*\%([-*+]\s\|\%(\d\+\|#\)\.\s\|\.\.\|$\)', 'bW')
    let line = getline('.')
    if line =~ s:itemization_pattern
      let ind -= 2
    elseif line =~ s:enumeration_pattern
      let ind -= matchend(line, s:enumeration_pattern)
    elseif line =~ '^\s*\.\.'
      let ind -= 3
    endif
  endif

  return ind
endfunction

You can also look at tweaking the s:enumeration_pattern regexp. You didn't really mention which cases fail for you, so I can't really help you there.

3
  • Thanks @Carpetsmoker. I'll give these options a go later, and let you know how it goes.
    – ravnsgaard
    Jun 21, 2017 at 9:14
  • The s:enumeration_pattern was indeed the problem here. I've disabled it for now, but I'll look into tweaking it instead. Thanks for your input, @Carpetsmoker. Appreciated.
    – ravnsgaard
    Jun 21, 2017 at 17:50
  • A final note on this. The tweak is actually very simple: s:enumeration_pattern now starts with ^\s+ instead of ^\s*. Then if I want a numbered list, I need to start with at least one whitespace character on that line to trigger the automatic indentation, but I always do that anyway. This way it doesn't foul my normal flow, though.
    – ravnsgaard
    Jun 22, 2017 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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