|
|
|
set makeprg=ghc\ %\ -o\ %< " Компилятор
|
|
|
|
|
|
|
|
set expandtab
|
|
|
|
set tabstop=8
|
|
|
|
set shiftwidth=8
|
|
|
|
|
|
|
|
set formatprg=stylish-haskell
|
|
|
|
|
|
|
|
runtime syntax/custom/HaskellConceal.vim
|
|
|
|
|
|
|
|
" =============================================================================
|
|
|
|
" Descriptions: Provide a function providing folding information for haskell
|
|
|
|
" files.
|
|
|
|
" Maintainer: Vincent B (twinside@gmail.com)
|
|
|
|
" Warning: Assume the presence of type signatures on top of your functions to
|
|
|
|
" work well.
|
|
|
|
" Usage: drop in ~/vimfiles/plugin or ~/.vim/plugin
|
|
|
|
" Version: 1.2
|
|
|
|
" Changelog: - 1.2 : Reacting to file type instead of file extension.
|
|
|
|
" - 1.1 : Adding foldtext to bet more information.
|
|
|
|
" - 1.0 : initial version
|
|
|
|
" =============================================================================
|
|
|
|
" Top level bigdefs
|
|
|
|
fun! s:HaskellFoldMaster( line ) "{{{
|
|
|
|
return a:line =~# '^data\s'
|
|
|
|
\ || a:line =~# '^type\s'
|
|
|
|
\ || a:line =~# '^newtype\s'
|
|
|
|
\ || a:line =~# '^class\s'
|
|
|
|
\ || a:line =~# '^instance\s'
|
|
|
|
\ || a:line =~ '^[^:]\+\s*::'
|
|
|
|
endfunction "}}}
|
|
|
|
|
|
|
|
" Top Level one line shooters.
|
|
|
|
fun! s:HaskellSnipGlobal(line) "{{{
|
|
|
|
return a:line =~# '^module'
|
|
|
|
\ || a:line =~# '^import'
|
|
|
|
\ || a:line =~# '^infix[lr]\s'
|
|
|
|
endfunction "}}}
|
|
|
|
|
|
|
|
" The real folding function
|
|
|
|
fun! HaskellFold( lineNum ) "{{{
|
|
|
|
let line = getline( a:lineNum )
|
|
|
|
|
|
|
|
" Beginning of comment
|
|
|
|
if line =~ '^\s*--' || line =~ '^\s*{-'
|
|
|
|
return 2
|
|
|
|
endif
|
|
|
|
|
|
|
|
if line =~ '^import'
|
|
|
|
return 2
|
|
|
|
endif
|
|
|
|
|
|
|
|
if s:HaskellSnipGlobal( line )
|
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
|
|
|
|
if line =~ '^\s*$'
|
|
|
|
let nextline = getline(a:lineNum + 1)
|
|
|
|
if s:HaskellFoldMaster( nextline ) > 0 || s:HaskellSnipGlobal( nextline ) > 0
|
|
|
|
\ || nextline =~ "^--" || nextline =~ "^{-"
|
|
|
|
return 0
|
|
|
|
else
|
|
|
|
return -1
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
|
|
|
|
return 1
|
|
|
|
endfunction "}}}
|
|
|
|
|
|
|
|
" This function skim over function definitions
|
|
|
|
" skiping comments line :
|
|
|
|
" -- ....
|
|
|
|
" and merging lines without first non space element, to
|
|
|
|
" catch the full type expression.
|
|
|
|
fun! HaskellFoldText() "{{{
|
|
|
|
let i = v:foldstart
|
|
|
|
let retVal = ''
|
|
|
|
let began = 0
|
|
|
|
|
|
|
|
let commentOnlyLine = '^\s*--.*$'
|
|
|
|
let monoLineComment = '\s*--.*$'
|
|
|
|
let nonEmptyLine = '^\s\+\S'
|
|
|
|
let emptyLine = '^\s*$'
|
|
|
|
let multilineCommentBegin = '^\s*{-'
|
|
|
|
let multilineCommentEnd = '-}'
|
|
|
|
|
|
|
|
let short = get(g:, 'haskellFold_ShortText', 0)
|
|
|
|
let isMultiLine = 0
|
|
|
|
|
|
|
|
let line = getline(i)
|
|
|
|
while i <= v:foldend
|
|
|
|
|
|
|
|
if isMultiLine
|
|
|
|
if line =~ multilineCommentEnd
|
|
|
|
let isMultiLine = 0
|
|
|
|
let line = substitute(line, '.*-}', '', '')
|
|
|
|
|
|
|
|
if line =~ emptyLine
|
|
|
|
let i = i + 1
|
|
|
|
let line = getline(i)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
let i = i + 1
|
|
|
|
let line = getline(i)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if line =~ multilineCommentBegin
|
|
|
|
let isMultiLine = 1
|
|
|
|
continue
|
|
|
|
elseif began == 0 && !(line =~ commentOnlyLine)
|
|
|
|
let retVal = substitute(line, monoLineComment, ' ','')
|
|
|
|
let began = 1
|
|
|
|
elseif began != 0 && line =~ nonEmptyLine && !short
|
|
|
|
let tempVal = substitute( line, '\s\+\(.*\)$', ' \1', '' )
|
|
|
|
let retVal = retVal . substitute(tempVal, '\s\+--.*', ' ','')
|
|
|
|
elseif began != 0
|
|
|
|
break
|
|
|
|
endif
|
|
|
|
|
|
|
|
let i = i + 1
|
|
|
|
let line = getline(i)
|
|
|
|
endif
|
|
|
|
endwhile
|
|
|
|
|
|
|
|
if retVal == ''
|
|
|
|
" We didn't found any meaningfull text
|
|
|
|
return foldtext()
|
|
|
|
endif
|
|
|
|
|
|
|
|
return retVal
|
|
|
|
endfunction "}}}
|
|
|
|
|
|
|
|
setlocal foldexpr=HaskellFold(v:lnum)
|
|
|
|
setlocal foldtext=HaskellFoldText()
|
|
|
|
setlocal foldmethod=expr
|
|
|
|
|
|
|
|
" =============================================================================
|
|
|
|
" vim-pointfree depends on
|
|
|
|
" [pointfree](https://hackage.haskell.org/package/pointfree), so make sure that
|
|
|
|
" it is installed and available in your $PATH.
|
|
|
|
"
|
|
|
|
" 'm00qek/vim-pointfree'
|
|
|
|
" =============================================================================
|
|
|
|
|
|
|
|
if exists('g:haskell_pointfree')
|
|
|
|
finish
|
|
|
|
endif
|
|
|
|
|
|
|
|
let g:haskell_pointfree = 1
|
|
|
|
|
|
|
|
function! HaskellPointfreeLineCoordinates()
|
|
|
|
return { 'line': line('.') }
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeLineApply(pointfree_window, coordinates)
|
|
|
|
let l:current_line = getline(a:firstline, a:lastline)
|
|
|
|
|
|
|
|
call HaskellPointfreeWindowClose(a:pointfree_window)
|
|
|
|
|
|
|
|
call setline(a:coordinates.line, l:current_line)
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeLineApply_command(window, coordinates)
|
|
|
|
return "HaskellPointfreeLineApply(" . a:window . ", " . string(a:coordinates). ")"
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeLineExpression(coordinates)
|
|
|
|
return join(getline(a:firstline, a:lastline), "\n")
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeVisualCoordinates()
|
|
|
|
let [start_line, start_column] = getpos("'<")[1:2]
|
|
|
|
let [end_line, end_column] = getpos("'>")[1:2]
|
|
|
|
|
|
|
|
return { 'start_line': start_line,
|
|
|
|
\ 'start_column': start_column,
|
|
|
|
\ 'end_line': end_line,
|
|
|
|
\ 'end_column': end_column
|
|
|
|
\ }
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeVisualApply(pointfree_window, coordinates)
|
|
|
|
let l:current_line = getline(a:firstline, a:lastline)[0]
|
|
|
|
let l:hreg = getreg("h")
|
|
|
|
call setreg("h", trim(l:current_line))
|
|
|
|
|
|
|
|
call HaskellPointfreeWindowClose(a:pointfree_window)
|
|
|
|
|
|
|
|
call setpos("'<", [ a:pointfree_window
|
|
|
|
\ , a:coordinates.start_line
|
|
|
|
\ , a:coordinates.start_column ])
|
|
|
|
|
|
|
|
call setpos("'>", [ a:pointfree_window
|
|
|
|
\ , a:coordinates.end_line
|
|
|
|
\ , a:coordinates.end_column ])
|
|
|
|
|
|
|
|
normal! gv"hp
|
|
|
|
call setreg("h", l:hreg)
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeVisualApply_command(window, coordinates)
|
|
|
|
return "HaskellPointfreeVisualApply(" . a:window . ", " . string(a:coordinates). ")"
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeVisualExpression(coordinates)
|
|
|
|
let lines = getline(a:coordinates.start_line, a:coordinates.end_line)
|
|
|
|
if len(lines) == 0
|
|
|
|
return ''
|
|
|
|
endif
|
|
|
|
|
|
|
|
let l:start = a:coordinates.start_column - 1
|
|
|
|
let l:end = a:coordinates.end_column - (&selection == 'inclusive' ? 1 : 2)
|
|
|
|
|
|
|
|
let lines[0] = lines[0][l:start :]
|
|
|
|
let lines[-1] = lines[-1][: l:end]
|
|
|
|
|
|
|
|
return join(lines, "\n")
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:close_if_pointfree(winnr)
|
|
|
|
if &l:filetype == 'haskell.pointfree'
|
|
|
|
silent bdelete!
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:nmap(key, func)
|
|
|
|
execute 'nnoremap <silent> <buffer> ' . a:key . ' :call ' . a:func . '<CR>'
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeWindowClose(window)
|
|
|
|
silent windo call s:close_if_pointfree(winnr())
|
|
|
|
call win_gotoid(a:window)
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeWindowOpen(current_window, suggestions, writer)
|
|
|
|
execute 'silent botright 10new'
|
|
|
|
call setline(1, a:suggestions)
|
|
|
|
|
|
|
|
setlocal readonly nomodifiable
|
|
|
|
setlocal nonumber
|
|
|
|
let &l:filetype = 'haskell.pointfree'
|
|
|
|
setlocal syntax=haskell
|
|
|
|
|
|
|
|
call s:nmap('<CR>' , a:writer)
|
|
|
|
call s:nmap('<Esc>', 'HaskellPointfreeWindowClose(' . a:current_window . ")")
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:pointfree(expression)
|
|
|
|
let l:suggestions = system('pointfree --verbose '.shellescape(a:expression))
|
|
|
|
let l:suggestions = split(l:suggestions, "\n")[3:]
|
|
|
|
|
|
|
|
if v:shell_error == 0
|
|
|
|
return [v:true, insert(l:suggestions, a:expression)]
|
|
|
|
endif
|
|
|
|
|
|
|
|
return [v:false, "Sorry, I couldn't pointfree your expression :("]
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:pointfree_window(Expression, Writer, coordinates)
|
|
|
|
let l:current_window = win_getid()
|
|
|
|
let [l:success, l:suggestions] = s:pointfree(a:Expression(a:coordinates))
|
|
|
|
|
|
|
|
if l:success
|
|
|
|
call HaskellPointfreeWindowOpen(l:current_window,
|
|
|
|
\ l:suggestions,
|
|
|
|
\ a:Writer(l:current_window, a:coordinates))
|
|
|
|
else
|
|
|
|
echoerr l:suggestions
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeOptmized(expression)
|
|
|
|
let [l:success, l:suggestions] = s:pointfree(a:expression)
|
|
|
|
|
|
|
|
if l:success
|
|
|
|
return l:suggestions[-1]
|
|
|
|
else
|
|
|
|
echoerr l:suggestions
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeSelection()
|
|
|
|
call s:pointfree_window(function('HaskellPointfreeVisualExpression'),
|
|
|
|
\ function('HaskellPointfreeVisualApply_command'),
|
|
|
|
\ HaskellPointfreeVisualCoordinates())
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! HaskellPointfreeSuggestions()
|
|
|
|
call s:pointfree_window(function('HaskellPointfreeLineExpression'),
|
|
|
|
\ function('HaskellPointfreeLineApply_command'),
|
|
|
|
\ HaskellPointfreeLineCoordinates())
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
nnoremap <silent> <Leader>. :call HaskellPointfreeSuggestions()<CR>
|
|
|
|
vnoremap <silent> <Leader>. :call HaskellPointfreeSelection()<CR>
|
|
|
|
|
|
|
|
" =============================================================================
|
|
|
|
|