1 // Scintilla source code edit control
2 /** @file LexMatlab.cxx
4 ** Written by José Fonseca
6 ** Changes by Christoph Dalitz 2003/12/04:
7 ** - added support for Octave
8 ** - Strings can now be included both in single or double quotes
10 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
11 // The License.txt file describes the conditions under which this software may be distributed.
23 #include "StyleContext.h"
25 #include "Scintilla.h"
29 using namespace Scintilla
;
32 static bool IsMatlabCommentChar(int c
) {
36 static bool IsOctaveCommentChar(int c
) {
37 return (c
== '%' || c
== '#') ;
40 static bool IsMatlabComment(Accessor
&styler
, int pos
, int len
) {
41 return len
> 0 && IsMatlabCommentChar(styler
[pos
]) ;
44 static bool IsOctaveComment(Accessor
&styler
, int pos
, int len
) {
45 return len
> 0 && IsOctaveCommentChar(styler
[pos
]) ;
48 static inline bool IsAWordChar(const int ch
) {
49 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
52 static inline bool IsAWordStart(const int ch
) {
53 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
56 static void ColouriseMatlabOctaveDoc(
57 unsigned int startPos
, int length
, int initStyle
,
58 WordList
*keywordlists
[], Accessor
&styler
,
59 bool (*IsCommentChar
)(int)) {
61 WordList
&keywords
= *keywordlists
[0];
63 styler
.StartAt(startPos
);
65 bool transpose
= false;
67 StyleContext
sc(startPos
, length
, initStyle
, styler
);
69 for (; sc
.More(); sc
.Forward()) {
71 if (sc
.state
== SCE_MATLAB_OPERATOR
) {
72 if (sc
.chPrev
== '.') {
73 if (sc
.ch
== '*' || sc
.ch
== '/' || sc
.ch
== '\\' || sc
.ch
== '^') {
74 sc
.ForwardSetState(SCE_MATLAB_DEFAULT
);
76 } else if (sc
.ch
== '\'') {
77 sc
.ForwardSetState(SCE_MATLAB_DEFAULT
);
80 sc
.SetState(SCE_MATLAB_DEFAULT
);
83 sc
.SetState(SCE_MATLAB_DEFAULT
);
85 } else if (sc
.state
== SCE_MATLAB_KEYWORD
) {
86 if (!isalnum(sc
.ch
) && sc
.ch
!= '_') {
88 sc
.GetCurrentLowered(s
, sizeof(s
));
89 if (keywords
.InList(s
)) {
90 sc
.SetState(SCE_MATLAB_DEFAULT
);
93 sc
.ChangeState(SCE_MATLAB_IDENTIFIER
);
94 sc
.SetState(SCE_MATLAB_DEFAULT
);
98 } else if (sc
.state
== SCE_MATLAB_NUMBER
) {
99 if (!isdigit(sc
.ch
) && sc
.ch
!= '.'
100 && !(sc
.ch
== 'e' || sc
.ch
== 'E')
101 && !((sc
.ch
== '+' || sc
.ch
== '-') && (sc
.chPrev
== 'e' || sc
.chPrev
== 'E'))) {
102 sc
.SetState(SCE_MATLAB_DEFAULT
);
105 } else if (sc
.state
== SCE_MATLAB_STRING
) {
107 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
110 } else if (sc
.ch
== '\'') {
111 sc
.ForwardSetState(SCE_MATLAB_DEFAULT
);
113 } else if (sc
.state
== SCE_MATLAB_DOUBLEQUOTESTRING
) {
115 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
118 } else if (sc
.ch
== '\"') {
119 sc
.ForwardSetState(SCE_MATLAB_DEFAULT
);
121 } else if (sc
.state
== SCE_MATLAB_COMMENT
|| sc
.state
== SCE_MATLAB_COMMAND
) {
123 sc
.SetState(SCE_MATLAB_DEFAULT
);
128 if (sc
.state
== SCE_MATLAB_DEFAULT
) {
129 if (IsCommentChar(sc
.ch
)) {
130 sc
.SetState(SCE_MATLAB_COMMENT
);
131 } else if (sc
.ch
== '!' && sc
.chNext
!= '=' ) {
132 sc
.SetState(SCE_MATLAB_COMMAND
);
133 } else if (sc
.ch
== '\'') {
135 sc
.SetState(SCE_MATLAB_OPERATOR
);
137 sc
.SetState(SCE_MATLAB_STRING
);
139 } else if (sc
.ch
== '"') {
140 sc
.SetState(SCE_MATLAB_DOUBLEQUOTESTRING
);
141 } else if (isdigit(sc
.ch
) || (sc
.ch
== '.' && isdigit(sc
.chNext
))) {
142 sc
.SetState(SCE_MATLAB_NUMBER
);
143 } else if (isalpha(sc
.ch
)) {
144 sc
.SetState(SCE_MATLAB_KEYWORD
);
145 } else if (isoperator(static_cast<char>(sc
.ch
)) || sc
.ch
== '@' || sc
.ch
== '\\') {
146 if (sc
.ch
== ')' || sc
.ch
== ']') {
151 sc
.SetState(SCE_MATLAB_OPERATOR
);
160 static void ColouriseMatlabDoc(unsigned int startPos
, int length
, int initStyle
,
161 WordList
*keywordlists
[], Accessor
&styler
) {
162 ColouriseMatlabOctaveDoc(startPos
, length
, initStyle
, keywordlists
, styler
, IsMatlabCommentChar
);
165 static void ColouriseOctaveDoc(unsigned int startPos
, int length
, int initStyle
,
166 WordList
*keywordlists
[], Accessor
&styler
) {
167 ColouriseMatlabOctaveDoc(startPos
, length
, initStyle
, keywordlists
, styler
, IsOctaveCommentChar
);
170 static void FoldMatlabOctaveDoc(unsigned int startPos
, int length
, int,
171 WordList
*[], Accessor
&styler
,
172 bool (*IsComment
)(Accessor
&, int, int)) {
174 int endPos
= startPos
+ length
;
176 // Backtrack to previous line in case need to fix its fold status
177 int lineCurrent
= styler
.GetLine(startPos
);
179 if (lineCurrent
> 0) {
181 startPos
= styler
.LineStart(lineCurrent
);
185 int indentCurrent
= styler
.IndentAmount(lineCurrent
, &spaceFlags
, IsComment
);
186 char chNext
= styler
[startPos
];
187 for (int i
= startPos
; i
< endPos
; i
++) {
189 chNext
= styler
.SafeGetCharAt(i
+ 1);
191 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n') || (i
== endPos
)) {
192 int lev
= indentCurrent
;
193 int indentNext
= styler
.IndentAmount(lineCurrent
+ 1, &spaceFlags
, IsComment
);
194 if (!(indentCurrent
& SC_FOLDLEVELWHITEFLAG
)) {
195 // Only non whitespace lines can be headers
196 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext
& SC_FOLDLEVELNUMBERMASK
)) {
197 lev
|= SC_FOLDLEVELHEADERFLAG
;
198 } else if (indentNext
& SC_FOLDLEVELWHITEFLAG
) {
199 // Line after is blank so check the next - maybe should continue further?
201 int indentNext2
= styler
.IndentAmount(lineCurrent
+ 2, &spaceFlags2
, IsComment
);
202 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext2
& SC_FOLDLEVELNUMBERMASK
)) {
203 lev
|= SC_FOLDLEVELHEADERFLAG
;
207 indentCurrent
= indentNext
;
208 styler
.SetLevel(lineCurrent
, lev
);
214 static void FoldMatlabDoc(unsigned int startPos
, int length
, int initStyle
,
215 WordList
*keywordlists
[], Accessor
&styler
) {
216 FoldMatlabOctaveDoc(startPos
, length
, initStyle
, keywordlists
, styler
, IsMatlabComment
);
219 static void FoldOctaveDoc(unsigned int startPos
, int length
, int initStyle
,
220 WordList
*keywordlists
[], Accessor
&styler
) {
221 FoldMatlabOctaveDoc(startPos
, length
, initStyle
, keywordlists
, styler
, IsOctaveComment
);
224 static const char * const matlabWordListDesc
[] = {
229 static const char * const octaveWordListDesc
[] = {
234 LexerModule
lmMatlab(SCLEX_MATLAB
, ColouriseMatlabDoc
, "matlab", FoldMatlabDoc
, matlabWordListDesc
);
236 LexerModule
lmOctave(SCLEX_OCTAVE
, ColouriseOctaveDoc
, "octave", FoldOctaveDoc
, octaveWordListDesc
);