OSDN Git Service

Commit DialogBox compile Okay
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / LexCmake.cxx
diff --git a/ext/scintilla/src/LexCmake.cxx b/ext/scintilla/src/LexCmake.cxx
new file mode 100644 (file)
index 0000000..c29d739
--- /dev/null
@@ -0,0 +1,456 @@
+// Scintilla source code edit control\r
+/** @file LexCmake.cxx\r
+ ** Lexer for Cmake\r
+ **/\r
+// Copyright 2007 by Cristian Adam <cristian [dot] adam [at] gmx [dot] net>\r
+// based on the NSIS lexer\r
+// The License.txt file describes the conditions under which this software may be distributed.\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdio.h>\r
+#include <stdarg.h>\r
+\r
+#include "Platform.h"\r
+\r
+#include "PropSet.h"\r
+#include "Accessor.h"\r
+#include "KeyWords.h"\r
+#include "Scintilla.h"\r
+#include "SciLexer.h"\r
+\r
+#ifdef SCI_NAMESPACE\r
+using namespace Scintilla;\r
+#endif\r
+\r
+static bool isCmakeNumber(char ch)\r
+{\r
+    return(ch >= '0' && ch <= '9');\r
+}\r
+\r
+static bool isCmakeChar(char ch)\r
+{\r
+    return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');\r
+}\r
+\r
+static bool isCmakeLetter(char ch)\r
+{\r
+    return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');\r
+}\r
+\r
+static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)\r
+{\r
+    int nNextLine = -1;\r
+    for ( unsigned int i = start; i < end; i++ ) {\r
+        char cNext = styler.SafeGetCharAt( i );\r
+        if ( cNext == '\n' ) {\r
+            nNextLine = i+1;\r
+            break;\r
+        }\r
+    }\r
+\r
+    if ( nNextLine == -1 ) // We never foudn the next line...\r
+        return false;\r
+\r
+    for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) {\r
+        char cNext = styler.SafeGetCharAt( firstChar );\r
+        if ( cNext == ' ' )\r
+            continue;\r
+        if ( cNext == '\t' )\r
+            continue;\r
+        if ( styler.Match(firstChar, "ELSE")  || styler.Match(firstChar, "else"))\r
+            return true;\r
+        break;\r
+    }\r
+\r
+    return false;\r
+}\r
+\r
+static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse)\r
+{\r
+    // If the word is too long, it is not what we are looking for\r
+    if ( end - start > 20 )\r
+        return foldlevel;\r
+\r
+    int newFoldlevel = foldlevel;\r
+\r
+    char s[20]; // The key word we are looking for has atmost 13 characters\r
+    for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) {\r
+        s[i] = static_cast<char>( styler[ start + i ] );\r
+        s[i + 1] = '\0';\r
+    }\r
+\r
+    if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0\r
+         || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0\r
+         || CompareCaseInsensitive(s, "ELSEIF") == 0 )\r
+        newFoldlevel++;\r
+    else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0\r
+              || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0)\r
+        newFoldlevel--;\r
+    else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 )\r
+        newFoldlevel++;\r
+    else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 )\r
+        newFoldlevel++;\r
+\r
+    return newFoldlevel;\r
+}\r
+\r
+static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )\r
+{\r
+    char word[100] = {0};\r
+    char lowercaseWord[100] = {0};\r
+\r
+    WordList &Commands = *keywordLists[0];\r
+    WordList &Parameters = *keywordLists[1];\r
+    WordList &UserDefined = *keywordLists[2];\r
+\r
+    for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) {\r
+        word[i] = static_cast<char>( styler[ start + i ] );\r
+        lowercaseWord[i] = static_cast<char>(tolower(word[i]));\r
+    }\r
+\r
+    // Check for special words...\r
+    if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 )\r
+        return SCE_CMAKE_MACRODEF;\r
+\r
+    if ( CompareCaseInsensitive(word, "IF") == 0 ||  CompareCaseInsensitive(word, "ENDIF") == 0 )\r
+        return SCE_CMAKE_IFDEFINEDEF;\r
+\r
+    if ( CompareCaseInsensitive(word, "ELSEIF") == 0  || CompareCaseInsensitive(word, "ELSE") == 0 )\r
+        return SCE_CMAKE_IFDEFINEDEF;\r
+\r
+    if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0)\r
+        return SCE_CMAKE_WHILEDEF;\r
+\r
+    if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0)\r
+        return SCE_CMAKE_FOREACHDEF;\r
+\r
+    if ( Commands.InList(lowercaseWord) )\r
+        return SCE_CMAKE_COMMANDS;\r
+\r
+    if ( Parameters.InList(word) )\r
+        return SCE_CMAKE_PARAMETERS;\r
+\r
+\r
+    if ( UserDefined.InList(word) )\r
+        return SCE_CMAKE_USERDEFINED;\r
+\r
+    if ( strlen(word) > 3 ) {\r
+        if ( word[1] == '{' && word[strlen(word)-1] == '}' )\r
+            return SCE_CMAKE_VARIABLE;\r
+    }\r
+\r
+    // To check for numbers\r
+    if ( isCmakeNumber( word[0] ) ) {\r
+        bool bHasSimpleCmakeNumber = true;\r
+        for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) {\r
+            if ( !isCmakeNumber( word[j] ) ) {\r
+                bHasSimpleCmakeNumber = false;\r
+                break;\r
+            }\r
+        }\r
+\r
+        if ( bHasSimpleCmakeNumber )\r
+            return SCE_CMAKE_NUMBER;\r
+    }\r
+\r
+    return SCE_CMAKE_DEFAULT;\r
+}\r
+\r
+static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)\r
+{\r
+    int state = SCE_CMAKE_DEFAULT;\r
+    if ( startPos > 0 )\r
+        state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox\r
+\r
+    styler.StartAt( startPos );\r
+    styler.GetLine( startPos );\r
+\r
+    unsigned int nLengthDoc = startPos + length;\r
+    styler.StartSegment( startPos );\r
+\r
+    char cCurrChar;\r
+    bool bVarInString = false;\r
+    bool bClassicVarInString = false;\r
+\r
+    unsigned int i;\r
+    for ( i = startPos; i < nLengthDoc; i++ ) {\r
+        cCurrChar = styler.SafeGetCharAt( i );\r
+        char cNextChar = styler.SafeGetCharAt(i+1);\r
+\r
+        switch (state) {\r
+        case SCE_CMAKE_DEFAULT:\r
+            if ( cCurrChar == '#' ) { // we have a comment line\r
+                styler.ColourTo(i-1, state );\r
+                state = SCE_CMAKE_COMMENT;\r
+                break;\r
+            }\r
+            if ( cCurrChar == '"' ) {\r
+                styler.ColourTo(i-1, state );\r
+                state = SCE_CMAKE_STRINGDQ;\r
+                bVarInString = false;\r
+                bClassicVarInString = false;\r
+                break;\r
+            }\r
+            if ( cCurrChar == '\'' ) {\r
+                styler.ColourTo(i-1, state );\r
+                state = SCE_CMAKE_STRINGRQ;\r
+                bVarInString = false;\r
+                bClassicVarInString = false;\r
+                break;\r
+            }\r
+            if ( cCurrChar == '`' ) {\r
+                styler.ColourTo(i-1, state );\r
+                state = SCE_CMAKE_STRINGLQ;\r
+                bVarInString = false;\r
+                bClassicVarInString = false;\r
+                break;\r
+            }\r
+\r
+            // CMake Variable\r
+            if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) {\r
+                styler.ColourTo(i-1,state);\r
+                state = SCE_CMAKE_VARIABLE;\r
+\r
+                // If it is a number, we must check and set style here first...\r
+                if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )\r
+                    styler.ColourTo( i, SCE_CMAKE_NUMBER);\r
+\r
+                break;\r
+            }\r
+\r
+            break;\r
+        case SCE_CMAKE_COMMENT:\r
+            if ( cNextChar == '\n' || cNextChar == '\r' ) {\r
+                // Special case:\r
+                if ( cCurrChar == '\\' ) {\r
+                    styler.ColourTo(i-2,state);\r
+                    styler.ColourTo(i,SCE_CMAKE_DEFAULT);\r
+                }\r
+                else {\r
+                    styler.ColourTo(i,state);\r
+                    state = SCE_CMAKE_DEFAULT;\r
+                }\r
+            }\r
+            break;\r
+        case SCE_CMAKE_STRINGDQ:\r
+        case SCE_CMAKE_STRINGLQ:\r
+        case SCE_CMAKE_STRINGRQ:\r
+\r
+            if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )\r
+                break; // Ignore the next character, even if it is a quote of some sort\r
+\r
+            if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) {\r
+                styler.ColourTo(i,state);\r
+                state = SCE_CMAKE_DEFAULT;\r
+                break;\r
+            }\r
+\r
+            if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) {\r
+                styler.ColourTo(i,state);\r
+                state = SCE_CMAKE_DEFAULT;\r
+                break;\r
+            }\r
+\r
+            if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) {\r
+                styler.ColourTo(i,state);\r
+                state = SCE_CMAKE_DEFAULT;\r
+                break;\r
+            }\r
+\r
+            if ( cNextChar == '\r' || cNextChar == '\n' ) {\r
+                int nCurLine = styler.GetLine(i+1);\r
+                int nBack = i;\r
+                // We need to check if the previous line has a \ in it...\r
+                bool bNextLine = false;\r
+\r
+                while ( nBack > 0 ) {\r
+                    if ( styler.GetLine(nBack) != nCurLine )\r
+                        break;\r
+\r
+                    char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here\r
+\r
+                    if ( cTemp == '\\' ) {\r
+                        bNextLine = true;\r
+                        break;\r
+                    }\r
+                    if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )\r
+                        break;\r
+\r
+                    nBack--;\r
+                }\r
+\r
+                if ( bNextLine ) {\r
+                    styler.ColourTo(i+1,state);\r
+                }\r
+                if ( bNextLine == false ) {\r
+                    styler.ColourTo(i,state);\r
+                    state = SCE_CMAKE_DEFAULT;\r
+                }\r
+            }\r
+            break;\r
+\r
+        case SCE_CMAKE_VARIABLE:\r
+\r
+            // CMake Variable:\r
+            if ( cCurrChar == '$' )\r
+                state = SCE_CMAKE_DEFAULT;\r
+            else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )\r
+                state = SCE_CMAKE_DEFAULT;\r
+            else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) {\r
+                state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler );\r
+                styler.ColourTo( i, state);\r
+                state = SCE_CMAKE_DEFAULT;\r
+            }\r
+            else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) {\r
+                if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER )\r
+                    styler.ColourTo( i-1, SCE_CMAKE_NUMBER );\r
+\r
+                state = SCE_CMAKE_DEFAULT;\r
+\r
+                if ( cCurrChar == '"' ) {\r
+                    state = SCE_CMAKE_STRINGDQ;\r
+                    bVarInString = false;\r
+                    bClassicVarInString = false;\r
+                }\r
+                else if ( cCurrChar == '`' ) {\r
+                    state = SCE_CMAKE_STRINGLQ;\r
+                    bVarInString = false;\r
+                    bClassicVarInString = false;\r
+                }\r
+                else if ( cCurrChar == '\'' ) {\r
+                    state = SCE_CMAKE_STRINGRQ;\r
+                    bVarInString = false;\r
+                    bClassicVarInString = false;\r
+                }\r
+                else if ( cCurrChar == '#' ) {\r
+                    state = SCE_CMAKE_COMMENT;\r
+                }\r
+            }\r
+            break;\r
+        }\r
+\r
+        if ( state == SCE_CMAKE_COMMENT) {\r
+            styler.ColourTo(i,state);\r
+        }\r
+        else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) {\r
+            bool bIngoreNextDollarSign = false;\r
+\r
+            if ( bVarInString && cCurrChar == '$' ) {\r
+                bVarInString = false;\r
+                bIngoreNextDollarSign = true;\r
+            }\r
+            else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) {\r
+                styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);\r
+                bVarInString = false;\r
+                bIngoreNextDollarSign = false;\r
+            }\r
+\r
+            else if ( bVarInString && !isCmakeChar(cNextChar) ) {\r
+                int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler);\r
+                if ( nWordState == SCE_CMAKE_VARIABLE )\r
+                    styler.ColourTo( i, SCE_CMAKE_STRINGVAR);\r
+                bVarInString = false;\r
+            }\r
+            // Covers "${TEST}..."\r
+            else if ( bClassicVarInString && cNextChar == '}' ) {\r
+                styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);\r
+                bClassicVarInString = false;\r
+            }\r
+\r
+            // Start of var in string\r
+            if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) {\r
+                styler.ColourTo( i-1, state);\r
+                bClassicVarInString = true;\r
+                bVarInString = false;\r
+            }\r
+            else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) {\r
+                styler.ColourTo( i-1, state);\r
+                bVarInString = true;\r
+                bClassicVarInString = false;\r
+            }\r
+        }\r
+    }\r
+\r
+    // Colourise remaining document\r
+    styler.ColourTo(nLengthDoc-1,state);\r
+}\r
+\r
+static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)\r
+{\r
+    // No folding enabled, no reason to continue...\r
+    if ( styler.GetPropertyInt("fold") == 0 )\r
+        return;\r
+\r
+    bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;\r
+\r
+    int lineCurrent = styler.GetLine(startPos);\r
+    unsigned int safeStartPos = styler.LineStart( lineCurrent );\r
+\r
+    bool bArg1 = true;\r
+    int nWordStart = -1;\r
+\r
+    int levelCurrent = SC_FOLDLEVELBASE;\r
+    if (lineCurrent > 0)\r
+        levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;\r
+    int levelNext = levelCurrent;\r
+\r
+    for (unsigned int i = safeStartPos; i < startPos + length; i++) {\r
+        char chCurr = styler.SafeGetCharAt(i);\r
+\r
+        if ( bArg1 ) {\r
+            if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) {\r
+                nWordStart = i;\r
+            }\r
+            else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) {\r
+                int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse);\r
+\r
+                if ( newLevel == levelNext ) {\r
+                    if ( foldAtElse ) {\r
+                        if ( CmakeNextLineHasElse(i, startPos + length, styler) )\r
+                            levelNext--;\r
+                    }\r
+                }\r
+                else\r
+                    levelNext = newLevel;\r
+                bArg1 = false;\r
+            }\r
+        }\r
+\r
+        if ( chCurr == '\n' ) {\r
+            if ( bArg1 && foldAtElse) {\r
+                if ( CmakeNextLineHasElse(i, startPos + length, styler) )\r
+                    levelNext--;\r
+            }\r
+\r
+            // If we are on a new line...\r
+            int levelUse = levelCurrent;\r
+            int lev = levelUse | levelNext << 16;\r
+            if (levelUse < levelNext )\r
+                lev |= SC_FOLDLEVELHEADERFLAG;\r
+            if (lev != styler.LevelAt(lineCurrent))\r
+                styler.SetLevel(lineCurrent, lev);\r
+\r
+            lineCurrent++;\r
+            levelCurrent = levelNext;\r
+            bArg1 = true; // New line, lets look at first argument again\r
+            nWordStart = -1;\r
+        }\r
+    }\r
+\r
+    int levelUse = levelCurrent;\r
+    int lev = levelUse | levelNext << 16;\r
+    if (levelUse < levelNext)\r
+        lev |= SC_FOLDLEVELHEADERFLAG;\r
+    if (lev != styler.LevelAt(lineCurrent))\r
+        styler.SetLevel(lineCurrent, lev);\r
+}\r
+\r
+static const char * const cmakeWordLists[] = {\r
+    "Commands",\r
+    "Parameters",\r
+    "UserDefined",\r
+    0,\r
+    0,};\r
+\r
+LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists);\r