Upgraded to scintilla 3.2.3
[TortoiseGit.git] / ext / scintilla / lexers / LexPO.cxx
blobb72a366d5fc8aa10b713a96ae791487afa0758c7
1 // Scintilla source code edit control
2 /** @file LexPO.cxx
3 ** Lexer for GetText Translation (PO) files.
4 **/
5 // Copyright 2012 by Colomban Wendling <ban@herbesfolles.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 // see https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files for the syntax reference
9 // some details are taken from the GNU msgfmt behavior (like that indent is allows in front of lines)
11 // TODO:
12 // * add keywords for flags (fuzzy, c-format, ...)
13 // * highlight formats inside c-format strings (%s, %d, etc.)
14 // * style for previous untranslated string? ("#|" comment)
16 #include <stdlib.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <assert.h>
21 #include <ctype.h>
23 #include "ILexer.h"
24 #include "Scintilla.h"
25 #include "SciLexer.h"
27 #include "WordList.h"
28 #include "LexAccessor.h"
29 #include "Accessor.h"
30 #include "StyleContext.h"
31 #include "CharacterSet.h"
32 #include "LexerModule.h"
34 #ifdef SCI_NAMESPACE
35 using namespace Scintilla;
36 #endif
38 static void ColourisePODoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
39 StyleContext sc(startPos, length, initStyle, styler);
40 bool escaped = false;
41 int curLine = styler.GetLine(startPos);
42 // the line state holds the last state on or before the line that isn't the default style
43 int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : SCE_PO_DEFAULT;
45 for (; sc.More(); sc.Forward()) {
46 // whether we should leave a state
47 switch (sc.state) {
48 case SCE_PO_COMMENT:
49 case SCE_PO_PROGRAMMER_COMMENT:
50 case SCE_PO_REFERENCE:
51 case SCE_PO_FLAGS:
52 case SCE_PO_FUZZY:
53 if (sc.atLineEnd)
54 sc.SetState(SCE_PO_DEFAULT);
55 else if (sc.state == SCE_PO_FLAGS && sc.Match("fuzzy"))
56 // here we behave like the previous parser, but this should probably be highlighted
57 // on its own like a keyword rather than changing the whole flags style
58 sc.ChangeState(SCE_PO_FUZZY);
59 break;
61 case SCE_PO_MSGCTXT:
62 case SCE_PO_MSGID:
63 case SCE_PO_MSGSTR:
64 if (isspacechar(sc.ch))
65 sc.SetState(SCE_PO_DEFAULT);
66 break;
68 case SCE_PO_ERROR:
69 if (sc.atLineEnd)
70 sc.SetState(SCE_PO_DEFAULT);
71 break;
73 case SCE_PO_MSGCTXT_TEXT:
74 case SCE_PO_MSGID_TEXT:
75 case SCE_PO_MSGSTR_TEXT:
76 if (sc.atLineEnd) { // invalid inside a string
77 if (sc.state == SCE_PO_MSGCTXT_TEXT)
78 sc.ChangeState(SCE_PO_MSGCTXT_TEXT_EOL);
79 else if (sc.state == SCE_PO_MSGID_TEXT)
80 sc.ChangeState(SCE_PO_MSGID_TEXT_EOL);
81 else if (sc.state == SCE_PO_MSGSTR_TEXT)
82 sc.ChangeState(SCE_PO_MSGSTR_TEXT_EOL);
83 sc.SetState(SCE_PO_DEFAULT);
84 escaped = false;
85 } else {
86 if (escaped)
87 escaped = false;
88 else if (sc.ch == '\\')
89 escaped = true;
90 else if (sc.ch == '"')
91 sc.ForwardSetState(SCE_PO_DEFAULT);
93 break;
96 // whether we should enter a new state
97 if (sc.state == SCE_PO_DEFAULT) {
98 // forward to the first non-white character on the line
99 bool atLineStart = sc.atLineStart;
100 if (atLineStart) {
101 while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch))
102 sc.Forward();
105 if (atLineStart && sc.ch == '#') {
106 if (sc.chNext == '.')
107 sc.SetState(SCE_PO_PROGRAMMER_COMMENT);
108 else if (sc.chNext == ':')
109 sc.SetState(SCE_PO_REFERENCE);
110 else if (sc.chNext == ',')
111 sc.SetState(SCE_PO_FLAGS);
112 else
113 sc.SetState(SCE_PO_COMMENT);
114 } else if (atLineStart && sc.Match("msgid")) { // includes msgid_plural
115 sc.SetState(SCE_PO_MSGID);
116 } else if (atLineStart && sc.Match("msgstr")) { // includes [] suffixes
117 sc.SetState(SCE_PO_MSGSTR);
118 } else if (atLineStart && sc.Match("msgctxt")) {
119 sc.SetState(SCE_PO_MSGCTXT);
120 } else if (sc.ch == '"') {
121 if (curLineState == SCE_PO_MSGCTXT || curLineState == SCE_PO_MSGCTXT_TEXT)
122 sc.SetState(SCE_PO_MSGCTXT_TEXT);
123 else if (curLineState == SCE_PO_MSGID || curLineState == SCE_PO_MSGID_TEXT)
124 sc.SetState(SCE_PO_MSGID_TEXT);
125 else if (curLineState == SCE_PO_MSGSTR || curLineState == SCE_PO_MSGSTR_TEXT)
126 sc.SetState(SCE_PO_MSGSTR_TEXT);
127 else
128 sc.SetState(SCE_PO_ERROR);
129 } else if (! isspacechar(sc.ch))
130 sc.SetState(SCE_PO_ERROR);
132 if (sc.state != SCE_PO_DEFAULT)
133 curLineState = sc.state;
136 if (sc.atLineEnd) {
137 // Update the line state, so it can be seen by next line
138 curLine = styler.GetLine(sc.currentPos);
139 styler.SetLineState(curLine, curLineState);
142 sc.Complete();
145 static const char *const poWordListDesc[] = {
149 LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", 0, poWordListDesc);