diff options
Diffstat (limited to 'lexers')
| -rw-r--r-- | lexers/LexAsm.cxx | 191 | ||||
| -rw-r--r-- | lexers/LexBasic.cxx | 63 | ||||
| -rw-r--r-- | lexers/LexD.cxx | 63 | 
3 files changed, 294 insertions, 23 deletions
| diff --git a/lexers/LexAsm.cxx b/lexers/LexAsm.cxx index b00420945..47ed4bb86 100644 --- a/lexers/LexAsm.cxx +++ b/lexers/LexAsm.cxx @@ -4,17 +4,17 @@   ** Written by The Black Horus   ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10   ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring - ** Converted to lexer object by "Udo Lechner" <dlchnr(at)gmx(dot)net> + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>   **/  // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>  // The License.txt file describes the conditions under which this software may be distributed.  #include <stdlib.h>  #include <string.h> -#include <ctype.h>  #include <stdio.h>  #include <stdarg.h>  #include <assert.h> +#include <ctype.h>  #ifdef _MSC_VER  #pragma warning(disable: 4786) @@ -22,6 +22,7 @@  #include <string>  #include <map> +#include <set>  #include "ILexer.h"  #include "Scintilla.h" @@ -29,7 +30,6 @@  #include "WordList.h"  #include "LexAccessor.h" -#include "Accessor.h"  #include "StyleContext.h"  #include "CharacterSet.h"  #include "LexerModule.h" @@ -62,11 +62,39 @@ static inline bool IsAsmOperator(const int ch) {  	return false;  } +static bool IsStreamCommentStyle(int style) { +	return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK; +} + +static inline int LowerCase(int c) { +	if (c >= 'A' && c <= 'Z') +		return 'a' + c - 'A'; +	return c; +} +  // An individual named option for use in an OptionSet  // Options used for LexerAsm  struct OptionsAsm { +	std::string delimiter; +	bool fold; +	bool foldSyntaxBased; +	bool foldCommentMultiline; +	bool foldCommentExplicit; +	std::string foldExplicitStart; +	std::string foldExplicitEnd; +	bool foldExplicitAnywhere; +	bool foldCompact;  	OptionsAsm() { +		delimiter = ""; +		fold = false; +		foldSyntaxBased = true; +		foldCommentMultiline = false; +		foldCommentExplicit = false; +		foldExplicitStart = ""; +		foldExplicitEnd   = ""; +		foldExplicitAnywhere = false; +		foldCompact = true;  	}  }; @@ -77,11 +105,40 @@ static const char * const asmWordListDesc[] = {  	"Directives",  	"Directive operands",  	"Extended instructions", +	"Directives4Foldstart", +	"Directives4Foldend",  	0  };  struct OptionSetAsm : public OptionSet<OptionsAsm> {  	OptionSetAsm() { +		DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter, +			"Character used for COMMENT directive's delimiter, replacing the standard \"~\"."); + +		DefineProperty("fold", &OptionsAsm::fold); + +		DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased, +			"Set this property to 0 to disable syntax based folding."); + +		DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline, +			"Set this property to 1 to enable folding multi-line comments."); + +		DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit, +			"This option enables folding explicit fold points when using the Asm lexer. " +			"Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " +			"at the end of a section that should fold."); + +		DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart, +			"The string to use for explicit fold start points, replacing the standard ;{."); + +		DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd, +			"The string to use for explicit fold end points, replacing the standard ;}."); + +		DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere, +			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + +		DefineProperty("fold.compact", &OptionsAsm::foldCompact); +  		DefineWordListSets(asmWordListDesc);  	}  }; @@ -93,6 +150,8 @@ class LexerAsm : public ILexer {  	WordList directive;  	WordList directiveOperand;  	WordList extInstruction; +	WordList directives4foldstart; +	WordList directives4foldend;  	OptionsAsm options;  	OptionSetAsm osAsm;  public: @@ -160,6 +219,12 @@ int SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) {  	case 5:  		wordListN = &extInstruction;  		break; +	case 6: +		wordListN = &directives4foldstart; +		break; +	case 7: +		wordListN = &directives4foldend; +		break;  	}  	int firstModification = -1;  	if (wordListN) { @@ -208,7 +273,7 @@ void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle,  			if (!IsAsmOperator(sc.ch)) {  			    sc.SetState(SCE_ASM_DEFAULT);  			} -		}else if (sc.state == SCE_ASM_NUMBER) { +		} else if (sc.state == SCE_ASM_NUMBER) {  			if (!IsAWordChar(sc.ch)) {  				sc.SetState(SCE_ASM_DEFAULT);  			} @@ -216,6 +281,7 @@ void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle,  			if (!IsAWordChar(sc.ch) ) {  				char s[100];  				sc.GetCurrentLowered(s, sizeof(s)); +				bool IsDirective = false;  				if (cpuInstruction.InList(s)) {  					sc.ChangeState(SCE_ASM_CPUINSTRUCTION); @@ -225,15 +291,32 @@ void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle,  					sc.ChangeState(SCE_ASM_REGISTER);  				}  else if (directive.InList(s)) {  					sc.ChangeState(SCE_ASM_DIRECTIVE); +					IsDirective = true;  				} else if (directiveOperand.InList(s)) {  					sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND);  				} else if (extInstruction.InList(s)) {  					sc.ChangeState(SCE_ASM_EXTINSTRUCTION);  				}  				sc.SetState(SCE_ASM_DEFAULT); +				if (IsDirective && !strcmp(s, "comment")) { +					char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; +					while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) { +						sc.ForwardSetState(SCE_ASM_DEFAULT); +					} +					if (sc.ch == delimiter) { +						sc.SetState(SCE_ASM_COMMENTDIRECTIVE); +					} +				}  			} -		} -		else if (sc.state == SCE_ASM_COMMENT ) { +		} else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) { +			char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; +			if (sc.ch == delimiter) { +				while (!sc.atLineEnd) { +					sc.Forward(); +				} +				sc.SetState(SCE_ASM_DEFAULT); +			} +		} else if (sc.state == SCE_ASM_COMMENT ) {  			if (sc.atLineEnd) {  				sc.SetState(SCE_ASM_DEFAULT);  			} @@ -282,9 +365,101 @@ void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle,  	sc.Complete();  } -void SCI_METHOD LexerAsm::Fold(unsigned int /* startPos */, int /* length */, int /* initStyle */, IDocument* /* pAccess */) { +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "else". + +void SCI_METHOD LexerAsm::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { -	return; +	if (!options.fold) +		return; + +	LexAccessor styler(pAccess); + +	unsigned int endPos = startPos + length; +	int visibleChars = 0; +	int lineCurrent = styler.GetLine(startPos); +	int levelCurrent = SC_FOLDLEVELBASE; +	if (lineCurrent > 0) +		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; +	int levelMinCurrent = levelCurrent; +	int levelNext = levelCurrent; +	char chNext = styler[startPos]; +	int styleNext = styler.StyleAt(startPos); +	int style = initStyle; +	char word[100]; +	int wordlen = 0; +	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); +	for (unsigned int i = startPos; i < endPos; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); +		int stylePrev = style; +		style = styleNext; +		styleNext = styler.StyleAt(i + 1); +		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); +		if (options.foldCommentMultiline && IsStreamCommentStyle(style)) { +			if (!IsStreamCommentStyle(stylePrev)) { +				levelNext++; +			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) { +				// Comments don't end at end of line and the next character may be unstyled. +				levelNext--; +			} +		} +		if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) { +			if (userDefinedFoldMarkers) { +				if (styler.Match(i, options.foldExplicitStart.c_str())) { + 					levelNext++; +				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + 					levelNext--; + 				} +			} else { +				if (ch == ';') { +					if (chNext == '{') { +						levelNext++; +					} else if (chNext == '}') { +						levelNext--; +					} +				} + 			} + 		} +		if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) { +			word[wordlen++] = static_cast<char>(LowerCase(ch)); +			if (wordlen == 100) {                   // prevent overflow   +				word[0] = '\0'; +				wordlen = 1; +			} +			if (styleNext != SCE_ASM_DIRECTIVE) {   // reading directive ready +				word[wordlen] = '\0'; +				wordlen = 0; +				if (directives4foldstart.InList(word)) { +					levelNext++; +				} else if (directives4foldend.InList(word)){ +					levelNext--; +				}     +			} +		} +		if (!IsASpace(ch)) +			visibleChars++; +		if (atEOL || (i == endPos-1)) { +			int levelUse = levelCurrent; +			int lev = levelUse | levelNext << 16; +			if (visibleChars == 0 && options.foldCompact) +				lev |= SC_FOLDLEVELWHITEFLAG; +			if (levelUse < levelNext) +				lev |= SC_FOLDLEVELHEADERFLAG; +			if (lev != styler.LevelAt(lineCurrent)) { +				styler.SetLevel(lineCurrent, lev); +			} +			lineCurrent++; +			levelCurrent = levelNext; +			levelMinCurrent = levelCurrent; +			if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { +				// There is an empty line at end of file so give it same level and empty +				styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); +			} +			visibleChars = 0; +		} +	}  }  LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc); diff --git a/lexers/LexBasic.cxx b/lexers/LexBasic.cxx index 057afed65..55641edc1 100644 --- a/lexers/LexBasic.cxx +++ b/lexers/LexBasic.cxx @@ -1,7 +1,7 @@  // Scintilla source code edit control  /** @file LexBasic.cxx   ** Lexer for BlitzBasic and PureBasic. - ** Converted to lexer object by "Udo Lechner" <dlchnr(at)gmx(dot)net> + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>   **/  // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>  // The License.txt file describes the conditions under which this software may be distributed. @@ -22,6 +22,7 @@  #include <stdio.h>  #include <stdarg.h>  #include <assert.h> +#include <ctype.h>  #ifdef _MSC_VER  #pragma warning(disable: 4786) @@ -36,7 +37,6 @@  #include "WordList.h"  #include "LexAccessor.h" -#include "Accessor.h"  #include "StyleContext.h"  #include "CharacterSet.h"  #include "LexerModule.h" @@ -147,9 +147,19 @@ static int CheckFreeFoldPoint(char const *token, int &level) {  // Options used for LexerBasic  struct OptionsBasic {  	bool fold; +	bool foldSyntaxBased; +	bool foldCommentExplicit; +	std::string foldExplicitStart; +	std::string foldExplicitEnd; +	bool foldExplicitAnywhere;  	bool foldCompact;  	OptionsBasic() {  		fold = false; +		foldSyntaxBased = true; +		foldCommentExplicit = false; +		foldExplicitStart = ""; +		foldExplicitEnd   = ""; +		foldExplicitAnywhere = false;  		foldCompact = true;  	}  }; @@ -182,6 +192,23 @@ struct OptionSetBasic : public OptionSet<OptionsBasic> {  	OptionSetBasic(const char * const wordListDescriptions[]) {  		DefineProperty("fold", &OptionsBasic::fold); +		DefineProperty("fold.basic.syntax.based", &OptionsBasic::foldSyntaxBased, +			"Set this property to 0 to disable syntax based folding."); + +		DefineProperty("fold.basic.comment.explicit", &OptionsBasic::foldCommentExplicit, +			"This option enables folding explicit fold points when using the Basic lexer. " +			"Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start " +			"and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded."); + +		DefineProperty("fold.basic.explicit.start", &OptionsBasic::foldExplicitStart, +			"The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB)."); + +		DefineProperty("fold.basic.explicit.end", &OptionsBasic::foldExplicitEnd, +			"The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB)."); + +		DefineProperty("fold.basic.explicit.anywhere", &OptionsBasic::foldExplicitAnywhere, +			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); +  		DefineProperty("fold.compact", &OptionsBasic::foldCompact);  		DefineWordListSets(wordListDescriptions); @@ -235,7 +262,7 @@ public:  		return new LexerBasic(';', CheckPureFoldPoint, purebasicWordListDesc);  	}  	static ILexer *LexerFactoryFreeBasic() { -		return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc); +		return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc );  	}  }; @@ -397,7 +424,6 @@ void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initS  	if (!options.fold)  		return; -  	LexAccessor styler(pAccess);  	int line = styler.GetLine(startPos); @@ -406,12 +432,16 @@ void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initS  	int endPos = startPos + length;  	char word[256];  	int wordlen = 0; +	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); +	int cNext = styler[startPos];  	// Scan for tokens at the start of the line (they may include  	// whitespace, for tokens like "End Function"  	for (int i = startPos; i < endPos; i++) { -		int c = styler.SafeGetCharAt(i); -		if (!done && !go) { +		int c = cNext; +		cNext = styler.SafeGetCharAt(i + 1); +		bool atEOL = (c == '\r' && cNext != '\n') || (c == '\n'); +		if (options.foldSyntaxBased && !done && !go) {  			if (wordlen) { // are we scanning a token already?  				word[wordlen] = static_cast<char>(LowerCase(c));  				if (!IsIdentifier(c)) { // done with token @@ -441,7 +471,26 @@ void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initS  				}  			}  		} -		if (c == '\n') { // line end +		if (options.foldCommentExplicit && ((styler.StyleAt(i) == SCE_B_COMMENT) || options.foldExplicitAnywhere)) { +			if (userDefinedFoldMarkers) { +				if (styler.Match(i, options.foldExplicitStart.c_str())) { + 					level |= SC_FOLDLEVELHEADERFLAG; +					go = 1; +				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + 					go = -1; + 				} +			} else { +				if (c == comment_char) { +					if (cNext == '{') { +						level |= SC_FOLDLEVELHEADERFLAG; +						go = 1; +					} else if (cNext == '}') { +						go = -1; +					} +				} + 			} + 		} +		if (atEOL) { // line end  			if (!done && wordlen == 0 && options.foldCompact) // line was only space  				level |= SC_FOLDLEVELWHITEFLAG;  			if (level != styler.LevelAt(line)) diff --git a/lexers/LexD.cxx b/lexers/LexD.cxx index 4b7d08daf..5b8f9e723 100644 --- a/lexers/LexD.cxx +++ b/lexers/LexD.cxx @@ -2,17 +2,17 @@   ** Lexer for D.   **   ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com> - ** Converted to lexer object by "Udo Lechner" <dlchnr(at)gmx(dot)net> + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>   **/  // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>  // The License.txt file describes the conditions under which this software may be distributed.  #include <stdlib.h>  #include <string.h> -#include <ctype.h>  #include <stdio.h>  #include <stdarg.h>  #include <assert.h> +#include <ctype.h>  #ifdef _MSC_VER  #pragma warning(disable: 4786) @@ -27,7 +27,6 @@  #include "WordList.h"  #include "LexAccessor.h" -#include "Accessor.h"  #include "StyleContext.h"  #include "CharacterSet.h"  #include "LexerModule.h" @@ -79,13 +78,25 @@ static bool IsStreamCommentStyle(int style) {  // Options used for LexerD  struct OptionsD {  	bool fold; +	bool foldSyntaxBased;  	bool foldComment; +	bool foldCommentMultiline; +	bool foldCommentExplicit; +	std::string foldExplicitStart; +	std::string foldExplicitEnd; +	bool foldExplicitAnywhere;  	bool foldCompact;  	int  foldAtElseInt;  	bool foldAtElse;  	OptionsD() {  		fold = false; +		foldSyntaxBased = true;  		foldComment = false; +		foldCommentMultiline = true; +		foldCommentExplicit = true; +		foldExplicitStart = ""; +		foldExplicitEnd   = ""; +		foldExplicitAnywhere = false;  		foldCompact = true;  		foldAtElseInt = -1;  		foldAtElse = false; @@ -107,8 +118,26 @@ struct OptionSetD : public OptionSet<OptionsD> {  	OptionSetD() {  		DefineProperty("fold", &OptionsD::fold); +		DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased, +			"Set this property to 0 to disable syntax based folding."); +  		DefineProperty("fold.comment", &OptionsD::foldComment); +		DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline, +			"Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + +		DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit, +			"Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + +		DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart, +			"The string to use for explicit fold start points, replacing the standard //{."); + +		DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd, +			"The string to use for explicit fold end points, replacing the standard //}."); + +		DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere, +			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); +  		DefineProperty("fold.compact", &OptionsD::foldCompact);  		DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt, @@ -448,7 +477,6 @@ void SCI_METHOD LexerD::Lex(unsigned int startPos, int length, int initStyle, ID  void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { -  	if (!options.fold)  		return; @@ -466,6 +494,7 @@ void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, I  	int styleNext = styler.StyleAt(startPos);  	int style = initStyle;  	bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse; +	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();  	for (unsigned int i = startPos; i < endPos; i++) {  		char ch = chNext;  		chNext = styler.SafeGetCharAt(i + 1); @@ -473,7 +502,7 @@ void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, I  		style = styleNext;  		styleNext = styler.StyleAt(i + 1);  		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); -		if (options.foldComment && IsStreamCommentStyle(style)) { +		if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) {  			if (!IsStreamCommentStyle(stylePrev)) {  				levelNext++;  			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) { @@ -481,7 +510,25 @@ void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, I  				levelNext--;  			}  		} -		if (style == SCE_D_OPERATOR) { +		if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) { +			if (userDefinedFoldMarkers) { +				if (styler.Match(i, options.foldExplicitStart.c_str())) { + 					levelNext++; +				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + 					levelNext--; + 				} +			} else { +				if ((ch == '/') && (chNext == '/')) { +					char chNext2 = styler.SafeGetCharAt(i + 2); +					if (chNext2 == '{') { +						levelNext++; +					} else if (chNext2 == '}') { +						levelNext--; +					} +				} + 			} + 		} +		if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) {  			if (ch == '{') {  				// Measure the minimum before a '{' to allow  				// folding on "} else {" @@ -494,14 +541,14 @@ void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, I  			}  		}  		if (atEOL || (i == endPos-1)) { -			if (options.foldComment) {  // Handle nested comments +			if (options.foldComment && options.foldCommentMultiline) {  // Handle nested comments  				int nc;  				nc =  styler.GetLineState(lineCurrent);  				nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0;  				levelNext += nc;  			}  			int levelUse = levelCurrent; -			if (foldAtElse) { +			if (options.foldSyntaxBased && foldAtElse) {  				levelUse = levelMinCurrent;  			}  			int lev = levelUse | levelNext << 16; | 
