diff options
Diffstat (limited to '')
| -rw-r--r-- | ftplugin/coffee.vim | 404 | ||||
| -rw-r--r-- | ftplugin/cucumber.vim | 148 | ||||
| -rw-r--r-- | ftplugin/eruby.vim | 102 | ||||
| -rw-r--r-- | ftplugin/haml.vim | 68 | ||||
| -rw-r--r-- | ftplugin/haskell.vim | 13 | ||||
| -rw-r--r-- | ftplugin/less.vim | 25 | ||||
| -rw-r--r-- | ftplugin/ocaml.vim | 505 | ||||
| -rw-r--r-- | ftplugin/ruby.vim | 395 | ||||
| -rw-r--r-- | ftplugin/sass.vim | 22 | ||||
| -rw-r--r-- | ftplugin/scss.vim | 12 | ||||
| -rw-r--r-- | ftplugin/stylus.vim | 61 | ||||
| -rw-r--r-- | ftplugin/textile.vim | 59 | 
12 files changed, 1814 insertions, 0 deletions
| diff --git a/ftplugin/coffee.vim b/ftplugin/coffee.vim new file mode 100644 index 00000000..c44fe979 --- /dev/null +++ b/ftplugin/coffee.vim @@ -0,0 +1,404 @@ +" 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 +call coffee#CoffeeSetUpVariables() + +setlocal formatoptions-=t formatoptions+=croql +setlocal comments=:# commentstring=#\ %s +setlocal omnifunc=javascriptcomplete#CompleteJS + +" Create custom augroups. +augroup CoffeeBufUpdate | augroup END +augroup CoffeeBufNew | augroup END + +" Enable coffee compiler if a compiler isn't set already. +if !len(&l:makeprg) +  compiler coffee +endif + +" Switch to the window for buf. +function! s:SwitchWindow(buf) +  exec bufwinnr(a:buf) 'wincmd w' +endfunction + +" Create a new scratch buffer and return the bufnr of it. After the function +" returns, vim remains in the scratch buffer so more set up can be done. +function! s:ScratchBufBuild(src, vert, size) +  if a:size <= 0 +    if a:vert +      let size = winwidth(bufwinnr(a:src)) / 2 +    else +      let size = winheight(bufwinnr(a:src)) / 2 +    endif +  endif + +  if a:vert +    vertical belowright new +    exec 'vertical resize' size +  else +    belowright new +    exec 'resize' size +  endif + +  setlocal bufhidden=wipe buftype=nofile nobuflisted noswapfile nomodifiable +  nnoremap <buffer> <silent> q :hide<CR> + +  return bufnr('%') +endfunction + +" Replace buffer contents with text and delete the last empty line. +function! s:ScratchBufUpdate(buf, text) +  " Move to the scratch buffer. +  call s:SwitchWindow(a:buf) + +  " Double check we're in the scratch buffer before overwriting. +  if bufnr('%') != a:buf +    throw 'unable to change to scratch buffer' +  endif + +  setlocal modifiable +    silent exec '% delete _' +    silent put! =a:text +    silent exec '$ delete _' +  setlocal nomodifiable +endfunction + +" Parse the output of coffee into a qflist entry for src buffer. +function! s:ParseCoffeeError(output, src, startline) +  " Coffee error is always on first line? +  let match = matchlist(a:output, +  \                     '^\(\f\+\|\[stdin\]\):\(\d\):\(\d\): error: \(.\{-}\)' . "\n") + +  if !len(match) +    return +  endif + +  " Consider the line number from coffee as relative and add it to the beginning +  " line number of the range the command was called on, then subtract one for +  " zero-based relativity. +  call setqflist([{'bufnr': a:src, 'lnum': a:startline + str2nr(match[2]) - 1, +  \                'type': 'E', 'col': str2nr(match[3]), 'text': match[4]}], 'r') +endfunction + +" Reset source buffer variables. +function! s:CoffeeCompileResetVars() +  " Variables defined in source buffer: +  "   b:coffee_compile_buf: bufnr of output buffer +  " Variables defined in output buffer: +  "   b:coffee_src_buf: bufnr of source buffer +  "   b:coffee_compile_pos: previous cursor position in output buffer + +  let b:coffee_compile_buf = -1 +endfunction + +function! s:CoffeeWatchResetVars() +  " Variables defined in source buffer: +  "   b:coffee_watch_buf: bufnr of output buffer +  " Variables defined in output buffer: +  "   b:coffee_src_buf: bufnr of source buffer +  "   b:coffee_watch_pos: previous cursor position in output buffer + +  let b:coffee_watch_buf = -1 +endfunction + +function! s:CoffeeRunResetVars() +  " Variables defined in CoffeeRun source buffer: +  "   b:coffee_run_buf: bufnr of output buffer +  " Variables defined in CoffeeRun output buffer: +  "   b:coffee_src_buf: bufnr of source buffer +  "   b:coffee_run_pos: previous cursor position in output buffer + +  let b:coffee_run_buf = -1 +endfunction + +" Clean things up in the source buffers. +function! s:CoffeeCompileClose() +  " Switch to the source buffer if not already in it. +  silent! call s:SwitchWindow(b:coffee_src_buf) +  call s:CoffeeCompileResetVars() +endfunction + +function! s:CoffeeWatchClose() +  silent! call s:SwitchWindow(b:coffee_src_buf) +  silent! autocmd! CoffeeAuWatch * <buffer> +  call s:CoffeeWatchResetVars() +endfunction + +function! s:CoffeeRunClose() +  silent! call s:SwitchWindow(b:coffee_src_buf) +  call s:CoffeeRunResetVars() +endfunction + +" Compile the lines between startline and endline and put the result into buf. +function! s:CoffeeCompileToBuf(buf, startline, endline) +  let src = bufnr('%') +  let input = join(getline(a:startline, a:endline), "\n") + +  " Coffee doesn't like empty input. +  if !len(input) +    " Function should still return within output buffer. +    call s:SwitchWindow(a:buf) +    return +  endif + +  " Pipe lines into coffee. +  let output = system(g:coffee_compiler . +  \                   ' -scb' . +  \                   ' ' . b:coffee_litcoffee . +  \                   ' 2>&1', input) + +  " Paste output into output buffer. +  call s:ScratchBufUpdate(a:buf, output) + +  " Highlight as JavaScript if there were no compile errors. +  if v:shell_error +    call s:ParseCoffeeError(output, src, a:startline) +    setlocal filetype= +  else +    " Clear the quickfix list. +    call setqflist([], 'r') +    setlocal filetype=javascript +  endif +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) +  if a:args =~ '\<watch\>' +    echoerr 'CoffeeCompile watch is deprecated! Please use CoffeeWatch instead' +    sleep 5 +    call s:CoffeeWatch(a:args) +    return +  endif + +  " Switch to the source buffer if not already in it. +  silent! call s:SwitchWindow(b:coffee_src_buf) + +  " Bail if not in source buffer. +  if !exists('b:coffee_compile_buf') +    return +  endif + +  " Build the output buffer if it doesn't exist. +  if bufwinnr(b:coffee_compile_buf) == -1 +    let src = bufnr('%') + +    let vert = exists('g:coffee_compile_vert') || a:args =~ '\<vert\%[ical]\>' +    let size = str2nr(matchstr(a:args, '\<\d\+\>')) + +    " Build the output buffer and save the source bufnr. +    let buf = s:ScratchBufBuild(src, vert, size) +    let b:coffee_src_buf = src + +    " Set the buffer name. +    exec 'silent! file [CoffeeCompile ' . src . ']' + +    " Clean up the source buffer when the output buffer is closed. +    autocmd BufWipeout <buffer> call s:CoffeeCompileClose() +    " Save the cursor when leaving the output buffer. +    autocmd BufLeave <buffer> let b:coffee_compile_pos = getpos('.') + +    " Run user-defined commands on new buffer. +    silent doautocmd CoffeeBufNew User CoffeeCompile + +    " Switch back to the source buffer and save the output bufnr. This also +    " triggers BufLeave above. +    call s:SwitchWindow(src) +    let b:coffee_compile_buf = buf +  endif + +  " Fill the scratch buffer. +  call s:CoffeeCompileToBuf(b:coffee_compile_buf, a:startline, a:endline) +  " Reset cursor to previous position. +  call setpos('.', b:coffee_compile_pos) + +  " Run any user-defined commands on the scratch buffer. +  silent doautocmd CoffeeBufUpdate User CoffeeCompile +endfunction + +" Update the scratch buffer and switch back to the source buffer. +function! s:CoffeeWatchUpdate() +  call s:CoffeeCompileToBuf(b:coffee_watch_buf, 1, '$') +  call setpos('.', b:coffee_watch_pos) +  silent doautocmd CoffeeBufUpdate User CoffeeWatch +  call s:SwitchWindow(b:coffee_src_buf) +endfunction + +" Continually compile a source buffer. +function! s:CoffeeWatch(args) +  silent! call s:SwitchWindow(b:coffee_src_buf) + +  if !exists('b:coffee_watch_buf') +    return +  endif + +  if bufwinnr(b:coffee_watch_buf) == -1 +    let src = bufnr('%') + +    let vert = exists('g:coffee_watch_vert') || a:args =~ '\<vert\%[ical]\>' +    let size = str2nr(matchstr(a:args, '\<\d\+\>')) + +    let buf = s:ScratchBufBuild(src, vert, size) +    let b:coffee_src_buf = src + +    exec 'silent! file [CoffeeWatch ' . src . ']' + +    autocmd BufWipeout <buffer> call s:CoffeeWatchClose() +    autocmd BufLeave <buffer> let b:coffee_watch_pos = getpos('.') + +    silent doautocmd CoffeeBufNew User CoffeeWatch + +    call s:SwitchWindow(src) +    let b:coffee_watch_buf = buf +  endif + +  " Make sure only one watch autocmd is defined on this buffer. +  silent! autocmd! CoffeeAuWatch * <buffer> + +  augroup CoffeeAuWatch +    autocmd InsertLeave <buffer> call s:CoffeeWatchUpdate() +    autocmd BufWritePost <buffer> call s:CoffeeWatchUpdate() +  augroup END + +  call s:CoffeeWatchUpdate() +endfunction + +" Run a snippet of CoffeeScript between startline and endline. +function! s:CoffeeRun(startline, endline, args) +  silent! call s:SwitchWindow(b:coffee_src_buf) + +  if !exists('b:coffee_run_buf') +    return +  endif + +  if bufwinnr(b:coffee_run_buf) == -1 +    let src = bufnr('%') + +    let buf = s:ScratchBufBuild(src, exists('g:coffee_run_vert'), 0) +    let b:coffee_src_buf = src + +    exec 'silent! file [CoffeeRun ' . src . ']' + +    autocmd BufWipeout <buffer> call s:CoffeeRunClose() +    autocmd BufLeave <buffer> let b:coffee_run_pos = getpos('.') + +    silent doautocmd CoffeeBufNew User CoffeeRun + +    call s:SwitchWindow(src) +    let b:coffee_run_buf = buf +  endif + +  if a:startline == 1 && a:endline == line('$') +    let output = system(g:coffee_compiler . +    \                   ' ' . b:coffee_litcoffee . +    \                   ' ' . fnameescape(expand('%')) . +    \                   ' ' . a:args) +  else +    let input = join(getline(a:startline, a:endline), "\n") + +    if !len(input) +      return +    endif + +    let output = system(g:coffee_compiler . +    \                   ' -s' . +    \                   ' ' . b:coffee_litcoffee . +    \                   ' ' . a:args, input) +  endif + +  call s:ScratchBufUpdate(b:coffee_run_buf, output) +  call setpos('.', b:coffee_run_pos) + +  silent doautocmd CoffeeBufUpdate User CoffeeRun +endfunction + +" Run coffeelint on a file, and add any errors between startline and endline +" to the quickfix list. +function! s:CoffeeLint(startline, endline, bang, args) +  let input = join(getline(a:startline, a:endline), "\n") + +  if !len(input) +    return +  endif + +  let output = system(g:coffee_linter . +  \                   ' -s --csv' . +  \                   ' ' . b:coffee_litcoffee . +  \                   ' ' . g:coffee_lint_options . +  \                   ' ' . a:args . +  \                   ' 2>&1', input) + +  " Convert output into an array and strip off the csv header. +  let lines = split(output, "\n")[1:] +  let buf = bufnr('%') +  let qflist = [] + +  for line in lines +    let match = matchlist(line, '^stdin,\(\d\+\),\d*,\(error\|warn\),\(.\+\)$') + +    " Ignore unmatched lines. +    if !len(match) +      continue +    endif + +    " The 'type' will result in either 'E' or 'W'. +    call add(qflist, {'bufnr': buf, 'lnum': a:startline + str2nr(match[1]) - 1, +    \                 'type': toupper(match[2][0]), 'text': match[3]}) +  endfor + +  " Replace the quicklist with our items. +  call setqflist(qflist, 'r') + +  " If not given a bang, jump to first error. +  if !len(a:bang) +    silent! cc 1 +  endif +endfunction + +" Complete arguments for Coffee* commands. +function! s:CoffeeComplete(cmd, cmdline, cursor) +  let args = ['vertical'] + +  " If no partial command, return all possibilities. +  if !len(a:cmd) +    return args +  endif + +  let pat = '^' . a:cmd + +  for arg in args +    if arg =~ pat +      return [arg] +    endif +  endfor +endfunction + +" Set initial state variables if they don't exist +if !exists('b:coffee_compile_buf') +  call s:CoffeeCompileResetVars() +endif + +if !exists('b:coffee_watch_buf') +  call s:CoffeeWatchResetVars() +endif + +if !exists('b:coffee_run_buf') +  call s:CoffeeRunResetVars() +endif + +command! -range=% -bar -nargs=* -complete=customlist,s:CoffeeComplete +\        CoffeeCompile call s:CoffeeCompile(<line1>, <line2>, <q-args>) +command! -bar -nargs=* -complete=customlist,s:CoffeeComplete +\        CoffeeWatch call s:CoffeeWatch(<q-args>) +command! -range=% -bar -nargs=* CoffeeRun +\        call s:CoffeeRun(<line1>, <line2>, <q-args>) +command! -range=% -bang -bar -nargs=* CoffeeLint +\        call s:CoffeeLint(<line1>, <line2>, <q-bang>, <q-args>) diff --git a/ftplugin/cucumber.vim b/ftplugin/cucumber.vim new file mode 100644 index 00000000..1c1f0f25 --- /dev/null +++ b/ftplugin/cucumber.vim @@ -0,0 +1,148 @@ +" Vim filetype plugin +" Language:	Cucumber +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2010 Aug 09 + +" Only do this when not done yet for this buffer +if (exists("b:did_ftplugin")) +  finish +endif +let b:did_ftplugin = 1 + +setlocal formatoptions-=t formatoptions+=croql +setlocal comments=:# commentstring=#\ %s +setlocal omnifunc=CucumberComplete + +let b:undo_ftplugin = "setl fo< com< cms< ofu<" + +let b:cucumber_root = expand('%:p:h:s?.*[\/]\%(features\|stories\)\zs[\/].*??') + +if !exists("g:no_plugin_maps") && !exists("g:no_cucumber_maps") +  nnoremap <silent><buffer> <C-]>       :<C-U>exe <SID>jump('edit',v:count)<CR> +  nnoremap <silent><buffer> [<C-D>      :<C-U>exe <SID>jump('edit',v:count)<CR> +  nnoremap <silent><buffer> ]<C-D>      :<C-U>exe <SID>jump('edit',v:count)<CR> +  nnoremap <silent><buffer> <C-W>]      :<C-U>exe <SID>jump('split',v:count)<CR> +  nnoremap <silent><buffer> <C-W><C-]>  :<C-U>exe <SID>jump('split',v:count)<CR> +  nnoremap <silent><buffer> <C-W>d      :<C-U>exe <SID>jump('split',v:count)<CR> +  nnoremap <silent><buffer> <C-W><C-D>  :<C-U>exe <SID>jump('split',v:count)<CR> +  nnoremap <silent><buffer> <C-W>}      :<C-U>exe <SID>jump('pedit',v:count)<CR> +  nnoremap <silent><buffer> [d          :<C-U>exe <SID>jump('pedit',v:count)<CR> +  nnoremap <silent><buffer> ]d          :<C-U>exe <SID>jump('pedit',v:count)<CR> +  let b:undo_ftplugin .= +        \ "|sil! nunmap <buffer> <C-]>" . +        \ "|sil! nunmap <buffer> [<C-D>" . +        \ "|sil! nunmap <buffer> ]<C-D>" . +        \ "|sil! nunmap <buffer> <C-W>]" . +        \ "|sil! nunmap <buffer> <C-W><C-]>" . +        \ "|sil! nunmap <buffer> <C-W>d" . +        \ "|sil! nunmap <buffer> <C-W><C-D>" . +        \ "|sil! nunmap <buffer> <C-W>}" . +        \ "|sil! nunmap <buffer> [d" . +        \ "|sil! nunmap <buffer> ]d" +endif + +function! s:jump(command,count) +  let steps = s:steps('.') +  if len(steps) == 0 || len(steps) < a:count +    return 'echoerr "No matching step found"' +  elseif len(steps) > 1 && !a:count +    return 'echoerr "Multiple matching steps found"' +  else +    let c = a:count ? a:count-1 : 0 +    return a:command.' +'.steps[c][1].' '.escape(steps[c][0],' %#') +  endif +endfunction + +function! s:allsteps() +  let step_pattern = '\C^\s*\K\k*\>\s*(\=\s*\zs\S.\{-\}\ze\s*)\=\s*\%(do\|{\)\s*\%(|[^|]*|\s*\)\=\%($\|#\)' +  let steps = [] +  for file in split(glob(b:cucumber_root.'/**/*.rb'),"\n") +    let lines = readfile(file) +    let num = 0 +    for line in lines +      let num += 1 +      if line =~ step_pattern +        let type = matchstr(line,'\w\+') +        let steps += [[file,num,type,matchstr(line,step_pattern)]] +      endif +    endfor +  endfor +  return steps +endfunction + +function! s:steps(lnum) +  let c = match(getline(a:lnum), '\S') + 1 +  while synIDattr(synID(a:lnum,c,1),'name') !~# '^$\|Region$' +    let c = c + 1 +  endwhile +  let step = matchstr(getline(a:lnum)[c-1 : -1],'^\s*\zs.\{-\}\ze\s*$') +  return filter(s:allsteps(),'s:stepmatch(v:val[3],step)') +endfunction + +function! s:stepmatch(receiver,target) +  if a:receiver =~ '^[''"].*[''"]$' +    let pattern = '^'.escape(substitute(a:receiver[1:-2],'$\w\+','(.*)','g'),'/').'$' +  elseif a:receiver =~ '^/.*/$' +    let pattern = a:receiver[1:-2] +  elseif a:receiver =~ '^%r..*.$' +    let pattern = escape(a:receiver[3:-2],'/') +  else +    return 0 +  endif +  try +    let vimpattern = substitute(substitute(pattern,'\\\@<!(?:','%(','g'),'\\\@<!\*?','{-}','g') +    if a:target =~# '\v'.vimpattern +      return 1 +    endif +  catch +  endtry +  if has("ruby") && pattern !~ '\\\@<!#{' +    ruby VIM.command("return #{if (begin; Kernel.eval('/'+VIM.evaluate('pattern')+'/'); rescue SyntaxError; end) === VIM.evaluate('a:target') then 1 else 0 end}") +  else +    return 0 +  endif +endfunction + +function! s:bsub(target,pattern,replacement) +  return  substitute(a:target,'\C\\\@<!'.a:pattern,a:replacement,'g') +endfunction + +function! CucumberComplete(findstart,base) abort +  let indent = indent('.') +  let group = synIDattr(synID(line('.'),indent+1,1),'name') +  let type = matchstr(group,'\Ccucumber\zs\%(Given\|When\|Then\)') +  let e = matchend(getline('.'),'^\s*\S\+\s') +  if type == '' || col('.') < col('$') || e < 0 +    return -1 +  endif +  if a:findstart +    return e +  endif +  let steps = [] +  for step in s:allsteps() +    if step[2] ==# type +      if step[3] =~ '^[''"]' +        let steps += [step[3][1:-2]] +      elseif step[3] =~ '^/\^.*\$/$' +        let pattern = step[3][2:-3] +        let pattern = substitute(pattern,'\C^(?:|I )','I ','') +        let pattern = s:bsub(pattern,'\\[Sw]','w') +        let pattern = s:bsub(pattern,'\\d','1') +        let pattern = s:bsub(pattern,'\\[sWD]',' ') +        let pattern = s:bsub(pattern,'\[\^\\\="\]','_') +        let pattern = s:bsub(pattern,'[[:alnum:]. _-][?*]?\=','') +        let pattern = s:bsub(pattern,'\[\([^^]\).\{-\}\]','\1') +        let pattern = s:bsub(pattern,'+?\=','') +        let pattern = s:bsub(pattern,'(\([[:alnum:]. -]\{-\}\))','\1') +        let pattern = s:bsub(pattern,'\\\([[:punct:]]\)','\1') +        if pattern !~ '[\\()*?]' +          let steps += [pattern] +        endif +      endif +    endif +  endfor +  call filter(steps,'strpart(v:val,0,strlen(a:base)) ==# a:base') +  return sort(steps) +endfunction + +" vim:set sts=2 sw=2: diff --git a/ftplugin/eruby.vim b/ftplugin/eruby.vim new file mode 100644 index 00000000..9bb8e86f --- /dev/null +++ b/ftplugin/eruby.vim @@ -0,0 +1,102 @@ +" Vim filetype plugin +" Language:		eRuby +" Maintainer:		Tim Pope <vimNOSPAM@tpope.org> +" URL:			https://github.com/vim-ruby/vim-ruby +" Release Coordinator:	Doug Kearns <dougkearns@gmail.com> + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") +  finish +endif + +let s:save_cpo = &cpo +set cpo-=C + +" Define some defaults in case the included ftplugins don't set them. +let s:undo_ftplugin = "" +let s:browsefilter = "All Files (*.*)\t*.*\n" +let s:match_words = "" + +if !exists("g:eruby_default_subtype") +  let g:eruby_default_subtype = "html" +endif + +if &filetype =~ '^eruby\.' +  let b:eruby_subtype = matchstr(&filetype,'^eruby\.\zs\w\+') +elseif !exists("b:eruby_subtype") +  let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$") +  let b:eruby_subtype = matchstr(s:lines,'eruby_subtype=\zs\w\+') +  if b:eruby_subtype == '' +    let b:eruby_subtype = matchstr(substitute(expand("%:t"),'\c\%(\.erb\|\.eruby\|\.erubis\)\+$','',''),'\.\zs\w\+$') +  endif +  if b:eruby_subtype == 'rhtml' +    let b:eruby_subtype = 'html' +  elseif b:eruby_subtype == 'rb' +    let b:eruby_subtype = 'ruby' +  elseif b:eruby_subtype == 'yml' +    let b:eruby_subtype = 'yaml' +  elseif b:eruby_subtype == 'js' +    let b:eruby_subtype = 'javascript' +  elseif b:eruby_subtype == 'txt' +    " Conventional; not a real file type +    let b:eruby_subtype = 'text' +  elseif b:eruby_subtype == '' +    let b:eruby_subtype = g:eruby_default_subtype +  endif +endif + +if exists("b:eruby_subtype") && b:eruby_subtype != '' +  exe "runtime! ftplugin/".b:eruby_subtype.".vim ftplugin/".b:eruby_subtype."_*.vim ftplugin/".b:eruby_subtype."/*.vim" +else +  runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +endif +unlet! b:did_ftplugin + +" Override our defaults if these were set by an included ftplugin. +if exists("b:undo_ftplugin") +  let s:undo_ftplugin = b:undo_ftplugin +  unlet b:undo_ftplugin +endif +if exists("b:browsefilter") +  let s:browsefilter = b:browsefilter +  unlet b:browsefilter +endif +if exists("b:match_words") +  let s:match_words = b:match_words +  unlet b:match_words +endif + +runtime! ftplugin/ruby.vim ftplugin/ruby_*.vim ftplugin/ruby/*.vim +let b:did_ftplugin = 1 + +" Combine the new set of values with those previously included. +if exists("b:undo_ftplugin") +  let s:undo_ftplugin = b:undo_ftplugin . " | " . s:undo_ftplugin +endif +if exists ("b:browsefilter") +  let s:browsefilter = substitute(b:browsefilter,'\cAll Files (\*\.\*)\t\*\.\*\n','','') . s:browsefilter +endif +if exists("b:match_words") +  let s:match_words = b:match_words . ',' . s:match_words +endif + +" Change the browse dialog on Win32 to show mainly eRuby-related files +if has("gui_win32") +  let b:browsefilter="eRuby Files (*.erb, *.rhtml)\t*.erb;*.rhtml\n" . s:browsefilter +endif + +" Load the combined list of match_words for matchit.vim +if exists("loaded_matchit") +  let b:match_words = s:match_words +endif + +" TODO: comments= +setlocal commentstring=<%#%s%> + +let b:undo_ftplugin = "setl cms< " +      \ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: nowrap sw=2 sts=2 ts=8: diff --git a/ftplugin/haml.vim b/ftplugin/haml.vim new file mode 100644 index 00000000..8c693fa0 --- /dev/null +++ b/ftplugin/haml.vim @@ -0,0 +1,68 @@ +" Vim filetype plugin +" Language:	Haml +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2010 May 21 + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") +  finish +endif + +let s:save_cpo = &cpo +set cpo-=C + +" Define some defaults in case the included ftplugins don't set them. +let s:undo_ftplugin = "" +let s:browsefilter = "All Files (*.*)\t*.*\n" +let s:match_words = "" + +runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +unlet! b:did_ftplugin +set matchpairs-=<:> + +" Override our defaults if these were set by an included ftplugin. +if exists("b:undo_ftplugin") +  let s:undo_ftplugin = b:undo_ftplugin +  unlet b:undo_ftplugin +endif +if exists("b:browsefilter") +  let s:browsefilter = b:browsefilter +  unlet b:browsefilter +endif +if exists("b:match_words") +  let s:match_words = b:match_words +  unlet b:match_words +endif + +runtime! ftplugin/ruby.vim ftplugin/ruby_*.vim ftplugin/ruby/*.vim +let b:did_ftplugin = 1 + +" Combine the new set of values with those previously included. +if exists("b:undo_ftplugin") +  let s:undo_ftplugin = b:undo_ftplugin . " | " . s:undo_ftplugin +endif +if exists ("b:browsefilter") +  let s:browsefilter = substitute(b:browsefilter,'\cAll Files (\*\.\*)\t\*\.\*\n','','') . s:browsefilter +endif +if exists("b:match_words") +  let s:match_words = b:match_words . ',' . s:match_words +endif + +" Change the browse dialog on Win32 to show mainly Haml-related files +if has("gui_win32") +  let b:browsefilter="Haml Files (*.haml)\t*.haml\nSass Files (*.sass)\t*.sass\n" . s:browsefilter +endif + +" Load the combined list of match_words for matchit.vim +if exists("loaded_matchit") +  let b:match_words = s:match_words +endif + +setlocal comments= commentstring=-#\ %s + +let b:undo_ftplugin = "setl cms< com< " +      \ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin + +let &cpo = s:save_cpo + +" vim:set sw=2: diff --git a/ftplugin/haskell.vim b/ftplugin/haskell.vim new file mode 100644 index 00000000..9025b0e0 --- /dev/null +++ b/ftplugin/haskell.vim @@ -0,0 +1,13 @@ +" +" general Haskell source settings +" (shared functions are in autoload/haskellmode.vim) +" +" (Claus Reinke, last modified: 28/04/2009) +" +" part of haskell plugins: http://projects.haskell.org/haskellmode-vim +" please send patches to <claus.reinke@talk21.com> + +" try gf on import line, or ctrl-x ctrl-i, or [I, [i, .. +setlocal include=^import\\s*\\(qualified\\)\\?\\s* +setlocal includeexpr=substitute(v:fname,'\\.','/','g').'.' +setlocal suffixesadd=hs,lhs,hsc
\ No newline at end of file diff --git a/ftplugin/less.vim b/ftplugin/less.vim new file mode 100644 index 00000000..b6eaf6a3 --- /dev/null +++ b/ftplugin/less.vim @@ -0,0 +1,25 @@ +" Vim filetype plugin +" Language:	    LessCSS +" Author:	    Tim Pope <vimNOSPAM@tpope.org> +" Maintainer:   Leonard Ehrenfried <leonard.ehrenfried@web.de> +" Last Change:  2011 Sep 30 + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") +  finish +endif +let b:did_ftplugin = 1 + +let b:undo_ftplugin = "setl cms< def< inc< inex< ofu< sua<" + +setlocal iskeyword+=- +setlocal commentstring=//\ %s +setlocal define=^\\s*\\%(@mixin\\\|=\\) +setlocal includeexpr=substitute(v:fname,'\\%(.*/\\\|^\\)\\zs','_','') +setlocal omnifunc=csscomplete#CompleteCSS +setlocal suffixesadd=.less +setlocal comments=s1:/*,mb:*,ex:*/ + +let &l:include = '^\s*@import\s\+\%(url(\)\=["'']\=' + +" vim:set sw=2: diff --git a/ftplugin/ocaml.vim b/ftplugin/ocaml.vim new file mode 100644 index 00000000..2b39d27c --- /dev/null +++ b/ftplugin/ocaml.vim @@ -0,0 +1,505 @@ +" Language:    OCaml +" Maintainer:  David Baelde        <firstname.name@ens-lyon.org> +"              Mike Leary          <leary@nwlink.com> +"              Markus Mottl        <markus.mottl@gmail.com> +"              Stefano Zacchiroli  <zack@bononia.it> +" URL:         http://www.ocaml.info/vim/ftplugin/ocaml.vim +" Last Change: 2009 Nov 10 - Improved .annot support +"                            (MM for <radugrigore@gmail.com>) +"              2009 Nov 10 - Added support for looking up definitions +"                            (MM for <ygrek@autistici.org>) +" +if exists("b:did_ftplugin") +  finish +endif +let b:did_ftplugin=1 + +" Error handling -- helps moving where the compiler wants you to go +let s:cposet=&cpoptions +set cpo-=C +setlocal efm= +      \%EFile\ \"%f\"\\,\ line\ %l\\,\ characters\ %c-%*\\d:, +      \%EFile\ \"%f\"\\,\ line\ %l\\,\ character\ %c:%m, +      \%+EReference\ to\ unbound\ regexp\ name\ %m, +      \%Eocamlyacc:\ e\ -\ line\ %l\ of\ \"%f\"\\,\ %m, +      \%Wocamlyacc:\ w\ -\ %m, +      \%-Zmake%.%#, +      \%C%m, +      \%D%*\\a[%*\\d]:\ Entering\ directory\ `%f', +      \%X%*\\a[%*\\d]:\ Leaving\ directory\ `%f', +      \%D%*\\a:\ Entering\ directory\ `%f', +      \%X%*\\a:\ Leaving\ directory\ `%f', +      \%DMaking\ %*\\a\ in\ %f + +" Add mappings, unless the user didn't want this. +if !exists("no_plugin_maps") && !exists("no_ocaml_maps") +  " (un)commenting +  if !hasmapto('<Plug>Comment') +    nmap <buffer> <LocalLeader>c <Plug>LUncomOn +    vmap <buffer> <LocalLeader>c <Plug>BUncomOn +    nmap <buffer> <LocalLeader>C <Plug>LUncomOff +    vmap <buffer> <LocalLeader>C <Plug>BUncomOff +  endif + +  nnoremap <buffer> <Plug>LUncomOn mz0i(* <ESC>$A *)<ESC>`z +  nnoremap <buffer> <Plug>LUncomOff :s/^(\* \(.*\) \*)/\1/<CR>:noh<CR> +  vnoremap <buffer> <Plug>BUncomOn <ESC>:'<,'><CR>`<O<ESC>0i(*<ESC>`>o<ESC>0i*)<ESC>`< +  vnoremap <buffer> <Plug>BUncomOff <ESC>:'<,'><CR>`<dd`>dd`< + +  if !hasmapto('<Plug>Abbrev') +    iabbrev <buffer> ASF (assert false (* XXX *)) +    iabbrev <buffer> ASS (assert (0=1) (* XXX *)) +  endif +endif + +" Let % jump between structure elements (due to Issac Trotts) +let b:mw = '' +let b:mw = b:mw . ',\<let\>:\<and\>:\(\<in\>\|;;\)' +let b:mw = b:mw . ',\<if\>:\<then\>:\<else\>' +let b:mw = b:mw . ',\<\(for\|while\)\>:\<do\>:\<done\>,' +let b:mw = b:mw . ',\<\(object\|sig\|struct\|begin\)\>:\<end\>' +let b:mw = b:mw . ',\<\(match\|try\)\>:\<with\>' +let b:match_words = b:mw + +let b:match_ignorecase=0 + +" switching between interfaces (.mli) and implementations (.ml) +if !exists("g:did_ocaml_switch") +  let g:did_ocaml_switch = 1 +  map <LocalLeader>s :call OCaml_switch(0)<CR> +  map <LocalLeader>S :call OCaml_switch(1)<CR> +  fun OCaml_switch(newwin) +    if (match(bufname(""), "\\.mli$") >= 0) +      let fname = substitute(bufname(""), "\\.mli$", ".ml", "") +      if (a:newwin == 1) +        exec "new " . fname +      else +        exec "arge " . fname +      endif +    elseif (match(bufname(""), "\\.ml$") >= 0) +      let fname = bufname("") . "i" +      if (a:newwin == 1) +        exec "new " . fname +      else +        exec "arge " . fname +      endif +    endif +  endfun +endif + +" Folding support + +" Get the modeline because folding depends on indentation +let s:s = line2byte(line('.'))+col('.')-1 +if search('^\s*(\*:o\?caml:') +  let s:modeline = getline(".") +else +  let s:modeline = "" +endif +if s:s > 0 +  exe 'goto' s:s +endif + +" Get the indentation params +let s:m = matchstr(s:modeline,'default\s*=\s*\d\+') +if s:m != "" +  let s:idef = matchstr(s:m,'\d\+') +elseif exists("g:omlet_indent") +  let s:idef = g:omlet_indent +else +  let s:idef = 2 +endif +let s:m = matchstr(s:modeline,'struct\s*=\s*\d\+') +if s:m != "" +  let s:i = matchstr(s:m,'\d\+') +elseif exists("g:omlet_indent_struct") +  let s:i = g:omlet_indent_struct +else +  let s:i = s:idef +endif + +" Set the folding method +if exists("g:ocaml_folding") +  setlocal foldmethod=expr +  setlocal foldexpr=OMLetFoldLevel(v:lnum) +endif + +" - Only definitions below, executed once ------------------------------------- + +if exists("*OMLetFoldLevel") +  finish +endif + +function s:topindent(lnum) +  let l = a:lnum +  while l > 0 +    if getline(l) =~ '\s*\%(\<struct\>\|\<sig\>\|\<object\>\)' +      return indent(l) +    endif +    let l = l-1 +  endwhile +  return -s:i +endfunction + +function OMLetFoldLevel(l) + +  " This is for not merging blank lines around folds to them +  if getline(a:l) !~ '\S' +    return -1 +  endif + +  " We start folds for modules, classes, and every toplevel definition +  if getline(a:l) =~ '^\s*\%(\<val\>\|\<module\>\|\<class\>\|\<type\>\|\<method\>\|\<initializer\>\|\<inherit\>\|\<exception\>\|\<external\>\)' +    exe 'return ">' (indent(a:l)/s:i)+1 '"' +  endif + +  " Toplevel let are detected thanks to the indentation +  if getline(a:l) =~ '^\s*let\>' && indent(a:l) == s:i+s:topindent(a:l) +    exe 'return ">' (indent(a:l)/s:i)+1 '"' +  endif + +  " We close fold on end which are associated to struct, sig or object. +  " We use syntax information to do that. +  if getline(a:l) =~ '^\s*end\>' && synIDattr(synID(a:l, indent(a:l)+1, 0), "name") != "ocamlKeyword" +    return (indent(a:l)/s:i)+1 +  endif + +  " Folds end on ;; +  if getline(a:l) =~ '^\s*;;' +    exe 'return "<' (indent(a:l)/s:i)+1 '"' +  endif + +  " Comments around folds aren't merged to them. +  if synIDattr(synID(a:l, indent(a:l)+1, 0), "name") == "ocamlComment" +    return -1 +  endif + +  return '=' +endfunction + +" Vim support for OCaml .annot files (requires Vim with python support) +" +" Executing OCamlPrintType(<mode>) function will display in the Vim bottom +" line(s) the type of an ocaml value getting it from the corresponding .annot +" file (if any).  If Vim is in visual mode, <mode> should be "visual" and the +" selected ocaml value correspond to the highlighted text, otherwise (<mode> +" can be anything else) it corresponds to the literal found at the current +" cursor position. +" +" .annot files are parsed lazily the first time OCamlPrintType is invoked; is +" also possible to force the parsing using the OCamlParseAnnot() function. +" +" Typing '<LocalLeader>t' (usually ',t') will cause OCamlPrintType function  +" to be invoked with the right argument depending on the current mode (visual  +" or not). +" +" Copyright (C) <2003-2004> Stefano Zacchiroli <zack@bononia.it> +" +" Created:        Wed, 01 Oct 2003 18:16:22 +0200 zack +" LastModified:   Wed, 25 Aug 2004 18:28:39 +0200 zack + +" '<LocalLeader>d' will find the definition of the name under the cursor +" and position cursor on it (only for current file) or print fully qualified name +" (for external definitions). (ocaml >= 3.11) +" +" Additionally '<LocalLeader>t' will show whether function call is tail call +" or not. Current implementation requires selecting the whole function call +" expression (in visual mode) to work. (ocaml >= 3.11) +" +" Copyright (C) 2009 <ygrek@autistici.org> + +if !has("python") +  finish +endif + +python << EOF + +import re +import os +import os.path +import string +import time +import vim + +debug = False + +class AnnExc(Exception): +    def __init__(self, reason): +        self.reason = reason + +no_annotations = AnnExc("No annotations (.annot) file found") +annotation_not_found = AnnExc("No type annotation found for the given text") +definition_not_found = AnnExc("No definition found for the given text") +def malformed_annotations(lineno, reason): +    return AnnExc("Malformed .annot file (line = %d, reason = %s)" % (lineno,reason)) + +class Annotations: +    """ +      .annot ocaml file representation + +      File format (copied verbatim from caml-types.el) + +      file ::= block * +      block ::= position <SP> position <LF> annotation * +      position ::= filename <SP> num <SP> num <SP> num +      annotation ::= keyword open-paren <LF> <SP> <SP> data <LF> close-paren + +      <SP> is a space character (ASCII 0x20) +      <LF> is a line-feed character (ASCII 0x0A) +      num is a sequence of decimal digits +      filename is a string with the lexical conventions of O'Caml +      open-paren is an open parenthesis (ASCII 0x28) +      close-paren is a closed parenthesis (ASCII 0x29) +      data is any sequence of characters where <LF> is always followed by +           at least two space characters. + +      - in each block, the two positions are respectively the start and the +        end of the range described by the block. +      - in a position, the filename is the name of the file, the first num +        is the line number, the second num is the offset of the beginning +        of the line, the third num is the offset of the position itself. +      - the char number within the line is the difference between the third +        and second nums. + +      Possible keywords are \"type\", \"ident\" and \"call\". +    """ + +    def __init__(self): +        self.__filename = None  # last .annot parsed file +        self.__ml_filename = None # as above but s/.annot/.ml/ +        self.__timestamp = None # last parse action timestamp +        self.__annot = {} +        self.__refs = {} +        self.__calls = {} +        self.__re = re.compile( +          '^"[^"]*"\s+(\d+)\s+(\d+)\s+(\d+)\s+"[^"]*"\s+(\d+)\s+(\d+)\s+(\d+)$') +        self.__re_int_ref = re.compile('^int_ref\s+(\w+)\s"[^"]*"\s+(\d+)\s+(\d+)\s+(\d+)') +        self.__re_def_full = re.compile( +          '^def\s+(\w+)\s+"[^"]*"\s+(\d+)\s+(\d+)\s+(\d+)\s+"[^"]*"\s+(\d+)\s+(\d+)\s+(\d+)$') +        self.__re_def = re.compile('^def\s+(\w+)\s"[^"]*"\s+(\d+)\s+(\d+)\s+(\d+)\s+') +        self.__re_ext_ref = re.compile('^ext_ref\s+(\S+)') +        self.__re_kw = re.compile('^(\w+)\($') + +    def __parse(self, fname): +        try: +            f = open(fname) +            self.__annot = {} # erase internal mappings when file is reparsed +            self.__refs = {} +            self.__calls = {} +            line = f.readline() # position line +            lineno = 1 +            while (line != ""): +                m = self.__re.search(line) +                if (not m): +                    raise malformed_annotations(lineno,"re doesn't match") +                line1 = int(m.group(1)) +                col1 = int(m.group(3)) - int(m.group(2)) +                line2 = int(m.group(4)) +                col2 = int(m.group(6)) - int(m.group(5)) +                while 1: +                    line = f.readline() # keyword or position line +                    lineno += 1 +                    m = self.__re_kw.search(line) +                    if (not m): +                        break +                    desc = [] +                    line = f.readline() # description +                    lineno += 1 +                    if (line == ""): raise malformed_annotations(lineno,"no content") +                    while line != ")\n": +                        desc.append(string.strip(line)) +                        line = f.readline() +                        lineno += 1 +                        if (line == ""): raise malformed_annotations(lineno,"bad content") +                    desc = string.join(desc, "\n") +                    key = ((line1, col1), (line2, col2)) +                    if (m.group(1) == "type"): +                        if not self.__annot.has_key(key): +                            self.__annot[key] = desc +                    if (m.group(1) == "call"): # region, accessible only in visual mode +                        if not self.__calls.has_key(key): +                            self.__calls[key] = desc +                    if (m.group(1) == "ident"): +                        m = self.__re_int_ref.search(desc) +                        if m: +                          line = int(m.group(2)) +                          col = int(m.group(4)) - int(m.group(3)) +                          name = m.group(1) +                        else: +                          line = -1 +                          col = -1 +                          m = self.__re_ext_ref.search(desc) +                          if m: +                            name = m.group(1) +                          else: +                            line = -2 +                            col = -2 +                            name = desc +                        if not self.__refs.has_key(key): +                          self.__refs[key] = (line,col,name) +            f.close() +            self.__filename = fname +            self.__ml_filename = vim.current.buffer.name +            self.__timestamp = int(time.time()) +        except IOError: +            raise no_annotations + +    def parse(self): +        annot_file = os.path.splitext(vim.current.buffer.name)[0] + ".annot" +        previous_head, head, tail = '***', annot_file, '' +        while not os.path.isfile(annot_file) and head != previous_head: +            previous_head = head +            head, x = os.path.split(head) +            if tail == '': +              tail = x +            else: +              os.path.join(x, tail) +            annot_file = os.path.join(head, '_build', tail) +        self.__parse(annot_file) + +    def check_file(self): +        if vim.current.buffer.name == None: +            raise no_annotations +        if vim.current.buffer.name != self.__ml_filename or  \ +          os.stat(self.__filename).st_mtime > self.__timestamp: +            self.parse() + +    def get_type(self, (line1, col1), (line2, col2)): +        if debug: +            print line1, col1, line2, col2 +        self.check_file() +        try: +            try: +              extra = self.__calls[(line1, col1), (line2, col2)] +              if extra == "tail": +                extra = " (* tail call *)" +              else: +                extra = " (* function call *)" +            except KeyError: +              extra = "" +            return self.__annot[(line1, col1), (line2, col2)] + extra +        except KeyError: +            raise annotation_not_found + +    def get_ident(self, (line1, col1), (line2, col2)): +        if debug: +            print line1, col1, line2, col2 +        self.check_file() +        try: +            (line,col,name) = self.__refs[(line1, col1), (line2, col2)] +            if line >= 0 and col >= 0: +              vim.command("normal "+str(line)+"gg"+str(col+1)+"|") +              #current.window.cursor = (line,col) +            if line == -2: +              m = self.__re_def_full.search(name) +              if m: +                l2 = int(m.group(5)) +                c2 = int(m.group(7)) - int(m.group(6)) +                name = m.group(1) +              else: +                m = self.__re_def.search(name) +                if m: +                  l2 = int(m.group(2)) +                  c2 = int(m.group(4)) - int(m.group(3)) +                  name = m.group(1) +                else: +                  l2 = -1 +              if False and l2 >= 0: +                # select region +                if c2 == 0 and l2 > 0: +                  vim.command("normal v"+str(l2-1)+"gg"+"$") +                else: +                  vim.command("normal v"+str(l2)+"gg"+str(c2)+"|") +            return name +        except KeyError: +            raise definition_not_found + +word_char_RE = re.compile("^[\w.]$") + +  # TODO this function should recognize ocaml literals, actually it's just an +  # hack that recognize continuous sequences of word_char_RE above +def findBoundaries(line, col): +    """ given a cursor position (as returned by vim.current.window.cursor) +    return two integers identify the beggining and end column of the word at +    cursor position, if any. If no word is at the cursor position return the +    column cursor position twice """ +    left, right = col, col +    line = line - 1 # mismatch vim/python line indexes +    (begin_col, end_col) = (0, len(vim.current.buffer[line]) - 1) +    try: +        while word_char_RE.search(vim.current.buffer[line][left - 1]): +            left = left - 1 +    except IndexError: +        pass +    try: +        while word_char_RE.search(vim.current.buffer[line][right + 1]): +            right = right + 1 +    except IndexError: +        pass +    return (left, right) + +annot = Annotations() # global annotation object + +def get_marks(mode): +    if mode == "visual":  # visual mode: lookup highlighted text +        (line1, col1) = vim.current.buffer.mark("<") +        (line2, col2) = vim.current.buffer.mark(">") +    else: # any other mode: lookup word at cursor position +        (line, col) = vim.current.window.cursor +        (col1, col2) = findBoundaries(line, col) +        (line1, line2) = (line, line) +    begin_mark = (line1, col1) +    end_mark = (line2, col2 + 1) +    return (begin_mark,end_mark) + +def printOCamlType(mode): +    try: +        (begin_mark,end_mark) = get_marks(mode) +        print annot.get_type(begin_mark, end_mark) +    except AnnExc, exc: +        print exc.reason + +def gotoOCamlDefinition(mode): +    try: +        (begin_mark,end_mark) = get_marks(mode) +        print annot.get_ident(begin_mark, end_mark) +    except AnnExc, exc: +        print exc.reason + +def parseOCamlAnnot(): +    try: +        annot.parse() +    except AnnExc, exc: +        print exc.reason + +EOF + +fun! OCamlPrintType(current_mode) +  if (a:current_mode == "visual") +    python printOCamlType("visual") +  else +    python printOCamlType("normal") +  endif +endfun + +fun! OCamlGotoDefinition(current_mode) +  if (a:current_mode == "visual") +    python gotoOCamlDefinition("visual") +  else +    python gotoOCamlDefinition("normal") +  endif +endfun + +fun! OCamlParseAnnot() +  python parseOCamlAnnot() +endfun + +map <LocalLeader>t :call OCamlPrintType("normal")<RETURN> +vmap <LocalLeader>t :call OCamlPrintType("visual")<RETURN> +map <LocalLeader>d :call OCamlGotoDefinition("normal")<RETURN> +vmap <LocalLeader>d :call OCamlGotoDefinition("visual")<RETURN> + +let &cpoptions=s:cposet +unlet s:cposet + +" vim:sw=2 diff --git a/ftplugin/ruby.vim b/ftplugin/ruby.vim new file mode 100644 index 00000000..9630a940 --- /dev/null +++ b/ftplugin/ruby.vim @@ -0,0 +1,395 @@ +" Vim filetype plugin +" Language:		Ruby +" Maintainer:		Tim Pope <vimNOSPAM@tpope.org> +" URL:			https://github.com/vim-ruby/vim-ruby +" Release Coordinator:  Doug Kearns <dougkearns@gmail.com> +" ---------------------------------------------------------------------------- + +if (exists("b:did_ftplugin")) +  finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +if has("gui_running") && !has("gui_win32") +  setlocal keywordprg=ri\ -T\ -f\ bs +else +  setlocal keywordprg=ri +endif + +" Matchit support +if exists("loaded_matchit") && !exists("b:match_words") +  let b:match_ignorecase = 0 + +  let b:match_words = +	\ '\<\%(if\|unless\|case\|while\|until\|for\|do\|class\|module\|def\|begin\)\>=\@!' . +	\ ':' . +	\ '\<\%(else\|elsif\|ensure\|when\|rescue\|break\|redo\|next\|retry\)\>' . +	\ ':' . +	\ '\<end\>' . +	\ ',{:},\[:\],(:)' + +  let b:match_skip = +	\ "synIDattr(synID(line('.'),col('.'),0),'name') =~ '" . +	\ "\\<ruby\\%(String\\|StringDelimiter\\|ASCIICode\\|Escape\\|" . +	\ "Interpolation\\|NoInterpolation\\|Comment\\|Documentation\\|" . +	\ "ConditionalModifier\\|RepeatModifier\\|OptionalDo\\|" . +	\ "Function\\|BlockArgument\\|KeywordAsMethod\\|ClassVariable\\|" . +	\ "InstanceVariable\\|GlobalVariable\\|Symbol\\)\\>'" +endif + +setlocal formatoptions-=t formatoptions+=croql + +setlocal include=^\\s*\\<\\(load\\>\\\|require\\>\\\|autoload\\s*:\\=[\"']\\=\\h\\w*[\"']\\=,\\) +setlocal includeexpr=substitute(substitute(v:fname,'::','/','g'),'$','.rb','') +setlocal suffixesadd=.rb + +if exists("&ofu") && has("ruby") +  setlocal omnifunc=rubycomplete#Complete +endif + +" To activate, :set ballooneval +if has('balloon_eval') && exists('+balloonexpr') +  setlocal balloonexpr=RubyBalloonexpr() +endif + + +" TODO: +"setlocal define=^\\s*def + +setlocal comments=:# +setlocal commentstring=#\ %s + +if !exists('g:ruby_version_paths') +  let g:ruby_version_paths = {} +endif + +function! s:query_path(root) +  let code = "print $:.join %q{,}" +  if &shell =~# 'sh' && $PATH !~# '\s' +    let prefix = 'env PATH='.$PATH.' ' +  else +    let prefix = '' +  endif +  if &shellxquote == "'" +    let path_check = prefix.'ruby -e "' . code . '"' +  else +    let path_check = prefix."ruby -e '" . code . "'" +  endif + +  let cd = haslocaldir() ? 'lcd' : 'cd' +  let cwd = getcwd() +  try +    exe cd fnameescape(a:root) +    let path = split(system(path_check),',') +    exe cd fnameescape(cwd) +    return path +  finally +    exe cd fnameescape(cwd) +  endtry +endfunction + +function! s:build_path(path) +  let path = join(map(copy(a:path), 'v:val ==# "." ? "" : v:val'), ',') +  if &g:path !~# '\v^\.%(,/%(usr|emx)/include)=,,$' +    let path = substitute(&g:path,',,$',',','') . ',' . path +  endif +  return path +endfunction + +if !exists('b:ruby_version') && !exists('g:ruby_path') && isdirectory(expand('%:p:h')) +  let s:version_file = findfile('.ruby-version', '.;') +  if !empty(s:version_file) +    let b:ruby_version = get(readfile(s:version_file, '', 1), '') +    if !has_key(g:ruby_version_paths, b:ruby_version) +      let g:ruby_version_paths[b:ruby_version] = s:query_path(fnamemodify(s:version_file, ':p:h')) +    endif +  endif +endif + +if exists("g:ruby_path") +  let s:ruby_path = type(g:ruby_path) == type([]) ? join(g:ruby_path, ',') : g:ruby_path +elseif has_key(g:ruby_version_paths, get(b:, 'ruby_version', '')) +  let s:ruby_paths = g:ruby_version_paths[b:ruby_version] +  let s:ruby_path = s:build_path(s:ruby_paths) +else +  if !exists('g:ruby_default_path') +    if has("ruby") && has("win32") +      ruby ::VIM::command( 'let g:ruby_default_path = split("%s",",")' % $:.join(%q{,}) ) +    elseif executable('ruby') +      let g:ruby_default_path = s:query_path($HOME) +    else +      let g:ruby_default_path = map(split($RUBYLIB,':'), 'v:val ==# "." ? "" : v:val') +    endif +  endif +  let s:ruby_paths = g:ruby_default_path +  let s:ruby_path = s:build_path(s:ruby_paths) +endif + +if stridx(&l:path, s:ruby_path) == -1 +  let &l:path = s:ruby_path +endif +if exists('s:ruby_paths') && stridx(&l:tags, join(map(copy(s:ruby_paths),'v:val."/tags"'),',')) == -1 +  let &l:tags = &tags . ',' . join(map(copy(s:ruby_paths),'v:val."/tags"'),',') +endif + +if has("gui_win32") && !exists("b:browsefilter") +  let b:browsefilter = "Ruby Source Files (*.rb)\t*.rb\n" . +                     \ "All Files (*.*)\t*.*\n" +endif + +let b:undo_ftplugin = "setl fo< inc< inex< sua< def< com< cms< path< tags< kp<" +      \."| unlet! b:browsefilter b:match_ignorecase b:match_words b:match_skip" +      \."| if exists('&ofu') && has('ruby') | setl ofu< | endif" +      \."| if has('balloon_eval') && exists('+bexpr') | setl bexpr< | endif" + +if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") +  nnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','b','n')<CR> +  nnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','','n')<CR> +  nnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','b','n')<CR> +  nnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','','n')<CR> +  xnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','b','v')<CR> +  xnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>','rubyDefine','','v')<CR> +  xnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','b','v')<CR> +  xnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>','rubyDefine','','v')<CR> + +  nnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','b','n')<CR> +  nnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','','n')<CR> +  nnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','b','n')<CR> +  nnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','','n')<CR> +  xnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','b','v')<CR> +  xnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>','rubyModule\<Bar>rubyClass','','v')<CR> +  xnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','b','v')<CR> +  xnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>','rubyModule\<Bar>rubyClass','','v')<CR> + +  let b:undo_ftplugin = b:undo_ftplugin +        \."| sil! exe 'unmap <buffer> [[' | sil! exe 'unmap <buffer> ]]' | sil! exe 'unmap <buffer> []' | sil! exe 'unmap <buffer> ]['" +        \."| sil! exe 'unmap <buffer> [m' | sil! exe 'unmap <buffer> ]m' | sil! exe 'unmap <buffer> [M' | sil! exe 'unmap <buffer> ]M'" + +  if maparg('im','n') == '' +    onoremap <silent> <buffer> im :<C-U>call <SID>wrap_i('[m',']M')<CR> +    onoremap <silent> <buffer> am :<C-U>call <SID>wrap_a('[m',']M')<CR> +    xnoremap <silent> <buffer> im :<C-U>call <SID>wrap_i('[m',']M')<CR> +    xnoremap <silent> <buffer> am :<C-U>call <SID>wrap_a('[m',']M')<CR> +    let b:undo_ftplugin = b:undo_ftplugin +          \."| sil! exe 'ounmap <buffer> im' | sil! exe 'ounmap <buffer> am'" +          \."| sil! exe 'xunmap <buffer> im' | sil! exe 'xunmap <buffer> am'" +  endif + +  if maparg('iM','n') == '' +    onoremap <silent> <buffer> iM :<C-U>call <SID>wrap_i('[[','][')<CR> +    onoremap <silent> <buffer> aM :<C-U>call <SID>wrap_a('[[','][')<CR> +    xnoremap <silent> <buffer> iM :<C-U>call <SID>wrap_i('[[','][')<CR> +    xnoremap <silent> <buffer> aM :<C-U>call <SID>wrap_a('[[','][')<CR> +    let b:undo_ftplugin = b:undo_ftplugin +          \."| sil! exe 'ounmap <buffer> iM' | sil! exe 'ounmap <buffer> aM'" +          \."| sil! exe 'xunmap <buffer> iM' | sil! exe 'xunmap <buffer> aM'" +  endif + +  if maparg("\<C-]>",'n') == '' +    nnoremap <silent> <buffer> <C-]>       :<C-U>exe  v:count1."tag <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> g<C-]>      :<C-U>exe         "tjump <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> g]          :<C-U>exe       "tselect <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> <C-W>]      :<C-U>exe v:count1."stag <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> <C-W><C-]>  :<C-U>exe v:count1."stag <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> <C-W>g<C-]> :<C-U>exe        "stjump <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> <C-W>g]     :<C-U>exe      "stselect <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> <C-W>}      :<C-U>exe          "ptag <C-R>=RubyCursorIdentifier()<CR>"<CR> +    nnoremap <silent> <buffer> <C-W>g}     :<C-U>exe        "ptjump <C-R>=RubyCursorIdentifier()<CR>"<CR> +    let b:undo_ftplugin = b:undo_ftplugin +          \."| sil! exe 'nunmap <buffer> <C-]>'| sil! exe 'nunmap <buffer> g<C-]>'| sil! exe 'nunmap <buffer> g]'" +          \."| sil! exe 'nunmap <buffer> <C-W>]'| sil! exe 'nunmap <buffer> <C-W><C-]>'" +          \."| sil! exe 'nunmap <buffer> <C-W>g<C-]>'| sil! exe 'nunmap <buffer> <C-W>g]'" +          \."| sil! exe 'nunmap <buffer> <C-W>}'| sil! exe 'nunmap <buffer> <C-W>g}'" +  endif + +  if maparg("gf",'n') == '' +    " By using findfile() rather than gf's normal behavior, we prevent +    " erroneously editing a directory. +    nnoremap <silent> <buffer> gf         :<C-U>exe <SID>gf(v:count1,"gf",'edit')<CR> +    nnoremap <silent> <buffer> <C-W>f     :<C-U>exe <SID>gf(v:count1,"\<Lt>C-W>f",'split')<CR> +    nnoremap <silent> <buffer> <C-W><C-F> :<C-U>exe <SID>gf(v:count1,"\<Lt>C-W>\<Lt>C-F>",'split')<CR> +    nnoremap <silent> <buffer> <C-W>gf    :<C-U>exe <SID>gf(v:count1,"\<Lt>C-W>gf",'tabedit')<CR> +    let b:undo_ftplugin = b:undo_ftplugin +          \."| sil! exe 'nunmap <buffer> gf' | sil! exe 'nunmap <buffer> <C-W>f' | sil! exe 'nunmap <buffer> <C-W><C-F>' | sil! exe 'nunmap <buffer> <C-W>gf'" +  endif +endif + +let &cpo = s:cpo_save +unlet s:cpo_save + +if exists("g:did_ruby_ftplugin_functions") +  finish +endif +let g:did_ruby_ftplugin_functions = 1 + +function! RubyBalloonexpr() +  if !exists('s:ri_found') +    let s:ri_found = executable('ri') +  endif +  if s:ri_found +    let line = getline(v:beval_lnum) +    let b = matchstr(strpart(line,0,v:beval_col),'\%(\w\|[:.]\)*$') +    let a = substitute(matchstr(strpart(line,v:beval_col),'^\w*\%([?!]\|\s*=\)\?'),'\s\+','','g') +    let str = b.a +    let before = strpart(line,0,v:beval_col-strlen(b)) +    let after  = strpart(line,v:beval_col+strlen(a)) +    if str =~ '^\.' +      let str = substitute(str,'^\.','#','g') +      if before =~ '\]\s*$' +        let str = 'Array'.str +      elseif before =~ '}\s*$' +        " False positives from blocks here +        let str = 'Hash'.str +      elseif before =~ "[\"'`]\\s*$" || before =~ '\$\d\+\s*$' +        let str = 'String'.str +      elseif before =~ '\$\d\+\.\d\+\s*$' +        let str = 'Float'.str +      elseif before =~ '\$\d\+\s*$' +        let str = 'Integer'.str +      elseif before =~ '/\s*$' +        let str = 'Regexp'.str +      else +        let str = substitute(str,'^#','.','') +      endif +    endif +    let str = substitute(str,'.*\.\s*to_f\s*\.\s*','Float#','') +    let str = substitute(str,'.*\.\s*to_i\%(nt\)\=\s*\.\s*','Integer#','') +    let str = substitute(str,'.*\.\s*to_s\%(tr\)\=\s*\.\s*','String#','') +    let str = substitute(str,'.*\.\s*to_sym\s*\.\s*','Symbol#','') +    let str = substitute(str,'.*\.\s*to_a\%(ry\)\=\s*\.\s*','Array#','') +    let str = substitute(str,'.*\.\s*to_proc\s*\.\s*','Proc#','') +    if str !~ '^\w' +      return '' +    endif +    silent! let res = substitute(system("ri -f rdoc -T \"".str.'"'),'\n$','','') +    if res =~ '^Nothing known about' || res =~ '^Bad argument:' || res =~ '^More than one method' +      return '' +    endif +    return res +  else +    return "" +  endif +endfunction + +function! s:searchsyn(pattern,syn,flags,mode) +  norm! m' +  if a:mode ==# 'v' +    norm! gv +  endif +  let i = 0 +  let cnt = v:count ? v:count : 1 +  while i < cnt +    let i = i + 1 +    let line = line('.') +    let col  = col('.') +    let pos = search(a:pattern,'W'.a:flags) +    while pos != 0 && s:synname() !~# a:syn +      let pos = search(a:pattern,'W'.a:flags) +    endwhile +    if pos == 0 +      call cursor(line,col) +      return +    endif +  endwhile +endfunction + +function! s:synname() +  return synIDattr(synID(line('.'),col('.'),0),'name') +endfunction + +function! s:wrap_i(back,forward) +  execute 'norm k'.a:forward +  let line = line('.') +  execute 'norm '.a:back +  if line('.') == line - 1 +    return s:wrap_a(a:back,a:forward) +  endif +  execute 'norm jV'.a:forward.'k' +endfunction + +function! s:wrap_a(back,forward) +  execute 'norm '.a:forward +  if line('.') < line('$') && getline(line('.')+1) ==# '' +    let after = 1 +  endif +  execute 'norm '.a:back +  while getline(line('.')-1) =~# '^\s*#' && line('.') +    - +  endwhile +  if exists('after') +    execute 'norm V'.a:forward.'j' +  elseif line('.') > 1 && getline(line('.')-1) =~# '^\s*$' +    execute 'norm kV'.a:forward +  else +    execute 'norm V'.a:forward +  endif +endfunction + +function! RubyCursorIdentifier() +  let asciicode    = '\%(\w\|[]})\"'."'".']\)\@<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)' +  let number       = '\%(\%(\w\|[]})\"'."'".']\s*\)\@<!-\)\=\%(\<[[:digit:]_]\+\%(\.[[:digit:]_]\+\)\=\%([Ee][[:digit:]_]\+\)\=\>\|\<0[xXbBoOdD][[:xdigit:]_]\+\>\)\|'.asciicode +  let operator     = '\%(\[\]\|<<\|<=>\|[!<>]=\=\|===\=\|[!=]\~\|>>\|\*\*\|\.\.\.\=\|=>\|[~^&|*/%+-]\)' +  let method       = '\%(\<[_a-zA-Z]\w*\>\%([?!]\|\s*=>\@!\)\=\)' +  let global       = '$\%([!$&"'."'".'*+,./:;<=>?@\`~]\|-\=\w\+\>\)' +  let symbolizable = '\%(\%(@@\=\)\w\+\>\|'.global.'\|'.method.'\|'.operator.'\)' +  let pattern      = '\C\s*\%('.number.'\|\%(:\@<!:\)\='.symbolizable.'\)' +  let [lnum, col]  = searchpos(pattern,'bcn',line('.')) +  let raw          = matchstr(getline('.')[col-1 : ],pattern) +  let stripped     = substitute(substitute(raw,'\s\+=$','=',''),'^\s*:\=','','') +  return stripped == '' ? expand("<cword>") : stripped +endfunction + +function! s:gf(count,map,edit) abort +  if getline('.') =~# '^\s*require_relative\s*\(["'']\).*\1\s*$' +    let target = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') +    return a:edit.' %:h/'.target.'.rb' +  elseif getline('.') =~# '^\s*\%(require[( ]\|load[( ]\|autoload[( ]:\w\+,\)\s*\s*\%(::\)\=File\.expand_path(\(["'']\)\.\./.*\1,\s*__FILE__)\s*$' +    let target = matchstr(getline('.'),'\(["'']\)\.\./\zs.\{-\}\ze\1') +    return a:edit.' %:h/'.target.'.rb' +  elseif getline('.') =~# '^\s*\%(require \|load \|autoload :\w\+,\)\s*\(["'']\).*\1\s*$' +    let target = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') +  else +    let target = expand('<cfile>') +  endif +  let found = findfile(target, &path, a:count) +  if found ==# '' +    return 'norm! '.a:count.a:map +  else +    return a:edit.' '.fnameescape(found) +  endif +endfunction + +" +" Instructions for enabling "matchit" support: +" +" 1. Look for the latest "matchit" plugin at +" +"         http://www.vim.org/scripts/script.php?script_id=39 +" +"    It is also packaged with Vim, in the $VIMRUNTIME/macros directory. +" +" 2. Copy "matchit.txt" into a "doc" directory (e.g. $HOME/.vim/doc). +" +" 3. Copy "matchit.vim" into a "plugin" directory (e.g. $HOME/.vim/plugin). +" +" 4. Ensure this file (ftplugin/ruby.vim) is installed. +" +" 5. Ensure you have this line in your $HOME/.vimrc: +"         filetype plugin on +" +" 6. Restart Vim and create the matchit documentation: +" +"         :helptags ~/.vim/doc +" +"    Now you can do ":help matchit", and you should be able to use "%" on Ruby +"    keywords.  Try ":echo b:match_words" to be sure. +" +" Thanks to Mark J. Reed for the instructions.  See ":help vimrc" for the +" locations of plugin directories, etc., as there are several options, and it +" differs on Windows.  Email gsinclair@soyabean.com.au if you need help. +" + +" vim: nowrap sw=2 sts=2 ts=8: diff --git a/ftplugin/sass.vim b/ftplugin/sass.vim new file mode 100644 index 00000000..64232a08 --- /dev/null +++ b/ftplugin/sass.vim @@ -0,0 +1,22 @@ +" Vim filetype plugin +" Language:	Sass +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2010 Jul 26 + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") +  finish +endif +let b:did_ftplugin = 1 + +let b:undo_ftplugin = "setl cms< def< inc< inex< ofu< sua<" + +setlocal commentstring=//\ %s +setlocal define=^\\s*\\%(@mixin\\\|=\\) +setlocal includeexpr=substitute(v:fname,'\\%(.*/\\\|^\\)\\zs','_','') +setlocal omnifunc=csscomplete#CompleteCSS +setlocal suffixesadd=.sass,.scss,.css + +let &l:include = '^\s*@import\s\+\%(url(\)\=["'']\=' + +" vim:set sw=2: diff --git a/ftplugin/scss.vim b/ftplugin/scss.vim new file mode 100644 index 00000000..981fb1b8 --- /dev/null +++ b/ftplugin/scss.vim @@ -0,0 +1,12 @@ +" Vim filetype plugin +" Language:	SCSS +" Maintainer:	Tim Pope <vimNOSPAM@tpope.org> +" Last Change:	2010 Jul 26 + +if exists("b:did_ftplugin") +  finish +endif + +runtime! ftplugin/sass.vim + +" vim:set sw=2: diff --git a/ftplugin/stylus.vim b/ftplugin/stylus.vim new file mode 100644 index 00000000..17386596 --- /dev/null +++ b/ftplugin/stylus.vim @@ -0,0 +1,61 @@ +" Vim filetype plugin +" Language: Stylus +" Maintainer: Marc Harter +" Credits: Tim Pope + +" Only do this when not done yet for this buffer +if exists("b:did_ftplugin") +  finish +endif + +let s:save_cpo = &cpo +set cpo-=C + +" Define some defaults in case the included ftplugins don't set them. +let s:undo_ftplugin = "" +let s:browsefilter = "All Files (*.*)\t*.*\n" +let s:match_words = "" + +runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +unlet! b:did_ftplugin + +" Override our defaults if these were set by an included ftplugin. +if exists("b:undo_ftplugin") +  let s:undo_ftplugin = b:undo_ftplugin +  unlet b:undo_ftplugin +endif +if exists("b:browsefilter") +  let s:browsefilter = b:browsefilter +  unlet b:browsefilter +endif +if exists("b:match_words") +  let s:match_words = b:match_words +  unlet b:match_words +endif + +" Change the browse dialog on Win32 to show mainly Styl-related files +if has("gui_win32") +  let b:browsefilter="Stylus Files (*.styl)\t*.styl\n" . s:browsefilter +endif + +" Load the combined list of match_words for matchit.vim +if exists("loaded_matchit") +  let b:match_words = s:match_words +endif + +setlocal comments= commentstring=//\ %s + +" Add '-' and '#' to the what makes up a keyword. +" This means that 'e' and 'w' work properly now, for properties +" and valid variable names. +setl iskeyword+=#,- + +let b:undo_ftplugin = "setl cms< com< " +      \ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin + +let &cpo = s:save_cpo + +" Add a Stylus command (to see if it's valid) +command! Stylus !clear; cat % | stylus + +" vim:set sw=2: diff --git a/ftplugin/textile.vim b/ftplugin/textile.vim new file mode 100644 index 00000000..a840e600 --- /dev/null +++ b/ftplugin/textile.vim @@ -0,0 +1,59 @@ +" textile.vim +" +" Tim Harper (tim.theenchanter.com) + +command! -nargs=0 TextileRenderFile call TextileRenderBufferToFile() +command! -nargs=0 TextileRenderTab call TextileRenderBufferToTab() +command! -nargs=0 TextilePreview call TextileRenderBufferToPreview() +noremap <buffer> <Leader>rp :TextilePreview<CR> +noremap <buffer> <Leader>rf :TextileRenderFile<CR> +noremap <buffer> <Leader>rt :TextileRenderTab<CR> +setlocal ignorecase +setlocal wrap +setlocal lbr + +function! TextileRender(lines) +  if (system('which ruby') == "") +    throw "Could not find ruby!" +  end + +  let text = join(a:lines, "\n") +  let html = system("ruby -e \"def e(msg); puts msg; exit 1; end; begin; require 'rubygems'; rescue LoadError; e('rubygems not found'); end; begin; require 'redcloth'; rescue LoadError; e('RedCloth gem not installed.  Run this from the terminal: sudo gem install RedCloth'); end; puts(RedCloth.new(\\$stdin.read).to_html(:textile))\"", text) +  return html +endfunction + +function! TextileRenderFile(lines, filename) +  let html = TextileRender(getbufline(bufname("%"), 1, '$')) +  let html = "<html><head><title>" . bufname("%") . "</title></head><body>\n" . html . "\n</body></html>" +  return writefile(split(html, "\n"), a:filename) +endfunction + +function! TextileRenderBufferToPreview() +  let filename = "/tmp/textile-preview.html" +  call TextileRenderFile(getbufline(bufname("%"), 1, '$'), filename) +  " Verify if browser was set +  if !exists("g:TextileBrowser") +    let g:TextileBrowser='Safari' +  endif +  " call configured browser according OS +  if !exists("g:TextileOS") || g:TextileOS == 'mac' +    call system("open -a \"".g:TextileBrowser."\" ".filename) +  else +    echo g:TextileBrowser." ".filename +    call system(g:TextileBrowser." ".filename) +  endif +endfunction + +function! TextileRenderBufferToFile() +  let filename = input("Filename:", substitute(bufname("%"), "textile$", "html", ""), "file") +  call TextileRenderFile(getbufline(bufname("%"), 1, '$'), filename) +  echo "Rendered to '" . filename . "'" +endfunction + +function! TextileRenderBufferToTab() +  let html = TextileRender(getbufline(bufname("%"), 1, '$')) +  tabnew +  call append("^", split(html, "\n")) +  set syntax=html +endfunction + | 
