Skip to content

Commit

Permalink
Make vim respect the tab width settings
Browse files Browse the repository at this point in the history
Somehow the dune filetype in neovim ends up with the "lisp" option set
despite this not being explicitly configured. Without this setting
indentation of dune files does not happen at all, as it's needed for vim
to indent lines based on parentheses. Unfortunately when "lisp" is set,
it also causes the softtabstop and shiftwidth settings to be ignored,
presumably to allow for indentation conventions in lisp where elements
of lists are aligned to the first element of the list, regardless of its
indentation. The default behaviour with "lisp" enabled also effectively
uses a softtabstop of 2, and this can't be overriden by setting the
softtabstop variable.

This makes it frustrating to edit dune files in vim, as the indentation
inserted by the editor won't match the 1-space indentation commonly
found in dune files. The workaround is to to set lispoptions=expr:1
which allows vim to use a custom indentexpr when "lisp" is set, and
to supply a custom indentexpr function which changes the indentation
based on unmatched parentheses, which is an approximation of the
behaviour of `dune format-dune-file`.

Signed-off-by: Stephen Sherratt <[email protected]>
  • Loading branch information
gridbugs committed Nov 8, 2024
1 parent 81be9d0 commit bd3040c
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions indent/dune.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,36 @@
" Language: dune
" Maintainers: Markus Mottl <[email protected]>
" URL: https://github.com/ocaml/vim-ocaml
" Last Change: 2020 Dec 31
" Last Change: 2024 Nov 8 - Make vim respect the tab width settings (Stephen Sherratt)
" 2020 Dec 31

if exists("b:did_indent")
finish
endif
let b:did_indent = 1

" A rough approximation of the indentation behaviour implemented by
" `dune format-dune-file`.
function! DuneIndent()
let prev_line = getline(v:lnum - 1)
let prev_indent = indent(v:lnum - 1)
let current_indent = prev_indent
for i in range(len(prev_line))
if prev_line[i] == '('
let current_indent += &shiftwidth
endif
if prev_line[i] == ')'
let current_indent -= &shiftwidth
endif
endfor
return current_indent
endfunction

" dune format-dune-file uses 1 space to indent
setlocal softtabstop=1 shiftwidth=1 expandtab
" Explicitly set "lisp" since without this setting vim will not auto indent
" sexp files like dune files at all. When "lisp" is enabled, vim doesn't
" respect softtabstop or shiftwidth by default, so a custom indentexpr is
" needed.
setlocal softtabstop=1 shiftwidth=1 expandtab lisp indentexpr=DuneIndent() lispoptions=expr:1

let b:undo_indent = "setl et< sts< sw<"

0 comments on commit bd3040c

Please sign in to comment.