| 842 | |
| 843 | |
| 844 | void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, int /*initStyle - unused*/, IDocument *pAccess) { |
| 845 | if (!options.fold) |
| 846 | return; |
| 847 | |
| 848 | Accessor styler(pAccess, NULL); |
| 849 | |
| 850 | const Sci_Position maxPos = startPos + length; |
| 851 | const Sci_Position maxLines = (maxPos == styler.Length()) ? styler.GetLine(maxPos) : styler.GetLine(maxPos - 1); // Requested last line |
| 852 | const Sci_Position docLines = styler.GetLine(styler.Length()); // Available last line |
| 853 | |
| 854 | // Backtrack to previous non-blank line so we can determine indent level |
| 855 | // for any white space lines (needed esp. within triple quoted strings) |
| 856 | // and so we can fix any preceding fold level (which is why we go back |
| 857 | // at least one line in all cases) |
| 858 | int spaceFlags = 0; |
| 859 | Sci_Position lineCurrent = styler.GetLine(startPos); |
| 860 | int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); |
| 861 | while (lineCurrent > 0) { |
| 862 | lineCurrent--; |
| 863 | indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); |
| 864 | if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && |
| 865 | (!IsCommentLine(lineCurrent, styler)) && |
| 866 | (!IsQuoteLine(lineCurrent, styler))) |
| 867 | break; |
| 868 | } |
| 869 | int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; |
| 870 | |
| 871 | // Set up initial loop state |
| 872 | startPos = styler.LineStart(lineCurrent); |
| 873 | int prev_state = SCE_P_DEFAULT & 31; |
| 874 | if (lineCurrent >= 1) |
| 875 | prev_state = styler.StyleAt(startPos - 1) & 31; |
| 876 | int prevQuote = options.foldQuotes && IsPyTripleQuoteStringState(prev_state); |
| 877 | |
| 878 | // Process all characters to end of requested range or end of any triple quote |
| 879 | //that hangs over the end of the range. Cap processing in all cases |
| 880 | // to end of document (in case of unclosed quote at end). |
| 881 | while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote)) { |
| 882 | |
| 883 | // Gather info |
| 884 | int lev = indentCurrent; |
| 885 | Sci_Position lineNext = lineCurrent + 1; |
| 886 | int indentNext = indentCurrent; |
| 887 | int quote = false; |
| 888 | if (lineNext <= docLines) { |
| 889 | // Information about next line is only available if not at end of document |
| 890 | indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); |
| 891 | Sci_Position lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext); |
| 892 | const int style = styler.StyleAt(lookAtPos) & 31; |
| 893 | quote = options.foldQuotes && IsPyTripleQuoteStringState(style); |
| 894 | } |
| 895 | const int quote_start = (quote && !prevQuote); |
| 896 | const int quote_continue = (quote && prevQuote); |
| 897 | if (!quote || !prevQuote) |
| 898 | indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; |
| 899 | if (quote) |
| 900 | indentNext = indentCurrentLevel; |
| 901 | if (indentNext & SC_FOLDLEVELWHITEFLAG) |
nothing calls this directly
no test coverage detected