aboutsummaryrefslogtreecommitdiff
path: root/dotfiles/.local/share/nvim/site/autoload/neomake/makers/ft/haskell.vim
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/.local/share/nvim/site/autoload/neomake/makers/ft/haskell.vim')
-rw-r--r--dotfiles/.local/share/nvim/site/autoload/neomake/makers/ft/haskell.vim169
1 files changed, 169 insertions, 0 deletions
diff --git a/dotfiles/.local/share/nvim/site/autoload/neomake/makers/ft/haskell.vim b/dotfiles/.local/share/nvim/site/autoload/neomake/makers/ft/haskell.vim
new file mode 100644
index 0000000..64a5227
--- /dev/null
+++ b/dotfiles/.local/share/nvim/site/autoload/neomake/makers/ft/haskell.vim
@@ -0,0 +1,169 @@
+unlet! s:makers
+unlet! s:uses_cabal
+
+function! neomake#makers#ft#haskell#EnabledMakers() abort
+ if !exists('s:makers')
+ " cache whether each maker is available, to avoid lots of (UI blocking)
+ " system calls
+ " TODO: figure out how to do all this configuration async instead of
+ " caching it--that would allow the user to change directories from
+ " within vim and recalculate maker availability without restarting vim
+ let commands = ['ghc-mod', 'hdevtools', 'hlint', 'liquid']
+ let s:makers = []
+ let s:jobs = []
+ for command in commands
+ " stack may be able to find a maker binary that's not on the normal
+ " path so check for that first
+ if executable('stack')
+ " run the maker command using stack to see whether stack can
+ " find it use the help flag to run the maker command without
+ " doing anything
+ let stack_command = [
+ \ 'stack'
+ \ , 'exec'
+ \ , '--'
+ \ , command
+ \ , '--help'
+ \ ]
+ if has('nvim')
+ let job_id = jobstart(
+ \ stack_command,
+ \ { 'command': command
+ \ , 'on_exit': function('s:CheckStackMakerAsync')
+ \ })
+ if job_id > 0
+ call add(s:jobs, job_id)
+ endif
+ else
+ call extend(stack_command, ['> /dev/null 2>&1;', 'echo $?'])
+ if system(join(stack_command, ' ')) == 0
+ call add(s:makers, substitute(command, '-', '', 'g'))
+ endif
+ endif
+ elseif executable(command) " no stack bin so check for maker bin
+ call add(s:makers, substitute(command, '-', '', 'g'))
+ endif
+ endfor
+ if has('nvim')
+ call jobwait(s:jobs)
+ endif
+ endif
+ return s:makers
+endfunction
+
+function! neomake#makers#ft#haskell#hdevtools() abort
+ let params = {
+ \ 'exe': 'hdevtools',
+ \ 'args': ['check', '-g-Wall'],
+ \ 'mapexpr': s:CleanUpSpaceAndBackticks(),
+ \ 'errorformat':
+ \ '%-Z %#,'.
+ \ '%W%f:%l:%v: Warning: %m,'.
+ \ '%W%f:%l:%v: Warning:,'.
+ \ '%E%f:%l:%v: %m,'.
+ \ '%E%>%f:%l:%v:,'.
+ \ '%+C %#%m,'.
+ \ '%W%>%f:%l:%v:,'.
+ \ '%+C %#%tarning: %m,'
+ \ }
+ " hdevtools needs the GHC-PACKAGE-PATH environment variable to exist
+ " when running on a project WITHOUT a cabal file, but it needs the
+ " GHC-PACKAGE-PATH to NOT exist when running on a with a project WITH
+ " a cabal file
+ if !exists('s:uses_cabal')
+ let s:uses_cabal = 0
+ if executable('stack')
+ let output = neomake#compat#systemlist(['stack', '--verbosity', 'silent', 'path', '--project-root'])
+ if !empty(output)
+ let rootdir = output[0]
+ if !empty(glob(rootdir . '/*.cabal'))
+ let s:uses_cabal = 1
+ endif
+ endif
+ endif
+ endif
+ if s:uses_cabal
+ let params['stackexecargs'] = ['--no-ghc-package-path']
+ endif
+ return s:TryStack(params)
+endfunction
+
+function! neomake#makers#ft#haskell#ghcmod() abort
+ " This filters out newlines, which is what neovim gives us instead of the
+ " null bytes that ghc-mod sometimes spits out.
+ let mapexpr = 'substitute(v:val, "\n", "", "g")'
+ return s:TryStack({
+ \ 'exe': 'ghc-mod',
+ \ 'args': ['check'],
+ \ 'mapexpr': mapexpr,
+ \ 'errorformat':
+ \ '%-G%\s%#,' .
+ \ '%f:%l:%c:%trror: %m,' .
+ \ '%f:%l:%c:%tarning: %m,'.
+ \ '%f:%l:%c: %trror: %m,' .
+ \ '%f:%l:%c: %tarning: %m,' .
+ \ '%E%f:%l:%c:%m,' .
+ \ '%E%f:%l:%c:,' .
+ \ '%Z%m'
+ \ })
+endfunction
+
+function! neomake#makers#ft#haskell#HlintEntryProcess(entry) abort
+ " Postprocess hlint output to make it more readable as a single line
+ let a:entry.text = substitute(a:entry.text, '\v(Found:)\s*\n', ' | \1', 'g')
+ let a:entry.text = substitute(a:entry.text, '\v(Why not:)\s*\n', ' | \1', 'g')
+ let a:entry.text = substitute(a:entry.text, '^No hints$', '', 'g')
+ call neomake#postprocess#compress_whitespace(a:entry)
+endfunction
+
+function! neomake#makers#ft#haskell#hlint() abort
+ return s:TryStack({
+ \ 'exe': 'hlint',
+ \ 'postprocess': function('neomake#makers#ft#haskell#HlintEntryProcess'),
+ \ 'args': [],
+ \ 'errorformat':
+ \ '%E%f:%l:%v: Error: %m,' .
+ \ '%W%f:%l:%v: Warning: %m,' .
+ \ '%I%f:%l:%v: Suggestion: %m,' .
+ \ '%C%m'
+ \ })
+endfunction
+
+function! neomake#makers#ft#haskell#liquid() abort
+ return s:TryStack({
+ \ 'exe': 'liquid',
+ \ 'args': [],
+ \ 'mapexpr': s:CleanUpSpaceAndBackticks(),
+ \ 'errorformat':
+ \ '%E %f:%l:%c-%.%#Error: %m,' .
+ \ '%C%.%#|%.%#,' .
+ \ '%C %#^%#,' .
+ \ '%C%m,'
+ \ })
+endfunction
+
+function! s:CheckStackMakerAsync(_job_id, data, _event) dict abort
+ if a:data == 0
+ call add(s:makers, substitute(self.command, '-', '', 'g'))
+ endif
+endfunction
+
+function! s:TryStack(maker) abort
+ if executable('stack')
+ if !has_key(a:maker, 'stackexecargs')
+ let a:maker['stackexecargs'] = []
+ endif
+ let a:maker['args'] =
+ \ ['--verbosity', 'silent', 'exec']
+ \ + a:maker['stackexecargs']
+ \ + ['--', a:maker['exe']]
+ \ + a:maker['args']
+ let a:maker['exe'] = 'stack'
+ endif
+ return a:maker
+endfunction
+
+function! s:CleanUpSpaceAndBackticks() abort
+ return 'substitute(substitute(v:val, " \\{2,\\}", " ", "g"), "`", "''", "g")'
+endfunction
+" vim: ts=4 sw=4 et