2

In some very specific scenarios, the auto indenter has almost unexplainable behavior that is very annoying. Example with haskell MultiWayIf syntax (cursor is at the "!"):

test
    | test
    | test = if
        |!

when I press space, this turns into:

test
    | test
    | test = if
                | !

I assume this is because it wants the pipe to be indented visually after the if keyword, because when I press enter here:

    | test = if!

it ends up here:

    | test = if
                !

but I do not want this behavior, and there should be some way to turn it off without turning off auto indentation entirely.

To be clear, the desired behavior would be this:

    | test = if!

(enter is pressed)

    | test = if
        !

to conform with the four spaces for every level indentation style I have set in my .vimrc (set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab ).

2
  • Welcome to Vi and Vim! In many cases the indent programs are hacky Vimscript that mostly works. If you have a formatting program for Haskell i can suggest s more robust solution (and I would love to know what it is if you do!). Note that it won’t help with indent as you type, but it can be made to reformat sections of the file.
    – D. Ben Knoble
    Commented Aug 14, 2020 at 13:12
  • @D.BenKnoble I did not use a haskell formatter, but when I looked into them based on your suggestion, haskell-formatter is the one I prefer. It actually has a different way of formatting this MultiWayIf syntax which does not trigger the auto indenter that I might try to use, but I am still interested in hearing this robust solution. Commented Aug 14, 2020 at 16:31

1 Answer 1

1

There are two options that can be set to run arbitrary programs to format text (code). When they aren't set, vim will work with lots of other (often complex, and often somewhat hacky) options to indent or format your text.

These options are equalprg (trigged by =) and formatprg (triggered by gq). Technically one is for indenting and the other for formatting, but since most formatting programs do both these days you may not care; pick the one you use the most.

It's not specified for equalprg, but the program you use for either (take input on standard in, write formatted output to standard out).

So in the case of haskell-formatter, you would do

" ~/.vim/after/indent/haskell.vim
setlocal equalprg=haskell-formatter
" or
setlocal formatprg=haskell-formatter

Then use = or gq to fix your code. You may find that some programs don't handle single lines too well; in that case, using =ap or gqap tends to work better. gg=G and gggqG take care of the whole file, but at that point it may be easier to run :%!haskell-formatter.

You could technically drop these lines in an ftplugin file, too, but this seems a bit cleaner to me.

An alternative, if you need to always reindent/reformat the whole file:

" ~/.vim/after/indent/haskell.vim
setlocal equalprg=haskell-formatter
" ~/.vim/after/ftplugin/haskell.vim
nnoremap <buffer> = :execute '%!' &l:equalprg<CR>
" or
nnoremap <buffer> == :execute '%!' &l:equalprg<CR>
" or
nnoremap <buffer> = gg=G
" ... you get the idea

You could similarly remap gq (or gqgq + gqq) and use &l:formatprg.

Make sure to set b:undo_ftplugin if you care about such things.

If you want to restore cursor position/etc., I would use winsaveview()/winrestview().

2
  • One problem with this solution. haskell-formatter only formats the code if it compiles correctly, and MultiWayIf is a language option that has to be explicitly enabled in a pragma statement at the beginning of the document. =ap doesn't work on MultiWayIf formatting because it doesn't read a pragma statement at the beginning of the input. Is there any way you could work around this without having to format the whole file every time? Commented Aug 15, 2020 at 0:20
  • Hm. Some people remap = or == to format the whole file. Imo it’s a bug if a formatter doesn’t work on code that doesn’t compile since the formatter isn’t compiling code, (usually it just needs to be syntactically correct). Regardless, this is a fairly common issue (rustfmt has the same issue). I wonder if there’s a way to configure the formatter; alternately, you may try a different one?
    – D. Ben Knoble
    Commented Aug 15, 2020 at 13:15

Your Answer

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

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