diff options
| -rw-r--r-- | include/SciLexer.h | 1 | ||||
| -rw-r--r-- | include/Scintilla.iface | 1 | ||||
| -rw-r--r-- | src/LexAU3.cxx | 318 | 
3 files changed, 280 insertions, 40 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h index 5c8307a59..c3e936e48 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -726,6 +726,7 @@  #define SCE_AU3_VARIABLE 9  #define SCE_AU3_SENT 10  #define SCE_AU3_PREPROCESSOR 11 +#define SCE_AU3_SPECIAL 12  #define SCE_APDL_DEFAULT 0  #define SCE_APDL_COMMENT 1  #define SCE_APDL_COMMENTBLOCK 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 6a5e54237..a430db791 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2495,6 +2495,7 @@ val SCE_AU3_OPERATOR=8  val SCE_AU3_VARIABLE=9  val SCE_AU3_SENT=10  val SCE_AU3_PREPROCESSOR=11 +val SCE_AU3_SPECIAL=12  # Lexical states for SCLEX_APDL  lex APDL=SCLEX_APDL SCE_APDL_  val SCE_APDL_DEFAULT=0 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);  | 
