[geany/geany] 07002d: Add coffescript syntax highlighting

Mark Dresselhaus git-noreply at xxxxx
Wed Nov 26 18:52:20 UTC 2014


Branch:      refs/heads/master
Author:      Mark Dresselhaus <m at rk-dresselhaus.de>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Wed, 26 Nov 2014 18:52:20 UTC
Commit:      07002d252a36b77d150536ffe0c860fa91f4f61d
             https://github.com/geany/geany/commit/07002d252a36b77d150536ffe0c860fa91f4f61d

Log Message:
-----------
Add coffescript syntax highlighting

imported lexer from Scintilla and added coffeescript filetype


Modified Paths:
--------------
    data/Makefile.am
    data/filetype_extensions.conf
    data/filetypes.coffeescript
    scintilla/Makefile.am
    scintilla/lexers/LexCoffeeScript.cxx
    scintilla/makefile.win32
    scintilla/src/Catalogue.cxx
    src/filetypes.c
    src/filetypes.h
    src/highlighting.c
    src/highlightingmappings.h

Modified: data/Makefile.am
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -15,6 +15,7 @@ filetypes = \
 	filetypes.Clojure.conf \
 	filetypes.cmake \
 	filetypes.cobol \
+	filetypes.coffeescript \
 	filetypes.common \
 	filetypes.conf \
 	filetypes.cpp \


Modified: data/filetype_extensions.conf
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -16,6 +16,7 @@ CUDA=*.cu;*.cuh;*.h;
 C#=*.cs;
 CMake=CMakeLists.txt;*.cmake;*.ctest;
 COBOL=*.cob;*.cpy;*.cbl;*.cobol;
+CoffeeScript=*.coffee;Cakefile;*.Cakefile;*.coffee.erb;*.iced;*.iced.erb
 Conf=*.conf;*.ini;config;*rc;*.cfg;*.desktop;*.properties;
 CSS=*.css;
 Cython=*.pyx;*.pxd;*.pxi;


Modified: data/filetypes.coffeescript
48 lines changed, 48 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,48 @@
+# For complete documentation of this file, please see Geany's main documentation
+[styling]
+character=character
+commentblock=comment
+commentline=comment_line
+default=default
+globalclass=class
+identifier=identifier_1
+number=number_1
+operator=operator
+regex=regex
+string=string_1
+stringeol=string_eol
+verbose_regex=regex
+verbose_regex_comment=comment
+word2=keyword_2
+word=keyword_1
+
+
+[settings]
+extension=coffee
+comment_single=#
+comment_open=###
+comment_close=###
+comment_use_indent=true
+context_action_cmd=
+
+
+[keywords]
+# all items must be in one line
+primary=and break by case catch class const continue default delete do each else extends false finally for get if in Infinity instanceof is isnt let loop NaN new no not null of off on or return set switch then this throw true try typeof undefined unless until void when where while with yes yield
+secondary=constructor decodeURI decodeURIComponent encodeURI encodeURIComponent eval isFinite isNaN parseFloat parseInt prototype require super
+# types, classes
+globalclass=Array Boolean Date Error EvalError Function Math Number Object RangeError ReferenceError RegExp String SyntaxError TypeError URIError
+
+[indentation]
+#width=4
+# 0 is spaces, 1 is tabs, 2 is tab & spaces
+#type=1
+
+[build-menu]
+FT_00_LB=Compile into _Javascript
+FT_00_CM=coffee --compile "%f"
+FT_01_LB=View compiled _Javascript
+FT_01_CM=coffee -p "%f"
+EX_00_LB=Run
+EX_00_CM=coffee "%f"
+


Modified: scintilla/Makefile.am
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -16,6 +16,7 @@ lexers/LexCPP.cxx \
 lexers/LexCSS.cxx \
 lexers/LexCaml.cxx \
 lexers/LexCmake.cxx \
+lexers/LexCoffeeScript.cxx \
 lexers/LexD.cxx \
 lexers/LexErlang.cxx \
 lexers/LexForth.cxx \


