Add coffescript syntax highlighting

imported lexer from Scintilla and added coffeescript filetype
This commit is contained in:
Mark Dresselhaus 2014-03-24 00:55:59 +01:00 committed by Colomban Wendling
parent d0986dd3f6
commit 07002d252a
11 changed files with 654 additions and 0 deletions

View File

@ -15,6 +15,7 @@ filetypes = \
filetypes.Clojure.conf \
filetypes.cmake \
filetypes.cobol \
filetypes.coffeescript \
filetypes.common \
filetypes.conf \
filetypes.cpp \

View File

@ -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;

View File

@ -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"

View File

@ -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 \

View File

@ -0,0 +1,569 @@
// Scintilla source code edit control
/** @file LexCoffeeScript.cxx
** Lexer for CoffeeScript.
**/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// Based on the Scintilla C++ Lexer
// Written by Eric Promislow <ericp@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);

View File

@ -70,6 +70,7 @@ LexBash.o \
LexCOBOL.o \
LexCSS.o \
LexCPP.o \
LexCoffeeScript.o \
LexHTML.o \
LexOthers.o \
LexPascal.o \

View File

@ -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);

View File

@ -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 );
}

View File

@ -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 */
}

View File

@ -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);

View File

@ -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