rapid.vim (8166B)
1 " ABB Rapid Command indent file for Vim 2 " Language: ABB Rapid Command 3 " Maintainer: Patrick Meiser-Knosowski <knosowski@graeffrobotics.de> 4 " Version: 2.2.7 5 " Last Change: 12. May 2023 6 " Credits: Based on indent/vim.vim 7 " 8 " Suggestions of improvement are very welcome. Please email me! 9 " 10 " Known bugs: ../doc/rapid.txt 11 " 12 " TODO 13 " * indent wrapped lines which do not end with an ; or special key word, 14 " maybe this is a better idea, but then () and [] has to be changed as 15 " well 16 " 17 18 if exists("g:rapidNoSpaceIndent") 19 if !exists("g:rapidSpaceIndent") 20 let g:rapidSpaceIndent = !g:rapidNoSpaceIndent 21 endif 22 unlet g:rapidNoSpaceIndent 23 endif 24 25 " Only load this indent file when no other was loaded. 26 if exists("b:did_indent") || get(g:,'rapidNoIndent',0) 27 finish 28 endif 29 let b:did_indent = 1 30 31 setlocal nolisp 32 setlocal nosmartindent 33 setlocal autoindent 34 setlocal indentexpr=GetRapidIndent() 35 if get(g:,'rapidNewStyleIndent',0) 36 setlocal indentkeys=!^F,o,O,0=~endmodule,0=~error,0=~undo,0=~backward,0=~endproc,0=~endrecord,0=~endtrap,0=~endfunc,0=~else,0=~endif,0=~endtest,0=~endfor,0=~endwhile,:,<[>,<]>,<(>,<)> 37 else 38 setlocal indentkeys=!^F,o,O,0=~endmodule,0=~error,0=~undo,0=~backward,0=~endproc,0=~endrecord,0=~endtrap,0=~endfunc,0=~else,0=~endif,0=~endtest,0=~endfor,0=~endwhile,: 39 endif 40 let b:undo_indent="setlocal lisp< si< ai< inde< indk<" 41 42 if get(g:,'rapidSpaceIndent',1) 43 " Use spaces for indention, 2 is enough. 44 " More or even tabs wastes space on the teach pendant. 45 setlocal softtabstop=2 46 setlocal shiftwidth=2 47 setlocal expandtab 48 setlocal shiftround 49 let b:undo_indent = b:undo_indent." sts< sw< et< sr<" 50 endif 51 52 " Only define the function once. 53 if exists("*GetRapidIndent") 54 finish 55 endif 56 57 let s:keepcpo= &cpo 58 set cpo&vim 59 60 function GetRapidIndent() 61 let ignorecase_save = &ignorecase 62 try 63 let &ignorecase = 0 64 return s:GetRapidIndentIntern() 65 finally 66 let &ignorecase = ignorecase_save 67 endtry 68 endfunction 69 70 function s:GetRapidIndentIntern() abort 71 72 let l:currentLineNum = v:lnum 73 let l:currentLine = getline(l:currentLineNum) 74 75 if l:currentLine =~ '^!' && !get(g:,'rapidCommentIndent',0) 76 " If current line is ! line comment, do not change indent 77 " This may be useful if code is commented out at the first column. 78 return 0 79 endif 80 81 " Find a non-blank line above the current line. 82 let l:preNoneBlankLineNum = s:RapidPreNoneBlank(v:lnum - 1) 83 if l:preNoneBlankLineNum == 0 84 " At the start of the file use zero indent. 85 return 0 86 endif 87 88 let l:preNoneBlankLine = getline(l:preNoneBlankLineNum) 89 let l:ind = indent(l:preNoneBlankLineNum) 90 91 " Define add a 'shiftwidth' pattern 92 let l:addShiftwidthPattern = '\c\v^\s*(' 93 let l:addShiftwidthPattern .= '((local|task)\s+)?(module|record|proc|func|trap)\s+\k' 94 let l:addShiftwidthPattern .= '|(backward|error|undo)>' 95 let l:addShiftwidthPattern .= ')' 96 " 97 " Define Subtract 'shiftwidth' pattern 98 let l:subtractShiftwidthPattern = '\c\v^\s*(' 99 let l:subtractShiftwidthPattern .= 'end(module|record|proc|func|trap)>' 100 let l:subtractShiftwidthPattern .= '|(backward|error|undo)>' 101 let l:subtractShiftwidthPattern .= ')' 102 103 " Add shiftwidth 104 if l:preNoneBlankLine =~ l:addShiftwidthPattern 105 \|| s:RapidLenTilStr(l:preNoneBlankLineNum, "then", 0)>=0 106 \|| s:RapidLenTilStr(l:preNoneBlankLineNum, "else", 0)>=0 107 \|| s:RapidLenTilStr(l:preNoneBlankLineNum, "do", 0)>=0 108 \|| s:RapidLenTilStr(l:preNoneBlankLineNum, "case", 0)>=0 109 \|| s:RapidLenTilStr(l:preNoneBlankLineNum, "default", 0)>=0 110 let l:ind += &sw 111 endif 112 113 " Subtract shiftwidth 114 if l:currentLine =~ l:subtractShiftwidthPattern 115 \|| s:RapidLenTilStr(l:currentLineNum, "endif", 0)>=0 116 \|| s:RapidLenTilStr(l:currentLineNum, "endfor", 0)>=0 117 \|| s:RapidLenTilStr(l:currentLineNum, "endwhile", 0)>=0 118 \|| s:RapidLenTilStr(l:currentLineNum, "endtest", 0)>=0 119 \|| s:RapidLenTilStr(l:currentLineNum, "else", 0)>=0 120 \|| s:RapidLenTilStr(l:currentLineNum, "elseif", 0)>=0 121 \|| s:RapidLenTilStr(l:currentLineNum, "case", 0)>=0 122 \|| s:RapidLenTilStr(l:currentLineNum, "default", 0)>=0 123 let l:ind = l:ind - &sw 124 endif 125 126 " First case (or default) after a test gets the indent of the test. 127 if (s:RapidLenTilStr(l:currentLineNum, "case", 0)>=0 || s:RapidLenTilStr(l:currentLineNum, "default", 0)>=0) && s:RapidLenTilStr(l:preNoneBlankLineNum, "test", 0)>=0 128 let l:ind += &sw 129 endif 130 131 " continued lines with () or [] 132 let l:OpenSum = s:RapidLoneParen(l:preNoneBlankLineNum,"(") + s:RapidLoneParen(l:preNoneBlankLineNum,"[") 133 if get(g:,'rapidNewStyleIndent',0) 134 let l:CloseSum = s:RapidLoneParen(l:preNoneBlankLineNum,")") + s:RapidLoneParen(l:currentLineNum,"]") 135 else 136 let l:CloseSum = s:RapidLoneParen(l:preNoneBlankLineNum,")") + s:RapidLoneParen(l:preNoneBlankLineNum,"]") 137 endif 138 if l:OpenSum > l:CloseSum 139 let l:ind += (l:OpenSum * 4 * &sw) 140 elseif l:OpenSum < l:CloseSum 141 let l:ind -= (l:CloseSum * 4 * &sw) 142 endif 143 144 return l:ind 145 endfunction 146 147 " Returns the length of the line until a:str occur outside a string or 148 " comment. Search starts at string index a:startIdx. 149 " If a:str is a word also add word boundaries and case insensitivity. 150 " Note: rapidTodoComment and rapidDebugComment are not taken into account. 151 function s:RapidLenTilStr(lnum, str, startIdx) abort 152 153 let l:line = getline(a:lnum) 154 let l:len = strlen(l:line) 155 let l:idx = a:startIdx 156 let l:str = a:str 157 if l:str =~ '^\k\+$' 158 let l:str = '\c\<' . l:str . '\>' 159 endif 160 161 while l:len > l:idx 162 let l:idx = match(l:line, l:str, l:idx) 163 if l:idx < 0 164 " a:str not found 165 return -1 166 endif 167 let l:synName = synIDattr(synID(a:lnum,l:idx+1,0),"name") 168 if l:synName != "rapidString" 169 \&& l:synName != "rapidConcealableString" 170 \&& (l:synName != "rapidComment" || l:str =~ '^!') 171 " a:str found outside string or line comment 172 return l:idx 173 endif 174 " a:str is part of string or line comment 175 let l:idx += 1 " continue search for a:str 176 endwhile 177 178 " a:str not found or l:len <= a:startIdx 179 return -1 180 endfunction 181 182 " a:lchar should be one of (, ), [, ], { or } 183 " returns the number of opening/closing parentheses which have no 184 " closing/opening match in getline(a:lnum) 185 function s:RapidLoneParen(lnum,lchar) abort 186 if a:lchar == "(" || a:lchar == ")" 187 let l:opnParChar = "(" 188 let l:clsParChar = ")" 189 elseif a:lchar == "[" || a:lchar == "]" 190 let l:opnParChar = "[" 191 let l:clsParChar = "]" 192 elseif a:lchar == "{" || a:lchar == "}" 193 let l:opnParChar = "{" 194 let l:clsParChar = "}" 195 else 196 return 0 197 endif 198 199 let l:line = getline(a:lnum) 200 201 " look for the first ! which is not part of a string 202 let l:len = s:RapidLenTilStr(a:lnum,"!",0) 203 if l:len == 0 204 return 0 " first char is !; ignored 205 endif 206 207 let l:opnParen = 0 208 " count opening brackets 209 let l:i = 0 210 while l:i >= 0 211 let l:i = s:RapidLenTilStr(a:lnum, l:opnParChar, l:i) 212 if l:i >= 0 213 let l:opnParen += 1 214 let l:i += 1 215 endif 216 endwhile 217 218 let l:clsParen = 0 219 " count closing brackets 220 let l:i = 0 221 while l:i >= 0 222 let l:i = s:RapidLenTilStr(a:lnum, l:clsParChar, l:i) 223 if l:i >= 0 224 let l:clsParen += 1 225 let l:i += 1 226 endif 227 endwhile 228 229 if (a:lchar == "(" || a:lchar == "[" || a:lchar == "{") && l:opnParen>l:clsParen 230 return (l:opnParen-l:clsParen) 231 elseif (a:lchar == ")" || a:lchar == "]" || a:lchar == "}") && l:clsParen>l:opnParen 232 return (l:clsParen-l:opnParen) 233 endif 234 235 return 0 236 endfunction 237 238 " This function works almost like prevnonblank() but handles %%%-headers and 239 " comments like blank lines 240 function s:RapidPreNoneBlank(lnum) abort 241 242 let nPreNoneBlank = prevnonblank(a:lnum) 243 244 while nPreNoneBlank>0 && getline(nPreNoneBlank) =~ '\v\c^\s*(\%\%\%|!)' 245 " Previous none blank line irrelevant. Look further aback. 246 let nPreNoneBlank = prevnonblank(nPreNoneBlank - 1) 247 endwhile 248 249 return nPreNoneBlank 250 endfunction 251 252 let &cpo = s:keepcpo 253 unlet s:keepcpo 254 255 " vim:sw=2 sts=2 et