Modified: scintilla/lexers/LexCoffeeScript.cxx
569 lines changed, 569 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,569 @@
+// Scintilla source code edit control
+/** @file LexCoffeeScript.cxx
+ ** Lexer for CoffeeScript.
+ **/
+// Copyright 1998-2011 by Neil Hodgson <neilh at scintilla.org>
+// Based on the Scintilla C++ Lexer
+// Written by Eric Promislow <ericp at activestate.com> in 2011 for the Komodo IDE
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "Platform.h"
+#include "ILexer.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#include "WordList.h"
+#include "LexAccessor.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "CharacterSet.h"
+#include "LexerModule.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static bool IsSpaceEquiv(int state) {
+	return (state <= SCE_COFFEESCRIPT_COMMENTDOC
+	    // including SCE_COFFEESCRIPT_DEFAULT, SCE_COFFEESCRIPT_COMMENT, SCE_COFFEESCRIPT_COMMENTLINE
+	    || state == SCE_COFFEESCRIPT_COMMENTLINEDOC
+	    || state == SCE_COFFEESCRIPT_COMMENTDOCKEYWORD
+	    || state == SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR
+	    || state == SCE_COFFEESCRIPT_COMMENTBLOCK
+	    || state == SCE_COFFEESCRIPT_VERBOSE_REGEX
+	    || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT
+	    || state == SCE_COFFEESCRIPT_WORD
+	    || state == SCE_COFFEESCRIPT_REGEX);
+}
+
+// Preconditions: sc.currentPos points to a character after '+' or '-'.
+// The test for pos reaching 0 should be redundant,
+// and is in only for safety measures.
+// Limitation: this code will give the incorrect answer for code like
+// a = b+++/ptn/...
+// Putting a space between the '++' post-inc operator and the '+' binary op
+// fixes this, and is highly recommended for readability anyway.
+static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) {
+	int pos = (int) sc.currentPos;
+	while (--pos > 0) {
+		char ch = styler[pos];
+		if (ch == '+' || ch == '-') {
+			return styler[pos - 1] == ch;
+		}
+	}
+	return false;
+}
+
+static bool followsReturnKeyword(StyleContext &sc, Accessor &styler) {
+    // Don't look at styles, so no need to flush.
+	int pos = (int) sc.currentPos;
+	int currentLine = styler.GetLine(pos);
+	int lineStartPos = styler.LineStart(currentLine);
+	while (--pos > lineStartPos) {
+		char ch = styler.SafeGetCharAt(pos);
+		if (ch != ' ' && ch != '\t') {
+			break;
+		}
+	}
+	const char *retBack = "nruter";
+	const char *s = retBack;
+	while (*s
+	       && pos >= lineStartPos
+	       && styler.SafeGetCharAt(pos) == *s) {
+		s++;
+		pos--;
+	}
+	return !*s;
+}
+
+static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                            Accessor &styler) {
+
+	WordList &keywords = *keywordlists[0];
+	WordList &keywords2 = *keywordlists[1];
+	WordList &keywords3 = *keywordlists[2];
+	WordList &keywords4 = *keywordlists[3];
+
+	// property styling.within.preprocessor
+	//	For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default)
+	//	or only from the initial # to the end of the command word(1).
+	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
+
+	CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
+	CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");
+
+	CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");
+
+	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+	CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
+
+	// property lexer.cpp.allow.dollars
+	//	Set to 0 to disallow the '$' character in identifiers with the cpp lexer.
+	if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) {
+		setWordStart.Add('$');
+		setWord.Add('$');
+	}
+
+	int chPrevNonWhite = ' ';
+	int visibleChars = 0;
+	bool lastWordWasUUID = false;
+	int styleBeforeDCKeyword = SCE_COFFEESCRIPT_DEFAULT;
+	bool continuationLine = false;
+	bool isIncludePreprocessor = false;
+
+	if (initStyle == SCE_COFFEESCRIPT_PREPROCESSOR) {
+		// Set continuationLine if last character of previous line is '\'
+		int lineCurrent = styler.GetLine(startPos);
+		if (lineCurrent > 0) {
+			int chBack = styler.SafeGetCharAt(startPos-1, 0);
+			int chBack2 = styler.SafeGetCharAt(startPos-2, 0);
+			int lineEndChar = '!';
+			if (chBack2 == '\r' && chBack == '\n') {
+				lineEndChar = styler.SafeGetCharAt(startPos-3, 0);
+			} else if (chBack == '\n' || chBack == '\r') {
+				lineEndChar = chBack2;
+			}
+			continuationLine = lineEndChar == '\\';
+		}
+	}
+
+	// look back to set chPrevNonWhite properly for better regex colouring
+	int endPos = startPos + length;
+        if (startPos > 0 && IsSpaceEquiv(initStyle)) {
+		unsigned int back = startPos;
+		styler.Flush();
+		while (back > 0 && IsSpaceEquiv(styler.StyleAt(--back)))
+			;
+		if (styler.StyleAt(back) == SCE_COFFEESCRIPT_OPERATOR) {
+			chPrevNonWhite = styler.SafeGetCharAt(back);
+		}
+		if (startPos != back) {
+			initStyle = styler.StyleAt(back);
+			if (IsSpaceEquiv(initStyle)) {
+				initStyle = SCE_COFFEESCRIPT_DEFAULT;
+			}
+		}
+		startPos = back;
+	}
+
+	StyleContext sc(startPos, endPos - startPos, initStyle, styler);
+
+	for (; sc.More(); sc.Forward()) {
+
+		if (sc.atLineStart) {
+			// Reset states to begining of colourise so no surprises
+			// if different sets of lines lexed.
+			visibleChars = 0;
+			lastWordWasUUID = false;
+			isIncludePreprocessor = false;
+		}
+
+		// Handle line continuation generically.
+		if (sc.ch == '\\') {
+			if (sc.chNext == '\n' || sc.chNext == '\r') {
+				sc.Forward();
+				if (sc.ch == '\r' && sc.chNext == '\n') {
+					sc.Forward();
+				}
+				continuationLine = true;
+				continue;
+			}
+		}
+
+		// Determine if the current state should terminate.
+		switch (sc.state) {
+			case SCE_COFFEESCRIPT_OPERATOR:
+				sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				break;
+			case SCE_COFFEESCRIPT_NUMBER:
+				// We accept almost anything because of hex. and number suffixes
+				if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_IDENTIFIER:
+				if (!setWord.Contains(sc.ch) || (sc.ch == '.') || (sc.ch == '$')) {
+					char s[1000];
+					sc.GetCurrent(s, sizeof(s));
+					if (keywords.InList(s)) {
+						lastWordWasUUID = strcmp(s, "uuid") == 0;
+						sc.ChangeState(SCE_COFFEESCRIPT_WORD);
+					} else if (keywords2.InList(s)) {
+						sc.ChangeState(SCE_COFFEESCRIPT_WORD2);
+					} else if (keywords4.InList(s)) {
+						sc.ChangeState(SCE_COFFEESCRIPT_GLOBALCLASS);
+					}
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_WORD:
+			case SCE_COFFEESCRIPT_WORD2:
+			case SCE_COFFEESCRIPT_GLOBALCLASS:
+				if (!setWord.Contains(sc.ch)) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_PREPROCESSOR:
+				if (sc.atLineStart && !continuationLine) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (stylingWithinPreprocessor) {
+					if (IsASpace(sc.ch)) {
+						sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+					}
+				} else {
+					if (sc.Match('/', '*') || sc.Match('/', '/')) {
+						sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+					}
+				}
+				break;
+			case SCE_COFFEESCRIPT_COMMENT:
+				if (sc.Match('*', '/')) {
+					sc.Forward();
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_COMMENTDOC:
+				if (sc.Match('*', '/')) {
+					sc.Forward();
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
+					// Verify that we have the conditions to mark a comment-doc-keyword
+					if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
+						styleBeforeDCKeyword = SCE_COFFEESCRIPT_COMMENTDOC;
+						sc.SetState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORD);
+					}
+				}
+				break;
+			case SCE_COFFEESCRIPT_COMMENTLINE:
+				if (sc.atLineStart) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_COMMENTLINEDOC:
+				if (sc.atLineStart) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
+					// Verify that we have the conditions to mark a comment-doc-keyword
+					if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
+						styleBeforeDCKeyword = SCE_COFFEESCRIPT_COMMENTLINEDOC;
+						sc.SetState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORD);
+					}
+				}
+				break;
+			case SCE_COFFEESCRIPT_COMMENTDOCKEYWORD:
+				if ((styleBeforeDCKeyword == SCE_COFFEESCRIPT_COMMENTDOC) && sc.Match('*', '/')) {
+					sc.ChangeState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR);
+					sc.Forward();
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (!setDoxygen.Contains(sc.ch)) {
+					char s[100];
+					sc.GetCurrent(s, sizeof(s));
+					if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
+						sc.ChangeState(SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR);
+					}
+					sc.SetState(styleBeforeDCKeyword);
+				}
+				break;
+			case SCE_COFFEESCRIPT_STRING:
+				if (isIncludePreprocessor) {
+					if (sc.ch == '>') {
+						sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+						isIncludePreprocessor = false;
+					}
+				} else if (sc.ch == '\\') {
+					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+						sc.Forward();
+					}
+				} else if (sc.ch == '\"') {
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_CHARACTER:
+				if (sc.ch == '\\') {
+					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+						sc.Forward();
+					}
+				} else if (sc.ch == '\'') {
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_REGEX:
+				if (sc.atLineStart) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (sc.ch == '/') {
+					sc.Forward();
+					while ((sc.ch < 0x80) && islower(sc.ch))
+						sc.Forward();    // gobble regex flags
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (sc.ch == '\\') {
+					// Gobble up the quoted character
+					if (sc.chNext == '\\' || sc.chNext == '/') {
+						sc.Forward();
+					}
+				}
+				break;
+			case SCE_COFFEESCRIPT_STRINGEOL:
+				if (sc.atLineStart) {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_VERBATIM:
+				if (sc.ch == '\"') {
+					if (sc.chNext == '\"') {
+						sc.Forward();
+					} else {
+						sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+					}
+				}
+				break;
+			case SCE_COFFEESCRIPT_UUID:
+				if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
+					sc.SetState(SCE_COFFEESCRIPT_DEFAULT);
+				}
+				break;
+			case SCE_COFFEESCRIPT_COMMENTBLOCK:
+				if (sc.Match("###")) {
+					sc.Forward();
+					sc.Forward();
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (sc.ch == '\\') {
+					sc.Forward();
+				}
+				break;
+			case SCE_COFFEESCRIPT_VERBOSE_REGEX:
+				if (sc.Match("///")) {
+					sc.Forward();
+					sc.Forward();
+					sc.ForwardSetState(SCE_COFFEESCRIPT_DEFAULT);
+				} else if (sc.Match('#')) {
+					sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT);
+				} else if (sc.ch == '\\') {
+					sc.Forward();
+				}
+				break;
+			case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT:
+				if (sc.atLineStart) {
+					sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX);
+				}
+				break;
+		}
+
+		// Determine if a new state should be entered.
+		if (sc.state == SCE_COFFEESCRIPT_DEFAULT) {
+			if (sc.Match('@', '\"')) {
+				sc.SetState(SCE_COFFEESCRIPT_VERBATIM);
+				sc.Forward();
+			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+				if (lastWordWasUUID) {
+					sc.SetState(SCE_COFFEESCRIPT_UUID);
+					lastWordWasUUID = false;
+				} else {
+					sc.SetState(SCE_COFFEESCRIPT_NUMBER);
+				}
+			} else if (setWordStart.Contains(sc.ch) || (sc.ch == '@') || (sc.ch == '$')) {
+				if (lastWordWasUUID) {
+					sc.SetState(SCE_COFFEESCRIPT_UUID);
+					lastWordWasUUID = false;
+				} else {
+					sc.SetState(SCE_COFFEESCRIPT_IDENTIFIER);
+				}
+			} else if (sc.Match('/', '*')) {
+				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
+					sc.SetState(SCE_COFFEESCRIPT_COMMENTDOC);
+				} else {
+					sc.SetState(SCE_COFFEESCRIPT_COMMENT);
+				}
+				sc.Forward();	// Eat the * so it isn't used for the end of the comment
+			} else if (sc.Match("///")) {
+				sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX);
+				sc.Forward();
+				sc.Forward();
+			} else if (sc.ch == '/'
+				   && (setOKBeforeRE.Contains(chPrevNonWhite)
+				       || followsReturnKeyword(sc, styler))
+				   && (!setCouldBePostOp.Contains(chPrevNonWhite)
+				       || !FollowsPostfixOperator(sc, styler))) {
+				sc.SetState(SCE_COFFEESCRIPT_REGEX);	// JavaScript's RegEx
+			} else if (sc.ch == '\"') {
+				sc.SetState(SCE_COFFEESCRIPT_STRING);
+				isIncludePreprocessor = false;	// ensure that '>' won't end the string
+			} else if (isIncludePreprocessor && sc.ch == '<') {
+				sc.SetState(SCE_COFFEESCRIPT_STRING);
+			} else if (sc.ch == '\'') {
+				sc.SetState(SCE_COFFEESCRIPT_CHARACTER);
+			} else if (sc.ch == '#') {
+				if (sc.Match("###")) {
+					sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK);
+					sc.Forward();
+					sc.Forward();
+
+				} else {
+					sc.SetState(SCE_COFFEESCRIPT_COMMENTLINE);
+				}
+			} else if (isoperator(static_cast<char>(sc.ch))) {
+				sc.SetState(SCE_COFFEESCRIPT_OPERATOR);
+			}
+		}
+
+		if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) {
+			chPrevNonWhite = sc.ch;
+			visibleChars++;
+		}
+		continuationLine = false;
+	}
+	sc.Complete();
+}
+
+static bool IsCommentLine(int line, Accessor &styler) {
+	int pos = styler.LineStart(line);
+	int eol_pos = styler.LineStart(line + 1) - 1;
+	for (int i = pos; i < eol_pos; i++) {
+		char ch = styler[i];
+		if (ch == '#')
+			return true;
+        else if (ch == '/'
+                 && i < eol_pos - 1
+                 && styler[i + 1] == '*')
+			return true;
+		else if (ch != ' ' && ch != '\t')
+			return false;
+	}
+	return false;
+}
+
+static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int,
+				WordList *[], Accessor &styler) {
+	// A simplified version of FoldPyDoc
+	const int maxPos = startPos + length;
+	const int maxLines = styler.GetLine(maxPos - 1);             // Requested last line
+	const int docLines = styler.GetLine(styler.Length() - 1);  // Available last line
+
+	// property fold.coffeescript.comment
+	const bool foldComment = styler.GetPropertyInt("fold.coffeescript.comment") != 0;
+
+	const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0;
+
+	// Backtrack to previous non-blank line so we can determine indent level
+	// 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 spaceFlags = 0;
+	int lineCurrent = styler.GetLine(startPos);
+	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+	while (lineCurrent > 0) {
+		lineCurrent--;
+		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)
+		    && !IsCommentLine(lineCurrent, styler))
+			break;
+	}
+	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+
+	// Set up initial loop state
+	int prevComment = 0;
+	if (lineCurrent >= 1)
+		prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);
+
+	// Process all characters to end of requested range
+	// or comment that hangs over the end of the range.  Cap processing in all cases
+	// to end of document (in case of comment at end).
+	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) {
+
+		// Gather info
+		int lev = indentCurrent;
+		int lineNext = lineCurrent + 1;
+		int indentNext = indentCurrent;
+		if (lineNext <= docLines) {
+			// Information about next line is only available if not at end of document
+			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+		}
+		const int comment = foldComment && IsCommentLine(lineCurrent, styler);
+		const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
+		                           IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE));
+		const int comment_continue = (comment && prevComment);
+		if (!comment)
+			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+		if (indentNext & SC_FOLDLEVELWHITEFLAG)
+			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+		if (comment_start) {
+			// Place fold point at start of a block of comments
+			lev |= SC_FOLDLEVELHEADERFLAG;
+		} else if (comment_continue) {
+			// Add level to rest of lines in the block
+			lev = lev + 1;
+		}
+
+		// Skip past any blank lines for next indent level info; we skip also
+		// comments (all comments, not just those starting in column 0)
+		// which effectively folds them into surrounding code rather
+		// than screwing up folding.
+
+		while ((lineNext < docLines) &&
+		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
+		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+
+			lineNext++;
+			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+		}
+
+		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
+		const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments);
+
+		// Now set all the indent levels on the lines we skipped
+		// Do this from end to start.  Once we encounter one line
+		// which is indented more than the line after the end of
+		// the comment-block, use the level of the block before
+
+		int skipLine = lineNext;
+		int skipLevel = levelAfterComments;
+
+		while (--skipLine > lineCurrent) {
+			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
+
+			if (foldCompact) {
+				if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
+					skipLevel = levelBeforeComments;
+
+				int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
+
+				styler.SetLevel(skipLine, skipLevel | whiteFlag);
+			} else {
+				if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments &&
+					!(skipLineIndent & SC_FOLDLEVELWHITEFLAG) &&
+					!IsCommentLine(skipLine, styler))
+					skipLevel = levelBeforeComments;
+
+				styler.SetLevel(skipLine, skipLevel);
+			}
+		}
+
+		// Set fold header on non-comment line
+		if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
+				lev |= SC_FOLDLEVELHEADERFLAG;
+		}
+
+		// Keep track of block comment state of previous line
+		prevComment = comment_start || comment_continue;
+
+		// Set fold level for this line and move to next line
+		styler.SetLevel(lineCurrent, lev);
+		indentCurrent = indentNext;
+		lineCurrent = lineNext;
+	}
+}
+
+static const char *const csWordLists[] = {
+            "Keywords",
+            0,
+};
+
+LexerModule lmCoffeeScript(SCLEX_COFFEESCRIPT, ColouriseCoffeeScriptDoc, "coffeescript", FoldCoffeeScriptDoc, csWordLists);


