summaryrefslogtreecommitdiffstats
path: root/ftplugin
diff options
context:
space:
mode:
Diffstat (limited to 'ftplugin')
-rw-r--r--ftplugin/erlang.vim200
-rw-r--r--ftplugin/erlang_refactor.vim295
2 files changed, 428 insertions, 67 deletions
diff --git a/ftplugin/erlang.vim b/ftplugin/erlang.vim
index 49b64ebb..f75f47ae 100644
--- a/ftplugin/erlang.vim
+++ b/ftplugin/erlang.vim
@@ -1,85 +1,151 @@
" Vim ftplugin file
-" Language: Erlang
-" Author: Oscar Hellström <oscar@oscarh.net>
-" Contributors: Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
-" Eduardo Lopez (http://github.com/tapichu)
-" License: Vim license
-" Version: 2012/11/25
-
-if exists('b:did_ftplugin')
+" Language: Erlang
+" Maintainer: Oscar Hellström <oscar@oscarh.net>
+" URL: http://personal.oscarh.net
+" Contributor: Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
+" Version: 2010-09-03
+" ------------------------------------------------------------------------------
+" Usage:
+"
+" To enable folding put in your vimrc:
+" set foldenable
+"
+" Folding will make only one fold for a complete function, even though it has
+" more than one function head and body.
+"
+" To change this behaviour put in your vimrc file:
+" let g:erlangFoldSplitFunction=1
+"
+" ------------------------------------------------------------------------------
+" Plugin init
+if exists("b:did_ftplugin")
finish
-else
- let b:did_ftplugin = 1
endif
-if exists('s:did_function_definitions')
+" Don't load any other
+let b:did_ftplugin=1
+
+if exists('s:doneFunctionDefinitions')
call s:SetErlangOptions()
finish
-else
- let s:did_function_definitions = 1
-endif
-
-if !exists('g:erlang_keywordprg')
- let g:erlang_keywordprg = 'erl -man'
-endif
-
-if !exists('g:erlang_folding')
- let g:erlang_folding = 0
endif
-let s:erlang_fun_begin = '^\(\a\w*\|[''][^'']*['']\)(.*$'
-let s:erlang_fun_end = '^[^%]*\.\s*\(%.*\)\?$'
+let s:doneFunctionDefinitions=1
+" Local settings
function s:SetErlangOptions()
compiler erlang
if version >= 700
- setlocal omnifunc=erlang_complete#Complete
- endif
-
- if g:erlang_folding
- setlocal foldmethod=expr
- setlocal foldexpr=GetErlangFold(v:lnum)
- setlocal foldtext=ErlangFoldText()
- endif
-
- setlocal comments=:%%%,:%%,:%
- setlocal commentstring=%%s
- setlocal formatoptions+=ro
- setlocal suffixesadd=.erl
- let libs = substitute(system('which erl'), '/bin/erl', '/lib/erlang/lib/**/src/', '')
- execute 'setlocal path+=' . libs
- let &l:keywordprg = g:erlang_keywordprg
-endfunction
-
-function GetErlangFold(lnum)
- let lnum = a:lnum
- let line = getline(lnum)
-
- if line =~ s:erlang_fun_end
- return '<1'
- endif
-
- if line =~ s:erlang_fun_begin && foldlevel(lnum - 1) == 1
- return '1'
- endif
-
- if line =~ s:erlang_fun_begin
- return '>1'
+ setlocal omnifunc=erlangcomplete#Complete
endif
- return '='
+ setlocal foldmethod=expr
+ setlocal foldexpr=GetErlangFold(v:lnum)
+ setlocal foldtext=ErlangFoldText()
endfunction
-function ErlangFoldText()
- let line = getline(v:foldstart)
- let foldlen = v:foldend - v:foldstart + 1
- let lines = ' ' . foldlen . ' lines: ' . substitute(line, "[ \t]*", '', '')
- if foldlen < 10
- let lines = ' ' . lines
- endif
- let retval = '+' . v:folddashes . lines
-
- return retval
-endfunction
+" Define folding functions
+if !exists("*GetErlangFold")
+ " Folding params
+ let s:ErlangFunBegin = '^\a\w*(.*$'
+ let s:ErlangFunEnd = '^[^%]*\.\s*\(%.*\)\?$'
+ let s:ErlangBlankLine = '^\s*\(%.*\)\?$'
+
+ " Auxiliary fold functions
+ function s:GetNextNonBlank(lnum)
+ let lnum = nextnonblank(a:lnum + 1)
+ let line = getline(lnum)
+ while line =~ s:ErlangBlankLine && 0 != lnum
+ let lnum = nextnonblank(lnum + 1)
+ let line = getline(lnum)
+ endwhile
+ return lnum
+ endfunction
+
+ function s:GetFunName(str)
+ return matchstr(a:str, '^\a\w*(\@=')
+ endfunction
+
+ function s:GetFunArgs(str, lnum)
+ let str = a:str
+ let lnum = a:lnum
+ while str !~ '->\s*\(%.*\)\?$'
+ let lnum = s:GetNextNonBlank(lnum)
+ if 0 == lnum " EOF
+ return ""
+ endif
+ let str .= getline(lnum)
+ endwhile
+ return matchstr(str,
+ \ '\(^(\s*\)\@<=.*\(\s*)\(\s\+when\s\+.*\)\?\s\+->\s*\(%.*\)\?$\)\@=')
+ endfunction
+
+ function s:CountFunArgs(arguments)
+ let pos = 0
+ let ac = 0 " arg count
+ let arguments = a:arguments
+
+ " Change list / tuples into just one A(rgument)
+ let erlangTuple = '{\([A-Za-z_,|=\-\[\]]\|\s\)*}'
+ let erlangList = '\[\([A-Za-z_,|=\-{}]\|\s\)*\]'
+
+ " FIXME: Use searchpair?
+ while arguments =~ erlangTuple
+ let arguments = substitute(arguments, erlangTuple, "A", "g")
+ endwhile
+ " FIXME: Use searchpair?
+ while arguments =~ erlangList
+ let arguments = substitute(arguments, erlangList, "A", "g")
+ endwhile
+
+ let len = strlen(arguments)
+ while pos < len && pos > -1
+ let ac += 1
+ let pos = matchend(arguments, ',\s*', pos)
+ endwhile
+ return ac
+ endfunction
+
+ " Main fold function
+ function GetErlangFold(lnum)
+ let lnum = a:lnum
+ let line = getline(lnum)
+
+ if line =~ s:ErlangFunEnd
+ return '<1'
+ endif
+
+ if line =~ s:ErlangFunBegin && foldlevel(lnum - 1) == 1
+ if exists("g:erlangFoldSplitFunction") && g:erlangFoldSplitFunction
+ return '>1'
+ else
+ return '1'
+ endif
+ endif
+
+ if line =~ s:ErlangFunBegin
+ return '>1'
+ endif
+
+ return '='
+ endfunction
+
+ " Erlang fold description (foldtext function)
+ function ErlangFoldText()
+ let foldlen = v:foldend - v:foldstart
+ if 1 < foldlen
+ let lines = "lines"
+ else
+ let lines = "line"
+ endif
+ let line = getline(v:foldstart)
+ let name = s:GetFunName(line)
+ let arguments = s:GetFunArgs(strpart(line, strlen(name)), v:foldstart)
+ let argcount = s:CountFunArgs(arguments)
+ let retval = "+" . v:folddashes . " " . name . "/" . argcount
+ let retval .= " (" . foldlen . " " . lines . ")"
+ return retval
+ endfunction
+endif
call s:SetErlangOptions()
diff --git a/ftplugin/erlang_refactor.vim b/ftplugin/erlang_refactor.vim
new file mode 100644
index 00000000..f809db9b
--- /dev/null
+++ b/ftplugin/erlang_refactor.vim
@@ -0,0 +1,295 @@
+" Erlang refactor file
+" Language: Erlang
+" Maintainer: Pawel 'kTT' Salata <rockplayer.pl@gmail.com>
+" URL: http://ktototaki.info
+
+if exists("b:did_ftplugin_erlang")
+ finish
+endif
+
+" Don't load any other
+let b:did_ftplugin_erlang=1
+
+if !exists('g:erlangRefactoring') || g:erlangRefactoring == 0
+ finish
+endif
+
+if !exists('g:erlangWranglerPath')
+ let g:erlangWranglerPath = '/usr/share/wrangler/'
+endif
+
+if glob(g:erlangWranglerPath) == ""
+ call confirm("Wrong path to wrangler dir")
+ finish
+endif
+
+autocmd VimLeavePre * call StopWranglerServer()
+
+let s:erlangServerName = "wrangler_vim"
+
+" Starting background erlang session with wrangler on
+function! StartWranglerServer()
+ let wranglerEbinDir = g:erlangWranglerPath . "/ebin"
+ let command = "erl_call -s -sname " . s:erlangServerName . " -x 'erl -pa " . wranglerEbinDir . "'"
+ call system(command)
+ call s:send_rpc('application', 'start', '[wrangler_app]')
+endfunction
+
+" Stopping erlang session
+function! StopWranglerServer()
+ echo s:send_rpc('erlang', 'halt', '')
+endfunction
+
+" Sending rpc call to erlang session
+function! s:send_rpc(module, fun, args)
+ let command = "erl_call -sname " . s:erlangServerName . " -a '" . a:module . " " . a:fun . " " . a:args . "'"
+ let result = system(command)
+ if match(result, 'erl_call: failed to connect to node .*') != -1
+ call StartWranglerServer()
+ return system(command)
+ endif
+ return result
+endfunction
+
+function! ErlangUndo()
+ echo s:send_rpc("wrangler_undo_server", "undo", "[]")
+ :e!
+endfunction
+
+function! s:trim(text)
+ return substitute(a:text, "^\\s\\+\\|\\s\\+$", "", "g")
+endfunction
+
+function! s:get_msg(result, tuple_start)
+ let msg_begin = '{' . a:tuple_start . ','
+ let matching_start = match(a:result, msg_begin)
+ if matching_start != -1
+ return s:trim(matchstr(a:result, '[^}]*', matching_start + strlen(msg_begin)))
+ endif
+ return ""
+endfunction
+
+" Check if there is an error in result
+function! s:check_for_error(result)
+ let msg = s:get_msg(a:result, 'ok')
+ if msg != ""
+ return [0, msg]
+ endif
+ let msg = s:get_msg(a:result, 'warning')
+ if msg != ""
+ return [1, msg]
+ endif
+ let msg = s:get_msg(a:result, 'error')
+ if msg != ""
+ return [2, msg]
+ endif
+ return [-1, ""]
+endfunction
+
+" Sending apply changes to file
+function! s:send_confirm()
+ let choice = confirm("What do you want?", "&Preview\n&Confirm\nCa&ncel", 0)
+ if choice == 1
+ echo "TODO: Display preview :)"
+ elseif choice == 2
+ let module = 'wrangler_preview_server'
+ let fun = 'commit'
+ let args = '[]'
+ return s:send_rpc(module, fun, args)
+ else
+ let module = 'wrangler_preview_server'
+ let fun = 'abort'
+ let args = '[]'
+ return s:send_rpc(module, fun, args)
+ echo "Canceled"
+ endif
+endfunction
+
+" Manually send confirm, for testing purpose only
+function! SendConfirm()
+ echo s:send_confirm()
+endfunction
+
+" Format and send function extracton call
+function! s:call_extract(start_line, start_col, end_line, end_col, name)
+ let file = expand("%:p")
+ let module = 'wrangler'
+ let fun = 'fun_extraction'
+ let args = '["' . file . '", {' . a:start_line . ', ' . a:start_col . '}, {' . a:end_line . ', ' . a:end_col . '}, "' . a:name . '", ' . &sw . ']'
+ let result = s:send_rpc(module, fun, args)
+ let [error_code, msg] = s:check_for_error(result)
+ if error_code != 0
+ call confirm(msg)
+ return 0
+ endif
+ echo "This files will be changed: " . matchstr(msg, "[^]]*", 1)
+ echo s:send_confirm()
+ return 1
+endfunction
+
+function! ErlangExtractFunction(mode) range
+ silent w!
+ let name = inputdialog("New function name: ")
+ if name != ""
+ if a:mode == "v"
+ let start_pos = getpos("'<")
+ let start_line = start_pos[1]
+ let start_col = start_pos[2]
+
+ let end_pos = getpos("'>")
+ let end_line = end_pos[1]
+ let end_col = end_pos[2]
+ elseif a:mode == "n"
+ let pos = getpos(".")
+ let start_line = pos[1]
+ let start_col = pos[2]
+ let end_line = pos[1]
+ let end_col = pos[2]
+ else
+ echo "Mode not supported."
+ return
+ endif
+ if s:call_extract(start_line, start_col, end_line, end_col, name)
+ let temp = &autoread
+ set autoread
+ :e
+ if temp == 0
+ set noautoread
+ endif
+ endif
+ else
+ echo "Empty function name. Ignoring."
+ endif
+endfunction
+nmap <A-r>e :call ErlangExtractFunction("n")<ENTER>
+vmap <A-r>e :call ErlangExtractFunction("v")<ENTER>
+
+function! s:call_rename(mode, line, col, name, search_path)
+ let file = expand("%:p")
+ let module = 'wrangler'
+ let fun = 'rename_' . a:mode
+ let args = '["' . file .'", '
+ if a:mode != "mod"
+ let args = args . a:line . ', ' . a:col . ', '
+ endif
+ let args = args . '"' . a:name . '", ["' . a:search_path . '"], ' . &sw . ']'
+ let result = s:send_rpc(module, fun, args)
+ let [error_code, msg] = s:check_for_error(result)
+ if error_code != 0
+ call confirm(msg)
+ return 0
+ endif
+ echo "This files will be changed: " . matchstr(msg, "[^]]*", 1)
+ echo s:send_confirm()
+ return 1
+endfunction
+
+function! ErlangRename(mode)
+ silent w!
+ if a:mode == "mod"
+ let name = inputdialog('Rename module to: ')
+ else
+ let name = inputdialog('Rename "' . expand("<cword>") . '" to: ')
+ endif
+ if name != ""
+ let search_path = expand("%:p:h")
+ "let search_path = inputdialog('Search path: ', expand("%:p:h"))
+ let pos = getpos(".")
+ let line = pos[1]
+ let col = pos[2]
+ let current_filename = expand("%")
+ let current_filepath = expand("%:p")
+ let new_filename = name . '.erl'
+ if s:call_rename(a:mode, line, col, name, search_path)
+ if a:mode == "mod"
+ execute ':bd ' . current_filename
+ execute ':e ' . new_filename
+ silent execute '!mv ' . current_filepath . ' ' . current_filepath . '.bak'
+ redraw!
+ else
+ let temp = &autoread
+ set autoread
+ :e
+ if temp == 0
+ set noautoread
+ endif
+ endif
+ endif
+ else
+ echo "Empty name. Ignoring."
+ endif
+endfunction
+
+function! ErlangRenameFunction()
+ call ErlangRename("fun")
+endfunction
+map <A-r>f :call ErlangRenameFunction()<ENTER>
+
+function! ErlangRenameVariable()
+ call ErlangRename("var")
+endfunction
+map <A-r>v :call ErlangRenameVariable()<ENTER>
+
+function! ErlangRenameModule()
+ call ErlangRename("mod")
+endfunction
+map <A-r>m :call ErlangRenameModule()<ENTER>
+
+function! ErlangRenameProcess()
+ call ErlangRename("process")
+endfunction
+map <A-r>p :call ErlangRenameProcess()<ENTER>
+
+function! s:call_tuple_fun_args(start_line, start_col, end_line, end_col, search_path)
+ let file = expand("%:p")
+ let module = 'wrangler'
+ let fun = 'tuple_funpar'
+ let args = '["' . file . '", {' . a:start_line . ', ' . a:start_col . '}, {' . a:end_line . ', ' . a:end_col . '}, ["' . a:search_path . '"], ' . &sw . ']'
+ let result = s:send_rpc(module, fun, args)
+ if s:check_for_error(result)
+ return 0
+ endif
+ call s:send_confirm()
+ return 1
+endfunction
+
+function! ErlangTupleFunArgs(mode)
+ silent w!
+ let search_path = expand("%:p:h")
+ "let search_path = inputdialog('Search path: ', expand("%:p:h"))
+ if a:mode == "v"
+ let start_pos = getpos("'<")
+ let start_line = start_pos[1]
+ let start_col = start_pos[2]
+
+ let end_pos = getpos("'>")
+ let end_line = end_pos[1]
+ let end_col = end_pos[2]
+ if s:call_tuple_fun_args(start_line, start_col, end_line, end_col, search_path)
+ let temp = &autoread
+ set autoread
+ :e
+ if temp == 0
+ set noautoread
+ endif
+ endif
+ elseif a:mode == "n"
+ let pos = getpos(".")
+ let line = pos[1]
+ let col = pos[2]
+ if s:call_tuple_fun_args(line, col, line, col, search_path)
+ let temp = &autoread
+ set autoread
+ :e
+ if temp == 0
+ set noautoread
+ endif
+ endif
+ else
+ echo "Mode not supported."
+ endif
+endfunction
+nmap <A-r>t :call ErlangTupleFunArgs("n")<ENTER>
+vmap <A-r>t :call ErlangTupleFunArgs("v")<ENTER>
+
+" vim: set foldmethod=marker: