From f18347dd8b4dbbaaccb038e00db883e4d074e538 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Thu, 10 Jan 2013 10:51:04 +1100 Subject: Updated to style hidden commands differently. From Mike Lischke. --- lexers/LexMySQL.cxx | 185 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 116 insertions(+), 69 deletions(-) (limited to 'lexers/LexMySQL.cxx') 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 + * Improved by Mike Lischke * Adopted from LexSQL.cxx by Anders Karlsson * Original work by Neil Hodgson * Copyright 1998-2005 by Neil Hodgson @@ -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(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); -- cgit v1.2.3