Modified: scintilla/makefile.win32
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -70,6 +70,7 @@ LexBash.o \
 LexCOBOL.o \
 LexCSS.o \
 LexCPP.o \
+LexCoffeeScript.o \
 LexHTML.o \
 LexOthers.o \
 LexPascal.o \


Modified: scintilla/src/Catalogue.cxx
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -85,6 +85,7 @@ int Scintilla_LinkLexers() {
 	LINK_LEXER(lmCmake);
 	LINK_LEXER(lmCOBOL);
 	LINK_LEXER(lmCPP);
+	LINK_LEXER(lmCoffeeScript);
 	LINK_LEXER(lmCss);
 	LINK_LEXER(lmD);
 	LINK_LEXER(lmDiff);


Modified: src/filetypes.c
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -190,6 +190,7 @@ static void init_builtin_filetypes(void)
 	FT_INIT( BATCH,      NONE,         "Batch",            NULL,                      SCRIPT,      SCRIPT   );
 	FT_INIT( POWERSHELL, NONE,         "PowerShell",       NULL,                      SOURCE_FILE, SCRIPT   );
 	FT_INIT( RUST,       RUST,         "Rust",             NULL,                      SOURCE_FILE, COMPILED );
+	FT_INIT( COFFEESCRIPT, NONE,       "CoffeeScript",     NULL,                      SOURCE_FILE, SCRIPT   );
 }
 
 


