Search code examples
vimneovim

neovim auto-indentation nuances


I've just switched from vim to neovim. The following vim config settings get the behaviour I want from indentation:

set tabstop=4
set shiftwidth=4
set softtabstop=4
set autoindent
set backspace=indent,eol,start

The relevant part here is the autoindent:

set autoindent

On each newline, this causes vim to match the indentation of the previous line:

def demo_autoindent():
    a = 'This line was manually indented'
····

The declaration of a was manually indented one step, but the second line was auto-indented to the same level. Here I have represented the auto-indent with a series of · characters.

Neovim matches this behaviour. However, Neovim tries to be a bit clever with blocks, or in this case declaring dictionaries in python:

def example_neovim():
    b = {
············

Note that Neovim has not auto-indented this line. If it had, it would have the same 4-space indent as the declaration of b. Instead, Neovim has added an extra two indents, bringing the total to 12-spaces.

Clearly what it intends to do is add one further indent:

def example_neovim_intention():
    c = {
········

How do I configure Neovim to either:

  1. Match the behaviour of vim, just auto-indent to the same level.
  2. Add a single (rather than a double) extra indent when declaring e.g. a dict.

Solution

  • I was facing exactly the same issue, I used VIM for quite a long time and recently I switch to NeoVim.

    Auto indention on for every other languages except "python" works well. I found this document quite useful: https://neovim.io/doc/user/indent.html#_python.

    :h ft-python-indent
    

    NeoVim will check this variable g:python_indent, if it is not defined a default one will be created, and it would be something like this (NeoVim 0.8.2):

    {
      'disable_parentheses_indenting': v:false,
      'closed_paren_align_last_line': v:true,
      'searchpair_timeout': 150,
      'continue': 'shiftwidth() * 2',
      'open_paren': 'shiftwidth() * 2',
      'nested_paren': 'shiftwidth()'
    }
    

    Change these properties continue,open_paren and closed_paren_align_last_line as follows.

    {
      'disable_parentheses_indenting': v:false,
      'closed_paren_align_last_line': v:false,
      'searchpair_timeout': 150,
      'continue': 'shiftwidth()',
      'open_paren': 'shiftwidth()',
      'nested_paren': 'shiftwidth()'
    }
    

    Another Approach

    This can fix the weird indention issue easier. It work on my side, but maybe buggy according to the replies below.

    Setup nvim-treesitter/nvim-treesitter and turn on tree-sitter's indention feature.

    require('nvim-treesitter/nvim-treesitter').setup {
      ...
      indent = { enable = true },
      ...
    }