Search code examples
vimerrorformat

Setup errorformat for multi line error message produces by ghcide


I'm trying to setup errorformat for ghcide, which produces following output.

ghcide version: 0.0.4 (GHC: 8.6.5)
Ghcide setup tester in /opt/devel/haskell/haskell-vim-now.
Report bugs at https://github.com/digital-asset/ghcide/issues

Step 1/6: Finding files to test in /opt/devel/haskell/haskell-vim-now
Found 1 files

Step 2/6: Looking for hie.yaml files that control setup
Found 1 cradle

Step 3/6, Cradle 1/1: Implicit cradle for /opt/devel/haskell/haskell-vim-now
Cradle {cradleRootDir = "/opt/devel/haskell/haskell-vim-now", cradleOptsProg = CradleAction: default}

Step 4/6, Cradle 1/1: Loading GHC Session

Step 5/6: Initializing the IDE

Step 6/6: Type checking the files
File:     foo.hs
Range:    1:4-1:5
Source:   typecheck
Severity: DsError
Message: 
  ESC[0;91mfoo.hs:1:5: error:
  • No instance for (Num String) arising from the literal ‘5’
  • In the expression: 5
  In an equation for ‘x’: x = 5ESC[0m
Completed (1 file worked, 0 files failed)

With following ~/.vim/compiler/ghcide.vim:

CompilerSet  errorformat=%-Gghcide\ %s
CompilerSet  errorformat+=%-GReport\ bugs\ at\ %s
CompilerSet  errorformat+=%-GStep\ %s
CompilerSet  errorformat+=%-GFound\ %s
CompilerSet  errorformat+=%-GCradle\ %s
CompilerSet  errorformat+=%-GRange:\ %s
CompilerSet  errorformat+=%-GFile:\ %s
CompilerSet  errorformat+=%-GSource:\ %s
CompilerSet  errorformat+=%-GSeverity:\ %s
CompilerSet  errorformat+=%-GCompleted\ %s
" exclude empty or whitespace-only lines
CompilerSet  errorformat+=%-G\\s%#
CompilerSet  errorformat+=%E!\ Message:%>%trror%m
setlocal makeprg=ghcide\ %

Quickfix buffer shows only remaining four lines:

:clist                                                                                                                                                                                                             
 1: Message:-                                                                                                                                                                                                      
 2:   ^[[0;91mfoo.hs:1:5: error:                                                                                                                                                                                   
 3:   • No instance for (Num String) arising from the literal ‘5’                                                                                                                                                  
 4:   • In the expression: 5  

Since I couldn't figure out by my self how aforementioned multi line message could be mapped into single clist entry, I'm looking for help.


Solution

  • You could try this:

    CompilerSet errorformat=%-Gghcide\ %s
    CompilerSet errorformat+=%-GReport\ bugs\ at\ %s
    CompilerSet errorformat+=%-GStep\ %s
    CompilerSet errorformat+=%-GFound\ %s
    CompilerSet errorformat+=%-GCradle\ %s
    CompilerSet errorformat+=%-GRange:\ %s
    CompilerSet errorformat+=%-GFile:\ %s
    CompilerSet errorformat+=%-GSource:\ %s
    CompilerSet errorformat+=%-GSeverity:\ %s
    CompilerSet errorformat+=%-GCompleted\ %s
    " exclude empty or whitespace-only lines
    CompilerSet errorformat+=%-G\\s%#
    CompilerSet errorformat+=%EMessage:%\\s%#%>
    CompilerSet errorformat+=%C%\\s%#ESC[%\\d%#;%\\d%#m%f:%l:%c:%m
    CompilerSet errorformat+=%C%m
    CompilerSet errorformat+=%ZCompleted%m
    

    The difference compared to your original code is in the last 4 lines:

    CompilerSet errorformat+=%EMessage:%\\s%#%>
    CompilerSet errorformat+=%C%\\s%#ESC[%\\d%#;%\\d%#m%f:%l:%c:%m
    CompilerSet errorformat+=%C%m
    CompilerSet errorformat+=%ZCompleted%m
    

    Originally, you used this:

    CompilerSet  errorformat+=%E!\ Message:%>%trror%m
    

    But in the compiler output you provided, the Message: line does not begin with a bang and a space, so I think it should be removed.

    Besides, %E already sets the type of the entry to error, so %t is not necessary. And there is no message on the line (the message is on the next lines), so you don't need %m. Finally, in the output, there is a trailing whitespace, so you need %\\s%#.

    All in all this gives:

    CompilerSet errorformat+=%EMessage:%\\s%#%>
    

    But you still need to extract the filename and the line/column position, which you can get with resp. %f, %l and %c:

    CompilerSet errorformat+=%C%\\s%#ESC[%\\d%#;%\\d%#m%f:%l:%c:%m
    

    Note that the format begins with %C which tells Vim that it matches the continuation of a multi-line message (see :h errorformat-multi-line).

    Finally, I think you want the rest of the message, until the Completed line, which you can get with:

    CompilerSet errorformat+=%C%m
    CompilerSet errorformat+=%ZCompleted%m