diff options
author | nyamatongwe <unknown> | 2013-01-10 10:51:04 +1100 |
---|---|---|
committer | nyamatongwe <unknown> | 2013-01-10 10:51:04 +1100 |
commit | f18347dd8b4dbbaaccb038e00db883e4d074e538 (patch) | |
tree | 2f9e9646cf5771a159b973d8a08901eccc3b595e | |
parent | afbd9cb251631e473247477c7798cd9ff69fa408 (diff) | |
download | scintilla-mirror-f18347dd8b4dbbaaccb038e00db883e4d074e538.tar.gz |
Updated to style hidden commands differently.
From Mike Lischke.
-rw-r--r-- | include/SciLexer.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 1 | ||||
-rw-r--r-- | lexers/LexMySQL.cxx | 185 |
3 files changed, 118 insertions, 69 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h index 85ba2a1cc..88d02a6f9 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -1345,6 +1345,7 @@ #define SCE_MYSQL_USER2 19 #define SCE_MYSQL_USER3 20 #define SCE_MYSQL_HIDDENCOMMAND 21 +#define SCE_MYSQL_PLACEHOLDER 22 #define SCE_PO_DEFAULT 0 #define SCE_PO_COMMENT 1 #define SCE_PO_MSGID 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index d6df3cc9d..ac0b78781 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -3920,6 +3920,7 @@ val SCE_MYSQL_USER1=18 val SCE_MYSQL_USER2=19 val SCE_MYSQL_USER3=20 val SCE_MYSQL_HIDDENCOMMAND=21 +val SCE_MYSQL_PLACEHOLDER=22 # Lexical state for SCLEX_PO lex Po=SCLEX_PO SCE_PO_ val SCE_PO_DEFAULT=0 diff --git a/lexers/LexMySQL.cxx b/lexers/LexMySQL.cxx index 305fa7451..f4823f822 100644 --- a/lexers/LexMySQL.cxx +++ b/lexers/LexMySQL.cxx @@ -3,7 +3,7 @@ * @file LexMySQL.cxx * Lexer for MySQL * - * Improved by Mike Lischke <mike.lischke@sun.com> + * Improved by Mike Lischke <mike.lischke@oracle.com> * Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com> * Original work by Neil Hodgson <neilh@scintilla.org> * Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> @@ -60,74 +60,99 @@ static inline bool IsANumberChar(int ch) { /** * Check if the current content context represent a keyword and set the context state if so. */ -static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[]) +static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[], int activeState) { int length = sc.LengthCurrent() + 1; // +1 for the next char char* s = new char[length]; sc.GetCurrentLowered(s, length); if (keywordlists[0]->InList(s)) - sc.ChangeState(SCE_MYSQL_MAJORKEYWORD); + sc.ChangeState(SCE_MYSQL_MAJORKEYWORD | activeState); else if (keywordlists[1]->InList(s)) - sc.ChangeState(SCE_MYSQL_KEYWORD); + sc.ChangeState(SCE_MYSQL_KEYWORD | activeState); else if (keywordlists[2]->InList(s)) - sc.ChangeState(SCE_MYSQL_DATABASEOBJECT); + sc.ChangeState(SCE_MYSQL_DATABASEOBJECT | activeState); else if (keywordlists[3]->InList(s)) - sc.ChangeState(SCE_MYSQL_FUNCTION); + sc.ChangeState(SCE_MYSQL_FUNCTION | activeState); else if (keywordlists[5]->InList(s)) - sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD); + sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD | activeState); else if (keywordlists[6]->InList(s)) - sc.ChangeState(SCE_MYSQL_USER1); + sc.ChangeState(SCE_MYSQL_USER1 | activeState); else if (keywordlists[7]->InList(s)) - sc.ChangeState(SCE_MYSQL_USER2); + sc.ChangeState(SCE_MYSQL_USER2 | activeState); else if (keywordlists[8]->InList(s)) - sc.ChangeState(SCE_MYSQL_USER3); + sc.ChangeState(SCE_MYSQL_USER3 | activeState); delete [] s; } //-------------------------------------------------------------------------------------------------- +#define HIDDENCOMMAND_STATE 0x40 // Offset for states within a hidden command. +#define MASKACTIVE(style) (style & ~HIDDENCOMMAND_STATE) + +static void SetDefaultState(StyleContext& sc, int activeState) +{ + if (activeState == 0) + sc.SetState(SCE_MYSQL_DEFAULT); + else + sc.SetState(SCE_MYSQL_HIDDENCOMMAND); +} + +static void ForwardDefaultState(StyleContext& sc, int activeState) +{ + if (activeState == 0) + sc.ForwardSetState(SCE_MYSQL_DEFAULT); + else + sc.ForwardSetState(SCE_MYSQL_HIDDENCOMMAND); +} + static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { - StyleContext sc(startPos, length, initStyle, styler); + StyleContext sc(startPos, length, initStyle, styler, 127); + int activeState = (initStyle == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : initStyle & HIDDENCOMMAND_STATE; for (; sc.More(); sc.Forward()) { // Determine if the current state should terminate. - switch (sc.state) + switch (MASKACTIVE(sc.state)) { case SCE_MYSQL_OPERATOR: - sc.SetState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); break; case SCE_MYSQL_NUMBER: // We stop the number definition on non-numerical non-dot non-eE non-sign char. if (!IsANumberChar(sc.ch)) - sc.SetState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); break; case SCE_MYSQL_IDENTIFIER: // Switch from identifier to keyword state and open a new state for the new char. if (!IsAWordChar(sc.ch)) { - CheckForKeyword(sc, keywordlists); + CheckForKeyword(sc, keywordlists, activeState); // Additional check for function keywords needed. // A function name must be followed by an opening parenthesis. - if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') - sc.ChangeState(SCE_MYSQL_DEFAULT); + if (MASKACTIVE(sc.state) == SCE_MYSQL_FUNCTION && sc.ch != '(') + { + if (activeState > 0) + sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND); + else + sc.ChangeState(SCE_MYSQL_DEFAULT); + } - sc.SetState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); } break; case SCE_MYSQL_VARIABLE: if (!IsAWordChar(sc.ch)) - sc.SetState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); break; case SCE_MYSQL_SYSTEMVARIABLE: if (!IsAWordChar(sc.ch)) @@ -138,10 +163,10 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, // Check for known system variables here. if (keywordlists[4]->InList(&s[2])) - sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE); + sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE | activeState); delete [] s; - sc.SetState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); } break; case SCE_MYSQL_QUOTEDIDENTIFIER: @@ -150,20 +175,19 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.chNext == '`') sc.Forward(); // Ignore it else - sc.ForwardSetState(SCE_MYSQL_DEFAULT); + ForwardDefaultState(sc, activeState); } break; case SCE_MYSQL_COMMENT: - case SCE_MYSQL_HIDDENCOMMAND: if (sc.Match('*', '/')) { sc.Forward(); - sc.ForwardSetState(SCE_MYSQL_DEFAULT); + ForwardDefaultState(sc, activeState); } break; case SCE_MYSQL_COMMENTLINE: if (sc.atLineStart) - sc.SetState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); break; case SCE_MYSQL_SQSTRING: if (sc.ch == '\\') @@ -175,7 +199,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.chNext == '\'') sc.Forward(); else - sc.ForwardSetState(SCE_MYSQL_DEFAULT); + ForwardDefaultState(sc, activeState); } break; case SCE_MYSQL_DQSTRING: @@ -188,76 +212,94 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.chNext == '\"') sc.Forward(); else - sc.ForwardSetState(SCE_MYSQL_DEFAULT); + ForwardDefaultState(sc, activeState); } break; + case SCE_MYSQL_PLACEHOLDER: + if (sc.Match('}', '>')) + { + sc.Forward(); + ForwardDefaultState(sc, activeState); + } + break; + } + + if (sc.state == SCE_MYSQL_HIDDENCOMMAND && sc.Match('*', '/')) + { + activeState = 0; + sc.Forward(); + ForwardDefaultState(sc, activeState); } // Determine if a new state should be entered. - if (sc.state == SCE_MYSQL_DEFAULT) + if (sc.state == SCE_MYSQL_DEFAULT || sc.state == SCE_MYSQL_HIDDENCOMMAND) { switch (sc.ch) { case '@': if (sc.chNext == '@') { - sc.SetState(SCE_MYSQL_SYSTEMVARIABLE); + sc.SetState(SCE_MYSQL_SYSTEMVARIABLE | activeState); sc.Forward(2); // Skip past @@. } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_MYSQL_VARIABLE); + sc.SetState(SCE_MYSQL_VARIABLE | activeState); sc.Forward(); // Skip past @. } else - sc.SetState(SCE_MYSQL_OPERATOR); + sc.SetState(SCE_MYSQL_OPERATOR | activeState); break; case '`': - sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER); + sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER | activeState); break; case '#': - sc.SetState(SCE_MYSQL_COMMENTLINE); + sc.SetState(SCE_MYSQL_COMMENTLINE | activeState); break; case '\'': - sc.SetState(SCE_MYSQL_SQSTRING); + sc.SetState(SCE_MYSQL_SQSTRING | activeState); break; case '\"': - sc.SetState(SCE_MYSQL_DQSTRING); + sc.SetState(SCE_MYSQL_DQSTRING | activeState); break; default: if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) - sc.SetState(SCE_MYSQL_NUMBER); + sc.SetState(SCE_MYSQL_NUMBER | activeState); else if (IsAWordStart(sc.ch)) - sc.SetState(SCE_MYSQL_IDENTIFIER); + sc.SetState(SCE_MYSQL_IDENTIFIER | activeState); else if (sc.Match('/', '*')) { - sc.SetState(SCE_MYSQL_COMMENT); + sc.SetState(SCE_MYSQL_COMMENT | activeState); // Skip comment introducer and check for hidden command. sc.Forward(2); if (sc.ch == '!') { + activeState = HIDDENCOMMAND_STATE; sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND); - sc.Forward(); } } + else if (sc.Match('<', '{')) + { + sc.SetState(SCE_MYSQL_PLACEHOLDER | activeState); + } else if (sc.Match("--")) { // Special MySQL single line comment. - sc.SetState(SCE_MYSQL_COMMENTLINE); + sc.SetState(SCE_MYSQL_COMMENTLINE | activeState); sc.Forward(2); // Check the third character too. It must be a space or EOL. if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r') - sc.ChangeState(SCE_MYSQL_OPERATOR); + sc.ChangeState(SCE_MYSQL_OPERATOR | activeState); } else if (isoperator(static_cast<char>(sc.ch))) - sc.SetState(SCE_MYSQL_OPERATOR); + sc.SetState(SCE_MYSQL_OPERATOR | activeState); } } } @@ -266,12 +308,12 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, // also at the end of a line. if (sc.state == SCE_MYSQL_IDENTIFIER) { - CheckForKeyword(sc, keywordlists); + CheckForKeyword(sc, keywordlists, activeState); // Additional check for function keywords needed. // A function name must be followed by an opening parenthesis. if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') - sc.ChangeState(SCE_MYSQL_DEFAULT); + SetDefaultState(sc, activeState); } sc.Complete(); @@ -284,7 +326,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, */ static bool IsStreamCommentStyle(int style) { - return style == SCE_MYSQL_COMMENT; + return MASKACTIVE(style) == SCE_MYSQL_COMMENT; } //-------------------------------------------------------------------------------------------------- @@ -323,6 +365,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL int styleNext = styler.StyleAt(startPos); int style = initStyle; + int activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE; bool endPending = false; bool whenPending = false; @@ -332,30 +375,23 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL for (unsigned int i = startPos; length > 0; i++, length--) { int stylePrev = style; + int lastActiveState = activeState; style = styleNext; styleNext = styler.StyleAt(i + 1); + activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE; char currentChar = nextChar; nextChar = styler.SafeGetCharAt(i + 1); bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n'); - switch (style) + switch (MASKACTIVE(style)) { case SCE_MYSQL_COMMENT: if (foldComment) { - // Multiline comment style /* .. */. - if (IsStreamCommentStyle(style)) - { - // Increase level if we just start a foldable comment. - if (!IsStreamCommentStyle(stylePrev)) - levelNext++; - else - // If we are in the middle of a foldable comment check if it ends now. - // Don't end at the line end, though. - if (!IsStreamCommentStyle(styleNext) && !atEOL) - levelNext--; - } + // Multiline comment style /* .. */ just started or is still in progress. + if (IsStreamCommentStyle(style) && !IsStreamCommentStyle(stylePrev)) + levelNext++; } break; case SCE_MYSQL_COMMENTLINE: @@ -377,6 +413,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL } break; case SCE_MYSQL_HIDDENCOMMAND: + /* if (endPending) { // A conditional command is not a white space so it should end the current block @@ -386,15 +423,9 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } - if (style != stylePrev) + }*/ + if (activeState != lastActiveState) levelNext++; - else - if (style != styleNext) - { - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) - levelNext = SC_FOLDLEVELBASE; - } break; case SCE_MYSQL_OPERATOR: if (endPending) @@ -480,7 +511,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL break; default: - if (!isspace(currentChar) && endPending) + if (!isspacechar(currentChar) && endPending) { // END followed by a non-whitespace character (not covered by other cases like identifiers) // also should end a folding block. Typical case: END followed by self defined delimiter. @@ -490,7 +521,23 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL } break; } - + + // Go up one level if we just ended a multi line comment. + if (IsStreamCommentStyle(stylePrev) && !IsStreamCommentStyle(style)) + { + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } + + if (activeState == 0 && lastActiveState != 0) + { + // Decrease fold level when we left a hidden command. + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } + if (atEOL) { // Apply the new folding level to this line. @@ -530,4 +577,4 @@ static const char * const mysqlWordListDesc[] = { 0 }; -LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc); +LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc, 7); |