diff --git a/data/Makefile.am b/data/Makefile.am index 0810225893..d677d4b46a 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -67,6 +67,7 @@ filetypes = \ filedefs/filetypes.rust \ filedefs/filetypes.Scala.conf \ filedefs/filetypes.sh \ + filedefs/filetypes.smalltalk \ filedefs/filetypes.sql \ filedefs/filetypes.Swift.conf \ filedefs/filetypes.TypeScript.conf \ diff --git a/data/filedefs/filetypes.smalltalk b/data/filedefs/filetypes.smalltalk new file mode 100644 index 0000000000..a45c6bdda4 --- /dev/null +++ b/data/filedefs/filetypes.smalltalk @@ -0,0 +1,56 @@ +# For complete documentation of this file, please see Geany's main documentation +[styling] +# Edit these in the colorscheme .conf file instead +default=default +special=operator +symbol=identifier_1 +assignment=operator +return=operator +number=number_1 +binary=operator +special_selector=keyword_3 +keyword_send=keyword_2 +global=class +self=keyword_1 +super=keyword_1 +nil=keyword_1 +bool=keyword_1 +comment=comment +string=string_1 +character=character + +[keywords] +# all items must be in one line +special_selector=ifTrue: ifFalse: whileTrue: whileFalse: ifNil: ifNotNil: whileTrue whileFalse repeat isNil notNil + +[settings] +# default extension used when saving files +extension=st + +# MIME type +mime_type=text/x-smalltalk + +# the following characters are these which a "word" can contains, see documentation +#wordchars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 + +# single comments, 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=4 +# 0 is spaces, 1 is tabs, 2 is tab & spaces +#type=1 diff --git a/data/filetype_extensions.conf b/data/filetype_extensions.conf index e1ff857e3a..965e5c10a8 100644 --- a/data/filetype_extensions.conf +++ b/data/filetype_extensions.conf @@ -65,6 +65,7 @@ Rust=*.rs; Ruby=*.rb;*.rhtml;*.ruby;*.gemspec;Gemfile;rakefile;Rakefile; Scala=*.scala;*.scl; Sh=*.sh;configure;configure.in;configure.in.in;configure.ac;*.ksh;*.mksh;*.zsh;*.ash;*.bash;.bashrc;bash.bashrc;.bash_*;bash_*;*.m4;PKGBUILD;*profile; +Smalltalk=*.st; SQL=*.sql; Swift=*.swift; Tcl=*.tcl;*.tk;*.wish;*.exp; diff --git a/scintilla/Makefile.am b/scintilla/Makefile.am index d7a179247a..be8ed0ad83 100644 --- a/scintilla/Makefile.am +++ b/scintilla/Makefile.am @@ -42,6 +42,7 @@ lexers/LexPO.cxx \ lexers/LexR.cxx \ lexers/LexRuby.cxx \ lexers/LexRust.cxx \ +lexers/LexSmalltalk.cxx \ lexers/LexSQL.cxx \ lexers/LexTCL.cxx \ lexers/LexTxt2tags.cxx \ diff --git a/scintilla/lexers/LexSmalltalk.cxx b/scintilla/lexers/LexSmalltalk.cxx new file mode 100644 index 0000000000..bd146d59c2 --- /dev/null +++ b/scintilla/lexers/LexSmalltalk.cxx @@ -0,0 +1,324 @@ +// Scintilla source code edit control +/** @file LexSmalltalk.cxx + ** Lexer for Smalltalk language. + ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com + **/ +// Copyright 1998-2002 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#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" + +using namespace Scintilla; + +/* +| lexTable classificationBlock charClasses | +charClasses := #(#DecDigit #Letter #Special #Upper #BinSel). +lexTable := ByteArray new: 128. +classificationBlock := [ :charClass :chars | + | flag | + flag := 1 bitShift: (charClasses indexOf: charClass) - 1. + chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]]. + +classificationBlock + value: #DecDigit value: '0123456789'; + value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + value: #Special value: '()[]{};.^:'; + value: #BinSel value: '~@%&*-+=|\/,<>?!'; + value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + +((String new: 500) streamContents: [ :stream | + stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'. + lexTable keysAndValuesDo: [ :index :value | + ((index - 1) rem: 16) == 0 ifTrue: [ + stream crLf; tab] + ifFalse: [ + stream space]. + stream print: value. + index ~= 256 ifTrue: [ + stream nextPut: $,]]. + stream crLf; nextPutAll: '};'; crLf. + + charClasses keysAndValuesDo: [ :index :name | + stream + crLf; + nextPutAll: ( + ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}') + expandMacrosWith: name with: (1 bitShift: (index - 1))) + ]]) edit +*/ + +// autogenerated {{{{ + +static int ClassificationTable[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16, + 16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0, +}; + +static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);} +static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);} +static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);} +static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);} +static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);} +// autogenerated }}}} + +static inline bool isAlphaNumeric(int ch) { + return isDecDigit(ch) || isLetter(ch); +} + +static inline bool isDigitOfRadix(int ch, int radix) +{ + if (isDecDigit(ch)) + return (ch - '0') < radix; + else if (!isUpper(ch)) + return false; + else + return (ch - 'A' + 10) < radix; +} + +static inline void skipComment(StyleContext& sc) +{ + while (sc.More() && sc.ch != '\"') + sc.Forward(); +} + +static inline void skipString(StyleContext& sc) +{ + while (sc.More()) { + if (sc.ch == '\'') { + if (sc.chNext != '\'') + return; + sc.Forward(); + } + sc.Forward(); + } +} + +static void handleHash(StyleContext& sc) +{ + if (isSpecial(sc.chNext)) { + sc.SetState(SCE_ST_SPECIAL); + return; + } + + sc.SetState(SCE_ST_SYMBOL); + sc.Forward(); + if (sc.ch == '\'') { + sc.Forward(); + skipString(sc); + } + else { + if (isLetter(sc.ch)) { + while (isAlphaNumeric(sc.chNext) || sc.chNext == ':') + sc.Forward(); + } + else if (isBinSel(sc.ch)) { + while (isBinSel(sc.chNext)) + sc.Forward(); + } + } +} + +static inline void handleSpecial(StyleContext& sc) +{ + if (sc.ch == ':' && sc.chNext == '=') { + sc.SetState(SCE_ST_ASSIGN); + sc.Forward(); + } + else { + if (sc.ch == '^') + sc.SetState(SCE_ST_RETURN); + else + sc.SetState(SCE_ST_SPECIAL); + } +} + +static inline void skipInt(StyleContext& sc, int radix) +{ + while (isDigitOfRadix(sc.chNext, radix)) + sc.Forward(); +} + +static void handleNumeric(StyleContext& sc) +{ + char num[256]; + int nl; + int radix; + + sc.SetState(SCE_ST_NUMBER); + num[0] = static_cast(sc.ch); + nl = 1; + while (isDecDigit(sc.chNext)) { + num[nl++] = static_cast(sc.chNext); + sc.Forward(); + if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check + break; + } + if (sc.chNext == 'r') { + num[nl] = 0; + if (num[0] == '-') + radix = atoi(num + 1); + else + radix = atoi(num); + sc.Forward(); + if (sc.chNext == '-') + sc.Forward(); + skipInt(sc, radix); + } + else + radix = 10; + if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix)) + return; + sc.Forward(); + skipInt(sc, radix); + if (sc.chNext == 's') { + // ScaledDecimal + sc.Forward(); + while (isDecDigit(sc.chNext)) + sc.Forward(); + return; + } + else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q') + return; + sc.Forward(); + if (sc.chNext == '+' || sc.chNext == '-') + sc.Forward(); + skipInt(sc, radix); +} + +static inline void handleBinSel(StyleContext& sc) +{ + sc.SetState(SCE_ST_BINARY); + while (isBinSel(sc.chNext)) + sc.Forward(); +} + +static void handleLetter(StyleContext& sc, WordList* specialSelectorList) +{ + char ident[256]; + int il; + int state; + bool doubleColonPresent; + + sc.SetState(SCE_ST_DEFAULT); + + ident[0] = static_cast(sc.ch); + il = 1; + while (isAlphaNumeric(sc.chNext)) { + ident[il++] = static_cast(sc.chNext); + sc.Forward(); + if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check + break; + } + + if (sc.chNext == ':') { + doubleColonPresent = true; + ident[il++] = ':'; + sc.Forward(); + } + else + doubleColonPresent = false; + ident[il] = 0; + + if (specialSelectorList->InList(ident)) + state = SCE_ST_SPEC_SEL; + else if (doubleColonPresent) + state = SCE_ST_KWSEND; + else if (isUpper(ident[0])) + state = SCE_ST_GLOBAL; + else { + if (!strcmp(ident, "self")) + state = SCE_ST_SELF; + else if (!strcmp(ident, "super")) + state = SCE_ST_SUPER; + else if (!strcmp(ident, "nil")) + state = SCE_ST_NIL; + else if (!strcmp(ident, "true") || !strcmp(ident, "false")) + state = SCE_ST_BOOL; + else + state = SCE_ST_DEFAULT; + } + + sc.ChangeState(state); +} + +static void colorizeSmalltalkDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *wordLists[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + if (initStyle == SCE_ST_COMMENT) { + skipComment(sc); + if (sc.More()) + sc.Forward(); + } + else if (initStyle == SCE_ST_STRING) { + skipString(sc); + if (sc.More()) + sc.Forward(); + } + + for (; sc.More(); sc.Forward()) { + int ch; + + ch = sc.ch; + if (ch == '\"') { + sc.SetState(SCE_ST_COMMENT); + sc.Forward(); + skipComment(sc); + } + else if (ch == '\'') { + sc.SetState(SCE_ST_STRING); + sc.Forward(); + skipString(sc); + } + else if (ch == '#') + handleHash(sc); + else if (ch == '$') { + sc.SetState(SCE_ST_CHARACTER); + sc.Forward(); + } + else if (isSpecial(ch)) + handleSpecial(sc); + else if (isDecDigit(ch)) + handleNumeric(sc); + else if (isLetter(ch)) + handleLetter(sc, wordLists[0]); + else if (isBinSel(ch)) { + if (ch == '-' && isDecDigit(sc.chNext)) + handleNumeric(sc); + else + handleBinSel(sc); + } + else + sc.SetState(SCE_ST_DEFAULT); + } + sc.Complete(); +} + +static const char* const smalltalkWordListDesc[] = { + "Special selectors", + 0 +}; + +LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc); diff --git a/scintilla/scintilla_changes.patch b/scintilla/scintilla_changes.patch index d70b4451c5..c0b53aea2d 100644 --- a/scintilla/scintilla_changes.patch +++ b/scintilla/scintilla_changes.patch @@ -171,7 +171,7 @@ index ed47aa8..e58f1ab 100644 LINK_LEXER(lmRust); - LINK_LEXER(lmSAS); - LINK_LEXER(lmScriptol); -- LINK_LEXER(lmSmalltalk); + LINK_LEXER(lmSmalltalk); - LINK_LEXER(lmSML); - LINK_LEXER(lmSorc); - LINK_LEXER(lmSpecman); diff --git a/scintilla/src/Catalogue.cxx b/scintilla/src/Catalogue.cxx index 735836d940..428af4da7d 100644 --- a/scintilla/src/Catalogue.cxx +++ b/scintilla/src/Catalogue.cxx @@ -99,6 +99,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmR); LINK_LEXER(lmRuby); LINK_LEXER(lmRust); + LINK_LEXER(lmSmalltalk); LINK_LEXER(lmSQL); LINK_LEXER(lmTCL); LINK_LEXER(lmTxt2tags); diff --git a/src/filetypes.c b/src/filetypes.c index 0ea102ded0..3d2a1e3a33 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -186,6 +186,7 @@ static void init_builtin_filetypes(void) FT_INIT( COFFEESCRIPT, NONE, "CoffeeScript", NULL, SOURCE_FILE, SCRIPT ); FT_INIT( GO, GO, "Go", NULL, SOURCE_FILE, COMPILED ); FT_INIT( ZEPHIR, ZEPHIR, "Zephir", NULL, SOURCE_FILE, COMPILED ); + FT_INIT( SMALLTALK, NONE, "Smalltalk", NULL, SOURCE_FILE, SCRIPT ); } diff --git a/src/filetypes.h b/src/filetypes.h index 26ec855f9c..d7cfbd99ce 100644 --- a/src/filetypes.h +++ b/src/filetypes.h @@ -106,6 +106,7 @@ typedef enum GEANY_FILETYPES_GO, GEANY_FILETYPES_ZEPHIR, GEANY_FILETYPES_BIBTEX, + GEANY_FILETYPES_SMALLTALK, /* ^ append items here */ GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */ } diff --git a/src/highlighting.c b/src/highlighting.c index 30e897587a..efa86bb9ef 100644 --- a/src/highlighting.c +++ b/src/highlighting.c @@ -1064,6 +1064,7 @@ void highlighting_init_styles(guint filetype_idx, GKeyFile *config, GKeyFile *co init_styleset_case(RUBY); init_styleset_case(RUST); init_styleset_case(SH); + init_styleset_case(SMALLTALK); init_styleset_case(SQL); init_styleset_case(TCL); init_styleset_case(TXT2TAGS); @@ -1152,6 +1153,7 @@ void highlighting_set_styles(ScintillaObject *sci, GeanyFiletype *ft) styleset_case(RUBY); styleset_case(RUST); styleset_case(SH); + styleset_case(SMALLTALK); styleset_case(SQL); styleset_case(TCL); styleset_case(TXT2TAGS); diff --git a/src/highlightingmappings.h b/src/highlightingmappings.h index 726ab2e235..d62b7e24b9 100644 --- a/src/highlightingmappings.h +++ b/src/highlightingmappings.h @@ -1409,6 +1409,35 @@ static const HLKeyword highlighting_keywords_SH[] = #define highlighting_properties_SH EMPTY_PROPERTIES +/* SMALLTALK */ +#define highlighting_lexer_SMALLTALK SCLEX_SMALLTALK +static const HLStyle highlighting_styles_SMALLTALK[] = +{ + { SCE_ST_DEFAULT, "default", FALSE }, + { SCE_ST_SPECIAL, "special", FALSE }, + { SCE_ST_SYMBOL, "symbol", FALSE }, + { SCE_ST_ASSIGN, "assignment", FALSE }, + { SCE_ST_RETURN, "return", FALSE }, + { SCE_ST_NUMBER, "number", FALSE }, + { SCE_ST_BINARY, "binary", FALSE }, + { SCE_ST_SPEC_SEL, "special_selector", FALSE }, + { SCE_ST_KWSEND, "keyword_send", FALSE }, + { SCE_ST_GLOBAL, "global", FALSE }, + { SCE_ST_SELF, "self", FALSE }, + { SCE_ST_SUPER, "super", FALSE }, + { SCE_ST_NIL, "nil", FALSE }, + { SCE_ST_BOOL, "bool", FALSE }, + { SCE_ST_COMMENT, "comment", FALSE }, + { SCE_ST_STRING, "string", FALSE }, + { SCE_ST_CHARACTER, "character", FALSE } +}; +static const HLKeyword highlighting_keywords_SMALLTALK[] = +{ + { 0, "special_selector", FALSE } +}; +#define highlighting_properties_SMALLTALK EMPTY_PROPERTIES + + /* SQL */ #define highlighting_lexer_SQL SCLEX_SQL static const HLStyle highlighting_styles_SQL[] =