File indexing completed on 2024-05-19 04:00:09
0001 var katescript = { 0002 "name": "Python", 0003 "author": "Paul Giannaros <paul@giannaros.org>, Gerald Senarclens de Grancy <oss@senarclens.eu>", 0004 "license": "LGPL", 0005 "revision": 4, 0006 "kate-version": "5.1", 0007 "indent-languages": ["Python"] 0008 }; // kate-script-header, must be at the start of the file without comments, pure json 0009 0010 // required katepart js libraries 0011 require ("range.js"); 0012 require ("string.js"); 0013 0014 openings = ['(', '[', '{']; 0015 closings = [')', ']', '}']; // requires same order as in openings 0016 unindenters = /\b(continue|pass|raise|return|break)\b/; 0017 immediate_unindenters = new Set(["else", "elif", "finally", "except"]) 0018 0019 triggerCharacters = ": "; 0020 0021 var debugMode = false; 0022 0023 function dbg() { 0024 if (debugMode) { 0025 debug.apply(this, arguments); 0026 } 0027 } 0028 0029 // Return the given line without comments and leading or trailing whitespace. 0030 // Eg. 0031 // getCode(x) -> "for i in range(3):" 0032 // if document.line(x) == " for i in range(3):" 0033 // getCode(x) -> "for i in range(3):" 0034 // if document.line(x) == "for i in range(3): " 0035 // getCode(x) -> "for i in range(3):" 0036 // if document.line(x) == "for i in range(3): # grand" 0037 function getCode(lineNr, virtcol=-1) { 0038 var line = document.line(lineNr); 0039 var code = ''; 0040 virtcol = virtcol >= 0 ? virtcol : document.firstVirtualColumn(lineNr); 0041 if (virtcol < 0) 0042 return code; 0043 for (; virtcol < line.length; ++virtcol) { 0044 if (document.isCode(lineNr, virtcol)) { 0045 code += line[virtcol]; 0046 } 0047 } 0048 return code.trim(); 0049 } 0050 0051 0052 // Return the indent if a opening bracket is not closed (incomplete sequence). 0053 // The calculated intent is the innermost opening bracket's position plus 1. 0054 // `lineNr`: the number of the line on which the brackets should be counted 0055 function _calcOpeningIndent(lineNr) { 0056 var line = document.line(lineNr); 0057 var countClosing = new Array(); 0058 closings.forEach(function(elem) { 0059 countClosing[elem] = 0; 0060 }); 0061 for (i = line.length - 1; i >= 0; --i) { 0062 if (document.isComment(lineNr, i) || document.isString(lineNr, i)) 0063 continue; 0064 if (closings.indexOf(line[i]) > -1) 0065 countClosing[line[i]]++; 0066 var index = openings.indexOf(line[i]); 0067 if (index > -1) { 0068 if (countClosing[closings[index]] == 0) { 0069 return i + 1; 0070 } 0071 countClosing[closings[index]]--; 0072 } 0073 } 0074 return -1; 0075 } 0076 0077 0078 // Return the indent if a closing bracket not opened (incomplete sequence). 0079 // The intent is the same as on the line with the unmatched opening bracket. 0080 // `lineNr`: the number of the line on which the brackets should be counted 0081 function _calcClosingIndent(lineNr, indentWidth) { 0082 var line = document.line(lineNr); 0083 var countClosing = new Array(); 0084 closings.forEach(function(elem) { 0085 countClosing[elem] = 0; 0086 }); 0087 for (i = line.length - 1; i >= 0; --i) { 0088 if (document.isComment(lineNr, i) || document.isString(lineNr, i)) 0089 continue; 0090 if (closings.indexOf(line[i]) > -1) 0091 countClosing[line[i]]++; 0092 var index = openings.indexOf(line[i]); 0093 if (index > -1) 0094 countClosing[closings[index]]--; 0095 } 0096 for (var key in countClosing) { 0097 if (countClosing[key] > 0) { // unmatched closing bracket 0098 for (--lineNr; lineNr >= 0; --lineNr) { 0099 if (_calcOpeningIndent(lineNr) > -1) { 0100 var indent = document.firstVirtualColumn(lineNr); 0101 if (shouldUnindent(lineNr + 1)) 0102 return Math.max(0, indent - indentWidth); 0103 return indent; 0104 } 0105 } 0106 } 0107 } 0108 return -1; 0109 } 0110 0111 0112 // Returns the indent for mismatched (opening or closing) brackets. 0113 // If there are no mismatched brackets, -1 is returned. 0114 // `lineNr`: number of the line for which the indent is calculated 0115 function calcBracketIndent(lineNr, indentWidth) { 0116 var indent = _calcOpeningIndent(lineNr - 1); 0117 if (indent > -1) 0118 return indent 0119 indent = _calcClosingIndent(lineNr - 1, indentWidth); 0120 if (indent > -1) 0121 return indent 0122 return -1; 0123 } 0124 0125 0126 // Return true if a single unindent should occur. 0127 function shouldUnindent(LineNr) { 0128 lastLine = getCode(LineNr - 1); 0129 if (lastLine.match(unindenters)) 0130 return 1; 0131 0132 // unindent if the last line was indented b/c of a backslash 0133 if (LineNr >= 2) { 0134 secondLastLine = getCode(LineNr - 2); 0135 if (secondLastLine.length && secondLastLine.substr(-1) == "\\") 0136 return 1; 0137 } 0138 return 0; 0139 } 0140 0141 function findLastIndent(lineNr) { 0142 for (; getCode(lineNr).length == 0; --lineNr); 0143 return document.firstVirtualColumn(lineNr); 0144 } 0145 0146 function getDocStringStart(line) { 0147 var currentLine = line; 0148 var currentString; 0149 0150 if (!document.isComment(line, document.firstVirtualColumn(line)) || document.line(currentLine).charAt(document.firstVirtualColumn(line)) === '#') { 0151 return -1; 0152 } 0153 0154 while (currentLine >= 0) { 0155 currentString = document.line(currentLine - 1); 0156 if (currentString.charAt(document.firstVirtualColumn(currentLine - 1)) !== '#') { 0157 if (currentString.includes("'''") || currentString.includes('"""')) { 0158 break; 0159 } 0160 } 0161 --currentLine; 0162 } 0163 return currentLine - 1; 0164 } 0165 0166 function getPrevDocStringEnd(line) { 0167 var currentLine = line; 0168 var currentString; 0169 0170 while (currentLine >= 0) { 0171 currentString = document.line(currentLine - 1); 0172 if (currentString.includes("'''") || currentString.includes('"""')) { 0173 break; 0174 } else if (getCode(currentLine - 1, 0).length) { 0175 return -1; 0176 } 0177 --currentLine; 0178 } 0179 return currentLine - 1; 0180 } 0181 0182 function getMultiLineStringStart(line) { 0183 var currentLine = line; 0184 var currentString; 0185 0186 if (!document.isString(line, document.firstVirtualColumn(line))) { 0187 return -1; 0188 } 0189 0190 while (currentLine >= 0) { 0191 currentString = document.line(currentLine - 1); 0192 if (!document.isComment(currentLine - 1, document.firstVirtualColumn(currentLine - 1))) { 0193 if (currentString.includes("'''") || currentString.includes('"""')) { 0194 break; 0195 } 0196 } 0197 --currentLine; 0198 } 0199 return currentLine - 1; 0200 } 0201 0202 function getPrevMultiLineStringEnd(line) { 0203 var currentLine = line; 0204 var currentString; 0205 0206 while (currentLine >= 0) { 0207 currentString = document.line(currentLine - 1); 0208 currentCode = getCode(document.line(currentLine - 1), 0); 0209 if (!document.isComment(currentLine - 1, document.firstVirtualColumn(currentLine - 1))) { 0210 if (currentString.includes("'''") || currentString.includes('"""')) { 0211 break; 0212 } else if (getCode(currentLine - 1, 0).length) { 0213 return -1; 0214 } 0215 } 0216 --currentLine; 0217 } 0218 return currentLine - 1; 0219 } 0220 0221 // Return the amount of characters (in spaces) to be indented. 0222 // Special indent() return values: 0223 // -2 = no indent 0224 // -1 = keep last indent 0225 // Follow PEP8 for unfinished sequences and argument lists. 0226 // Nested sequences are not implemented. (neither by Emacs' python-mode) 0227 function indent(line, indentWidth, character) { 0228 if (line == 0) // don't ever act on document's first line 0229 return -2; 0230 if (!document.line(line - 1).length) // empty line 0231 return -2; 0232 0233 if (triggerCharacters.indexOf(character) > -1 && character.length) { 0234 var virtcol = document.firstVirtualColumn(line); 0235 var lline = getCode(line, virtcol); 0236 if (character != " ") 0237 lline = lline.substring(0, lline.length - 1); 0238 if (immediate_unindenters.has(lline) && virtcol == findLastIndent(line - 1) && lline.length == document.line(line).length - virtcol - 1) 0239 return Math.max(0, virtcol - indentWidth); 0240 else 0241 return -2 0242 } 0243 0244 var virtcol = document.firstVirtualColumn(line - 1); 0245 var lastLine = getCode(line - 1, virtcol); 0246 var lastChar = lastLine.substr(-1); 0247 0248 // indent when opening bracket or backslash is at the end the previous line 0249 if (openings.indexOf(lastChar) >= 0 || lastChar == "\\") { 0250 return virtcol + indentWidth; 0251 } 0252 var indent = calcBracketIndent(line, indentWidth); 0253 if (lastLine.endsWith(':')) { 0254 if (indent > -1) 0255 indent += indentWidth; 0256 else 0257 indent = virtcol + indentWidth; 0258 } 0259 docStringStart = getDocStringStart(line); 0260 if (docStringStart > -1) { 0261 if (docStringStart === line) { 0262 return -1; 0263 } 0264 dbg("line = {" + document.line(line) + "} docStringStart = {" + document.line(docStringStart) + "}" + " dsno = " + docStringStart); 0265 return document.firstVirtualColumn(line) + document.firstVirtualColumn(docStringStart) - indentWidth; 0266 } 0267 multiLineStringStart = getMultiLineStringStart(line); 0268 dbg("docStringStart = " + docStringStart); 0269 dbg("multiLineStringStart = " + multiLineStringStart); 0270 if (multiLineStringStart > -1) { 0271 if (multiLineStringStart === line) { 0272 return -1; 0273 } 0274 return -2; 0275 } 0276 if (indent === -1) { 0277 prevMultiLineStringEnd = getPrevMultiLineStringEnd(line); 0278 if (prevMultiLineStringEnd > -1) { 0279 prevMultiLineStringStart = getMultiLineStringStart(prevMultiLineStringEnd); 0280 return document.firstVirtualColumn(prevMultiLineStringStart); 0281 } 0282 } 0283 if (indent === -1) { 0284 prevDocStringEnd = getPrevDocStringEnd(line); 0285 if (prevDocStringEnd > -1) { 0286 prevDocStringStart = getDocStringStart(prevDocStringEnd); 0287 return document.firstVirtualColumn(prevDocStringStart); 0288 } 0289 } 0290 // continue, pass, raise, return etc. should unindent 0291 if (shouldUnindent(line) && (indent == -1)) { 0292 indent = Math.max(0, virtcol - indentWidth); 0293 } 0294 return indent; 0295 } 0296 0297 // kate: space-indent on; indent-width 4; replace-tabs on;