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;