diff options
| author | nyamatongwe <unknown> | 2001-04-24 07:57:27 +0000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2001-04-24 07:57:27 +0000 | 
| commit | 109202c21363c45c2ddd0bccef1ba1638456427a (patch) | |
| tree | 767a2dc9374a950af13fdd99090f3a3649d3ff5c | |
| parent | 243bedc1b28dfe6cdeddf8e807039d96e202ee94 (diff) | |
| download | scintilla-mirror-109202c21363c45c2ddd0bccef1ba1638456427a.tar.gz | |
Initial version.
| -rw-r--r-- | src/KeyWords.cxx | 2 | ||||
| -rw-r--r-- | src/LexRuby.cxx | 376 | 
2 files changed, 378 insertions, 0 deletions
| diff --git a/src/KeyWords.cxx b/src/KeyWords.cxx index f28fcecfb..9ac71491b 100644 --- a/src/KeyWords.cxx +++ b/src/KeyWords.cxx @@ -105,6 +105,7 @@ int wxForceScintillaLexers(void) {    extern LexerModule lmPython;    extern LexerModule lmSQL;    extern LexerModule lmVB; +  extern LexerModule lmRuby;    if (        &lmAda @@ -119,6 +120,7 @@ int wxForceScintillaLexers(void) {        && &lmPython        && &lmSQL        && &lmVB +      && &lmRuby              )      {        return 1; diff --git a/src/LexRuby.cxx b/src/LexRuby.cxx new file mode 100644 index 000000000..722bf4261 --- /dev/null +++ b/src/LexRuby.cxx @@ -0,0 +1,376 @@ +// Scintilla source code edit control +/** @file LexRuby.cxx + ** Lexer for Ruby. + **/ +// Copyright 2001- by Clemens Wyss <wys@helbling.ch> +// 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 "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +/* Returns true if the "as" word that begins at start follows an import statement */ +static bool IsImportAs(unsigned int start, Accessor &styler) { +	unsigned int i; +	unsigned int j; +	char s[10]; + +	/* Find any import before start but after any statement terminator or quote */ +	i = start; +	while (i > 0) { +		char ch = styler[i - 1]; + +		if (ch == '\n' || ch == '\r' || ch == ';' || ch == '\'' || ch == '"' || ch == '`') +			break; +		if (ch == 't' && i > 5) { +			for (j = 0; j < 6; j++) +				s[j] = styler[(i - 6) + j]; +			s[j] = '\0'; +			if (strcmp(s, "require") == 0) +				return true; +			// if (strcmp(s, "include") == 0) +			//	return true; +		} +		i--; +	} + +        return false; +} + +static void ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) { +	char s[100]; +	bool wordIsNumber = isdigit(styler[start]); +	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { +		s[i] = styler[start + i]; +		s[i + 1] = '\0'; +	} +	char chAttr = SCE_P_IDENTIFIER; +	if (0 == strcmp(prevWord, "class")) +		chAttr = SCE_P_CLASSNAME; +	else if (0 == strcmp(prevWord, "module")) +		chAttr = SCE_P_CLASSNAME; +	else if (0 == strcmp(prevWord, "def")) +		chAttr = SCE_P_DEFNAME; +	else if (wordIsNumber) +		chAttr = SCE_P_NUMBER; +	else if (keywords.InList(s)) +		chAttr = SCE_P_WORD; +	else if (strcmp(s, "as") == 0 && IsImportAs(start, styler)) +		chAttr = SCE_P_WORD; +	// make sure that dot-qualifiers inside the word are lexed correct +	else for (unsigned int i = 0; i < end - start + 1; i++) { +		if (styler[start + i] == '.') { +			styler.ColourTo(start + i - 1, chAttr); +			styler.ColourTo(start + i, SCE_P_OPERATOR); +		} +	} +	styler.ColourTo(end, chAttr); +	strcpy(prevWord, s); +} + +static bool IsRbComment(Accessor &styler, int pos, int len) { +	return len>0 && styler[pos]=='#'; +} + +static bool IsRbStringStart(char ch, char chNext, char chNext2) { +	if (ch == '\'' || ch == '"') +		return true; +	if (ch == 'u' || ch == 'U') { +		if (chNext == '"' || chNext == '\'') +			return true; +		if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\'')) +			return true; +	} +	if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\'')) +		return true; + +	return false; +} + +static bool IsRbWordStart(char ch, char chNext, char chNext2) { +	return (iswordchar(ch) && !IsRbStringStart(ch, chNext, chNext2)); +} + +/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */ +static int GetRbStringState(Accessor &styler, int i, int *nextIndex) { +	char ch = styler.SafeGetCharAt(i); +	char chNext = styler.SafeGetCharAt(i + 1); + +	// Advance beyond r, u, or ur prefix, but bail if there are any unexpected chars +	if (ch == 'r' || ch == 'R') { +		i++; +		ch = styler.SafeGetCharAt(i); +		chNext = styler.SafeGetCharAt(i + 1); +	} +	else if (ch == 'u' || ch == 'U') { +		if (chNext == 'r' || chNext == 'R') +			i += 2; +		else +			i += 1; +		ch = styler.SafeGetCharAt(i); +		chNext = styler.SafeGetCharAt(i + 1); +	} + +	if (ch != '"' && ch != '\'') { +		*nextIndex = i + 1; +		return SCE_P_DEFAULT; +	} + +	if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) { +		*nextIndex = i + 3; + +		if (ch == '"') +			return SCE_P_TRIPLEDOUBLE; +		else +			return SCE_P_TRIPLE; +	} else { +		*nextIndex = i + 1; + +		if (ch == '"') +			return SCE_P_STRING; +		else +			return SCE_P_CHARACTER; +	} +} + +static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, +						   WordList *keywordlists[], Accessor &styler) { + +	int lengthDoc = startPos + length; + +	// Backtrack to previous line in case need to fix its tab whinging +	if (startPos > 0) { +		int lineCurrent = styler.GetLine(startPos); +		if (lineCurrent > 0) { +			startPos = styler.LineStart(lineCurrent-1); +			if (startPos == 0) +				initStyle = SCE_P_DEFAULT; +			else +				initStyle = styler.StyleAt(startPos-1); +		} +	} + +	// Ruby uses a different mask because bad indentation is marked by oring with 32 +	styler.StartAt(startPos, 127); + +	WordList &keywords = *keywordlists[0]; + +	int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); +	char prevWord[200]; +	prevWord[0] = '\0'; +	if (length == 0) +		return ; + +	int state = initStyle & 31; + +	int nextIndex = 0; +	char chPrev = ' '; +	char chPrev2 = ' '; +	char chNext = styler[startPos]; +	styler.StartSegment(startPos); +	bool atStartLine = true; +	int spaceFlags = 0; +	for (int i = startPos; i < lengthDoc; i++) { + +		if (atStartLine) { +			char chBad = static_cast<char>(64); +			char chGood = static_cast<char>(0); +			char chFlags = chGood; +			if (whingeLevel == 1) { +				chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood; +			} else if (whingeLevel == 2) { +				chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood; +			} else if (whingeLevel == 3) { +				chFlags = (spaceFlags & wsSpace) ? chBad : chGood; +			} else if (whingeLevel == 4) { +				chFlags = (spaceFlags & wsTab) ? chBad : chGood; +			} +			styler.SetFlags(chFlags, static_cast<char>(state)); +			atStartLine = false; +		} + +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); +		char chNext2 = styler.SafeGetCharAt(i + 2); + +		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { +			if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) { +				// Perform colourisation of white space and triple quoted strings at end of each line to allow +				// tab marking to work inside white space and triple quoted strings +				styler.ColourTo(i, state); +			} +			atStartLine = true; +		} + +		if (styler.IsLeadByte(ch)) { +			chNext = styler.SafeGetCharAt(i + 2); +			chPrev = ' '; +			chPrev2 = ' '; +			i += 1; +			continue; +		} + +		if (state == SCE_P_STRINGEOL) { +			if (ch != '\r' && ch != '\n') { +				styler.ColourTo(i - 1, state); +				state = SCE_P_DEFAULT; +			} +		} +		if (state == SCE_P_DEFAULT) { +			if (IsRbWordStart(ch, chNext, chNext2)) { +				styler.ColourTo(i - 1, state); +				state = SCE_P_WORD; +			} else if (ch == '#') { +				styler.ColourTo(i - 1, state); +				state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE; +			} else if (IsRbStringStart(ch, chNext, chNext2)) { +				styler.ColourTo(i - 1, state); +				state = GetRbStringState(styler, i, &nextIndex); +				if (nextIndex != i + 1) { +					i = nextIndex - 1; +					ch = ' '; +					chPrev = ' '; +					chNext = styler.SafeGetCharAt(i + 1); +				} +			} else if (isoperator(ch)) { +				styler.ColourTo(i - 1, state); +				styler.ColourTo(i, SCE_P_OPERATOR); +			} +		} else if (state == SCE_P_WORD) { +			if (!iswordchar(ch)) { +				ClassifyWordRb(styler.GetStartSegment(), i - 1, keywords, styler, prevWord); +				state = SCE_P_DEFAULT; +				if (ch == '#') { +					state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE; +				} else if (IsRbStringStart(ch, chNext, chNext2)) { +					styler.ColourTo(i - 1, state); +					state = GetRbStringState(styler, i, &nextIndex); +					if (nextIndex != i + 1) { +						i = nextIndex - 1; +						ch = ' '; +						chPrev = ' '; +						chNext = styler.SafeGetCharAt(i + 1); +					} +				} else if (isoperator(ch)) { +					styler.ColourTo(i, SCE_P_OPERATOR); +				} +			} +		} else { +			if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) { +				if (ch == '\r' || ch == '\n') { +					styler.ColourTo(i - 1, state); +					state = SCE_P_DEFAULT; +				} +			} else if (state == SCE_P_STRING) { +				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { +					styler.ColourTo(i - 1, state); +					state = SCE_P_STRINGEOL; +				} else if (ch == '\\') { +					if (chNext == '\"' || chNext == '\'' || chNext == '\\') { +						i++; +						ch = chNext; +						chNext = styler.SafeGetCharAt(i + 1); +					} +				} else if (ch == '\"') { +					styler.ColourTo(i, state); +					state = SCE_P_DEFAULT; +				} +			} else if (state == SCE_P_CHARACTER) { +				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { +					styler.ColourTo(i - 1, state); +					state = SCE_P_STRINGEOL; +				} else if (ch == '\\') { +					if (chNext == '\"' || chNext == '\'' || chNext == '\\') { +						i++; +						ch = chNext; +						chNext = styler.SafeGetCharAt(i + 1); +					} +				} else if (ch == '\'') { +					styler.ColourTo(i, state); +					state = SCE_P_DEFAULT; +				} +			} else if (state == SCE_P_TRIPLE) { +				if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { +					styler.ColourTo(i, state); +					state = SCE_P_DEFAULT; +				} +			} else if (state == SCE_P_TRIPLEDOUBLE) { +				if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { +					styler.ColourTo(i, state); +					state = SCE_P_DEFAULT; +				} +			} +		} +		chPrev2 = chPrev; +		chPrev = ch; +	} +	if (state == SCE_P_WORD) { +		ClassifyWordRb(styler.GetStartSegment(), lengthDoc, keywords, styler, prevWord); +	} else { +		styler.ColourTo(lengthDoc, state); +	} +} + +static void FoldRbDoc(unsigned int startPos, int length, int initStyle, +						   WordList *[], Accessor &styler) { +	int lengthDoc = startPos + length; + +	// Backtrack to previous line in case need to fix its fold status +	int lineCurrent = styler.GetLine(startPos); +	if (startPos > 0) { +		if (lineCurrent > 0) { +			lineCurrent--; +			startPos = styler.LineStart(lineCurrent); +			if (startPos == 0) +				initStyle = SCE_P_DEFAULT; +			else +				initStyle = styler.StyleAt(startPos-1); +		} +	} +	int state = initStyle & 31; +	int spaceFlags = 0; +	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsRbComment); +	if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) +		indentCurrent |= SC_FOLDLEVELWHITEFLAG; +	char chNext = styler[startPos]; +	for (int i = startPos; i < lengthDoc; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); +		int style = styler.StyleAt(i) & 31; + +		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { +			int lev = indentCurrent; +			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsRbComment); +			if ((style == SCE_P_TRIPLE) || (style== SCE_P_TRIPLEDOUBLE)) +				indentNext |= SC_FOLDLEVELWHITEFLAG; +			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, IsRbComment); +					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { +						lev |= SC_FOLDLEVELHEADERFLAG; +					} +				} +			} +			indentCurrent = indentNext; +			styler.SetLevel(lineCurrent, lev); +			lineCurrent++; +		} +	} +} +						    +LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc); | 