Modified: src/filetypes.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -100,6 +100,7 @@ typedef enum
 	GEANY_FILETYPES_BATCH,
 	GEANY_FILETYPES_POWERSHELL,
 	GEANY_FILETYPES_RUST,
+	GEANY_FILETYPES_COFFEESCRIPT,
 	/* ^ append items here */
 	GEANY_MAX_BUILT_IN_FILETYPES	/* Don't use this, use filetypes_array->len instead */
 }


Modified: src/highlighting.c
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -1001,6 +1001,7 @@ void highlighting_init_styles(guint filetype_idx, GKeyFile *config, GKeyFile *co
 		init_styleset_case(CAML);
 		init_styleset_case(CMAKE);
 		init_styleset_case(COBOL);
+		init_styleset_case(COFFEESCRIPT);
 		init_styleset_case(CONF);
 		init_styleset_case(CSS);
 		init_styleset_case(D);
@@ -1084,6 +1085,7 @@ void highlighting_set_styles(ScintillaObject *sci, GeanyFiletype *ft)
 		styleset_case(CAML);
 		styleset_case(CMAKE);
 		styleset_case(COBOL);
+		styleset_case(COFFEESCRIPT);
 		styleset_case(CONF);
 		styleset_case(CSS);
 		styleset_case(D);


Modified: src/highlightingmappings.h
28 lines changed, 28 insertions(+), 0 deletions(-)
===================================================================
@@ -333,6 +333,34 @@ static const HLKeyword highlighting_keywords_CMAKE[] =
 };
 #define highlighting_properties_CMAKE	EMPTY_PROPERTIES
 
