aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorkudah <kudahkukarek@gmail.com>2013-05-18 15:31:53 +0300
committerkudah <kudahkukarek@gmail.com>2013-05-18 15:31:53 +0300
commitad5a314d565a4c0fb8bffdf21d263edcfd79ce43 (patch)
tree60e3598507b354c9737dd178fba177e20023cdc4
parentc66fa75dcf753e2838e878809eff17124f4ef9b1 (diff)
downloadscintilla-mirror-ad5a314d565a4c0fb8bffdf21d263edcfd79ce43.tar.gz
Fix import list folding in fully indented modules
-rw-r--r--lexers/LexHaskell.cxx166
1 files changed, 87 insertions, 79 deletions
diff --git a/lexers/LexHaskell.cxx b/lexers/LexHaskell.cxx
index 38533d1b0..e56906b81 100644
--- a/lexers/LexHaskell.cxx
+++ b/lexers/LexHaskell.cxx
@@ -45,8 +45,6 @@
using namespace Scintilla;
#endif
-#define INDENT_OFFSET 1
-
static int u_iswalpha(int);
static int u_iswalnum(int);
static int u_iswupper(int);
@@ -141,10 +139,63 @@ static inline bool IsExternalStyle(int style) {
|| style == SCE_HA_LITERATE_CODEDELIM);
}
-inline int CommentBlockStyleFromNestLevel(const unsigned int nestLevel) {
+static inline int CommentBlockStyleFromNestLevel(const unsigned int nestLevel) {
return SCE_HA_COMMENTBLOCK + (nestLevel % 3);
}
+// Mangled version of lexlib/Accessor.cxx IndentAmount.
+// Modified to treat comment blocks as whitespace
+// plus special case for commentline/preprocessor.
+static int HaskellIndentAmount(Accessor &styler, const int line) {
+
+ // Determines the indentation level of the current line
+ // Comment blocks are treated as whitespace
+
+ int pos = styler.LineStart(line);
+ int eol_pos = styler.LineStart(line + 1) - 1;
+
+ char ch = styler[pos];
+ int style = styler.StyleAt(pos);
+
+ int indent = 0;
+ bool inPrevPrefix = line > 0;
+
+ int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
+
+ while (( ch == ' ' || ch == '\t'
+ || IsCommentBlockStyle(style)
+ || style == SCE_HA_LITERATE_CODEDELIM)
+ && (pos < eol_pos)) {
+ if (inPrevPrefix) {
+ char chPrev = styler[posPrev++];
+ if (chPrev != ' ' && chPrev != '\t') {
+ inPrevPrefix = false;
+ }
+ }
+ if (ch == '\t') {
+ indent = (indent / 8 + 1) * 8;
+ } else { // Space or comment block
+ indent++;
+ }
+ pos++;
+ ch = styler[pos];
+ style = styler.StyleAt(pos);
+ }
+
+ indent += SC_FOLDLEVELBASE;
+ // if completely empty line or the start of a comment or preprocessor...
+ if ( styler.LineStart(line) == styler.Length()
+ || ch == ' '
+ || ch == '\t'
+ || ch == '\n'
+ || ch == '\r'
+ || IsCommentStyle(style)
+ || style == SCE_HA_PREPROCESSOR)
+ return indent | SC_FOLDLEVELWHITEFLAG;
+ else
+ return indent;
+}
+
struct OptionsHaskell {
bool magicHash;
bool allowQuotes;
@@ -224,6 +275,7 @@ struct OptionSetHaskell : public OptionSet<OptionsHaskell> {
class LexerHaskell : public ILexer {
bool literate;
int firstImportLine;
+ int firstImportIndent;
WordList keywords;
WordList ffi;
WordList reserved_operators;
@@ -310,7 +362,8 @@ class LexerHaskell : public ILexer {
style = styler.StyleAt(currentPos);
if (ch == ' ' || ch == '\t'
- || IsCommentBlockStyle(style)) {
+ || IsCommentBlockStyle(style)
+ || style == SCE_HA_LITERATE_CODEDELIM) {
currentPos++;
} else {
break;
@@ -324,8 +377,26 @@ class LexerHaskell : public ILexer {
}
}
+ inline int IndentAmountWithOffset(Accessor &styler, const int line) const {
+ const int indent = HaskellIndentAmount(styler, line);
+ const int indentLevel = indent & SC_FOLDLEVELNUMBERMASK;
+ return indentLevel <= ((firstImportIndent - 1) + SC_FOLDLEVELBASE)
+ ? indent
+ : (indentLevel + firstImportIndent) | (indent & ~SC_FOLDLEVELNUMBERMASK);
+ }
+
+ inline int IndentLevelRemoveIndentOffset(const int indentLevel) const {
+ return indentLevel <= ((firstImportIndent - 1) + SC_FOLDLEVELBASE)
+ ? indentLevel
+ : indentLevel - firstImportIndent;
+ }
+
public:
- LexerHaskell(const bool literate_) : literate(literate_), firstImportLine(-1) {}
+ LexerHaskell(bool literate_)
+ : literate(literate_)
+ , firstImportLine(-1)
+ , firstImportIndent(0)
+ {}
virtual ~LexerHaskell() {}
void SCI_METHOD Release() {
@@ -893,73 +964,6 @@ void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initSty
sc.Complete();
}
-// Mangled version of lexlib/Accessor.cxx IndentAmount.
-// Modified to treat comment blocks as whitespace
-// plus special case for commentline/preprocessor.
-static int HaskellIndentAmount(Accessor &styler, int line) {
-
- // Determines the indentation level of the current line
- // Comment blocks are treated as whitespace
-
- int pos = styler.LineStart(line);
- int eol_pos = styler.LineStart(line + 1) - 1;
-
- char ch = styler[pos];
- int style = styler.StyleAt(pos);
-
- int indent = 0;
- bool inPrevPrefix = line > 0;
-
- int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
-
- while (( ch == ' ' || ch == '\t'
- || IsCommentBlockStyle(style)
- || style == SCE_HA_LITERATE_CODEDELIM)
- && (pos < eol_pos)) {
- if (inPrevPrefix) {
- char chPrev = styler[posPrev++];
- if (chPrev != ' ' && chPrev != '\t') {
- inPrevPrefix = false;
- }
- }
- if (ch == '\t') {
- indent = (indent / 8 + 1) * 8;
- } else { // Space or comment block
- indent++;
- }
- pos++;
- ch = styler[pos];
- style = styler.StyleAt(pos);
- }
-
- indent += SC_FOLDLEVELBASE;
- // if completely empty line or the start of a comment or preprocessor...
- if ( styler.LineStart(line) == styler.Length()
- || ch == ' '
- || ch == '\t'
- || ch == '\n'
- || ch == '\r'
- || IsCommentStyle(style)
- || style == SCE_HA_PREPROCESSOR)
- return indent | SC_FOLDLEVELWHITEFLAG;
- else
- return indent;
-}
-
-static inline int IndentAmountWithOffset(Accessor &styler, int line) {
- int indent = HaskellIndentAmount(styler, line);
- int indentLevel = indent & SC_FOLDLEVELNUMBERMASK;
- return indentLevel == (SC_FOLDLEVELBASE & SC_FOLDLEVELNUMBERMASK)
- ? indent
- : (indentLevel + INDENT_OFFSET) | (indent & ~SC_FOLDLEVELNUMBERMASK);
-}
-
-static inline int RemoveIndentOffset(int indentLevel) {
- return indentLevel == (SC_FOLDLEVELBASE & SC_FOLDLEVELNUMBERMASK)
- ? indentLevel
- : indentLevel - INDENT_OFFSET;
-}
-
void SCI_METHOD LexerHaskell::Fold(unsigned int startPos, int length, int // initStyle
,IDocument *pAccess) {
if (!options.fold)
@@ -967,6 +971,13 @@ void SCI_METHOD LexerHaskell::Fold(unsigned int startPos, int length, int // ini
Accessor styler(pAccess, NULL);
+ int lineCurrent = styler.GetLine(startPos);
+
+ if (lineCurrent <= firstImportLine) {
+ firstImportLine = -1; // readjust first import position
+ firstImportIndent = 0;
+ }
+
const int maxPos = startPos + length;
const int maxLines =
maxPos == styler.Length()
@@ -978,7 +989,6 @@ void SCI_METHOD LexerHaskell::Fold(unsigned int startPos, int length, int // ini
// for any white space lines
// and so we can fix any preceding fold level (which is why we go back
// at least one line in all cases)
- int lineCurrent = styler.GetLine(startPos);
bool importHere = LineContainsImport(lineCurrent, styler);
int indentCurrent = IndentAmountWithOffset(styler, lineCurrent);
@@ -992,15 +1002,12 @@ void SCI_METHOD LexerHaskell::Fold(unsigned int startPos, int length, int // ini
int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
- if (lineCurrent <= firstImportLine) {
- firstImportLine = -1; // readjust first import position
- }
-
if (importHere) {
+ indentCurrentLevel = IndentLevelRemoveIndentOffset(indentCurrentLevel);
if (firstImportLine == -1) {
firstImportLine = lineCurrent;
+ firstImportIndent = (1 + indentCurrentLevel) - SC_FOLDLEVELBASE;
}
- indentCurrentLevel = RemoveIndentOffset(indentCurrentLevel);
if (firstImportLine != lineCurrent) {
indentCurrentLevel++;
}
@@ -1040,10 +1047,11 @@ void SCI_METHOD LexerHaskell::Fold(unsigned int startPos, int length, int // ini
int indentNextLevel = indentNext & SC_FOLDLEVELNUMBERMASK;
if (importHere) {
+ indentNextLevel = IndentLevelRemoveIndentOffset(indentNextLevel);
if (firstImportLine == -1) {
firstImportLine = lineNext;
+ firstImportIndent = (1 + indentNextLevel) - SC_FOLDLEVELBASE;
}
- indentNextLevel = RemoveIndentOffset(indentNextLevel);
if (firstImportLine != lineNext) {
indentNextLevel++;
}