diff options
Diffstat (limited to 'vim/ftplugin')
-rwxr-xr-x | vim/ftplugin/coffee.vim | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/vim/ftplugin/coffee.vim b/vim/ftplugin/coffee.vim new file mode 100755 index 0000000..12ae3f0 --- /dev/null +++ b/vim/ftplugin/coffee.vim @@ -0,0 +1,221 @@ +" Language: CoffeeScript +" Maintainer: Mick Koch <kchmck@gmail.com> +" URL: http://github.com/kchmck/vim-coffee-script +" License: WTFPL + +if exists("b:did_ftplugin") + finish +endif + +let b:did_ftplugin = 1 + +setlocal formatoptions-=t formatoptions+=croql +setlocal comments=:# +setlocal commentstring=#\ %s +setlocal omnifunc=javascriptcomplete#CompleteJS + +" Enable CoffeeMake if it won't overwrite any settings. +if !len(&l:makeprg) + compiler coffee +endif + +" Reset the global variables used by CoffeeCompile. +function! s:CoffeeCompileResetVars() + " Position in the source buffer + let s:coffee_compile_src_buf = -1 + let s:coffee_compile_src_pos = [] + + " Position in the CoffeeCompile buffer + let s:coffee_compile_buf = -1 + let s:coffee_compile_win = -1 + let s:coffee_compile_pos = [] + + " If CoffeeCompile is watching a buffer + let s:coffee_compile_watch = 0 +endfunction + +" Save the cursor position when moving to and from the CoffeeCompile buffer. +function! s:CoffeeCompileSavePos() + let buf = bufnr('%') + let pos = getpos('.') + + if buf == s:coffee_compile_buf + let s:coffee_compile_pos = pos + else + let s:coffee_compile_src_buf = buf + let s:coffee_compile_src_pos = pos + endif +endfunction + +" Restore the cursor to the source buffer. +function! s:CoffeeCompileRestorePos() + let win = bufwinnr(s:coffee_compile_src_buf) + + if win != -1 + exec win 'wincmd w' + call setpos('.', s:coffee_compile_src_pos) + endif +endfunction + +" Close the CoffeeCompile buffer and clean things up. +function! s:CoffeeCompileClose() + silent! autocmd! CoffeeCompileAuPos + silent! autocmd! CoffeeCompileAuWatch + + call s:CoffeeCompileRestorePos() + call s:CoffeeCompileResetVars() +endfunction + +" Update the CoffeeCompile buffer given some input lines. +function! s:CoffeeCompileUpdate(startline, endline) + let input = join(getline(a:startline, a:endline), "\n") + + " Coffee doesn't like empty input. + if !len(input) + return + endif + + " Compile input. + let output = system('coffee -scb 2>&1', input) + + " Move to the CoffeeCompile buffer. + exec s:coffee_compile_win 'wincmd w' + + " Replace buffer contents with new output and delete the last empty line. + setlocal modifiable + exec '% delete _' + put! =output + exec '$ delete _' + setlocal nomodifiable + + " Highlight as JavaScript if there is no compile error. + if v:shell_error + setlocal filetype= + else + setlocal filetype=javascript + endif + + " Restore the cursor in the compiled output. + call setpos('.', s:coffee_compile_pos) +endfunction + +" Update the CoffeeCompile buffer with the whole source buffer and restore the +" cursor. +function! s:CoffeeCompileWatchUpdate() + call s:CoffeeCompileSavePos() + call s:CoffeeCompileUpdate(1, '$') + call s:CoffeeCompileRestorePos() +endfunction + +" Peek at compiled CoffeeScript in a scratch buffer. We handle ranges like this +" to prevent the cursor from being moved (and its position saved) before the +" function is called. +function! s:CoffeeCompile(startline, endline, args) + " Don't compile the CoffeeCompile buffer. + if bufnr('%') == s:coffee_compile_buf + return + endif + + " Parse arguments. + let watch = a:args =~ '\<watch\>' + let unwatch = a:args =~ '\<unwatch\>' + let size = str2nr(matchstr(a:args, '\<\d\+\>')) + + " Determine default split direction. + if exists("g:coffee_compile_vert") + let vert = 1 + else + let vert = a:args =~ '\<vert\%[ical]\>' + endif + + " Remove any watch listeners. + silent! autocmd! CoffeeCompileAuWatch + + " If just unwatching, don't compile. + if unwatch + let s:coffee_compile_watch = 0 + return + endif + + if watch + let s:coffee_compile_watch = 1 + endif + + call s:CoffeeCompileSavePos() + + " Build the CoffeeCompile buffer if it doesn't exist. + if s:coffee_compile_buf == -1 + let src_win = bufwinnr(s:coffee_compile_src_buf) + + " Create the new window and resize it. + if vert + let width = size ? size : winwidth(src_win) / 2 + + vertical new + exec 'vertical resize' width + else + " Try to guess the compiled output's height. + let height = size ? size : min([winheight(src_win) / 2, + \ a:endline - a:startline + 2]) + + botright new + exec 'resize' height + endif + + " Set up scratch buffer. + setlocal bufhidden=wipe buftype=nofile + setlocal nobuflisted nomodifiable noswapfile nowrap + + autocmd BufWipeout <buffer> call s:CoffeeCompileClose() + nnoremap <buffer> <silent> q :hide<CR> + + " Save the cursor position on each buffer switch. + augroup CoffeeCompileAuPos + autocmd BufEnter,BufLeave * call s:CoffeeCompileSavePos() + augroup END + + let s:coffee_compile_buf = bufnr('%') + let s:coffee_compile_win = bufwinnr(s:coffee_compile_buf) + endif + + " Go back to the source buffer and do the initial compile. + call s:CoffeeCompileRestorePos() + + if s:coffee_compile_watch + call s:CoffeeCompileWatchUpdate() + + augroup CoffeeCompileAuWatch + autocmd InsertLeave <buffer> call s:CoffeeCompileWatchUpdate() + augroup END + else + call s:CoffeeCompileUpdate(a:startline, a:endline) + endif +endfunction + +" Complete arguments for the CoffeeCompile command. +function! s:CoffeeCompileComplete(arg, cmdline, cursor) + let args = ['unwatch', 'vertical', 'watch'] + + if !len(a:arg) + return args + endif + + let match = '^' . a:arg + + for arg in args + if arg =~ match + return [arg] + endif + endfor +endfunction + +" Don't let new windows overwrite the CoffeeCompile variables. +if !exists("s:coffee_compile_buf") + call s:CoffeeCompileResetVars() +endif + +" Peek at compiled CoffeeScript. +command! -range=% -bar -nargs=* -complete=customlist,s:CoffeeCompileComplete +\ CoffeeCompile call s:CoffeeCompile(<line1>, <line2>, <q-args>) +" Run some CoffeeScript. +command! -range=% -bar CoffeeRun <line1>,<line2>:w !coffee -s |