+/* CoffeeScript */
+#define highlighting_lexer_COFFEESCRIPT		SCLEX_COFFEESCRIPT
+static const HLStyle highlighting_styles_COFFEESCRIPT[] =
+{
+	{ SCE_COFFEESCRIPT_DEFAULT,					"default",				FALSE },
+	{ SCE_COFFEESCRIPT_COMMENTLINE,				"commentline",			FALSE },
+	{ SCE_COFFEESCRIPT_NUMBER,					"number",				FALSE },
+	{ SCE_COFFEESCRIPT_WORD,					"word",					FALSE },
+	{ SCE_COFFEESCRIPT_STRING,					"string",				FALSE },
+	{ SCE_COFFEESCRIPT_CHARACTER,				"character",			FALSE },
+	{ SCE_COFFEESCRIPT_OPERATOR,				"operator",				FALSE },
+	{ SCE_COFFEESCRIPT_IDENTIFIER,				"identifier",			FALSE },
+	{ SCE_COFFEESCRIPT_STRINGEOL,				"stringeol",			FALSE },
+	{ SCE_COFFEESCRIPT_REGEX,					"regex",				FALSE },
+	{ SCE_COFFEESCRIPT_WORD2,					"word2",				FALSE },
+	{ SCE_COFFEESCRIPT_GLOBALCLASS,				"globalclass",			FALSE },
+	{ SCE_COFFEESCRIPT_COMMENTBLOCK,			"commentblock",			FALSE },
+	{ SCE_COFFEESCRIPT_VERBOSE_REGEX,			"verbose_regex",		FALSE },
+	{ SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT,	"verbose_regex_comment",FALSE }
+};
+static const HLKeyword highlighting_keywords_COFFEESCRIPT[] =
+{
+	{ 0, "primary",		FALSE },
+	{ 1, "secondary",	FALSE },
+	{ 3, "globalclass",	FALSE }
+};
+#define highlighting_properties_COFFEESCRIPT	EMPTY_PROPERTIES
+
 
 /* CSS */
 #define highlighting_lexer_CSS			SCLEX_CSS



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list