diff options
author | nyamatongwe <devnull@localhost> | 2004-05-29 23:12:23 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2004-05-29 23:12:23 +0000 |
commit | 8fba478c44b88995042ff64f59bad01ba16703aa (patch) | |
tree | 28594ead385a4832365479658037f00fa2ead974 /src | |
parent | 9e3117b190798fb5582122a32e0692066628db0e (diff) | |
download | scintilla-mirror-8fba478c44b88995042ff64f59bad01ba16703aa.tar.gz |
Updated AutoIt3 lexer from Jos.
Handles folding by syntax rathe rthan indentation.
Diffstat (limited to 'src')
-rw-r--r-- | src/LexAU3.cxx | 318 |
1 files changed, 278 insertions, 40 deletions
diff --git a/src/LexAU3.cxx b/src/LexAU3.cxx index 8bc1f062e..8e0f791d9 100644 --- a/src/LexAU3.cxx +++ b/src/LexAU3.cxx @@ -12,9 +12,15 @@ // Fixed "#comments_end" -> "#comments-end" // Fixed Sendkeys in Strings when not terminated with } // Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} -// April 26, 2004 Fixed # pre-processor statement inside of comment block would invalidly change the color. +// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. // Added logic for #include <xyz.au3> to treat the <> as string // Added underscore to IsAOperator. +// May 17, 2004 - Changed the folding logic from indent to keyword folding. +// Added Folding logic for blocks of single-commentlines or commentblock. +// triggered by: fold.comment=1 +// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 +// Added Special for #region - #endregion syntax highlight and folding. +// // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. // Scintilla source code edit control @@ -34,17 +40,13 @@ #include "Scintilla.h" #include "SciLexer.h" -static bool IsAU3Comment(Accessor &styler, int pos, int len) { - return len>0 && styler[pos]==';'; -} - static inline bool IsTypeCharacter(const int ch) { return ch == '$'; } static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '-'); + return (ch < 0x80) && (isalnum(ch) || ch == '_'); } static inline bool IsAWordStart(const int ch) @@ -57,7 +59,7 @@ static inline bool IsAOperator(char ch) { return false; if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || - ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '_' ) + ch == '(' || ch == ')' || ch == '[' || ch == ']' ) return true; return false; } @@ -111,9 +113,9 @@ static int GetSendKey(const char *szLine, char *szKey) // Check if the second portion is either a number or one of these keywords szKey[nKeyPos] = '\0'; szSpecial[nSpecPos] = '\0'; - if (strcmp(szSpecial,"down")==0 || strcmp(szSpecial,"up")==0 || - strcmp(szSpecial,"on")==0 || strcmp(szSpecial,"off")==0 || - strcmp(szSpecial,"toggle")==0 || nSpecNum == 1 ) + if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || + strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || + strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) { nFlag = 0; } @@ -121,9 +123,9 @@ static int GetSendKey(const char *szLine, char *szKey) { nFlag = 1; } - return nFlag; // 1 is bad, 0 is good + return nFlag; // 1 is bad, 0 is good -} // GetSendKey() +} // GetSendKey() static void ColouriseAU3Doc(unsigned int startPos, int length, int initStyle, @@ -135,6 +137,7 @@ static void ColouriseAU3Doc(unsigned int startPos, WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3]; WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; styler.StartAt(startPos); StyleContext sc(startPos, length, initStyle, styler); @@ -148,9 +151,9 @@ static void ColouriseAU3Doc(unsigned int startPos, { case SCE_AU3_COMMENTBLOCK: { - if (!IsAWordChar(sc.ch)) + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { - if ((strcmp(s, "#ce")==0 || strcmp(s, "#comments-end")==0)) + if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) {sc.SetState(SCE_AU3_COMMENT);} // set to comment line for the rest of the line else {sc.SetState(SCE_AU3_COMMENTBLOCK);} @@ -167,13 +170,18 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.SetState(SCE_AU3_DEFAULT); break; } + case SCE_AU3_SPECIAL: + { + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } case SCE_AU3_KEYWORD: { - if (!IsAWordChar(sc.ch)) + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) { if (!IsTypeCharacter(sc.ch)) { - if (strcmp(s, "#cs")==0 || strcmp(s, "#comments-start")==0 ) + if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) { sc.ChangeState(SCE_AU3_COMMENTBLOCK); sc.SetState(SCE_AU3_COMMENTBLOCK); @@ -193,11 +201,19 @@ static void ColouriseAU3Doc(unsigned int startPos, else if (keywords5.InList(s)) { sc.ChangeState(SCE_AU3_PREPROCESSOR); sc.SetState(SCE_AU3_DEFAULT); - if (strcmp(s, "#include")==0) + if (strcmp(s, "#include")== 0) { si = 3; // use to determine string start for #inlude <> } } + else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if (strcmp(s, "_") == 0) { + sc.ChangeState(SCE_AU3_OPERATOR); + sc.SetState(SCE_AU3_DEFAULT); + } else if (!IsAWordChar(sc.ch)) { sc.ChangeState(SCE_AU3_DEFAULT); sc.SetState(SCE_AU3_DEFAULT); @@ -302,8 +318,8 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.SetState(SCE_AU3_STRING); si = 2; } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_AU3_NUMBER);} - else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} + else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} } } //for (; sc.More(); sc.Forward()) @@ -311,11 +327,60 @@ static void ColouriseAU3Doc(unsigned int startPos, } // +static bool IsStreamCommentStyle(int style) { + return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; +} + // -static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +// Routine to find first none space on the current line and return its Style +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) +{ + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 1; + while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) + { + nsPos++; // skip to next char + + } // End While + return styler.StyleAt(nsPos); + +} // GetStyleFirstWord() + +// +// Routine to check the last not comment charater on a line to see if its a continuation +// +static bool IsContinuationLine(unsigned int szLine, Accessor &styler) { - int endPos = startPos + length; + int nsPos = styler.LineStart(szLine); + int nePos = styler.LineStart(szLine+1) - 2; + //int stylech = styler.StyleAt(nsPos); + while (nsPos < nePos) + { + //stylech = styler.StyleAt(nePos); + int stylech = styler.StyleAt(nsPos); + if (!(stylech == SCE_AU3_COMMENT)) { + char ch = styler.SafeGetCharAt(nePos); + if (!isspacechar(ch)) { + if (ch == '_') + return true; + else + return false; + } + } + nePos--; // skip to next char + } // End While + return false; +} // IsContinuationLine() + +// +static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + int endPos = startPos + length; + // get settings from the config files for folding comments and preprocessor lines + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; // Backtrack to previous line in case need to fix its fold status int lineCurrent = styler.GetLine(startPos); if (startPos > 0) { @@ -324,35 +389,207 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc startPos = styler.LineStart(lineCurrent); } } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsAU3Comment); - char chNext = styler[startPos]; + // vars for style of previous/current/next lines + //### int stylech = GetStyleFirstWord(lineCurrent,styler); + int style = GetStyleFirstWord(lineCurrent,styler); + //### int styleNext = 0; + int stylePrev = 0; + // find the first previous line without continuation character at the end + while (lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + if (lineCurrent > 0) { + stylePrev = GetStyleFirstWord(lineCurrent-1,styler); + } + // vars for getting first word to check for keywords + bool FirstWordStart = false; + bool FirstWordEnd = false; + char szKeyword[10]=""; + int szKeywordlen = 0; + char szThen[5]=""; + int szThenlen = 0; + bool ThenFoundLast = false; + // var for indentlevel + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + //### int levelPrev = 0; + // + int visibleChars = 0; + char chNext = styler.SafeGetCharAt(startPos); + char chPrev = ' '; + // for (int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsAU3Comment); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsAU3Comment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; + if (IsAWordChar(ch)) { + visibleChars++; + } + // get the syle for the current character neede to check in comment + //### stylech = styler.StyleAt(i); + int stylech = GetStyleFirstWord(lineCurrent,styler); + // get first word for the line for indent check max 9 characters + if (FirstWordStart && (!(FirstWordEnd))) { + if (!IsAWordChar(ch)) { + FirstWordEnd = true; + szKeyword[szKeywordlen] = '\0'; + } + else { + if (szKeywordlen < 10) { + szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch)); + } + } + } + // start the capture of the first word + if (!(FirstWordStart)) { + if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { + FirstWordStart = true; + szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch)); + } + } + // only process this logic when not in comment section + if (!(stylech == SCE_AU3_COMMENT)) { + if (ThenFoundLast) { + if (IsAWordChar(ch)) { + ThenFoundLast = false; + } + } + // find out if the word "then" is the last on a "if" line + if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + if (szThenlen == 4) { + szThen[0] = szThen[1]; + szThen[1] = szThen[2]; + szThen[2] = szThen[3]; + szThen[3] = static_cast<char>(tolower(ch)); + if (strcmp(szThen,"then") == 0 ) { + ThenFoundLast = true; + } + } + else { + szThen[szThenlen++] = static_cast<char>(tolower(ch)); + if (szThenlen == 5) { + szThen[4] = '\0'; } } } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); + } + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + // ************************** + // Folding logic for Keywords + // ************************** + // if a keyword is found on the current line and the line doesn't end with _ (continuation) + if (szKeywordlen > 0 && (!(chPrev == '_'))) { + szKeyword[szKeywordlen] = '\0'; + // only fold "if" last keyword is "then" (else its a one line if) + if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { + levelNext++; + } + // create new fold for these words + if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || + strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| + strcmp(szKeyword,"#region") == 0 ) { + levelNext++; + } + // create double Fold for select because Case will subtract one of the current level + if (strcmp(szKeyword,"select") == 0) { + levelNext++; + levelNext++; + } + // end the fold for these words before the current line + if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || + strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || + strcmp(szKeyword,"wend") == 0){ + levelNext--; + levelCurrent--; + } + // end the fold for these words before the current line and Start new fold + if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || + strcmp(szKeyword,"elseif") == 0 ) { + levelCurrent--; + } + // end the double fold for this word before the current line + if (strcmp(szKeyword,"endselect") == 0 ) { + levelNext--; + levelNext--; + levelCurrent--; + levelCurrent--; + } + // end the fold for these words on the current line + if (strcmp(szKeyword,"#endregion") == 0 ) { + levelNext--; + } + } + // Preprocessor and Comment folding + int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); + // ************************************* + // Folding logic for preprocessor blocks + // ************************************* + // process preprosessor line + if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { + if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext--; + } + } + // ********************************* + // Folding logic for Comment blocks + // ********************************* + if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block + if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENT) + && stylePrev == SCE_AU3_COMMENT + && style == SCE_AU3_COMMENT) { + levelNext--; + } + // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENTBLOCK) + && style == SCE_AU3_COMMENTBLOCK) { + levelNext--; + levelCurrent--; + } + } + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + //if (visibleChars == 0) + // lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + // reset values for the next line lineCurrent++; + stylePrev = style; + style = styleNext; + levelCurrent = levelNext; + //###levelPrev = levelCurrent; + visibleChars = 0; + // if the last character is an Underscore then don't reset since the line continues on the next line. + if (!(chPrev == '_')) { + szKeywordlen = 0; + szThenlen = 0; + FirstWordStart = false; + FirstWordEnd = false; + ThenFoundLast = false; + } } + // save the last processed character + if (!isspacechar(ch)) + chPrev = ch; } - } @@ -364,6 +601,7 @@ static const char * const AU3WordLists[] = { "#autoit macros", "#autoit Sent keys", "#autoit Pre-processors", + "#autoit Special", 0 }; LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); |