diff options
-rw-r--r-- | cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | doc/ScintillaHistory.html | 8 | ||||
-rw-r--r-- | include/SciLexer.h | 18 | ||||
-rw-r--r-- | include/Scintilla.iface | 20 | ||||
-rw-r--r-- | lexers/LexNim.cxx | 701 | ||||
-rw-r--r-- | src/Catalogue.cxx | 1 | ||||
-rw-r--r-- | win32/scintilla.mak | 3 |
7 files changed, 755 insertions, 0 deletions
diff --git a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj index e2df2d63d..837ebbde3 100644 --- a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj +++ b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj @@ -229,6 +229,7 @@ F437405F9F32C7DEFCA38C11 /* LexIndent.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 282E41F3B9E2BFEDD6A05BE7 /* LexIndent.cxx */; }; FDC7442CAD70B9A67EF1639D /* LexSAS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = A95147A1AB7CADB00DAFE724 /* LexSAS.cxx */; }; 5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7623427695416AB1270EE023 /* LexStata.cxx */; }; + 0ED84236A703D57578EBFD2F /* LexNim.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 47814937A6B72D2B0F065B61 /* LexNim.cxx */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -461,6 +462,7 @@ D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; A95147A1AB7CADB00DAFE724 /* LexSAS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSAS.cxx; path = ../../lexers/LexSAS.cxx; sourceTree = SOURCE_ROOT; }; 7623427695416AB1270EE023 /* LexStata.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexStata.cxx; path = ../../lexers/LexStata.cxx; sourceTree = SOURCE_ROOT; }; + 47814937A6B72D2B0F065B61 /* LexNim.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexNim.cxx; path = ../../lexers/LexNim.cxx; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -622,6 +624,7 @@ 114B6EE811FA7526004FB6AB /* LexMPT.cxx */, 114B6EE911FA7526004FB6AB /* LexMSSQL.cxx */, 114B6EEA11FA7526004FB6AB /* LexMySQL.cxx */, + 47814937A6B72D2B0F065B61 /* LexNim.cxx */, 114B6EEB11FA7526004FB6AB /* LexNimrod.cxx */, 114B6EEC11FA7526004FB6AB /* LexNsis.cxx */, 28B6470A1B54C0720009DC49 /* LexNull.cxx */, @@ -1120,6 +1123,7 @@ 3D994BD7A5EAC4FA5B3CFBDF /* LexMaxima.cxx in Sources */, FDC7442CAD70B9A67EF1639D /* LexSAS.cxx in Sources */, 5F804AA6B60FE695863A39FE /* LexStata.cxx in Sources */, + 0ED84236A703D57578EBFD2F /* LexNim.cxx in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 5ff4206a0..9ac34e475 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -538,6 +538,8 @@ <td>Gokul Krishnan</td> <td>John Horigan</td> <td>jj5</td> + </tr><tr> + <td>Jad Altahan</td> </tr> </table> <p> @@ -564,6 +566,12 @@ <li> Updated case conversion and character categories to Unicode 11. </li> + <li> + Added "nim" lexer (SCLEX_NIM) for the Nim language which was previously called Nimrod. + For compatibility, the old "nimrod" lexer is still present but is deprecated and will be removed at the + next major version. + <a href="https://sourceforge.net/p/scintilla/feature-requests/1242/">Feature #1242.</a> + </li> <li> On Cocoa, fix a crash that occurred when entering a dead key diacritic then a character that can not take that diacritic, such as option+e (acute accent) followed by g. diff --git a/include/SciLexer.h b/include/SciLexer.h index b6f864c6d..7a71679a7 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -138,6 +138,7 @@ #define SCLEX_MAXIMA 123 #define SCLEX_STATA 124 #define SCLEX_SAS 125 +#define SCLEX_NIM 126 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -1855,6 +1856,23 @@ #define SCE_SAS_BLOCK_KEYWORD 13 #define SCE_SAS_MACRO_FUNCTION 14 #define SCE_SAS_STATEMENT 15 +#define SCE_NIM_DEFAULT 0 +#define SCE_NIM_COMMENT 1 +#define SCE_NIM_COMMENTDOC 2 +#define SCE_NIM_COMMENTLINE 3 +#define SCE_NIM_COMMENTLINEDOC 4 +#define SCE_NIM_NUMBER 5 +#define SCE_NIM_STRING 6 +#define SCE_NIM_CHARACTER 7 +#define SCE_NIM_WORD 8 +#define SCE_NIM_TRIPLE 9 +#define SCE_NIM_TRIPLEDOUBLE 10 +#define SCE_NIM_BACKTICKS 11 +#define SCE_NIM_FUNCNAME 12 +#define SCE_NIM_STRINGEOL 13 +#define SCE_NIM_NUMERROR 14 +#define SCE_NIM_OPERATOR 15 +#define SCE_NIM_IDENTIFIER 16 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ #endif diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 57a2c3b11..9986f4c2c 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2948,6 +2948,7 @@ val SCLEX_INDENT=122 val SCLEX_MAXIMA=123 val SCLEX_STATA=124 val SCLEX_SAS=125 +val SCLEX_NIM=126 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -4901,6 +4902,25 @@ val SCE_SAS_MACRO_KEYWORD=12 val SCE_SAS_BLOCK_KEYWORD=13 val SCE_SAS_MACRO_FUNCTION=14 val SCE_SAS_STATEMENT=15 +# Lexical states for SCLEX_NIM +lex Nim=SCLEX_NIM SCE_NIM_ +val SCE_NIM_DEFAULT=0 +val SCE_NIM_COMMENT=1 +val SCE_NIM_COMMENTDOC=2 +val SCE_NIM_COMMENTLINE=3 +val SCE_NIM_COMMENTLINEDOC=4 +val SCE_NIM_NUMBER=5 +val SCE_NIM_STRING=6 +val SCE_NIM_CHARACTER=7 +val SCE_NIM_WORD=8 +val SCE_NIM_TRIPLE=9 +val SCE_NIM_TRIPLEDOUBLE=10 +val SCE_NIM_BACKTICKS=11 +val SCE_NIM_FUNCNAME=12 +val SCE_NIM_STRINGEOL=13 +val SCE_NIM_NUMERROR=14 +val SCE_NIM_OPERATOR=15 +val SCE_NIM_IDENTIFIER=16 # Events diff --git a/lexers/LexNim.cxx b/lexers/LexNim.cxx new file mode 100644 index 000000000..2cfc30eeb --- /dev/null +++ b/lexers/LexNim.cxx @@ -0,0 +1,701 @@ +// Scintilla source code edit control +/** @file LexNim.cxx +** Lexer for Nim +** Written by Jad Altahan (github.com/xv) +** Nim manual: https://nim-lang.org/docs/manual.html +**/ +// Copyright 1998-2001 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 <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <map> +#include <algorithm> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "CharacterCategory.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; + +struct OptionsNim { + bool fold; + bool foldCompact; + + OptionsNim() { + fold = true; + foldCompact = true; + } +}; + +static const char *const nimWordListDesc[] = { + "Keywords", + 0 +}; + +struct OptionSetNim : public OptionSet<OptionsNim> { + OptionSetNim() { + DefineProperty("fold", &OptionsNim::fold); + DefineProperty("fold.compact", &OptionsNim::foldCompact); + + DefineWordListSets(nimWordListDesc); + } +}; + +LexicalClass lexicalClasses[] = { + // Lexer Nim SCLEX_NIM SCE_NIM_: + 0, "SCE_NIM_DEFAULT", "default", "White space", + 1, "SCE_NIM_COMMENT", "comment block", "Block comment", + 2, "SCE_NIM_COMMENTDOC", "comment block doc", "Block doc comment", + 3, "SCE_NIM_COMMENTLINE", "comment line", "Line comment", + 4, "SCE_NIM_COMMENTLINEDOC", "comment doc", "Line doc comment", + 5, "SCE_NIM_NUMBER", "literal numeric", "Number", + 6, "SCE_NIM_STRING", "literal string", "String", + 7, "SCE_NIM_CHARACTER", "literal string", "Single quoted string", + 8, "SCE_NIM_WORD", "keyword", "Keyword", + 9, "SCE_NIM_TRIPLE", "literal string", "Triple quotes", + 10, "SCE_NIM_TRIPLEDOUBLE", "literal string", "Triple double quotes", + 11, "SCE_NIM_BACKTICKS", "operator definition", "Identifiers", + 12, "SCE_NIM_FUNCNAME", "identifier", "Function name definition", + 13, "SCE_NIM_STRINGEOL", "error literal string", "String is not closed", + 14, "SCE_NIM_NUMERROR", "numeric error", "Numeric format error", + 15, "SCE_NIM_OPERATOR", "operator", "Operators", + 16, "SCE_NIM_IDENTIFIER", "identifier", "Identifiers", +}; + +class LexerNim : public DefaultLexer { + CharacterSet setWord; + WordList keywords; + OptionsNim options; + OptionSetNim osNim; + +public: + LexerNim() : + DefaultLexer(lexicalClasses, ELEMENTS(lexicalClasses)), + setWord(CharacterSet::setAlphaNum, "_", 0x80, true) { } + + virtual ~LexerNim() { } + + void SCI_METHOD Release() override { + delete this; + } + + int SCI_METHOD Version() const override { + return lvRelease4; + } + + const char * SCI_METHOD PropertyNames() override { + return osNim.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char *name) override { + return osNim.PropertyType(name); + } + + const char * SCI_METHOD DescribeProperty(const char *name) override { + return osNim.DescribeProperty(name); + } + + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + + const char * SCI_METHOD DescribeWordListSets() override { + return osNim.DescribeWordListSets(); + } + + Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override; + + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; + + void * SCI_METHOD PrivateCall(int, void *) override { + return 0; + } + + int SCI_METHOD LineEndTypesSupported() override { + return SC_LINE_END_TYPE_UNICODE; + } + + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + + static ILexer4 *LexerFactoryNim() { + return new LexerNim(); + } +}; + +Sci_Position SCI_METHOD LexerNim::PropertySet(const char *key, const char *val) { + if (osNim.PropertySet(&options, key, val)) { + return 0; + } + + return -1; +} + +Sci_Position SCI_METHOD LexerNim::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + + switch (n) { + case 0: + wordListN = &keywords; + break; + } + + Sci_Position firstModification = -1; + + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + + return firstModification; +} + +enum NumType { + Binary, + Octal, + Exponent, + Hexadecimal, + Decimal, + FormatError +}; + +static int GetNumStyle(int numType) { + if (numType == NumType::FormatError) { + return SCE_NIM_NUMERROR; + } + + return SCE_NIM_NUMBER; +} + +static bool IsAWordChar(const int ch) { + return ch < 0x80 && (isalnum(ch) || ch == '_' || ch == '.'); +} + +static int IsNumHex(StyleContext &sc) { + return sc.chNext == 'x' || sc.chNext == 'X'; +} + +static int IsNumBinary(StyleContext &sc) { + return sc.chNext == 'b' || sc.chNext == 'B'; +} + +static int IsNumOctal(StyleContext &sc) { + return IsADigit(sc.chNext) + || sc.chNext == 'o' + || sc.chNext == 'c' || sc.chNext == 'C'; +} + +static bool IsNewline(const int ch) { + return (ch == '\n' || ch == '\r'); +} + +static bool IsTripleLiteral(const int style) { + return style == SCE_NIM_TRIPLE || style == SCE_NIM_TRIPLEDOUBLE; +} + +static bool IsLineComment(const int style) { + return style == SCE_NIM_COMMENTLINE || style == SCE_NIM_COMMENTLINEDOC; +} + +static bool IsStreamComment(const int style) { + return style == SCE_NIM_COMMENT || style == SCE_NIM_COMMENTDOC; +} + +void SCI_METHOD LexerNim::Lex(Sci_PositionU startPos, Sci_Position length, + int initStyle, IDocument *pAccess) { + // No one likes a leaky string + if (initStyle == SCE_NIM_STRINGEOL) { + initStyle = SCE_NIM_DEFAULT; + } + + Accessor styler(pAccess, NULL); + StyleContext sc(startPos, length, initStyle, styler); + + // Nim supports nested block comments! + Sci_Position lineCurrent = styler.GetLine(startPos); + int commentNestLevel = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) : 0; + + int numType = NumType::Decimal; + int decimalCount = 0; + + bool funcNameExists = false; + + for (; sc.More(); sc.Forward()) { + if (sc.atLineStart) { + if (sc.state == SCE_NIM_STRING) { + sc.SetState(SCE_NIM_STRING); + } + + lineCurrent = styler.GetLine(sc.currentPos); + styler.SetLineState(lineCurrent, commentNestLevel); + } + + // Handle string line continuation + if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') && + (sc.state == SCE_NIM_STRING || sc.state == SCE_NIM_CHARACTER)) { + sc.Forward(); + + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + + continue; + } + + switch (sc.state) { + case SCE_NIM_OPERATOR: + funcNameExists = false; + sc.SetState(SCE_NIM_DEFAULT); + break; + case SCE_NIM_NUMBER: + // For a type suffix, such as 0x80'u8 + if (sc.ch == '\'') { + if (sc.chNext == 'i' || sc.chNext == 'u' || + sc.chNext == 'f' || sc.chNext == 'd') { + sc.Forward(2); + } + } else if (sc.ch == '.') { + if (sc.chNext == '.') { + // Pass + } else if (numType <= NumType::Exponent) { + sc.SetState(SCE_NIM_OPERATOR); + break; + } else { + decimalCount++; + + if (numType == NumType::Decimal) { + if (decimalCount <= 1 && !IsAWordChar(sc.chNext)) { + break; + } + } else if (numType == NumType::Hexadecimal) { + if (decimalCount <= 1 && IsADigit(sc.chNext, 16)) { + break; + } + + sc.SetState(SCE_NIM_OPERATOR); + break; + } + } + } else if (sc.ch == '_') { + break; + } else if (numType == NumType::Decimal) { + if (sc.chPrev != '\'' && (sc.ch == 'e' || sc.ch == 'E')) { + numType = NumType::Exponent; + + if (sc.chNext == '-' || sc.chNext == '+') { + sc.Forward(); + } + + break; + } + + if (IsADigit(sc.ch)) { + break; + } + } else if (numType == NumType::Hexadecimal) { + if (IsADigit(sc.ch, 16)) { + break; + } + } else if (IsADigit(sc.ch)) { + if (numType == NumType::Exponent) { + break; + } + + if (numType == NumType::Octal) { + // Accept only 0-7 + if (sc.ch <= '7') { + break; + } + } else if (numType == NumType::Binary) { + // Accept only 0 and 1 + if (sc.ch <= '1') { + break; + } + } + + numType = NumType::FormatError; + break; + } + + sc.ChangeState(GetNumStyle(numType)); + sc.SetState(SCE_NIM_DEFAULT); + break; + case SCE_NIM_IDENTIFIER: + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + int style = SCE_NIM_IDENTIFIER; + + if (keywords.InList(s) && !funcNameExists) { + style = SCE_NIM_WORD; + } else if (funcNameExists) { + style = SCE_NIM_FUNCNAME; + } + + sc.ChangeState(style); + sc.SetState(SCE_NIM_DEFAULT); + + if (style == SCE_NIM_WORD) { + if (0 == strcmp(s, "proc") + || 0 == strcmp(s, "func") + || 0 == strcmp(s, "macro") + || 0 == strcmp(s, "method") + || 0 == strcmp(s, "template") + || 0 == strcmp(s, "iterator") + || 0 == strcmp(s, "converter")) { + funcNameExists = true; + } else { + funcNameExists = false; + } + } else { + funcNameExists = false; + } + } + break; + case SCE_NIM_COMMENT: + if (sc.Match(']', '#')) { + if (commentNestLevel > 0) { + commentNestLevel--; + } + + lineCurrent = styler.GetLine(sc.currentPos); + styler.SetLineState(lineCurrent, commentNestLevel); + sc.Forward(); + + if (commentNestLevel == 0) { + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + } else if (sc.Match('#', '[')) { + commentNestLevel++; + lineCurrent = styler.GetLine(sc.currentPos); + styler.SetLineState(lineCurrent, commentNestLevel); + } + break; + case SCE_NIM_COMMENTDOC: + if (sc.Match("]##")) { + if (commentNestLevel > 0) { + commentNestLevel--; + } + + lineCurrent = styler.GetLine(sc.currentPos); + styler.SetLineState(lineCurrent, commentNestLevel); + sc.Forward(2); + + if (commentNestLevel == 0) { + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + } else if (sc.Match("##[")) { + commentNestLevel++; + lineCurrent = styler.GetLine(sc.currentPos); + styler.SetLineState(lineCurrent, commentNestLevel); + } + break; + case SCE_NIM_COMMENTLINE: + case SCE_NIM_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_NIM_DEFAULT); + } + break; + case SCE_NIM_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_NIM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_NIM_STRINGEOL); + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + break; + case SCE_NIM_CHARACTER: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_NIM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_NIM_STRINGEOL); + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + break; + case SCE_NIM_BACKTICKS: + if (sc.ch == '`' || sc.atLineEnd) { + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + break; + case SCE_NIM_TRIPLEDOUBLE: + if (sc.Match(R"(""")")) { + sc.Forward(2); + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + break; + case SCE_NIM_TRIPLE: + if (sc.Match("'''")) { + sc.Forward(2); + sc.ForwardSetState(SCE_NIM_DEFAULT); + } + break; + } + + if (sc.state == SCE_NIM_DEFAULT) { + // Number + if (IsADigit(sc.ch) || (IsADigit(sc.chNext) && sc.ch == '.')) { + sc.SetState(SCE_NIM_NUMBER); + + numType = NumType::Decimal; + decimalCount = 0; + + if (sc.ch == '0') { + if (IsNumHex(sc)) { + numType = NumType::Hexadecimal; + } else if (IsNumBinary(sc)) { + numType = NumType::Binary; + } else if (IsNumOctal(sc)) { + numType = NumType::Octal; + } + + if (numType != NumType::Decimal) { + sc.Forward(); + } + } + } + // Raw string + else if ((sc.ch == 'r' || sc.ch == 'R') && sc.chNext == '\"') { + sc.SetState(SCE_NIM_STRING); + sc.Forward(); + } + // String and triple double literal + else if (sc.ch == '\"') { + if (sc.Match(R"(""")")) { + sc.SetState(SCE_NIM_TRIPLEDOUBLE); + } else { + sc.SetState(SCE_NIM_STRING); + } + } + // Charecter and triple literal + else if (sc.ch == '\'') { + if (sc.Match("'''")) { + sc.SetState(SCE_NIM_TRIPLE); + } else { + sc.SetState(SCE_NIM_CHARACTER); + } + } + // Operator definition + else if (sc.ch == '`') { + sc.SetState(SCE_NIM_BACKTICKS); + + if (funcNameExists) { + funcNameExists = false; + } + } + // Keyword + else if (iswordstart(sc.ch)) { + sc.SetState(SCE_NIM_IDENTIFIER); + } + // Comments + else if (sc.ch == '#') { + if (sc.Match("##[") || sc.Match("#[")) { + commentNestLevel++; + lineCurrent = styler.GetLine(sc.currentPos); + styler.SetLineState(lineCurrent, commentNestLevel); + } + + if (sc.Match("##[")) { + sc.SetState(SCE_NIM_COMMENTDOC); + sc.Forward(); + } else if (sc.Match("#[")) { + sc.SetState(SCE_NIM_COMMENT); + sc.Forward(); + } else if (sc.Match("##")) { + sc.SetState(SCE_NIM_COMMENTLINEDOC); + } else { + sc.SetState(SCE_NIM_COMMENTLINE); + } + } + // Operators + else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", sc.ch)) { + sc.SetState(SCE_NIM_OPERATOR); + + // Ignore decimal coloring in input like: range[0..5] + if (sc.Match('.', '.')) { + sc.Forward(); + + if (sc.chNext == '.') { + sc.Forward(); + } + } + } + } + + if (sc.atLineEnd) { + funcNameExists = false; + } + } + + sc.Complete(); +} + +// Adopted from Accessor.cxx +static int GetIndent(const Sci_Position line, Accessor &styler) { + Sci_Position startPos = styler.LineStart(line); + Sci_Position eolPos = styler.LineStart(line + 1) - 1; + + char ch = styler[startPos]; + int style = styler.StyleAt(startPos); + + int indent = 0; + bool inPrevPrefix = line > 0; + Sci_Position posPrev = inPrevPrefix ? styler.LineStart(line - 1) : 0; + + // No fold points inside block comments and triple literals + while ((IsASpaceOrTab(ch) + || IsStreamComment(style) + || IsTripleLiteral(style)) && (startPos < eolPos)) { + if (inPrevPrefix) { + char chPrev = styler[posPrev++]; + if (chPrev != ' ' && chPrev != '\t') { + inPrevPrefix = false; + } + } + + if (ch == '\t') { + indent = (indent / 8 + 1) * 8; + } else { + indent++; + } + + startPos++; + ch = styler[startPos]; + style = styler.StyleAt(startPos); + } + + indent += SC_FOLDLEVELBASE; + + if (styler.LineStart(line) == styler.Length() + || IsASpaceOrTab(ch) + || IsNewline(ch) + || IsLineComment(style)) { + return indent | SC_FOLDLEVELWHITEFLAG; + } else { + return indent; + } +} + +static int IndentAmount(const Sci_Position line, Accessor &styler) { + const int indent = GetIndent(line, styler); + const int indentLevel = indent & SC_FOLDLEVELNUMBERMASK; + return indentLevel <= SC_FOLDLEVELBASE ? indent : indentLevel | (indent & ~SC_FOLDLEVELNUMBERMASK); +} + +void SCI_METHOD LexerNim::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) { + if (!options.fold) { + return; + } + + Accessor styler(pAccess, NULL); + + const Sci_Position docLines = styler.GetLine(styler.Length()); + const Sci_Position maxPos = startPos + length; + const Sci_Position maxLines = styler.GetLine(maxPos == styler.Length() ? maxPos : maxPos - 1); + + Sci_Position lineCurrent = styler.GetLine(startPos); + int indentCurrent = IndentAmount(lineCurrent, styler); + + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = IndentAmount(lineCurrent, styler); + + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + break; + } + } + + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + indentCurrent = indentCurrentLevel | (indentCurrent & ~SC_FOLDLEVELNUMBERMASK); + + while (lineCurrent <= docLines && lineCurrent <= maxLines) { + Sci_Position lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + int lev = indentCurrent; + + if (lineNext <= docLines) { + indentNext = IndentAmount(lineNext, styler); + } + + if (indentNext & SC_FOLDLEVELWHITEFLAG) { + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + } + + while (lineNext < docLines && (indentNext & SC_FOLDLEVELWHITEFLAG)) { + lineNext++; + indentNext = IndentAmount(lineNext, styler); + } + + const int indentNextLevel = indentNext & SC_FOLDLEVELNUMBERMASK; + indentNext = indentNextLevel | (indentNext & ~SC_FOLDLEVELNUMBERMASK); + + const int levelBeforeComments = std::max(indentCurrentLevel, indentNextLevel); + + Sci_Position skipLine = lineNext; + int skipLevel = indentNextLevel; + + while (--skipLine > lineCurrent) { + int skipLineIndent = IndentAmount(skipLine, styler); + + if (options.foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel) { + skipLevel = levelBeforeComments; + } + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel && + !(skipLineIndent & SC_FOLDLEVELWHITEFLAG)) { + skipLevel = levelBeforeComments; + } + + styler.SetLevel(skipLine, skipLevel); + } + } + + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + + styler.SetLevel(lineCurrent, options.foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG); + + indentCurrent = indentNext; + indentCurrentLevel = indentNextLevel; + lineCurrent = lineNext; + } +} + +LexerModule lmNim(SCLEX_NIM, LexerNim::LexerFactoryNim, "nim", nimWordListDesc); diff --git a/src/Catalogue.cxx b/src/Catalogue.cxx index 55c15cca6..a5a61ea8c 100644 --- a/src/Catalogue.cxx +++ b/src/Catalogue.cxx @@ -142,6 +142,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmModula); LINK_LEXER(lmMSSQL); LINK_LEXER(lmMySQL); + LINK_LEXER(lmNim); LINK_LEXER(lmNimrod); LINK_LEXER(lmNncrontab); LINK_LEXER(lmNsis); diff --git a/win32/scintilla.mak b/win32/scintilla.mak index cdda0d0ec..d225e7131 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -167,6 +167,7 @@ LEXOBJS=\ $(DIR_O)\LexMPT.obj \ $(DIR_O)\LexMSSQL.obj \ $(DIR_O)\LexMySQL.obj \ + $(DIR_O)\LexNim.obj \ $(DIR_O)\LexNimrod.obj \ $(DIR_O)\LexNsis.obj \ $(DIR_O)\LexNull.obj \ @@ -656,6 +657,8 @@ $(DIR_O)\LexMSSQL.obj: ..\lexers\LexMSSQL.cxx $(LEX_HEADERS) $(DIR_O)\LexMySQL.obj: ..\lexers\LexMySQL.cxx $(LEX_HEADERS) +$(DIR_O)\LexNim.obj: ..\lexers\LexNim.cxx $(LEX_HEADERS) + $(DIR_O)\LexNimrod.obj: ..\lexers\LexNimrod.cxx $(LEX_HEADERS) $(DIR_O)\LexNsis.obj: ..\lexers\LexNsis.cxx $(LEX_HEADERS) |