Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: GitHub noreply@github.com Date: Sun, 10 Nov 2024 16:40:18 UTC Commit: c043996a9a3dc1b0aa36571cd5f5d61fd8d2eb59 https://github.com/geany/geany/commit/c043996a9a3dc1b0aa36571cd5f5d61fd8d2eb...
Log Message: ----------- Merge pull request #3973 from techee/dart
Add Dart support
Modified Paths: -------------- data/Makefile.am data/filedefs/filetypes.dart data/filetype_extensions.conf meson.build scintilla/Makefile.am scintilla/lexilla/lexers/LexDart.cxx scintilla/lexilla/src/Lexilla.cxx scintilla/scintilla_changes.patch src/editor.c src/filetypes.c src/filetypes.h src/highlighting.c src/highlightingmappings.h
Modified: data/Makefile.am 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -28,6 +28,7 @@ filetypes_dist = \ filedefs/filetypes.CUDA.conf \ filedefs/filetypes.Cython.conf \ filedefs/filetypes.d \ + filedefs/filetypes.dart \ filedefs/filetypes.diff \ filedefs/filetypes.docbook \ filedefs/filetypes.Dockerfile.conf \
Modified: data/filedefs/filetypes.dart 93 lines changed, 93 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,93 @@ +# For complete documentation of this file, please see Geany's main documentation +[styling] +# Edit these in the colorscheme .conf file instead + +default=default +commentline=comment_line +commentlinedoc=comment_doc +commentblock=comment +commentblockdoc=comment_doc +stringsq=string_1 +stringdq=string_1 +triplestringsq=string_1 +triplestringdq=string_1 +rawstringsq=string_1 +rawstringdq=string_1 +triplerawstringsq=string_1 +triplerawstringdq=string_1 +escapechar=string_2 +identifier=default +identifierstring=string_2 +operator=operator +operatorstring=string_2 +symbolidentifier=preprocessor +symboloperator=preprocessor +number=number_1 +key=other +metadata=decorator +kwprimary=keyword_1 +kwsecondary=keyword_1 +kwtertiary=keyword_2 +kwtype=class + +[keywords] +# all items must be in one line +primary=abstract as assert async await base break case catch class const continue covariant default deferred do else enum export extends extension external factory false final finally for get hide if implements import in interface is late library mixin native new null of on operator part required rethrow return sealed set show static super switch sync this throw true try type typedef var when while with yield +secondary=Function Never bool double dynamic int num void +tertiary=BigInt Comparable Comparator Completer DateTime Deprecated Directory DoubleLinkedQueue Duration Enum Error Exception Expando File FileLock FileMode FileStat FileSystemEntity FileSystemEvent Future FutureOr HashMap HashSet IOException Invocation Iterable IterableBase IterableMixin Iterator LinkedHashMap LinkedHashSet LinkedList LinkedListEntry List ListBase ListMixin ListQueue Map MapBase MapEntry MapMixin MapView Match Null OSError Object Pattern Platform Point Process Queue Random RawSocket RawSocketEvent Record Rectangle RegExp RegExpMatch RuneIterator Runes ServerSocket Set SetBase SetMixin Sink Socket SocketException SplayTreeMap SplayTreeSet StackTrace Stopwatch Stream String StringBuffer StringSink Symbol SystemHash Timer Type Uri UriData WeakReference + +[lexer_properties] + +[settings] +tag_parser=Java + +# default extension used when saving files +extension=dart + +# MIME type +mime_type=text/x-dart + +# these characters define word boundaries when making selections and searching +# using word matching options +#wordchars=_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 + +# single comment char, like # in this file +comment_single=// +# multiline comments +comment_open=/* +comment_close=*/ + +# set to false if a comment character/string should start at column 0 of a line, true uses any +# indentation of the line, e.g. setting to true causes the following on pressing CTRL+d +# #command_example(); +# setting to false would generate this +# # command_example(); +# This setting works only for single line comments +comment_use_indent=true + +# context action command (please see Geany's main documentation for details) +context_action_cmd= + +[indentation] +#width=2 +# 0 is spaces, 1 is tabs, 2 is tab & spaces +#type=0 + +[build-menu] +# %f will be replaced by the complete filename +# %e will be replaced by the filename without extension +FT_00_LB=_Compile +FT_00_CM=dart compile exe "%f" +FT_00_WD= +FT_01_LB=_Analyze +FT_01_CM=dart analyze "%f" +FT_01_WD= +FT_02_LB=_Test +FT_02_CM=dart test "%f" +FT_02_WD= +EX_00_LB=Dart _Run +EX_00_CM=dart run "%f" +EX_00_WD=%p +EX_01_LB=Flutter R_un +EX_01_CM=flutter run "%f" +EX_01_WD=%p
Modified: data/filetype_extensions.conf 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -26,6 +26,7 @@ Conf=*.conf;*.ini;config;*rc;*.cfg;*.desktop;*.properties; CSS=*.css; Cython=*.pyx;*.pxd;*.pxi; D=*.d;*.di; +Dart=*.dart; Diff=*.diff;*.patch;*.rej; Docbook=*.docbook; Dockerfile=Dockerfile;dockerfile;*.dockerfile;*.Dockerfile;Dockerfile.*;
Modified: meson.build 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -258,6 +258,7 @@ lexilla = static_library('lexilla', 'scintilla/lexilla/lexers/LexCPP.cxx', 'scintilla/lexilla/lexers/LexCSS.cxx', 'scintilla/lexilla/lexers/LexD.cxx', + 'scintilla/lexilla/lexers/LexDart.cxx', 'scintilla/lexilla/lexers/LexDiff.cxx', 'scintilla/lexilla/lexers/LexErlang.cxx', 'scintilla/lexilla/lexers/LexForth.cxx',
Modified: scintilla/Makefile.am 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -28,6 +28,7 @@ lexilla/lexers/LexCaml.cxx \ lexilla/lexers/LexCmake.cxx \ lexilla/lexers/LexCoffeeScript.cxx \ lexilla/lexers/LexD.cxx \ +lexilla/lexers/LexDart.cxx \ lexilla/lexers/LexDiff.cxx \ lexilla/lexers/LexErlang.cxx \ lexilla/lexers/LexForth.cxx \
Modified: scintilla/lexilla/lexers/LexDart.cxx 702 lines changed, 702 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,702 @@ +// Scintilla source code edit control +/** @file LexDart.cxx + ** Lexer for Dart. + **/ +// Based on Zufu Liu's Notepad4 Dart lexer +// Modified for Scintilla by Jiri Techet, 2024 +// The License.txt file describes the conditions under which this software may be distributed. + +#include <cassert> +#include <cstring> + +#include <string> +#include <string_view> +#include <vector> +#include <map> +#include <algorithm> + +#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" +#include "OptionSet.h" +#include "DefaultLexer.h" + +using namespace Scintilla; +using namespace Lexilla; + +namespace { +// Use an unnamed namespace to protect the functions and classes from name conflicts + +constexpr bool IsEOLChar(int ch) noexcept { + return ch == '\r' || ch == '\n'; +} + +constexpr bool IsAGraphic(int ch) noexcept { + // excludes C0 control characters and whitespace + return ch > 32 && ch < 127; +} + +constexpr bool IsIdentifierChar(int ch) noexcept { + return IsAlphaNumeric(ch) || ch == '_'; +} + +constexpr bool IsIdentifierStart(int ch) noexcept { + return IsUpperOrLowerCase(ch) || ch == '_'; +} + +constexpr bool IsNumberContinue(int chPrev, int ch, int chNext) noexcept { + return ((ch == '+' || ch == '-') && (chPrev == 'e' || chPrev == 'E')) + || (ch == '.' && chNext != '.'); +} + +constexpr bool IsNumberStart(int ch, int chNext) noexcept { + return IsADigit(ch) || (ch == '.' && IsADigit(chNext)); +} + +constexpr bool IsDecimalNumber(int chPrev, int ch, int chNext) noexcept { + return IsIdentifierChar(ch) || IsNumberContinue(chPrev, ch, chNext); +} + +struct EscapeSequence { + int outerState = SCE_DART_DEFAULT; + int digitsLeft = 0; + bool brace = false; + + // highlight any character as escape sequence. + bool resetEscapeState(int state, int chNext) noexcept { + if (IsEOLChar(chNext)) { + return false; + } + outerState = state; + brace = false; + digitsLeft = (chNext == 'x')? 3 : ((chNext == 'u') ? 5 : 1); + return true; + } + bool atEscapeEnd(int ch) noexcept { + --digitsLeft; + return digitsLeft <= 0 || !IsAHeXDigit(ch); + } +}; + +constexpr bool IsDartIdentifierStart(int ch) noexcept { + return IsIdentifierStart(ch) || ch == '$'; +} + +constexpr bool IsDartIdentifierChar(int ch) noexcept { + return IsIdentifierChar(ch) || ch == '$'; +} + +constexpr bool IsDefinableOperator(int ch) noexcept { + // https://github.com/dart-lang/sdk/blob/main/sdk/lib/core/symbol.dart + return AnyOf(ch, '+', '-', '*', '/', '%', '~', '&', '|', + '^', '<', '>', '=', '[', ']'); +} + +constexpr bool IsSpaceEquiv(int state) noexcept { + return state == SCE_DART_DEFAULT || + state == SCE_DART_COMMENTLINE || + state == SCE_DART_COMMENTLINEDOC || + state == SCE_DART_COMMENTBLOCK || + state == SCE_DART_COMMENTBLOCKDOC; +} + +constexpr bool IsTripleString(int state) noexcept { + return state == SCE_DART_TRIPLE_STRING_SQ || + state == SCE_DART_TRIPLE_STRING_DQ || + state == SCE_DART_TRIPLE_RAWSTRING_SQ || + state == SCE_DART_TRIPLE_RAWSTRING_DQ; +} + +constexpr bool IsDoubleQuoted(int state) noexcept { + return state == SCE_DART_STRING_DQ || + state == SCE_DART_RAWSTRING_DQ || + state == SCE_DART_TRIPLE_STRING_DQ || + state == SCE_DART_TRIPLE_RAWSTRING_DQ; +} + +constexpr bool IsRaw(int state) noexcept { + return state == SCE_DART_RAWSTRING_SQ || + state == SCE_DART_RAWSTRING_DQ || + state == SCE_DART_TRIPLE_RAWSTRING_SQ || + state == SCE_DART_TRIPLE_RAWSTRING_DQ; +} + +constexpr int GetStringQuote(int state) noexcept { + return IsDoubleQuoted(state) ? '"' : '''; +} + +enum { + DartLineStateMaskLineComment = 1, // line comment + DartLineStateMaskImport = (1 << 1), // import + DartLineStateMaskInterpolation = (1 << 2), // string interpolation +}; + +// string interpolating state +struct InterpolatingState { + int state; + int braceCount; +}; + +struct FoldLineState { + int lineComment; + int packageImport; + constexpr explicit FoldLineState(int lineState) noexcept: + lineComment(lineState & DartLineStateMaskLineComment), + packageImport((lineState >> 1) & 1) { + } +}; + +// Options used for LexerDart +struct OptionsDart { + bool fold = false; +}; + +const char * const dartWordListDesc[] = { + "Primary keywords", + "Secondary keywords", + "Tertiary keywords", + "Global type definitions", + nullptr +}; + +struct OptionSetDart : public OptionSet<OptionsDart> { + OptionSetDart() { + DefineProperty("fold", &OptionsDart::fold); + + DefineWordListSets(dartWordListDesc); + } +}; + + +LexicalClass lexicalClasses[] = { + // Lexer DART SCLEX_DART SCE_DART_: + 0, "SCE_DART_DEFAULT", "default", "White space", + 1, "SCE_DART_COMMENTLINE", "comment line", "Comment: //", + 2, "SCE_DART_COMMENTLINEDOC", "comment line documentation", "Comment: ///", + 3, "SCE_DART_COMMENTBLOCK", "comment", "Comment: /* */", + 4, "SCE_DART_COMMENTBLOCKDOC", "comment documentation", "Comment: /** */", + 5, "SCE_DART_STRING_SQ", "literal string", "Single quoted string", + 6, "SCE_DART_STRING_DQ", "literal string", "Double quoted string", + 7, "SCE_DART_TRIPLE_STRING_SQ", "literal string multiline", "Single quoted multiline string", + 8, "SCE_DART_TRIPLE_STRING_DQ", "literal string multiline", "Double quoted multiline string", + 9, "SCE_DART_RAWSTRING_SQ", "literal string raw", "Single quoted raw string", + 10, "SCE_DART_RAWSTRING_DQ", "literal string raw", "Double quoted raw string", + 11, "SCE_DART_TRIPLE_RAWSTRING_SQ", "literal string multiline raw", "Single quoted multiline raw string", + 12, "SCE_DART_TRIPLE_RAWSTRING_DQ", "literal string multiline raw", "Double quoted multiline raw string", + 13, "SCE_DART_ESCAPECHAR", "literal string escapesequence", "Escape sequence", + 14, "SCE_DART_IDENTIFIER", "identifier", "Identifier", + 15, "SCE_DART_IDENTIFIER_STRING", "identifier interpolated", "Identifier following $ inside strings", + 16, "SCE_DART_OPERATOR", "operator", "Operator", + 17, "SCE_DART_OPERATOR_STRING", "operator interpolated", "Braces following $ inside string", + 18, "SCE_DART_SYMBOL_IDENTIFIER", "identifier symbol", "Symbol name introduced by #", + 19, "SCE_DART_SYMBOL_OPERATOR", "operator symbol", "Operator introduced by #", + 20, "SCE_DART_NUMBER", "literal numeric", "Number", + 21, "SCE_DART_KEY", "key", "Keys preceding ':' and named parameters", + 22, "SCE_DART_METADATA", "preprocessor", "Metadata introduced by @", + 23, "SCE_DART_KW_PRIMARY", "keyword", "Primary keywords", + 24, "SCE_DART_KW_SECONDARY", "identifier", "Secondary keywords", + 25, "SCE_DART_KW_TERTIARY", "identifier", "Tertiary keywords", + 26, "SCE_DART_KW_TYPE", "identifier", "Global types", +}; + +class LexerDart : public DefaultLexer { + WordList keywordsPrimary; + WordList keywordsSecondary; + WordList keywordsTertiary; + WordList keywordsTypes; + OptionsDart options; + OptionSetDart osDart; +public: + LexerDart(const char *languageName_, int language_) : + DefaultLexer(languageName_, language_, lexicalClasses, std::size(lexicalClasses)) { + } + // Deleted so LexerDart objects can not be copied. + LexerDart(const LexerDart &) = delete; + LexerDart(LexerDart &&) = delete; + void operator=(const LexerDart &) = delete; + void operator=(LexerDart &&) = delete; + ~LexerDart() override = default; + + void SCI_METHOD Release() override { + delete this; + } + int SCI_METHOD Version() const override { + return lvRelease5; + } + const char *SCI_METHOD PropertyNames() override { + return osDart.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) override { + return osDart.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) override { + return osDart.DescribeProperty(name); + } + Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override; + const char *SCI_METHOD PropertyGet(const char *key) override { + return osDart.PropertyGet(key); + } + const char *SCI_METHOD DescribeWordListSets() override { + return osDart.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 nullptr; + } + + void BacktrackToStart(const LexAccessor &styler, int stateMask, Sci_PositionU &startPos, Sci_Position &lengthDoc, int &initStyle); + Sci_PositionU LookbackNonWhite(LexAccessor &styler, Sci_PositionU startPos, int &chPrevNonWhite, int &stylePrevNonWhite); + + static ILexer5 *LexerFactoryDart() { + return new LexerDart("dart", SCLEX_DART); + } +}; + +Sci_Position SCI_METHOD LexerDart::PropertySet(const char *key, const char *val) { + if (osDart.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +Sci_Position SCI_METHOD LexerDart::WordListSet(int n, const char *wl) { + WordList *wordListN = nullptr; + switch (n) { + case 0: + wordListN = &keywordsPrimary; + break; + case 1: + wordListN = &keywordsSecondary; + break; + case 2: + wordListN = &keywordsTertiary; + break; + case 3: + wordListN = &keywordsTypes; + break; + default: + break; + } + Sci_Position firstModification = -1; + if (wordListN && wordListN->Set(wl)) { + firstModification = 0; + } + return firstModification; +} + +void LexerDart::BacktrackToStart(const LexAccessor &styler, int stateMask, Sci_PositionU &startPos, Sci_Position &lengthDoc, int &initStyle) { + const Sci_Position currentLine = styler.GetLine(startPos); + if (currentLine != 0) { + Sci_Position line = currentLine - 1; + int lineState = styler.GetLineState(line); + while ((lineState & stateMask) != 0 && line != 0) { + --line; + lineState = styler.GetLineState(line); + } + if ((lineState & stateMask) == 0) { + ++line; + } + if (line != currentLine) { + const Sci_PositionU endPos = startPos + lengthDoc; + startPos = (line == 0) ? 0 : styler.LineStart(line); + lengthDoc = endPos - startPos; + initStyle = (startPos == 0) ? 0 : styler.StyleAt(startPos - 1); + } + } +} + +Sci_PositionU LexerDart::LookbackNonWhite(LexAccessor &styler, Sci_PositionU startPos, int &chPrevNonWhite, int &stylePrevNonWhite) { + do { + --startPos; + const unsigned style = styler.StyleAt(startPos); + if (!IsSpaceEquiv(style)) { + stylePrevNonWhite = style; + chPrevNonWhite = static_cast<unsigned char>(styler[startPos]); + break; + } + } while (startPos != 0); + return startPos; +} + +void LexerDart::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess) { + Accessor styler(pAccess, nullptr); + + int lineStateLineType = 0; + int commentLevel = 0; // nested block comment level + + std::vector<InterpolatingState> interpolatingStack; + + int visibleChars = 0; + int chBefore = 0; + int chPrevNonWhite = 0; + EscapeSequence escSeq; + + if (startPos != 0) { + // backtrack to the line where interpolation starts + BacktrackToStart(styler, DartLineStateMaskInterpolation, startPos, lengthDoc, initStyle); + } + + StyleContext sc(startPos, lengthDoc, initStyle, styler); + if (sc.currentLine > 0) { + const int lineState = styler.GetLineState(sc.currentLine - 1); + commentLevel = lineState >> 4; + } + if (startPos == 0) { + if (sc.Match('#', '!')) { + // Shell Shebang at beginning of file + sc.SetState(SCE_DART_COMMENTLINE); + sc.Forward(); + lineStateLineType = DartLineStateMaskLineComment; + } + } else if (IsSpaceEquiv(initStyle)) { + LookbackNonWhite(styler, startPos, chPrevNonWhite, initStyle); + chBefore = chPrevNonWhite; + } + + while (sc.More()) { + switch (sc.state) { + case SCE_DART_OPERATOR: + case SCE_DART_OPERATOR_STRING: + sc.SetState(SCE_DART_DEFAULT); + break; + + case SCE_DART_NUMBER: + if (!IsDecimalNumber(sc.chPrev, sc.ch, sc.chNext)) { + sc.SetState(SCE_DART_DEFAULT); + } + break; + + case SCE_DART_IDENTIFIER: + case SCE_DART_IDENTIFIER_STRING: + case SCE_DART_METADATA: + case SCE_DART_SYMBOL_IDENTIFIER: + if (!IsDartIdentifierChar(sc.ch) || (sc.ch == '$' && sc.state == SCE_DART_IDENTIFIER_STRING)) { + if (sc.state == SCE_DART_METADATA || sc.state == SCE_DART_SYMBOL_IDENTIFIER) { + if (sc.ch == '.') { + const int state = sc.state; + sc.SetState(SCE_DART_OPERATOR); + sc.ForwardSetState(state); + continue; + } + } else { + char s[64]; + sc.GetCurrent(s, sizeof(s)); + const int state = sc.state; + if (state == SCE_DART_IDENTIFIER_STRING) { + sc.SetState(escSeq.outerState); + continue; + } else if (keywordsPrimary.InList(s)) { + sc.ChangeState(SCE_DART_KW_PRIMARY); + if (strcmp(s, "import") == 0 || strcmp(s, "part") == 0) { + if (visibleChars == sc.LengthCurrent()) { + lineStateLineType = DartLineStateMaskImport; + } + } + } else if (keywordsSecondary.InList(s)) { + sc.ChangeState(SCE_DART_KW_SECONDARY); + } else if (keywordsTertiary.InList(s)) { + sc.ChangeState(SCE_DART_KW_TERTIARY); + } else if (keywordsTypes.InList(s)) { + sc.ChangeState(SCE_DART_KW_TYPE); + } else if (state == SCE_DART_IDENTIFIER && sc.ch == ':') { + if (chBefore == ',' || chBefore == '{' || chBefore == '(') { + sc.ChangeState(SCE_DART_KEY); // map key or named parameter + } + } + } + + sc.SetState(SCE_DART_DEFAULT); + } + break; + + case SCE_DART_SYMBOL_OPERATOR: + if (!IsDefinableOperator(sc.ch)) { + sc.SetState(SCE_DART_DEFAULT); + } + break; + + case SCE_DART_COMMENTLINE: + case SCE_DART_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_DART_DEFAULT); + } + break; + + case SCE_DART_COMMENTBLOCK: + case SCE_DART_COMMENTBLOCKDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + --commentLevel; + if (commentLevel == 0) { + sc.ForwardSetState(SCE_DART_DEFAULT); + } + } else if (sc.Match('/', '*')) { + sc.Forward(); + ++commentLevel; + } + break; + + case SCE_DART_STRING_SQ: + case SCE_DART_STRING_DQ: + case SCE_DART_TRIPLE_STRING_SQ: + case SCE_DART_TRIPLE_STRING_DQ: + case SCE_DART_RAWSTRING_SQ: + case SCE_DART_RAWSTRING_DQ: + case SCE_DART_TRIPLE_RAWSTRING_SQ: + case SCE_DART_TRIPLE_RAWSTRING_DQ: + if (sc.atLineStart && !IsTripleString(sc.state)) { + sc.SetState(SCE_DART_DEFAULT); + } else if (sc.ch == '\' && !IsRaw(sc.state)) { + if (escSeq.resetEscapeState(sc.state, sc.chNext)) { + sc.SetState(SCE_DART_ESCAPECHAR); + sc.Forward(); + if (sc.Match('u', '{')) { + escSeq.brace = true; + escSeq.digitsLeft = 7; // Unicode code point + sc.Forward(); + } + } + } else if (sc.ch == '$' && !IsRaw(sc.state)) { + escSeq.outerState = sc.state; + sc.SetState(SCE_DART_OPERATOR_STRING); + sc.Forward(); + if (sc.ch == '{') { + interpolatingStack.push_back({escSeq.outerState, 1}); + } else if (sc.ch != '$' && IsDartIdentifierStart(sc.ch)) { + sc.SetState(SCE_DART_IDENTIFIER_STRING); + } else { // error + sc.SetState(escSeq.outerState); + continue; + } + } else if (sc.ch == GetStringQuote(sc.state) && + (!IsTripleString(sc.state) || (sc.Match(IsDoubleQuoted(sc.state) ? R"(""")" : R"(''')")))) { + if (IsTripleString(sc.state)) { + sc.Forward(2); + } + sc.Forward(); + sc.SetState(SCE_DART_DEFAULT); + } + break; + + case SCE_DART_ESCAPECHAR: + if (escSeq.atEscapeEnd(sc.ch)) { + if (escSeq.brace && sc.ch == '}') { + sc.Forward(); + } + sc.SetState(escSeq.outerState); + continue; + } + break; + } + + if (sc.state == SCE_DART_DEFAULT) { + if (sc.ch == '/' && (sc.chNext == '/' || sc.chNext == '*')) { + const int chNext = sc.chNext; + sc.SetState((chNext == '/') ? SCE_DART_COMMENTLINE : SCE_DART_COMMENTBLOCK); + sc.Forward(2); + if (sc.ch == chNext && sc.chNext != chNext) { + if (sc.state == SCE_DART_COMMENTLINE) { + sc.ChangeState(SCE_DART_COMMENTLINEDOC); + } else { + sc.ChangeState(SCE_DART_COMMENTBLOCKDOC); + } + } + if (chNext == '/') { + if (visibleChars == 0) { + lineStateLineType = DartLineStateMaskLineComment; + } + } else { + commentLevel = 1; + } + continue; + } + if (sc.ch == 'r' && (sc.chNext == ''' || sc.chNext == '"')) { + sc.SetState((sc.chNext == ''') ? SCE_DART_RAWSTRING_SQ : SCE_DART_RAWSTRING_DQ); + sc.Forward(2); + if (sc.chPrev == ''' && sc.Match(''', ''')) { + sc.ChangeState(SCE_DART_TRIPLE_RAWSTRING_SQ); + sc.Forward(2); + } else if (sc.chPrev == '"' && sc.Match('"', '"')) { + sc.ChangeState(SCE_DART_TRIPLE_RAWSTRING_DQ); + sc.Forward(2); + } + continue; + } + if (sc.ch == '"') { + if (sc.Match(R"(""")")) { + sc.SetState(SCE_DART_TRIPLE_STRING_DQ); + sc.Forward(2); + } else { + chBefore = chPrevNonWhite; + sc.SetState(SCE_DART_STRING_DQ); + } + } else if (sc.ch == ''') { + if (sc.Match(R"(''')")) { + sc.SetState(SCE_DART_TRIPLE_STRING_SQ); + sc.Forward(2); + } else { + chBefore = chPrevNonWhite; + sc.SetState(SCE_DART_STRING_SQ); + } + } else if (IsNumberStart(sc.ch, sc.chNext)) { + sc.SetState(SCE_DART_NUMBER); + } else if ((sc.ch == '@' || sc.ch == '#') && IsDartIdentifierStart(sc.chNext)) { + sc.SetState((sc.ch == '@') ? SCE_DART_METADATA : SCE_DART_SYMBOL_IDENTIFIER); + } else if (IsDartIdentifierStart(sc.ch)) { + chBefore = chPrevNonWhite; + sc.SetState(SCE_DART_IDENTIFIER); + } else if (sc.ch == '#' && IsDefinableOperator(sc.chNext)) { + sc.SetState(SCE_DART_SYMBOL_OPERATOR); + } else if (IsAGraphic(sc.ch)) { + sc.SetState(SCE_DART_OPERATOR); + if (!interpolatingStack.empty() && AnyOf(sc.ch, '{', '}')) { + InterpolatingState ¤t = interpolatingStack.back(); + if (sc.ch == '{') { + current.braceCount += 1; + } else { + current.braceCount -= 1; + if (current.braceCount == 0) { + sc.ChangeState(SCE_DART_OPERATOR_STRING); + sc.ForwardSetState(current.state); + interpolatingStack.pop_back(); + continue; + } + } + } + } + } + + if (!isspacechar(sc.ch)) { + visibleChars++; + if (!IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + } + } + if (sc.atLineEnd) { + int lineState = (commentLevel << 4) | lineStateLineType; + if (!interpolatingStack.empty()) { + lineState |= DartLineStateMaskInterpolation; + } + styler.SetLineState(sc.currentLine, lineState); + lineStateLineType = 0; + visibleChars = 0; + } + sc.Forward(); + } + + sc.Complete(); +} + +void LexerDart::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess) { + if (!options.fold) + return; + + Accessor styler(pAccess, nullptr); + const Sci_PositionU endPos = startPos + lengthDoc; + Sci_Position lineCurrent = styler.GetLine(startPos); + while (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + initStyle = (startPos > 0) ? styler.StyleIndexAt(startPos) : 0; + if (initStyle != SCE_DART_COMMENTBLOCKDOC && initStyle != SCE_DART_COMMENTBLOCK && + initStyle != SCE_DART_TRIPLE_RAWSTRING_SQ && initStyle != SCE_DART_TRIPLE_RAWSTRING_DQ && + initStyle != SCE_DART_TRIPLE_STRING_SQ && initStyle != SCE_DART_TRIPLE_STRING_DQ) + break; + } + FoldLineState foldPrev(0); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) { + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + foldPrev = FoldLineState(styler.GetLineState(lineCurrent - 1)); + } + + int levelNext = levelCurrent; + FoldLineState foldCurrent(styler.GetLineState(lineCurrent)); + Sci_PositionU lineStartNext = styler.LineStart(lineCurrent + 1); + lineStartNext = std::min(lineStartNext, endPos); + + char chNext = styler[startPos]; + int styleNext = styler.StyleIndexAt(startPos); + int style = initStyle; + + while (startPos < endPos) { + const char ch = chNext; + const int stylePrev = style; + style = styleNext; + chNext = styler[++startPos]; + styleNext = styler.StyleIndexAt(startPos); + + switch (style) { + case SCE_DART_COMMENTBLOCKDOC: + case SCE_DART_COMMENTBLOCK: { + const int level = (ch == '/' && chNext == '*') ? 1 : ((ch == '*' && chNext == '/') ? -1 : 0); + if (level != 0) { + levelNext += level; + startPos++; + chNext = styler[startPos]; + styleNext = styler.StyleIndexAt(startPos); + } + } break; + + case SCE_DART_TRIPLE_RAWSTRING_SQ: + case SCE_DART_TRIPLE_RAWSTRING_DQ: + case SCE_DART_TRIPLE_STRING_SQ: + case SCE_DART_TRIPLE_STRING_DQ: + if (style != stylePrev && !AnyOf(stylePrev, SCE_DART_ESCAPECHAR, SCE_DART_OPERATOR_STRING, SCE_DART_IDENTIFIER_STRING)) { + levelNext++; + } + if (style != styleNext && !AnyOf(styleNext, SCE_DART_ESCAPECHAR, SCE_DART_OPERATOR_STRING, SCE_DART_IDENTIFIER_STRING)) { + levelNext--; + } + break; + + case SCE_DART_OPERATOR: + case SCE_DART_OPERATOR_STRING: + if (ch == '{' || ch == '[' || ch == '(') { + levelNext++; + } else if (ch == '}' || ch == ']' || ch == ')') { + levelNext--; + } + break; + } + + if (startPos == lineStartNext) { + const FoldLineState foldNext(styler.GetLineState(lineCurrent + 1)); + levelNext = std::max(levelNext, SC_FOLDLEVELBASE); + if (foldCurrent.lineComment) { + levelNext += foldNext.lineComment - foldPrev.lineComment; + } else if (foldCurrent.packageImport) { + levelNext += foldNext.packageImport - foldPrev.packageImport; + } + + const int levelUse = levelCurrent; + int lev = levelUse | (levelNext << 16); + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + styler.SetLevel(lineCurrent, lev); + + lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent + 1); + lineStartNext = std::min(lineStartNext, endPos); + levelCurrent = levelNext; + foldPrev = foldCurrent; + foldCurrent = foldNext; + } + } +} + +} // unnamed namespace end + +extern const LexerModule lmDart(SCLEX_DART, LexerDart::LexerFactoryDart, "dart", dartWordListDesc);
Modified: scintilla/lexilla/src/Lexilla.cxx 3 lines changed, 3 insertions(+), 0 deletions(-) =================================================================== @@ -59,6 +59,7 @@ extern LexerModule lmCPPNoCase; extern LexerModule lmCsound; extern LexerModule lmCss; extern LexerModule lmD; +extern LexerModule lmDart; extern LexerModule lmDataflex; extern LexerModule lmDiff; extern LexerModule lmDMAP; @@ -186,6 +187,7 @@ static void AddGeanyLexers() &lmCPP, &lmCss, &lmD, + &lmDart, &lmDiff, &lmErlang, &lmF77, @@ -273,6 +275,7 @@ void AddEachLexer() { &lmCsound, &lmCss, &lmD, + &lmDart, &lmDataflex, &lmDiff, &lmDMAP,
Modified: scintilla/scintilla_changes.patch 3 lines changed, 2 insertions(+), 1 deletions(-) =================================================================== @@ -62,7 +62,7 @@ diff --git scintilla/lexilla/src/Lexilla.cxx scintilla/lexilla/src/Lexilla.cxx index cd4b23617..af4a73db4 100644 --- scintilla/lexilla/src/Lexilla.cxx +++ scintilla/lexilla/src/Lexilla.cxx -@@ -167,8 +167,73 @@ +@@ -167,8 +167,74 @@
CatalogueModules catalogueLexilla;
@@ -84,6 +84,7 @@ index cd4b23617..af4a73db4 100644 + &lmCPP, + &lmCss, + &lmD, ++ &lmDart, + &lmDiff, + &lmErlang, + &lmF77,
Modified: src/editor.c 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -1321,6 +1321,7 @@ static gboolean lexer_has_braces(ScintillaObject *sci) case SCLEX_CIL: case SCLEX_CPP: case SCLEX_D: + case SCLEX_DART: case SCLEX_HTML: /* for PHP & JS */ case SCLEX_PHPSCRIPT: case SCLEX_PASCAL: /* for multiline comments? */ @@ -5148,6 +5149,7 @@ void editor_set_indentation_guides(GeanyEditor *editor) case SCLEX_OCTAVE: case SCLEX_RUST: case SCLEX_ZIG: + case SCLEX_DART: mode = SC_IV_LOOKBOTH; break;
Modified: src/filetypes.c 4 lines changed, 3 insertions(+), 1 deletions(-) =================================================================== @@ -194,6 +194,7 @@ static void init_builtin_filetypes(void) FT_INIT( PROLOG, NONE, "Prolog", NULL, SOURCE_FILE, COMPILED ); FT_INIT( NIM, NONE, "Nim", NULL, SOURCE_FILE, COMPILED ); FT_INIT( ZIG, NONE, "Zig", NULL, SOURCE_FILE, COMPILED ); + FT_INIT( DART, NONE, "Dart", NULL, SOURCE_FILE, COMPILED ); }
@@ -626,7 +627,8 @@ static GeanyFiletype *find_shebang(const gchar *utf8_filename, const gchar *line { "dmd", GEANY_FILETYPES_D }, { "wish", GEANY_FILETYPES_TCL }, { "node", GEANY_FILETYPES_JS }, - { "rust", GEANY_FILETYPES_RUST } + { "rust", GEANY_FILETYPES_RUST }, + { "dart", GEANY_FILETYPES_DART } }; gchar *tmp = g_path_get_basename(line + 2); gchar *basename_interpreter = tmp;
Modified: src/filetypes.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -114,6 +114,7 @@ typedef enum GEANY_FILETYPES_PROLOG, GEANY_FILETYPES_NIM, GEANY_FILETYPES_ZIG, + GEANY_FILETYPES_DART, /* ^ append items here */ GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */ }
Modified: src/highlighting.c 18 lines changed, 18 insertions(+), 0 deletions(-) =================================================================== @@ -1014,6 +1014,7 @@ void highlighting_init_styles(guint filetype_idx, GKeyFile *config, GKeyFile *co init_styleset_case(CONF); init_styleset_case(CSS); init_styleset_case(D); + init_styleset_case(DART); init_styleset_case(DIFF); init_styleset_case(LISP); init_styleset_case(ERLANG); @@ -1111,6 +1112,7 @@ void highlighting_set_styles(ScintillaObject *sci, GeanyFiletype *ft) styleset_case(CONF); styleset_case(CSS); styleset_case(D); + styleset_case(DART); styleset_case(DIFF); styleset_case(LISP); styleset_case(ERLANG); @@ -1693,6 +1695,16 @@ gboolean highlighting_is_string_style(gint lexer, gint style) style == SCE_ZIG_MULTISTRING || style == SCE_ZIG_CHARACTER || style == SCE_ZIG_ESCAPECHAR); + + case SCLEX_DART: + return (style == SCE_DART_STRING_SQ || + style == SCE_DART_STRING_DQ || + style == SCE_DART_TRIPLE_STRING_SQ || + style == SCE_DART_TRIPLE_STRING_DQ || + style == SCE_DART_RAWSTRING_SQ || + style == SCE_DART_RAWSTRING_DQ || + style == SCE_DART_TRIPLE_RAWSTRING_SQ || + style == SCE_DART_TRIPLE_RAWSTRING_DQ); } return FALSE; } @@ -1950,6 +1962,12 @@ gboolean highlighting_is_comment_style(gint lexer, gint style) return (style == SCE_ZIG_COMMENTLINE || style == SCE_ZIG_COMMENTLINEDOC || style == SCE_ZIG_COMMENTLINETOP); + + case SCLEX_DART: + return (style == SCE_DART_COMMENTLINE || + style == SCE_DART_COMMENTLINEDOC || + style == SCE_DART_COMMENTBLOCK || + style == SCE_DART_COMMENTBLOCKDOC); } return FALSE; }
Modified: src/highlightingmappings.h 42 lines changed, 42 insertions(+), 0 deletions(-) =================================================================== @@ -538,6 +538,48 @@ static const HLKeyword highlighting_keywords_D[] = #define highlighting_properties_D EMPTY_PROPERTIES
+/* DART */ +#define highlighting_lexer_DART SCLEX_DART +static const HLStyle highlighting_styles_DART[] = +{ + { SCE_DART_DEFAULT, "default", FALSE }, + { SCE_DART_COMMENTLINE, "commentline", FALSE }, + { SCE_DART_COMMENTLINEDOC, "commentlinedoc", FALSE }, + { SCE_DART_COMMENTBLOCK, "commentblock", FALSE }, + { SCE_DART_COMMENTBLOCKDOC, "commentblockdoc", FALSE }, + { SCE_DART_STRING_SQ, "stringsq", FALSE }, + { SCE_DART_STRING_DQ, "stringdq", FALSE }, + { SCE_DART_TRIPLE_STRING_SQ, "triplestringsq", FALSE }, + { SCE_DART_TRIPLE_STRING_DQ, "triplestringdq", FALSE }, + { SCE_DART_RAWSTRING_SQ, "rawstringsq", FALSE }, + { SCE_DART_RAWSTRING_DQ, "rawstringdq", FALSE }, + { SCE_DART_TRIPLE_RAWSTRING_SQ, "triplerawstringsq", FALSE }, + { SCE_DART_TRIPLE_RAWSTRING_DQ, "triplerawstringdq", FALSE }, + { SCE_DART_ESCAPECHAR, "escapechar", FALSE }, + { SCE_DART_IDENTIFIER, "identifier", FALSE }, + { SCE_DART_IDENTIFIER_STRING, "identifierstring", FALSE }, + { SCE_DART_OPERATOR, "operator", FALSE }, + { SCE_DART_OPERATOR_STRING, "operatorstring", FALSE }, + { SCE_DART_SYMBOL_IDENTIFIER, "symbolidentifier", FALSE }, + { SCE_DART_SYMBOL_OPERATOR, "symboloperator", FALSE }, + { SCE_DART_NUMBER, "number", FALSE }, + { SCE_DART_KEY, "key", FALSE }, + { SCE_DART_METADATA, "metadata", FALSE }, + { SCE_DART_KW_PRIMARY, "kwprimary", FALSE }, + { SCE_DART_KW_SECONDARY, "kwsecondary", FALSE }, + { SCE_DART_KW_TERTIARY, "kwtertiary", FALSE }, + { SCE_DART_KW_TYPE, "kwtype", FALSE }, +}; +static const HLKeyword highlighting_keywords_DART[] = +{ + { 0, "primary", FALSE }, + { 1, "secondary", FALSE }, + { 2, "tertiary", FALSE }, + { 3, "types", FALSE }, +}; +#define highlighting_properties_DART EMPTY_PROPERTIES + + /* Diff */ #define highlighting_lexer_DIFF SCLEX_DIFF static const HLStyle highlighting_styles_DIFF[] =
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).