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 ' . a:key . ' :call ' . a:func . '' 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('' , a:writer) call s:nmap('', '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 . :call HaskellPointfreeSuggestions() vnoremap . :call HaskellPointfreeSelection() " =============================================================================