Search code examples
vimindentationauto-indent

Getting vim to auto-indent this syntax


I've successfully gotten vim to understand my language's syntax for highlighting, but I'm unsure how to get it to automatically indent my code properly. The language itself is somewhat Lisp-like, but it uses both brackets [] and parentheses () as delimiters. The resulting code indentation should look something like this:

[foo [bar baz] [qux
  [do a thing]
  [more doing a thing]
  [^ ()
    ; some stuff here
    [foobar]]]]
[back to here]

Basically, each unclosed bracket or parenthesis should indent the line by two spaces. Closing said delimiter should decrease the following lines by the same amount.

I've looked into autoindent, but it doesn't seem sufficient for what I'd like to do, unless I'm missing something. The alternative, indentexpr, seems more promising, but I don't think I understand how to use it.

How can I get a working indentation system for my syntax?


Solution

  • Have you tried 'lisp' option? It produces

    [foo [bar baz] [qux
                     [do a thing]
                     [more doing a thing]
                     [^ ()
                        ; some stuff here
                        [foobar]]]]
    [back to here]
    

    on your example.

    You can also construct your own indentexpr. Very simple one will be

    if exists("b:did_indent")
       finish
    endif
    let b:did_indent = 1
    if exists('*shiftwidth')
        let s:shiftwidth=function('shiftwidth')
    else
        function s:shiftwidth()
            return &shiftwidth
        endfunction
    endif
    function! YourLangIndent(lnum)
        if a:lnum==1
            return 0
        endif
        let line=getline(a:lnum-1)
        return indent(prevnonblank(a:lnum-1))+s:shiftwidth()*(len(substitute(line, '[^[]', '', 'g'))-len(substitute(line, '[^]]', '', 'g')))
    endfunction
    setlocal indentexpr=YourLangIndent(v:lnum)
    let b:undo_indent='setlocal indentexpr<'
    

    . Its result:

    [foo [bar baz] [qux
            [do a thing]
            [more doing a thing]
            [^ ()
                ; some stuff here
                [foobar]]]]
    [back to here]
    

    (for &sw set to 4, half the amount of spaces for &sw set to 2).