home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / runtime / dos / indent / r.vim < prev    next >
Encoding:
Text File  |  2012-05-31  |  14.9 KB  |  493 lines

  1. " Vim indent file
  2. " Language:    R
  3. " Author:    Jakson Alves de Aquino <jalvesaq@gmail.com>
  4. " Last Change:    Fri Oct 14, 2011  09:50PM
  5.  
  6.  
  7. " Only load this indent file when no other was loaded.
  8. if exists("b:did_r_indent")
  9.     finish
  10. endif
  11. let b:did_r_indent = 1
  12.  
  13. setlocal indentkeys=0{,0},:,!^F,o,O,e
  14. setlocal indentexpr=GetRIndent()
  15.  
  16. " Only define the function once.
  17. if exists("*GetRIndent")
  18.     finish
  19. endif
  20.  
  21. " Options to make the indentation more similar to Emacs/ESS:
  22. if !exists("g:r_indent_align_args")
  23.     let g:r_indent_align_args = 1
  24. endif
  25. if !exists("g:r_indent_ess_comments")
  26.     let g:r_indent_ess_comments = 0
  27. endif
  28. if !exists("g:r_indent_comment_column")
  29.     let g:r_indent_comment_column = 40
  30. endif
  31. if ! exists("g:r_indent_ess_compatible")
  32.     let g:r_indent_ess_compatible = 0
  33. endif
  34.  
  35. function s:RDelete_quotes(line)
  36.     let i = 0
  37.     let j = 0
  38.     let line1 = ""
  39.     let llen = strlen(a:line)
  40.     while i < llen
  41.         if a:line[i] == '"'
  42.             let i += 1
  43.             let line1 = line1 . 's'
  44.             while !(a:line[i] == '"' && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen
  45.                 let i += 1
  46.             endwhile
  47.             if a:line[i] == '"'
  48.                 let i += 1
  49.             endif
  50.         else
  51.             if a:line[i] == "'"
  52.                 let i += 1
  53.                 let line1 = line1 . 's'
  54.                 while !(a:line[i] == "'" && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen
  55.                     let i += 1
  56.                 endwhile
  57.                 if a:line[i] == "'"
  58.                     let i += 1
  59.                 endif
  60.             else
  61.                 if a:line[i] == "`"
  62.                     let i += 1
  63.                     let line1 = line1 . 's'
  64.                     while a:line[i] != "`" && i < llen
  65.                         let i += 1
  66.                     endwhile
  67.                     if a:line[i] == "`"
  68.                         let i += 1
  69.                     endif
  70.                 endif
  71.             endif
  72.         endif
  73.         if i == llen
  74.             break
  75.         endif
  76.         let line1 = line1 . a:line[i]
  77.         let j += 1
  78.         let i += 1
  79.     endwhile
  80.     return line1
  81. endfunction
  82.  
  83. " Convert foo(bar()) int foo()
  84. function s:RDelete_parens(line)
  85.     if s:Get_paren_balance(a:line, "(", ")") != 0
  86.         return a:line
  87.     endif
  88.     let i = 0
  89.     let j = 0
  90.     let line1 = ""
  91.     let llen = strlen(a:line)
  92.     while i < llen
  93.         let line1 = line1 . a:line[i]
  94.         if a:line[i] == '('
  95.             let nop = 1
  96.             while nop > 0 && i < llen
  97.                 let i += 1
  98.                 if a:line[i] == ')'
  99.                     let nop -= 1
  100.                 else
  101.                     if a:line[i] == '('
  102.                         let nop += 1 
  103.                     endif
  104.                 endif
  105.             endwhile
  106.             let line1 = line1 . a:line[i]
  107.         endif
  108.         let i += 1
  109.     endwhile
  110.     return line1
  111. endfunction
  112.  
  113. function! s:Get_paren_balance(line, o, c)
  114.     let line2 = substitute(a:line, a:o, "", "g")
  115.     let openp = strlen(a:line) - strlen(line2)
  116.     let line3 = substitute(line2, a:c, "", "g")
  117.     let closep = strlen(line2) - strlen(line3)
  118.     return openp - closep
  119. endfunction
  120.  
  121. function! s:Get_matching_brace(linenr, o, c, delbrace)
  122.     let line = SanitizeRLine(getline(a:linenr))
  123.     if a:delbrace == 1
  124.         let line = substitute(line, '{$', "", "")
  125.     endif
  126.     let pb = s:Get_paren_balance(line, a:o, a:c)
  127.     let i = a:linenr
  128.     while pb != 0 && i > 1
  129.         let i -= 1
  130.         let pb += s:Get_paren_balance(SanitizeRLine(getline(i)), a:o, a:c)
  131.     endwhile
  132.     return i
  133. endfunction
  134.  
  135. " This function is buggy because there 'if's without 'else'
  136. " It must be rewritten relying more on indentation
  137. function! s:Get_matching_if(linenr, delif)
  138. "    let filenm = expand("%")
  139. "    call writefile([filenm], "/tmp/matching_if_" . a:linenr)
  140.     let line = SanitizeRLine(getline(a:linenr))
  141.     if a:delif
  142.         let line = substitute(line, "if", "", "g")
  143.     endif
  144.     let elsenr = 0
  145.     let i = a:linenr
  146.     let ifhere = 0
  147.     while i > 0
  148.         let line2 = substitute(line, '\<else\>', "xxx", "g")
  149.         let elsenr += strlen(line) - strlen(line2)
  150.         if line =~ '.*\s*if\s*()' || line =~ '.*\s*if\s*()'
  151.             let elsenr -= 1
  152.             if elsenr == 0
  153.                 let ifhere = i
  154.                 break
  155.             endif
  156.         endif
  157.         let i -= 1
  158.         let line = SanitizeRLine(getline(i))
  159.     endwhile
  160.     if ifhere
  161.         return ifhere
  162.     else
  163.         return a:linenr
  164.     endif
  165. endfunction
  166.  
  167. function! s:Get_last_paren_idx(line, o, c, pb)
  168.     let blc = a:pb
  169.     let line = substitute(a:line, '\t', s:curtabstop, "g")
  170.     let theidx = -1
  171.     let llen = strlen(line)
  172.     let idx = 0
  173.     while idx < llen
  174.         if line[idx] == a:o
  175.             let blc -= 1
  176.             if blc == 0
  177.                 let theidx = idx
  178.             endif
  179.         else
  180.             if line[idx] == a:c
  181.                 let blc += 1
  182.             endif
  183.         endif
  184.         let idx += 1
  185.     endwhile
  186.     return theidx + 1
  187. endfunction
  188.  
  189. " Get previous relevant line. Search back until getting a line that isn't
  190. " comment or blank
  191. function s:Get_prev_line(lineno)
  192.     let lnum = a:lineno - 1
  193.     let data = getline( lnum )
  194.     while lnum > 0 && (data =~ '^\s*#' || data =~ '^\s*$')
  195.         let lnum = lnum - 1
  196.         let data = getline( lnum )
  197.     endwhile
  198.     return lnum
  199. endfunction
  200.  
  201. " This function is also used by r-plugin/common_global.vim
  202. " Delete from '#' to the end of the line, unless the '#' is inside a string.
  203. function SanitizeRLine(line)
  204.     let newline = s:RDelete_quotes(a:line)
  205.     let newline = s:RDelete_parens(newline)
  206.     let newline = substitute(newline, '#.*', "", "")
  207.     let newline = substitute(newline, '\s*$', "", "")
  208.     return newline
  209. endfunction
  210.  
  211. function GetRIndent()
  212.  
  213.     let clnum = line(".")    " current line
  214.  
  215.     let cline = getline(clnum)
  216.     if cline =~ '^\s*#'
  217.         if g:r_indent_ess_comments == 1
  218.             if cline =~ '^\s*###'
  219.                 return 0
  220.             endif
  221.             if cline !~ '^\s*##'
  222.                 return g:r_indent_comment_column
  223.             endif
  224.         endif
  225.     endif
  226.  
  227.     let cline = SanitizeRLine(cline)
  228.  
  229.     if cline =~ '^\s*}' || cline =~ '^\s*}\s*)$'
  230.         let indline = s:Get_matching_brace(clnum, '{', '}', 1)
  231.         if indline > 0 && indline != clnum
  232.             let iline = SanitizeRLine(getline(indline))
  233.             if s:Get_paren_balance(iline, "(", ")") == 0 || iline =~ '(\s*{$'
  234.                 return indent(indline)
  235.             else
  236.                 let indline = s:Get_matching_brace(indline, '(', ')', 1)
  237.                 return indent(indline)
  238.             endif
  239.         endif
  240.     endif
  241.  
  242.     " Find the first non blank line above the current line
  243.     let lnum = s:Get_prev_line(clnum)
  244.     " Hit the start of the file, use zero indent.
  245.     if lnum == 0
  246.         return 0
  247.     endif
  248.  
  249.     let line = SanitizeRLine(getline(lnum))
  250.  
  251.     if &filetype == "rhelp"
  252.         if cline =~ '^\\dontshow{' || cline =~ '^\\dontrun{' || cline =~ '^\\donttest{' || cline =~ '^\\testonly{'
  253.             return 0
  254.         endif
  255.         if line =~ '^\\examples{' || line =~ '^\\usage{' || line =~ '^\\dontshow{' || line =~ '^\\dontrun{' || line =~ '^\\donttest{' || line =~ '^\\testonly{'
  256.             return 0
  257.         endif
  258.         if line =~ '^\\method{.*}{.*}(.*'
  259.             let line = substitute(line, '^\\method{\(.*\)}{.*}', '\1', "")
  260.         endif
  261.     endif
  262.  
  263.     if cline =~ '^\s*{'
  264.         if g:r_indent_ess_compatible && line =~ ')$'
  265.             let nlnum = lnum
  266.             let nline = line
  267.             while s:Get_paren_balance(nline, '(', ')') < 0
  268.                 let nlnum = s:Get_prev_line(nlnum)
  269.                 let nline = SanitizeRLine(getline(nlnum)) . nline
  270.             endwhile
  271.             if nline =~ '^\s*function\s*(' && indent(nlnum) == &sw
  272.                 return 0
  273.             endif
  274.         endif
  275.         if s:Get_paren_balance(line, "(", ")") == 0
  276.             return indent(lnum)
  277.         endif
  278.     endif
  279.  
  280.     " line is an incomplete command:
  281.     if line =~ '\<\(if\|while\|for\|function\)\s*()$' || line =~ '\<else$' || line =~ '<-$'
  282.         return indent(lnum) + &sw
  283.     endif
  284.  
  285.     " Deal with () and []
  286.  
  287.     let pb = s:Get_paren_balance(line, '(', ')')
  288.  
  289.     if line =~ '^\s*{$' || line =~ '(\s*{' || (pb == 0 && (line =~ '{$' || line =~ '(\s*{$'))
  290.         return indent(lnum) + &sw
  291.     endif
  292.  
  293.     let bb = s:Get_paren_balance(line, '[', ']')
  294.  
  295.     let s:curtabstop = repeat(' ', &tabstop)
  296.     if g:r_indent_align_args == 1
  297.  
  298.         if pb == 0 && bb == 0 && (line =~ '.*[,&|\-\*+<>]$' || cline =~ '^\s*[,&|\-\*+<>]')
  299.             return indent(lnum)
  300.         endif
  301.  
  302.         if pb > 0
  303.             if &filetype == "rhelp"
  304.                 let ind = s:Get_last_paren_idx(line, '(', ')', pb)
  305.             else
  306.                 let ind = s:Get_last_paren_idx(getline(lnum), '(', ')', pb)
  307.             endif
  308.             return ind
  309.         endif
  310.  
  311.         if pb < 0 && line =~ '.*[,&|\-\*+<>]$'
  312.             let lnum = s:Get_prev_line(lnum)
  313.             while pb < 1 && lnum > 0
  314.                 let line = SanitizeRLine(getline(lnum))
  315.                 let line = substitute(line, '\t', s:curtabstop, "g")
  316.                 let ind = strlen(line)
  317.                 while ind > 0
  318.                     if line[ind] == ')'
  319.                         let pb -= 1
  320.                     else
  321.                         if line[ind] == '('
  322.                             let pb += 1
  323.                         endif
  324.                     endif
  325.                     if pb == 1
  326.                         return ind + 1
  327.                     endif
  328.                     let ind -= 1
  329.                 endwhile
  330.                 let lnum -= 1
  331.             endwhile
  332.             return 0
  333.         endif
  334.  
  335.         if bb > 0
  336.             let ind = s:Get_last_paren_idx(getline(lnum), '[', ']', bb)
  337.             return ind
  338.         endif
  339.     endif
  340.  
  341.     let post_block = 0
  342.     if line =~ '}$'
  343.         let lnum = s:Get_matching_brace(lnum, '{', '}', 0)
  344.         let line = SanitizeRLine(getline(lnum))
  345.         if lnum > 0 && line =~ '^\s*{'
  346.             let lnum = s:Get_prev_line(lnum)
  347.             let line = SanitizeRLine(getline(lnum))
  348.         endif
  349.         let pb = s:Get_paren_balance(line, '(', ')')
  350.         let post_block = 1
  351.     endif
  352.  
  353.     let post_fun = 0
  354.     if pb < 0 && line !~ ')\s*[,&|\-\*+<>]$'
  355.         let post_fun = 1
  356.         while pb < 0 && lnum > 0
  357.             let lnum -= 1
  358.             let linepiece = SanitizeRLine(getline(lnum))
  359.             let pb += s:Get_paren_balance(linepiece, "(", ")")
  360.             let line = linepiece . line
  361.         endwhile
  362.         if line =~ '{$' && post_block == 0
  363.             return indent(lnum) + &sw
  364.         endif
  365.  
  366.         " Now we can do some tests again
  367.         if cline =~ '^\s*{'
  368.             return indent(lnum)
  369.         endif
  370.         if post_block == 0
  371.             let newl = SanitizeRLine(line)
  372.             if newl =~ '\<\(if\|while\|for\|function\)\s*()$' || newl =~ '\<else$' || newl =~ '<-$'
  373.                 return indent(lnum) + &sw
  374.             endif
  375.         endif
  376.     endif
  377.  
  378.     if cline =~ '^\s*else'
  379.         if line =~ '<-\s*if\s*()'
  380.             return indent(lnum) + &sw
  381.         else
  382.             if line =~ '\<if\s*()'
  383.                 return indent(lnum)
  384.             else
  385.                 return indent(lnum) - &sw
  386.             endif
  387.         endif
  388.     endif
  389.  
  390.     if bb < 0 && line =~ '.*]'
  391.         while bb < 0 && lnum > 0
  392.             let lnum -= 1
  393.             let linepiece = SanitizeRLine(getline(lnum))
  394.             let bb += s:Get_paren_balance(linepiece, "[", "]")
  395.             let line = linepiece . line
  396.         endwhile
  397.         let line = s:RDelete_parens(line)
  398.     endif
  399.  
  400.     let plnum = s:Get_prev_line(lnum)
  401.     let ppost_else = 0
  402.     if plnum > 0
  403.         let pline = SanitizeRLine(getline(plnum))
  404.         let ppost_block = 0
  405.         if pline =~ '}$'
  406.             let ppost_block = 1
  407.             let plnum = s:Get_matching_brace(plnum, '{', '}', 0)
  408.             let pline = SanitizeRLine(getline(plnum))
  409.             if pline =~ '^\s*{$' && plnum > 0
  410.                 let plnum = s:Get_prev_line(plnum)
  411.                 let pline = SanitizeRLine(getline(plnum))
  412.             endif
  413.         endif
  414.  
  415.         if pline =~ 'else$'
  416.             let ppost_else = 1
  417.             let plnum = s:Get_matching_if(plnum, 0)
  418.             let pline = SanitizeRLine(getline(plnum))
  419.         endif
  420.  
  421.         if pline =~ '^\s*else\s*if\s*('
  422.             let pplnum = s:Get_prev_line(plnum)
  423.             let ppline = SanitizeRLine(getline(pplnum))
  424.             while ppline =~ '^\s*else\s*if\s*(' || ppline =~ '^\s*if\s*()\s*\S$'
  425.                 let plnum = pplnum
  426.                 let pline = ppline
  427.                 let pplnum = s:Get_prev_line(plnum)
  428.                 let ppline = SanitizeRLine(getline(pplnum))
  429.             endwhile
  430.             while ppline =~ '\<\(if\|while\|for\|function\)\s*()$' || ppline =~ '\<else$' || ppline =~ '<-$'
  431.                 let plnum = pplnum
  432.                 let pline = ppline
  433.                 let pplnum = s:Get_prev_line(plnum)
  434.                 let ppline = SanitizeRLine(getline(pplnum))
  435.             endwhile
  436.         endif
  437.  
  438.         let ppb = s:Get_paren_balance(pline, '(', ')')
  439.         if ppb < 0 && (pline =~ ')\s*{$' || pline =~ ')$')
  440.             while ppb < 0 && plnum > 0
  441.                 let plnum -= 1
  442.                 let linepiece = SanitizeRLine(getline(plnum))
  443.                 let ppb += s:Get_paren_balance(linepiece, "(", ")")
  444.                 let pline = linepiece . pline
  445.             endwhile
  446.             let pline = s:RDelete_parens(pline)
  447.         endif
  448.     endif
  449.  
  450.     let ind = indent(lnum)
  451.     let pind = indent(plnum)
  452.  
  453.     if g:r_indent_align_args == 0 && pb != 0
  454.         let ind += pb * &sw
  455.         return ind
  456.     endif
  457.  
  458.     if g:r_indent_align_args == 0 && bb != 0
  459.         let ind += bb * &sw
  460.         return ind
  461.     endif
  462.  
  463.     if ind == pind || (ind == (pind  + &sw) && pline =~ '{$' && ppost_else == 0)
  464.         return ind
  465.     endif
  466.  
  467.     let pline = getline(plnum)
  468.     let pbb = s:Get_paren_balance(pline, '[', ']')
  469.  
  470.     while pind < ind && plnum > 0 && ppb == 0 && pbb == 0
  471.         let ind = pind
  472.         let plnum = s:Get_prev_line(plnum)
  473.         let pline = getline(plnum)
  474.         let ppb = s:Get_paren_balance(pline, '(', ')')
  475.         let pbb = s:Get_paren_balance(pline, '[', ']')
  476.         while pline =~ '^\s*else'
  477.             let plnum = s:Get_matching_if(plnum, 1)
  478.             let pline = getline(plnum)
  479.             let ppb = s:Get_paren_balance(pline, '(', ')')
  480.             let pbb = s:Get_paren_balance(pline, '[', ']')
  481.         endwhile
  482.         let pind = indent(plnum)
  483.         if ind == (pind  + &sw) && pline =~ '{$'
  484.             return ind
  485.         endif
  486.     endwhile
  487.  
  488.     return ind
  489.  
  490. endfunction
  491.  
  492. " vim: sw=4
  493.