diff options
-rw-r--r-- | lexers/LexOthers.cxx | 112 | ||||
-rw-r--r-- | lexers/LexPO.cxx | 150 | ||||
-rw-r--r-- | src/Catalogue.cxx | 2 | ||||
-rw-r--r-- | win32/scintilla.mak | 3 | ||||
-rw-r--r-- | win32/scintilla_vc6.mak | 3 |
5 files changed, 157 insertions, 113 deletions
diff --git a/lexers/LexOthers.cxx b/lexers/LexOthers.cxx index fb8c97b31..d27c83545 100644 --- a/lexers/LexOthers.cxx +++ b/lexers/LexOthers.cxx @@ -614,117 +614,6 @@ static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Ac } while (static_cast<int>(startPos) + length > curLineStart); } -// see https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files for the syntax reference -// some details are taken from the GNU msgfmt behavior (like that indent is allows in front of lines) -static void ColourisePoDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { - StyleContext sc(startPos, length, initStyle, styler); - bool escaped = false; - int curLine = styler.GetLine(startPos); - // the line state holds the last state on or before the line that isn't the default style - int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : SCE_PO_DEFAULT; - - for (; sc.More(); sc.Forward()) { - // whether we should leave a state - switch (sc.state) { - case SCE_PO_COMMENT: - case SCE_PO_PROGRAMMER_COMMENT: - case SCE_PO_REFERENCE: - case SCE_PO_FLAGS: - case SCE_PO_FUZZY: - if (sc.atLineEnd) - sc.SetState(SCE_PO_DEFAULT); - else if (sc.state == SCE_PO_FLAGS && sc.Match("fuzzy")) - // here we behave like the previous parser, but this should probably be highlighted - // on its own like a keyword rather than changing the whole flags style - sc.ChangeState(SCE_PO_FUZZY); - break; - - case SCE_PO_MSGCTXT: - case SCE_PO_MSGID: - case SCE_PO_MSGSTR: - if (isspacechar(sc.ch)) - sc.SetState(SCE_PO_DEFAULT); - break; - - case SCE_PO_ERROR: - if (sc.atLineEnd) - sc.SetState(SCE_PO_DEFAULT); - break; - - case SCE_PO_MSGCTXT_TEXT: - case SCE_PO_MSGID_TEXT: - case SCE_PO_MSGSTR_TEXT: - if (sc.atLineEnd) { // invalid inside a string - if (sc.state == SCE_PO_MSGCTXT_TEXT) - sc.ChangeState(SCE_PO_MSGCTXT_TEXT_EOL); - else if (sc.state == SCE_PO_MSGID_TEXT) - sc.ChangeState(SCE_PO_MSGID_TEXT_EOL); - else if (sc.state == SCE_PO_MSGSTR_TEXT) - sc.ChangeState(SCE_PO_MSGSTR_TEXT_EOL); - sc.SetState(SCE_PO_DEFAULT); - escaped = false; - } else { - if (escaped) - escaped = false; - else if (sc.ch == '\\') - escaped = true; - else if (sc.ch == '"') - sc.ForwardSetState(SCE_PO_DEFAULT); - } - break; - } - - // whether we should enter a new state - if (sc.state == SCE_PO_DEFAULT) { - // forward to the first non-white character on the line - bool atLineStart = sc.atLineStart; - if (atLineStart) { - while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch)) - sc.Forward(); - } - - if (atLineStart && sc.ch == '#') { - if (sc.chNext == '.') - sc.SetState(SCE_PO_PROGRAMMER_COMMENT); - else if (sc.chNext == ':') - sc.SetState(SCE_PO_REFERENCE); - else if (sc.chNext == ',') - sc.SetState(SCE_PO_FLAGS); - else if (sc.chNext == '|') - sc.SetState(SCE_PO_COMMENT); // previous untranslated string, no special style yet - else - sc.SetState(SCE_PO_COMMENT); - } else if (atLineStart && sc.Match("msgid")) { // includes msgid_plural - sc.SetState(SCE_PO_MSGID); - } else if (atLineStart && sc.Match("msgstr")) { // includes [] suffixes - sc.SetState(SCE_PO_MSGSTR); - } else if (atLineStart && sc.Match("msgctxt")) { - sc.SetState(SCE_PO_MSGCTXT); - } else if (sc.ch == '"') { - if (curLineState == SCE_PO_MSGCTXT || curLineState == SCE_PO_MSGCTXT_TEXT) - sc.SetState(SCE_PO_MSGCTXT_TEXT); - else if (curLineState == SCE_PO_MSGID || curLineState == SCE_PO_MSGID_TEXT) - sc.SetState(SCE_PO_MSGID_TEXT); - else if (curLineState == SCE_PO_MSGSTR || curLineState == SCE_PO_MSGSTR_TEXT) - sc.SetState(SCE_PO_MSGSTR_TEXT); - else - sc.SetState(SCE_PO_ERROR); - } else if (! isspacechar(sc.ch)) - sc.SetState(SCE_PO_ERROR); - - if (sc.state != SCE_PO_DEFAULT) - curLineState = sc.state; - } - - if (sc.atLineEnd) { - // Update the line state, so it can be seen by next line - curLine = styler.GetLine(sc.currentPos); - styler.SetLineState(curLine, curLineState); - } - } - sc.Complete(); -} - static inline bool isassignchar(unsigned char ch) { return (ch == '=') || (ch == ':'); } @@ -1537,7 +1426,6 @@ static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[ LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); -LexerModule lmPo(SCLEX_PO, ColourisePoDoc, "po", 0, emptyWordListDesc); LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc); LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc); diff --git a/lexers/LexPO.cxx b/lexers/LexPO.cxx new file mode 100644 index 000000000..d1ccda394 --- /dev/null +++ b/lexers/LexPO.cxx @@ -0,0 +1,150 @@ +// Scintilla source code edit control +/** @file LexPO.cxx + ** Lexer for GetText Translation (PO) files. + **/ +// Copyright 2012 by Colomban Wendling <ban@herbesfolles.org> +// The License.txt file describes the conditions under which this software may be distributed. + +// see https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files for the syntax reference +// some details are taken from the GNU msgfmt behavior (like that indent is allows in front of lines) + +// TODO: +// * add keywords for flags (fuzzy, c-format, ...) +// * highlight formats inside c-format strings (%s, %d, etc.) + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.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 void ColourisePODoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { + StyleContext sc(startPos, length, initStyle, styler); + bool escaped = false; + int curLine = styler.GetLine(startPos); + // the line state holds the last state on or before the line that isn't the default style + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : SCE_PO_DEFAULT; + + for (; sc.More(); sc.Forward()) { + // whether we should leave a state + switch (sc.state) { + case SCE_PO_COMMENT: + case SCE_PO_PROGRAMMER_COMMENT: + case SCE_PO_REFERENCE: + case SCE_PO_FLAGS: + case SCE_PO_FUZZY: + if (sc.atLineEnd) + sc.SetState(SCE_PO_DEFAULT); + else if (sc.state == SCE_PO_FLAGS && sc.Match("fuzzy")) + // here we behave like the previous parser, but this should probably be highlighted + // on its own like a keyword rather than changing the whole flags style + sc.ChangeState(SCE_PO_FUZZY); + break; + + case SCE_PO_MSGCTXT: + case SCE_PO_MSGID: + case SCE_PO_MSGSTR: + if (isspacechar(sc.ch)) + sc.SetState(SCE_PO_DEFAULT); + break; + + case SCE_PO_ERROR: + if (sc.atLineEnd) + sc.SetState(SCE_PO_DEFAULT); + break; + + case SCE_PO_MSGCTXT_TEXT: + case SCE_PO_MSGID_TEXT: + case SCE_PO_MSGSTR_TEXT: + if (sc.atLineEnd) { // invalid inside a string + if (sc.state == SCE_PO_MSGCTXT_TEXT) + sc.ChangeState(SCE_PO_MSGCTXT_TEXT_EOL); + else if (sc.state == SCE_PO_MSGID_TEXT) + sc.ChangeState(SCE_PO_MSGID_TEXT_EOL); + else if (sc.state == SCE_PO_MSGSTR_TEXT) + sc.ChangeState(SCE_PO_MSGSTR_TEXT_EOL); + sc.SetState(SCE_PO_DEFAULT); + escaped = false; + } else { + if (escaped) + escaped = false; + else if (sc.ch == '\\') + escaped = true; + else if (sc.ch == '"') + sc.ForwardSetState(SCE_PO_DEFAULT); + } + break; + } + + // whether we should enter a new state + if (sc.state == SCE_PO_DEFAULT) { + // forward to the first non-white character on the line + bool atLineStart = sc.atLineStart; + if (atLineStart) { + while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch)) + sc.Forward(); + } + + if (atLineStart && sc.ch == '#') { + if (sc.chNext == '.') + sc.SetState(SCE_PO_PROGRAMMER_COMMENT); + else if (sc.chNext == ':') + sc.SetState(SCE_PO_REFERENCE); + else if (sc.chNext == ',') + sc.SetState(SCE_PO_FLAGS); + else if (sc.chNext == '|') + sc.SetState(SCE_PO_COMMENT); // previous untranslated string, no special style yet + else + sc.SetState(SCE_PO_COMMENT); + } else if (atLineStart && sc.Match("msgid")) { // includes msgid_plural + sc.SetState(SCE_PO_MSGID); + } else if (atLineStart && sc.Match("msgstr")) { // includes [] suffixes + sc.SetState(SCE_PO_MSGSTR); + } else if (atLineStart && sc.Match("msgctxt")) { + sc.SetState(SCE_PO_MSGCTXT); + } else if (sc.ch == '"') { + if (curLineState == SCE_PO_MSGCTXT || curLineState == SCE_PO_MSGCTXT_TEXT) + sc.SetState(SCE_PO_MSGCTXT_TEXT); + else if (curLineState == SCE_PO_MSGID || curLineState == SCE_PO_MSGID_TEXT) + sc.SetState(SCE_PO_MSGID_TEXT); + else if (curLineState == SCE_PO_MSGSTR || curLineState == SCE_PO_MSGSTR_TEXT) + sc.SetState(SCE_PO_MSGSTR_TEXT); + else + sc.SetState(SCE_PO_ERROR); + } else if (! isspacechar(sc.ch)) + sc.SetState(SCE_PO_ERROR); + + if (sc.state != SCE_PO_DEFAULT) + curLineState = sc.state; + } + + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curLineState); + } + } + sc.Complete(); +} + +static const char *const poWordListDesc[] = { + 0 +}; + +LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", 0, poWordListDesc); diff --git a/src/Catalogue.cxx b/src/Catalogue.cxx index 2f752472b..cd69d814b 100644 --- a/src/Catalogue.cxx +++ b/src/Catalogue.cxx @@ -152,7 +152,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmPerl); LINK_LEXER(lmPHPSCRIPT); LINK_LEXER(lmPLM); - LINK_LEXER(lmPo); + LINK_LEXER(lmPO); LINK_LEXER(lmPOV); LINK_LEXER(lmPowerPro); LINK_LEXER(lmPowerShell); diff --git a/win32/scintilla.mak b/win32/scintilla.mak index e57da3c71..d7d8d3a30 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -146,6 +146,7 @@ LEXOBJS=\ $(DIR_O)\LexPB.obj \ $(DIR_O)\LexPerl.obj \ $(DIR_O)\LexPLM.obj \ + $(DIR_O)\LexPO.obj \ $(DIR_O)\LexPOV.obj \ $(DIR_O)\LexPowerPro.obj \ $(DIR_O)\LexPowerShell.obj \ @@ -408,6 +409,8 @@ $(DIR_O)\LexPerl.obj: ..\lexers\LexPerl.cxx $(LEX_HEADERS) $(DIR_O)\LexPLM.obj: ..\lexers\LexPLM.cxx $(LEX_HEADERS) +$(DIR_O)\LexPO.obj: ..\lexers\LexPO.cxx $(LEX_HEADERS) + $(DIR_O)\LexPOV.obj: ..\lexers\LexPOV.cxx $(LEX_HEADERS) $(DIR_O)\LexPowerPro.obj: ..\lexers\LexPowerPro.cxx $(LEX_HEADERS) diff --git a/win32/scintilla_vc6.mak b/win32/scintilla_vc6.mak index 2f900ab01..bfc9e6f18 100644 --- a/win32/scintilla_vc6.mak +++ b/win32/scintilla_vc6.mak @@ -143,6 +143,7 @@ LEXOBJS=\ $(DIR_O)\LexPB.obj \ $(DIR_O)\LexPerl.obj \ $(DIR_O)\LexPLM.obj \ + $(DIR_O)\LexPO.obj \ $(DIR_O)\LexPOV.obj \ $(DIR_O)\LexPowerPro.obj \ $(DIR_O)\LexPowerShell.obj \ @@ -402,6 +403,8 @@ $(DIR_O)\LexPerl.obj: ..\lexers\LexPerl.cxx $(LEX_HEADERS) $(DIR_O)\LexPLM.obj: ..\lexers\LexPLM.cxx $(LEX_HEADERS) +$(DIR_O)\LexPO.obj: ..\lexers\LexPO.cxx $(LEX_HEADERS) + $(DIR_O)\LexPOV.obj: ..\lexers\LexPOV.cxx $(LEX_HEADERS) $(DIR_O)\LexPowerPro.obj: ..\lexers\LexPowerPro.cxx $(LEX_HEADERS) |