Neil Hodgson wrote:
In LexCPP, the IsStateWord function is unused.
So are IsStateComment and IsStateString, presents in the latest version
of LexCPP. I don't know what are these functions, they can be old
vestigal code...
In a list of
#include lines, every second line is wrongly styled.
Uh? They look fine for me... Either in <foo> or "bar" style.
Oh, if I put styling.within.preprocessor=0, I can see this...
I always have styling.within.preprocessor=1, that's why this flag was
created...
OK, I believe I found what was wrong... I tested sc.atLineEnd, but
unlike the similar tests in this lexer, I forgot to reset visibleChars
to 0. I also added the PREPROCESSOR state to the list of initStyle that
must not leak...
This is on
Windows with CR+LF line ends.
http://scintilla.sourceforge.net/AlternatingIncludes.png
The LexLua changes look OK.
Actually, it has a similar problem (initStyle), but preprocessors are a
bit out of fashion in Lua...
In the properties files, it is hard to untangle the generically
useful parts, such as better descriptions of lexical states, from
personal preferences.
Yes, sorry, it was mostly provided for the list of keywords.
And, indeed, for the more detailled comments.
Speaking of personal preference, I think you should remove the
# tpl is X and Mail specific
comment in html.properties, "X and Mail" was my previous employer...
tpl is probably still a valid (read "quite common") extension for html.
The ECMAScript standard does not list true and
false as keywords but as literals.
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
I wasn't sure what you meant by literals...
Well, Netscape (inventor of JS) agrees:
http://wp.netscape.com/eng/mozilla/3.0/handbook/javascript/ident.htm
I suppose null is also a literal, although Netscape writes:
"null, a special keyword denoting a null value"...
I removed true and false from my list of keywords, although I still find
funny to see them like the other identifiers...
I put them in keywords2:
keywords2.*.js=true false null
but alas, it won't work in HTML or XML (SVG...).
--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --
// Scintilla source code edit control
/** @file LexCPP.cxx
** Lexer for C++, C, Java, and JavaScript.
**/
// Copyright 1998-2005 by Neil Hodgson <[EMAIL PROTECTED]>
// The License.txt file describes the conditions under which this software may
be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
#define KEYWORD_BOXHEADER 1
#define KEYWORD_FOLDCONTRACTED 2
static bool IsOKBeforeRE(int ch) {
return (ch == '(') || (ch == '=') || (ch == ',');
}
static inline bool IsAWordChar(int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}
static inline bool IsAWordStart(int ch) {
return (ch < 0x80) && (isalpha(ch) || ch == '_');
}
static inline bool IsADoxygenChar(int ch) {
return (islower(ch) || ch == '$' || ch == '@' ||
ch == '\\' || ch == '&' || ch == '<' ||
ch == '>' || ch == '#' || ch == '{' ||
ch == '}' || ch == '[' || ch == ']');
}
static void ColouriseCppDoc(
unsigned int startPos,
int length,
int initStyle,
WordList *keywordlists[],
Accessor &styler,
bool caseSensitive) {
WordList &keywords = *keywordlists[0];
WordList &keywords2 = *keywordlists[1];
WordList &keywords3 = *keywordlists[2];
WordList &keywords4 = *keywordlists[3];
bool stylingWithinPreprocessor =
styler.GetPropertyInt("styling.within.preprocessor") != 0;
int chPrevNonWhite = ' ';
int visibleChars = 0;
bool lastWordWasUUID = false;
// Do not leak onto next line
if (initStyle == SCE_C_STRINGEOL ||
initStyle == SCE_C_COMMENTLINE ||
initStyle == SCE_C_COMMENTLINEDOC ||
initStyle == SCE_C_PREPROCESSOR) {
initStyle = SCE_C_DEFAULT;
}
StyleContext sc(startPos, length, initStyle, styler);
for (; sc.More(); sc.Forward()) {
if (sc.atLineStart && (sc.state == SCE_C_STRING)) {
// Prevent SCE_C_STRINGEOL from leaking back to
previous line
sc.SetState(SCE_C_STRING);
}
// Handle line continuation generically.
if (sc.ch == '\\') {
if (sc.chNext == '\n' || sc.chNext == '\r') {
sc.Forward();
if (sc.ch == '\r' && sc.chNext == '\n') {
sc.Forward();
}
continue;
}
}
// Determine if the current state should terminate.
if (sc.state == SCE_C_OPERATOR) {
sc.SetState(SCE_C_DEFAULT);
} else if (sc.state == SCE_C_NUMBER) {
// We accept almost anything because of hex. and number
suffixes
if (!IsAWordChar(sc.ch)) {
sc.SetState(SCE_C_DEFAULT);
}
} else if (sc.state == SCE_C_IDENTIFIER) {
if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
char s[100];
if (caseSensitive) {
sc.GetCurrent(s, sizeof(s));
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
if (keywords.InList(s)) {
lastWordWasUUID = strcmp(s, "uuid") ==
0;
sc.ChangeState(SCE_C_WORD);
} else if (keywords2.InList(s)) {
sc.ChangeState(SCE_C_WORD2);
} else if (keywords4.InList(s)) {
sc.ChangeState(SCE_C_GLOBALCLASS);
}
sc.SetState(SCE_C_DEFAULT);
}
} else if (sc.state == SCE_C_PREPROCESSOR) {
if (stylingWithinPreprocessor) {
if (IsASpace(sc.ch)) {
sc.SetState(SCE_C_DEFAULT);
}
} else {
if ((sc.atLineEnd)) {
sc.ForwardSetState(SCE_C_DEFAULT);
} else if (sc.Match('/', '*') || sc.Match('/',
'/')) {
sc.SetState(SCE_C_DEFAULT);
}
}
} else if (sc.state == SCE_C_COMMENT) {
if (sc.Match('*', '/')) {
sc.Forward();
sc.ForwardSetState(SCE_C_DEFAULT);
}
} else if (sc.state == SCE_C_COMMENTDOC) {
if (sc.Match('*', '/')) {
sc.Forward();
sc.ForwardSetState(SCE_C_DEFAULT);
} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc
and Doxygen support
// Verify that we have the conditions to mark a
comment-doc-keyword
if ((IsASpace(sc.chPrev) || sc.chPrev == '*')
&& (!IsASpace(sc.chNext))) {
sc.SetState(SCE_C_COMMENTDOCKEYWORD);
}
}
} else if (sc.state == SCE_C_COMMENTLINE || sc.state ==
SCE_C_COMMENTLINEDOC) {
if (sc.atLineEnd) {
sc.ForwardSetState(SCE_C_DEFAULT);
}
} else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
if (sc.Match('*', '/')) {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
sc.Forward();
sc.ForwardSetState(SCE_C_DEFAULT);
} else if (!IsADoxygenChar(sc.ch)) {
char s[100];
if (caseSensitive) {
sc.GetCurrent(s, sizeof(s));
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
if (!isspace(sc.ch) || !keywords3.InList(s +
1)) {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
}
sc.SetState(SCE_C_COMMENTDOC);
}
} else if (sc.state == SCE_C_STRING) {
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' ||
sc.chNext == '\\') {
sc.Forward();
}
} else if (sc.ch == '\"') {
sc.ForwardSetState(SCE_C_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_C_STRINGEOL);
sc.ForwardSetState(SCE_C_DEFAULT);
}
} else if (sc.state == SCE_C_CHARACTER) {
if (sc.atLineEnd) {
sc.ChangeState(SCE_C_STRINGEOL);
sc.ForwardSetState(SCE_C_DEFAULT);
} else if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' ||
sc.chNext == '\\') {
sc.Forward();
}
} else if (sc.ch == '\'') {
sc.ForwardSetState(SCE_C_DEFAULT);
}
} else if (sc.state == SCE_C_REGEX) {
if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
sc.ForwardSetState(SCE_C_DEFAULT);
} else if (sc.ch == '\\') {
// Gobble up the quoted character
if (sc.chNext == '\\' || sc.chNext == '/') {
sc.Forward();
}
}
} else if (sc.state == SCE_C_VERBATIM) {
if (sc.ch == '\"') {
if (sc.chNext == '\"') {
sc.Forward();
} else {
sc.ForwardSetState(SCE_C_DEFAULT);
}
}
} else if (sc.state == SCE_C_UUID) {
if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
sc.SetState(SCE_C_DEFAULT);
}
}
// Determine if a new state should be entered.
if (sc.atLineStart) {
visibleChars = 0;
}
if (sc.state == SCE_C_DEFAULT) {
if (sc.Match('@', '\"')) {
sc.SetState(SCE_C_VERBATIM);
sc.Forward();
} else if (IsADigit(sc.ch) || (sc.ch == '.' &&
IsADigit(sc.chNext))) {
if (lastWordWasUUID) {
sc.SetState(SCE_C_UUID);
lastWordWasUUID = false;
} else {
sc.SetState(SCE_C_NUMBER);
}
} else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
if (lastWordWasUUID) {
sc.SetState(SCE_C_UUID);
lastWordWasUUID = false;
} else {
sc.SetState(SCE_C_IDENTIFIER);
}
} else if (sc.Match('/', '*')) {
if (sc.Match("/**") || sc.Match("/*!")) {
// Support of Qt/Doxygen doc. style
sc.SetState(SCE_C_COMMENTDOC);
} else {
sc.SetState(SCE_C_COMMENT);
}
sc.Forward(); // Eat the * so it isn't used
for the end of the comment
} else if (sc.Match('/', '/')) {
if ((sc.Match("///") && !sc.Match("////")) ||
sc.Match("//!"))
// Support of Qt/Doxygen doc. style
sc.SetState(SCE_C_COMMENTLINEDOC);
else
sc.SetState(SCE_C_COMMENTLINE);
} else if (sc.ch == '/' &&
IsOKBeforeRE(chPrevNonWhite)) {
sc.SetState(SCE_C_REGEX); // JavaScript's
RegEx
} else if (sc.ch == '\"') {
sc.SetState(SCE_C_STRING);
} else if (sc.ch == '\'') {
sc.SetState(SCE_C_CHARACTER);
} else if (sc.ch == '#' && visibleChars == 0) {
// Preprocessor commands are alone on their line
sc.SetState(SCE_C_PREPROCESSOR);
// Skip whitespace between # and preprocessor
word
do {
sc.Forward();
} while ((sc.ch == ' ' || sc.ch == '\t') &&
sc.More());
if (sc.atLineEnd) {
sc.SetState(SCE_C_DEFAULT);
}
} else if (isoperator(static_cast<char>(sc.ch))) {
sc.SetState(SCE_C_OPERATOR);
}
}
if (sc.atLineEnd) {
// Reset states to begining of colourise so no surprises
// if different sets of lines lexed.
chPrevNonWhite = ' ';
visibleChars = 0;
lastWordWasUUID = false;
}
if (!IsASpace(sc.ch)) {
chPrevNonWhite = sc.ch;
visibleChars++;
}
}
sc.Complete();
}
static bool IsStreamCommentStyle(int style) {
return style == SCE_C_COMMENT ||
style == SCE_C_COMMENTDOC ||
style == SCE_C_COMMENTDOCKEYWORD ||
style == SCE_C_COMMENTDOCKEYWORDERROR;
}
// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldNoBoxCppDoc(unsigned int startPos, int length, int initStyle,
Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
unsigned int endPos = startPos + length;
int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
int levelMinCurrent = levelCurrent;
int levelNext = levelCurrent;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
int style = initStyle;
for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int stylePrev = style;
style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (foldComment && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) {
levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
// Comments don't end at end of line and the
next character may be unstyled.
levelNext--;
}
}
if (foldComment && (style == SCE_C_COMMENTLINE)) {
if ((ch == '/') && (chNext == '/')) {
char chNext2 = styler.SafeGetCharAt(i + 2);
if (chNext2 == '{') {
levelNext++;
} else if (chNext2 == '}') {
levelNext--;
}
}
}
if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
if (ch == '#') {
unsigned int j = i + 1;
while ((j < endPos) &&
IsASpaceOrTab(styler.SafeGetCharAt(j))) {
j++;
}
if (styler.Match(j, "region") ||
styler.Match(j, "if")) {
levelNext++;
} else if (styler.Match(j, "end")) {
levelNext--;
}
}
}
if (style == SCE_C_OPERATOR) {
if (ch == '{') {
// Measure the minimum before a '{' to allow
// folding on "} else {"
if (levelMinCurrent > levelNext) {
levelMinCurrent = levelNext;
}
levelNext++;
} else if (ch == '}') {
levelNext--;
}
}
if (atEOL) {
int levelUse = levelCurrent;
if (foldAtElse) {
levelUse = levelMinCurrent;
}
int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
levelCurrent = levelNext;
levelMinCurrent = levelCurrent;
visibleChars = 0;
}
if (!isspacechar(ch))
visibleChars++;
}
}
static void FoldCppDoc(unsigned int startPos, int length, int initStyle,
WordList *[],
Accessor &styler) {
FoldNoBoxCppDoc(startPos, length, initStyle, styler);
}
static const char * const cppWordLists[] = {
"Primary keywords and identifiers",
"Secondary keywords and identifiers",
"Documentation comment keywords",
"Unused",
"Global classes and typedefs",
0,
};
static void ColouriseCppDocSensitive(unsigned int startPos, int length, int
initStyle, WordList *keywordlists[],
Accessor &styler) {
ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler,
true);
}
static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int
initStyle, WordList *keywordlists[],
Accessor &styler) {
ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler,
false);
}
LexerModule lmCPP(SCLEX_CPP, ColouriseCppDocSensitive, "cpp", FoldCppDoc,
cppWordLists);
LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, ColouriseCppDocInsensitive,
"cppnocase", FoldCppDoc, cppWordLists);
LexerModule lmTCL(SCLEX_TCL, ColouriseCppDocSensitive, "tcl", FoldCppDoc,
cppWordLists);
// Scintilla source code edit control
/** @file LexLua.cxx
** Lexer for Lua language.
**
** Written by Paul Winwood.
** Folder by Alexey Yutkin.
** Modified by Marcos E. Wurzius & Philippe Lhoste
**/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
return ch >= 0x80 ||
(isalnum(ch) || ch == '.' || ch == '_');
}
static inline bool IsAWordStart(int ch) {
return ch >= 0x80 ||
(isalpha(ch) || ch == '_');
}
static inline bool IsANumberChar(int ch) {
// Not exactly following number definition (several dots are seen as
OK, etc.)
// but probably enough in most cases.
return (ch < 0x80) &&
(isdigit(ch) || toupper(ch) == 'E' ||
ch == '.' || ch == '-' || ch == '+');
}
static inline bool IsLuaOperator(int ch) {
if (ch >= 0x80 || isalnum(ch)) {
return false;
}
// '.' left out as it is used to make up numbers
if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
ch == '(' || ch == ')' || ch == '=' ||
ch == '{' || ch == '}' || ch == '~' ||
ch == '[' || ch == ']' || ch == ';' ||
ch == '<' || ch == '>' || ch == ',' ||
ch == '.' || ch == '^' || ch == '%' || ch == ':') {
return true;
}
return false;
}
static void ColouriseLuaDoc(
unsigned int startPos,
int length,
int initStyle,
WordList *keywordlists[],
Accessor &styler) {
WordList &keywords = *keywordlists[0];
WordList &keywords2 = *keywordlists[1];
WordList &keywords3 = *keywordlists[2];
WordList &keywords4 = *keywordlists[3];
WordList &keywords5 = *keywordlists[4];
WordList &keywords6 = *keywordlists[5];
WordList &keywords7 = *keywordlists[6];
WordList &keywords8 = *keywordlists[7];
int currentLine = styler.GetLine(startPos);
// Initialize the literal string [[ ... ]] nesting level, if we are
inside such a string.
int literalStringLevel = 0;
if (initStyle == SCE_LUA_LITERALSTRING) {
literalStringLevel = styler.GetLineState(currentLine - 1);
}
// Initialize the block comment --[[ ... ]] nesting level, if we are
inside such a comment
int blockCommentLevel = 0;
if (initStyle == SCE_LUA_COMMENT) {
blockCommentLevel = styler.GetLineState(currentLine - 1);
}
// Do not leak onto next line
if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE
|| initStyle == SCE_LUA_PREPROCESSOR) {
initStyle = SCE_LUA_DEFAULT;
}
StyleContext sc(startPos, length, initStyle, styler);
if (startPos == 0 && sc.ch == '#') {
// shbang line: # is a comment only if first char of the script
sc.SetState(SCE_LUA_COMMENTLINE);
}
for (; sc.More(); sc.Forward()) {
if (sc.atLineEnd) {
// Update the line state, so it can be seen by next line
currentLine = styler.GetLine(sc.currentPos);
switch (sc.state) {
case SCE_LUA_LITERALSTRING:
// Inside a literal string, we set the line
state
styler.SetLineState(currentLine,
literalStringLevel);
break;
case SCE_LUA_COMMENT: // Block comment
// Inside a block comment, we set the line state
styler.SetLineState(currentLine,
blockCommentLevel);
break;
default:
// Reset the line state
styler.SetLineState(currentLine, 0);
break;
}
}
if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
// Prevent SCE_LUA_STRINGEOL from leaking back to
previous line
sc.SetState(SCE_LUA_STRING);
}
// Handle string line continuation
if ((sc.state == SCE_LUA_STRING || sc.state ==
SCE_LUA_CHARACTER) &&
sc.ch == '\\') {
if (sc.chNext == '\n' || sc.chNext == '\r') {
sc.Forward();
if (sc.ch == '\r' && sc.chNext == '\n') {
sc.Forward();
}
continue;
}
}
// Determine if the current state should terminate.
if (sc.state == SCE_LUA_OPERATOR) {
sc.SetState(SCE_LUA_DEFAULT);
} else if (sc.state == SCE_LUA_NUMBER) {
// We stop the number definition on non-numerical
non-dot non-eE non-sign char
if (!IsANumberChar(sc.ch)) {
sc.SetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_IDENTIFIER) {
if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
char s[100];
sc.GetCurrent(s, sizeof(s));
if (keywords.InList(s)) {
sc.ChangeState(SCE_LUA_WORD);
} else if (keywords2.InList(s)) {
sc.ChangeState(SCE_LUA_WORD2);
} else if (keywords3.InList(s)) {
sc.ChangeState(SCE_LUA_WORD3);
} else if (keywords4.InList(s)) {
sc.ChangeState(SCE_LUA_WORD4);
} else if (keywords5.InList(s)) {
sc.ChangeState(SCE_LUA_WORD5);
} else if (keywords6.InList(s)) {
sc.ChangeState(SCE_LUA_WORD6);
} else if (keywords6.InList(s)) {
sc.ChangeState(SCE_LUA_WORD6);
} else if (keywords7.InList(s)) {
sc.ChangeState(SCE_LUA_WORD7);
} else if (keywords8.InList(s)) {
sc.ChangeState(SCE_LUA_WORD8);
}
sc.SetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_COMMENTLINE) {
if (sc.atLineEnd) {
sc.ForwardSetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_PREPROCESSOR) {
if (sc.atLineEnd) {
sc.ForwardSetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_STRING) {
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' ||
sc.chNext == '\\') {
sc.Forward();
}
} else if (sc.ch == '\"') {
sc.ForwardSetState(SCE_LUA_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_LUA_STRINGEOL);
sc.ForwardSetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_CHARACTER) {
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' ||
sc.chNext == '\\') {
sc.Forward();
}
} else if (sc.ch == '\'') {
sc.ForwardSetState(SCE_LUA_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_LUA_STRINGEOL);
sc.ForwardSetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_LITERALSTRING) {
if (sc.Match('[', '[')) {
literalStringLevel++;
sc.Forward();
sc.SetState(SCE_LUA_LITERALSTRING);
} else if (sc.Match(']', ']') && literalStringLevel >
0) {
literalStringLevel--;
sc.Forward();
if (literalStringLevel == 0) {
sc.ForwardSetState(SCE_LUA_DEFAULT);
}
}
} else if (sc.state == SCE_LUA_COMMENT) { // Lua 5.0's
block comment
if (sc.Match('[', '[')) {
blockCommentLevel++;
sc.Forward();
} else if (sc.Match(']', ']') && blockCommentLevel > 0)
{
blockCommentLevel--;
sc.Forward();
if (blockCommentLevel == 0) {
sc.ForwardSetState(SCE_LUA_DEFAULT);
}
}
}
// Determine if a new state should be entered.
if (sc.state == SCE_LUA_DEFAULT) {
if (IsADigit(sc.ch) || (sc.ch == '.' &&
IsADigit(sc.chNext))) {
sc.SetState(SCE_LUA_NUMBER);
} else if (IsAWordStart(sc.ch)) {
sc.SetState(SCE_LUA_IDENTIFIER);
} else if (sc.Match('\"')) {
sc.SetState(SCE_LUA_STRING);
} else if (sc.Match('\'')) {
sc.SetState(SCE_LUA_CHARACTER);
} else if (sc.Match('[', '[')) {
literalStringLevel = 1;
sc.SetState(SCE_LUA_LITERALSTRING);
sc.Forward();
} else if (sc.Match("--[[")) { // Lua 5.0's block
comment
blockCommentLevel = 1;
sc.SetState(SCE_LUA_COMMENT);
sc.Forward(3);
} else if (sc.Match('-', '-')) {
sc.SetState(SCE_LUA_COMMENTLINE);
sc.Forward();
} else if (sc.atLineStart && sc.Match('$')) {
sc.SetState(SCE_LUA_PREPROCESSOR); //
Obsolete since Lua 4.0, but still in old code
} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
sc.SetState(SCE_LUA_OPERATOR);
}
}
}
sc.Complete();
}
static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */,
WordList *[],
Accessor &styler) {
unsigned int lengthDoc = startPos + length;
int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos);
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
char chNext = styler[startPos];
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
int styleNext = styler.StyleAt(startPos);
char s[10];
for (unsigned int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (style == SCE_LUA_WORD) {
if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' ||
ch == 'r' || ch == 'u') {
for (unsigned int j = 0; j < 8; j++) {
if (!iswordchar(styler[i + j])) {
break;
}
s[j] = styler[i + j];
s[j + 1] = '\0';
}
if ((strcmp(s, "if") == 0) || (strcmp(s, "do")
== 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
levelCurrent++;
}
if ((strcmp(s, "end") == 0) || (strcmp(s,
"elseif") == 0) || (strcmp(s, "until") == 0)) {
levelCurrent--;
}
}
} else if (style == SCE_LUA_OPERATOR) {
if (ch == '{' || ch == '(') {
levelCurrent++;
} else if (ch == '}' || ch == ')') {
levelCurrent--;
}
} else if (style == SCE_LUA_LITERALSTRING || style ==
SCE_LUA_COMMENT) {
if (ch == '[') {
levelCurrent++;
} else if (ch == ']') {
levelCurrent--;
}
}
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && foldCompact) {
lev |= SC_FOLDLEVELWHITEFLAG;
}
if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
lev |= SC_FOLDLEVELHEADERFLAG;
}
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;
}
if (!isspacechar(ch)) {
visibleChars++;
}
}
// Fill in the real level of the next line, keeping the current flags
as they will be filled in later
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
static const char * const luaWordListDesc[] = {
"Keywords",
"Basic functions",
"String, (table) & math functions",
"(coroutines), I/O & system facilities",
"user1",
"user2",
"user3",
"user4",
0
};
LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc,
luaWordListDesc);
_______________________________________________
Scintilla-interest mailing list
[email protected]
http://mailman.lyra.org/mailman/listinfo/scintilla-interest