codekingpro/portable-devtools
114k
1" Vim indent file2" Language: R3" Maintainer: This runtime file is looking for a new maintainer.4" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>5" Former Repository: https://github.com/jalvesaq/R-Vim-runtime6" Last Change: 2023 Oct 08 10:45AM7" 2024 Feb 19 by Vim Project (announce adoption)8 9 10" Only load this indent file when no other was loaded.11if exists("b:did_indent")12 finish13endif14let b:did_indent = 115 16setlocal indentkeys=0{,0},:,!^F,o,O,e17setlocal indentexpr=GetRIndent()18setlocal autoindent19 20let b:undo_indent = "setl inde< indk<"21 22" Only define the function once.23if exists("*GetRIndent")24 finish25endif26 27let s:cpo_save = &cpo28set cpo&vim29 30" Options to make the indentation more similar to Emacs/ESS:31let g:r_indent_align_args = get(g:, 'r_indent_align_args', 1)32let g:r_indent_ess_comments = get(g:, 'r_indent_ess_comments', 0)33let g:r_indent_comment_column = get(g:, 'r_indent_comment_column', 40)34let g:r_indent_ess_compatible = get(g:, 'r_indent_ess_compatible', 0)35let g:r_indent_op_pattern = get(g:, 'r_indent_op_pattern',36 \ '\(&\||\|+\|-\|\*\|/\|=\|\~\|%\|->\||>\)\s*$')37 38function s:RDelete_quotes(line)39 let i = 040 let j = 041 let line1 = ""42 let llen = strlen(a:line)43 while i < llen44 if a:line[i] == '"'45 let i += 146 let line1 = line1 . 's'47 while !(a:line[i] == '"' && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen48 let i += 149 endwhile50 if a:line[i] == '"'51 let i += 152 endif53 elseif a:line[i] == "'"54 let i += 155 let line1 = line1 . 's'56 while !(a:line[i] == "'" && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen57 let i += 158 endwhile59 if a:line[i] == "'"60 let i += 161 endif62 elseif a:line[i] == "`"63 let i += 164 let line1 = line1 . 's'65 while a:line[i] != "`" && i < llen66 let i += 167 endwhile68 if a:line[i] == "`"69 let i += 170 endif71 endif72 if i == llen73 break74 endif75 let line1 = line1 . a:line[i]76 let j += 177 let i += 178 endwhile79 return line180endfunction81 82" Convert foo(bar()) int foo()83function s:RDelete_parens(line)84 if s:Get_paren_balance(a:line, "(", ")") != 085 return a:line86 endif87 let i = 088 let j = 089 let line1 = ""90 let llen = strlen(a:line)91 while i < llen92 let line1 = line1 . a:line[i]93 if a:line[i] == '('94 let nop = 195 while nop > 0 && i < llen96 let i += 197 if a:line[i] == ')'98 let nop -= 199 elseif a:line[i] == '('100 let nop += 1101 endif102 endwhile103 let line1 = line1 . a:line[i]104 endif105 let i += 1106 endwhile107 return line1108endfunction109 110function s:Get_paren_balance(line, o, c)111 let line2 = substitute(a:line, a:o, "", "g")112 let openp = strlen(a:line) - strlen(line2)113 let line3 = substitute(line2, a:c, "", "g")114 let closep = strlen(line2) - strlen(line3)115 return openp - closep116endfunction117 118function s:Get_matching_brace(linenr, o, c, delbrace)119 let line = SanitizeRLine(getline(a:linenr))120 if a:delbrace == 1121 let line = substitute(line, '{$', "", "")122 endif123 let pb = s:Get_paren_balance(line, a:o, a:c)124 let i = a:linenr125 while pb != 0 && i > 1126 let i -= 1127 let pb += s:Get_paren_balance(SanitizeRLine(getline(i)), a:o, a:c)128 endwhile129 return i130endfunction131 132" This function is buggy because there 'if's without 'else'133" It must be rewritten relying more on indentation134function s:Get_matching_if(linenr, delif)135 let line = SanitizeRLine(getline(a:linenr))136 if a:delif137 let line = substitute(line, "if", "", "g")138 endif139 let elsenr = 0140 let i = a:linenr141 let ifhere = 0142 while i > 0143 let line2 = substitute(line, '\<else\>', "xxx", "g")144 let elsenr += strlen(line) - strlen(line2)145 if line =~ '.*\s*if\s*()' || line =~ '.*\s*if\s*()'146 let elsenr -= 1147 if elsenr == 0148 let ifhere = i149 break150 endif151 endif152 let i -= 1153 let line = SanitizeRLine(getline(i))154 endwhile155 if ifhere156 return ifhere157 else158 return a:linenr159 endif160endfunction161 162function s:Get_last_paren_idx(line, o, c, pb)163 let blc = a:pb164 let line = substitute(a:line, '\t', s:curtabstop, "g")165 let theidx = -1166 let llen = strlen(line)167 let idx = 0168 while idx < llen169 if line[idx] == a:o170 let blc -= 1171 if blc == 0172 let theidx = idx173 endif174 elseif line[idx] == a:c175 let blc += 1176 endif177 let idx += 1178 endwhile179 return theidx + 1180endfunction181 182" Get previous relevant line. Search back until getting a line that isn't183" comment or blank184function s:Get_prev_line(lineno)185 let lnum = a:lineno - 1186 let data = getline( lnum )187 while lnum > 0 && (data =~ '^\s*#' || data =~ '^\s*$')188 let lnum = lnum - 1189 let data = getline( lnum )190 endwhile191 return lnum192endfunction193 194" This function is also used by r-plugin/common_global.vim195" Delete from '#' to the end of the line, unless the '#' is inside a string.196function SanitizeRLine(line)197 let newline = s:RDelete_quotes(a:line)198 let newline = s:RDelete_parens(newline)199 let newline = substitute(newline, '#.*', "", "")200 let newline = substitute(newline, '\s*$', "", "")201 if &filetype == "rhelp" && newline =~ '^\\method{.*}{.*}(.*'202 let newline = substitute(newline, '^\\method{\(.*\)}{.*}', '\1', "")203 endif204 return newline205endfunction206 207function GetRIndent()208 209 let clnum = line(".") " current line210 211 let cline = getline(clnum)212 if cline =~ '^\s*#'213 if g:r_indent_ess_comments == 1214 if cline =~ '^\s*###'215 return 0216 endif217 if cline !~ '^\s*##'218 return g:r_indent_comment_column219 endif220 endif221 endif222 223 let cline = SanitizeRLine(cline)224 225 if cline =~ '^\s*}'226 let indline = s:Get_matching_brace(clnum, '{', '}', 1)227 if indline > 0 && indline != clnum228 let iline = SanitizeRLine(getline(indline))229 if s:Get_paren_balance(iline, "(", ")") == 0 || iline =~ '(\s*{$'230 return indent(indline)231 else232 let indline = s:Get_matching_brace(indline, '(', ')', 1)233 return indent(indline)234 endif235 endif236 endif237 238 if cline =~ '^\s*)$'239 let indline = s:Get_matching_brace(clnum, '(', ')', 1)240 return indent(indline)241 endif242 243 " Find the first non blank line above the current line244 let lnum = s:Get_prev_line(clnum)245 " Hit the start of the file, use zero indent.246 if lnum == 0247 return 0248 endif249 250 let line = SanitizeRLine(getline(lnum))251 252 if &filetype == "rhelp"253 if cline =~ '^\\dontshow{' || cline =~ '^\\dontrun{' || cline =~ '^\\donttest{' || cline =~ '^\\testonly{'254 return 0255 endif256 if line =~ '^\\examples{' || line =~ '^\\usage{' || line =~ '^\\dontshow{' || line =~ '^\\dontrun{' || line =~ '^\\donttest{' || line =~ '^\\testonly{'257 return 0258 endif259 endif260 261 if &filetype == "rnoweb" && line =~ "^<<.*>>="262 return 0263 endif264 265 if cline =~ '^\s*{' && s:Get_paren_balance(cline, '{', '}') > 0266 if g:r_indent_ess_compatible && line =~ ')$'267 let nlnum = lnum268 let nline = line269 while s:Get_paren_balance(nline, '(', ')') < 0270 let nlnum = s:Get_prev_line(nlnum)271 let nline = SanitizeRLine(getline(nlnum)) . nline272 endwhile273 if nline =~ '^\s*function\s*(' && indent(nlnum) == shiftwidth()274 return 0275 endif276 endif277 if s:Get_paren_balance(line, "(", ")") == 0278 return indent(lnum)279 endif280 endif281 282 " line is an incomplete command:283 if line =~ '\<\(if\|while\|for\|function\)\s*()$' || line =~ '\<else$' || line =~ '<-$' || line =~ '->$'284 return indent(lnum) + shiftwidth()285 endif286 287 " Deal with () and []288 289 let pb = s:Get_paren_balance(line, '(', ')')290 291 if line =~ '^\s*{$' || line =~ '(\s*{' || (pb == 0 && (line =~ '{$' || line =~ '(\s*{$'))292 return indent(lnum) + shiftwidth()293 endif294 295 let s:curtabstop = repeat(' ', &tabstop)296 297 if g:r_indent_align_args == 1298 if pb > 0 && line =~ '{$'299 return s:Get_last_paren_idx(line, '(', ')', pb) + shiftwidth()300 endif301 302 let bb = s:Get_paren_balance(line, '[', ']')303 304 if pb > 0305 if &filetype == "rhelp"306 let ind = s:Get_last_paren_idx(line, '(', ')', pb)307 else308 let ind = s:Get_last_paren_idx(getline(lnum), '(', ')', pb)309 endif310 return ind311 endif312 313 if pb < 0 && line =~ '.*[,&|\-\*+<>]$'314 if line =~ '.*[\-\*+>]$'315 let is_op = v:true316 else317 let is_op = v:false318 endif319 let lnum = s:Get_prev_line(lnum)320 while pb < 1 && lnum > 0321 let line = SanitizeRLine(getline(lnum))322 let line = substitute(line, '\t', s:curtabstop, "g")323 let ind = strlen(line)324 while ind > 0325 if line[ind] == ')'326 let pb -= 1327 elseif line[ind] == '('328 let pb += 1329 if is_op && pb == 0330 return indent(lnum)331 endif332 endif333 if pb == 1334 return ind + 1335 endif336 let ind -= 1337 endwhile338 let lnum -= 1339 endwhile340 return 0341 endif342 343 if bb > 0344 let ind = s:Get_last_paren_idx(getline(lnum), '[', ']', bb)345 return ind346 endif347 endif348 349 let post_block = 0350 if line =~ '}$' && s:Get_paren_balance(line, '{', '}') < 0351 let lnum = s:Get_matching_brace(lnum, '{', '}', 0)352 let line = SanitizeRLine(getline(lnum))353 if lnum > 0 && line =~ '^\s*{'354 let lnum = s:Get_prev_line(lnum)355 let line = SanitizeRLine(getline(lnum))356 endif357 let pb = s:Get_paren_balance(line, '(', ')')358 let post_block = 1359 endif360 361 " Indent after operator pattern362 let olnum = s:Get_prev_line(lnum)363 let oline = getline(olnum)364 if olnum > 0365 if substitute(line, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0366 if substitute(oline, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0367 return indent(lnum)368 else369 return indent(lnum) + shiftwidth()370 endif371 elseif substitute(oline, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0372 return indent(lnum) - shiftwidth()373 endif374 elseif substitute(line, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0375 return indent(lnum) + shiftwidth()376 endif377 378 let post_fun = 0379 if pb < 0 && line !~ ')\s*[,&|\-\*+<>]$'380 let post_fun = 1381 while pb < 0 && lnum > 0382 let lnum -= 1383 let linepiece = SanitizeRLine(getline(lnum))384 let pb += s:Get_paren_balance(linepiece, "(", ")")385 let line = linepiece . line386 endwhile387 if line =~ '{$' && post_block == 0388 return indent(lnum) + shiftwidth()389 endif390 391 " Now we can do some tests again392 if cline =~ '^\s*{'393 return indent(lnum)394 endif395 if post_block == 0396 let newl = SanitizeRLine(line)397 if newl =~ '\<\(if\|while\|for\|function\)\s*()$' || newl =~ '\<else$' || newl =~ '<-$'398 return indent(lnum) + shiftwidth()399 endif400 endif401 endif402 403 if cline =~ '^\s*else'404 if line =~ '<-\s*if\s*()'405 return indent(lnum) + shiftwidth()406 elseif line =~ '\<if\s*()'407 return indent(lnum)408 else409 return indent(lnum) - shiftwidth()410 endif411 endif412 413 let bb = s:Get_paren_balance(line, '[', ']')414 if bb < 0 && line =~ '.*]'415 while bb < 0 && lnum > 0416 let lnum -= 1417 let linepiece = SanitizeRLine(getline(lnum))418 let bb += s:Get_paren_balance(linepiece, "[", "]")419 let line = linepiece . line420 endwhile421 let line = s:RDelete_parens(line)422 endif423 424 let plnum = s:Get_prev_line(lnum)425 let ppost_else = 0426 if plnum > 0427 let pline = SanitizeRLine(getline(plnum))428 let ppost_block = 0429 if pline =~ '}$'430 let ppost_block = 1431 let plnum = s:Get_matching_brace(plnum, '{', '}', 0)432 let pline = SanitizeRLine(getline(plnum))433 if pline =~ '^\s*{$' && plnum > 0434 let plnum = s:Get_prev_line(plnum)435 let pline = SanitizeRLine(getline(plnum))436 endif437 endif438 439 if pline =~ 'else$'440 let ppost_else = 1441 let plnum = s:Get_matching_if(plnum, 0)442 let pline = SanitizeRLine(getline(plnum))443 endif444 445 if pline =~ '^\s*else\s*if\s*('446 let pplnum = s:Get_prev_line(plnum)447 let ppline = SanitizeRLine(getline(pplnum))448 while ppline =~ '^\s*else\s*if\s*(' || ppline =~ '^\s*if\s*()\s*\S$'449 let plnum = pplnum450 let pline = ppline451 let pplnum = s:Get_prev_line(plnum)452 let ppline = SanitizeRLine(getline(pplnum))453 endwhile454 while ppline =~ '\<\(if\|while\|for\|function\)\s*()$' || ppline =~ '\<else$' || ppline =~ '<-$'455 let plnum = pplnum456 let pline = ppline457 let pplnum = s:Get_prev_line(plnum)458 let ppline = SanitizeRLine(getline(pplnum))459 endwhile460 endif461 462 let ppb = s:Get_paren_balance(pline, '(', ')')463 if ppb < 0 && (pline =~ ')\s*{$' || pline =~ ')$')464 while ppb < 0 && plnum > 0465 let plnum -= 1466 let linepiece = SanitizeRLine(getline(plnum))467 let ppb += s:Get_paren_balance(linepiece, "(", ")")468 let pline = linepiece . pline469 endwhile470 let pline = s:RDelete_parens(pline)471 endif472 endif473 474 let ind = indent(lnum)475 476 if g:r_indent_align_args == 0 && pb != 0477 let ind += pb * shiftwidth()478 return ind479 endif480 481 if g:r_indent_align_args == 0 && bb != 0482 let ind += bb * shiftwidth()483 return ind484 endif485 486 if plnum > 0487 let pind = indent(plnum)488 else489 let pind = 0490 endif491 492 if ind == pind || (ind == (pind + shiftwidth()) && pline =~ '{$' && ppost_else == 0)493 return ind494 endif495 496 let pline = getline(plnum)497 let pbb = s:Get_paren_balance(pline, '[', ']')498 499 while pind < ind && plnum > 0 && ppb == 0 && pbb == 0500 let ind = pind501 let plnum = s:Get_prev_line(plnum)502 let pline = getline(plnum)503 let ppb = s:Get_paren_balance(pline, '(', ')')504 let pbb = s:Get_paren_balance(pline, '[', ']')505 while pline =~ '^\s*else'506 let plnum = s:Get_matching_if(plnum, 1)507 let pline = getline(plnum)508 let ppb = s:Get_paren_balance(pline, '(', ')')509 let pbb = s:Get_paren_balance(pline, '[', ']')510 endwhile511 let pind = indent(plnum)512 if ind == (pind + shiftwidth()) && pline =~ '{$'513 return ind514 endif515 endwhile516 517 return ind518endfunction519 520let &cpo = s:cpo_save521unlet s:cpo_save522 523" vim: sw=2524 