diff options
Diffstat (limited to 'lexers/LexBatch.cxx')
-rw-r--r-- | lexers/LexBatch.cxx | 835 |
1 files changed, 454 insertions, 381 deletions
diff --git a/lexers/LexBatch.cxx b/lexers/LexBatch.cxx index db7e37688..ee71c528f 100644 --- a/lexers/LexBatch.cxx +++ b/lexers/LexBatch.cxx @@ -41,7 +41,8 @@ static inline bool AtEOL(Accessor &styler, Sci_PositionU i) { // Tests for BATCH Operators static bool IsBOperator(char ch) { return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || - (ch == '|') || (ch == '?') || (ch == '*'); + (ch == '|') || (ch == '?') || (ch == '*')|| + (ch == '&') || (ch == '(') || (ch == ')'); } // Tests for BATCH Separators @@ -50,218 +51,198 @@ static bool IsBSeparator(char ch) { (ch == '\"') || (ch == '\'') || (ch == '/'); } -static void ColouriseBatchLine( - char *lineBuffer, - Sci_PositionU lengthLine, - Sci_PositionU startLine, - Sci_PositionU endPos, +// Tests for escape character +static bool IsEscaped(char* wordStr, Sci_PositionU pos) { + bool isQoted=false; + while (pos>0){ + pos--; + if (wordStr[pos]=='^') + isQoted=!isQoted; + else + break; + } + return isQoted; +} + +// Tests for quote character +static bool textQuoted(char *lineBuffer, Sci_PositionU endPos) { + char strBuffer[1024]; + strncpy(strBuffer, lineBuffer, endPos); + strBuffer[endPos] = '\0'; + char *pQuote; + pQuote = strchr(strBuffer, '"'); + bool CurrentStatus = false; + while (pQuote != NULL) + { + if (!IsEscaped(strBuffer, pQuote - strBuffer)) { + CurrentStatus = !CurrentStatus; + } + pQuote = strchr(pQuote + 1, '"'); + } + return CurrentStatus; +} + +static void ColouriseBatchDoc( + Sci_PositionU startPos, + Sci_Position length, + int /*initStyle*/, WordList *keywordlists[], Accessor &styler) { + // Always backtracks to the start of a line that is not a continuation + // of the previous line + if (startPos > 0) { + Sci_Position ln = styler.GetLine(startPos); // Current line number + while (startPos > 0) { + ln--; + if ((styler.SafeGetCharAt(startPos-3) == '^' && styler.SafeGetCharAt(startPos-2) == '\r' && styler.SafeGetCharAt(startPos-1) == '\n') + || styler.SafeGetCharAt(startPos-2) == '^') { // handle '^' line continuation + // When the line continuation is found, + // set the Start Position to the Start of the previous line + length+=startPos-styler.LineStart(ln); + startPos=styler.LineStart(ln); + } + else + break; + } + } - Sci_PositionU offset = 0; // Line Buffer Offset - Sci_PositionU cmdLoc; // External Command / Program Location - char wordBuffer[81]; // Word Buffer - large to catch long paths - Sci_PositionU wbl; // Word Buffer Length - Sci_PositionU wbo; // Word Buffer Offset - also Special Keyword Buffer Length - WordList &keywords = *keywordlists[0]; // Internal Commands - WordList &keywords2 = *keywordlists[1]; // External Commands (optional) + char lineBuffer[1024]; - // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords - // Toggling Regular Keyword Checking off improves readability - // Other Regular Keywords and External Commands / Programs might also benefit from toggling - // Need a more robust algorithm to properly toggle Regular Keyword Checking + styler.StartAt(startPos); + styler.StartSegment(startPos); + Sci_PositionU linePos = 0; + Sci_PositionU startLine = startPos; bool continueProcessing = true; // Used to toggle Regular Keyword Checking - // Special Keywords are those that allow certain characters without whitespace after the command - // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= - // Special Keyword Buffer used to determine if the first n characters is a Keyword - char sKeywordBuffer[10]; // Special Keyword Buffer - bool sKeywordFound; // Exit Special Keyword for-loop if found - - // Skip initial spaces - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - // Set External Command / Program Location - cmdLoc = offset; + bool isNotAssigned=false; // Used to flag Assignment in Set operation - // Check for Fake Label (Comment) or Real Label - return if found - if (lineBuffer[offset] == ':') { - if (lineBuffer[offset + 1] == ':') { - // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm - styler.ColourTo(endPos, SCE_BAT_COMMENT); - } else { - // Colorize Real Label - styler.ColourTo(endPos, SCE_BAT_LABEL); - } - return; - // Check for Drive Change (Drive Change is internal command) - return if found - } else if ((IsAlphabetic(lineBuffer[offset])) && - (lineBuffer[offset + 1] == ':') && - ((isspacechar(lineBuffer[offset + 2])) || - (((lineBuffer[offset + 2] == '\\')) && - (isspacechar(lineBuffer[offset + 3]))))) { - // Colorize Regular Keyword - styler.ColourTo(endPos, SCE_BAT_WORD); - return; - } + for (Sci_PositionU i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1) || (i==startPos + length-1)) { + // End of line (or of line buffer) (or End of Last Line) met, colourise it + lineBuffer[linePos] = '\0'; + Sci_PositionU lengthLine=linePos; + Sci_PositionU endPos=i; + Sci_PositionU offset = 0; // Line Buffer Offset + Sci_PositionU cmdLoc; // External Command / Program Location + char wordBuffer[81]; // Word Buffer - large to catch long paths + Sci_PositionU wbl; // Word Buffer Length + Sci_PositionU wbo; // Word Buffer Offset - also Special Keyword Buffer Length + WordList &keywords = *keywordlists[0]; // Internal Commands + WordList &keywords2 = *keywordlists[1]; // External Commands (optional) - // Check for Hide Command (@ECHO OFF/ON) - if (lineBuffer[offset] == '@') { - styler.ColourTo(startLine + offset, SCE_BAT_HIDE); - offset++; - } - // Skip next spaces - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } + // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords + // Toggling Regular Keyword Checking off improves readability + // Other Regular Keywords and External Commands / Programs might also benefit from toggling + // Need a more robust algorithm to properly toggle Regular Keyword Checking + bool stopLineProcessing=false; // Used to stop line processing if Comment or Drive Change found + // Special Keywords are those that allow certain characters without whitespace after the command + // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= + // Special Keyword Buffer used to determine if the first n characters is a Keyword + char sKeywordBuffer[10]; // Special Keyword Buffer + bool sKeywordFound; // Exit Special Keyword for-loop if found - // Read remainder of line word-at-a-time or remainder-of-word-at-a-time - while (offset < lengthLine) { - if (offset > startLine) { + // Skip initial spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } // Colorize Default Text styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Copy word from Line Buffer into Word Buffer - wbl = 0; - for (; offset < lengthLine && wbl < 80 && - !isspacechar(lineBuffer[offset]); wbl++, offset++) { - wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset])); - } - wordBuffer[wbl] = '\0'; - wbo = 0; + // Set External Command / Program Location + cmdLoc = offset; - // Check for Comment - return if found - if (CompareCaseInsensitive(wordBuffer, "rem") == 0) { - styler.ColourTo(endPos, SCE_BAT_COMMENT); - return; - } - // Check for Separator - if (IsBSeparator(wordBuffer[0])) { - // Check for External Command / Program - if ((cmdLoc == offset - wbl) && - ((wordBuffer[0] == ':') || - (wordBuffer[0] == '\\') || - (wordBuffer[0] == '.'))) { - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Colorize External Command / Program - if (!keywords2) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else if (keywords2.InList(wordBuffer)) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + // Check for Fake Label (Comment) or Real Label - return if found + if (lineBuffer[offset] == ':') { + if (lineBuffer[offset + 1] == ':') { + // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm + styler.ColourTo(endPos, SCE_BAT_COMMENT); } else { - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + // Colorize Real Label + styler.ColourTo(endPos, SCE_BAT_LABEL); } - // Reset External Command / Program Location - cmdLoc = offset; - } else { - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + stopLineProcessing=true; + // Check for Drive Change (Drive Change is internal command) - return if found + } else if ((IsAlphabetic(lineBuffer[offset])) && + (lineBuffer[offset + 1] == ':') && + ((isspacechar(lineBuffer[offset + 2])) || + (((lineBuffer[offset + 2] == '\\')) && + (isspacechar(lineBuffer[offset + 3]))))) { + // Colorize Regular Keyword + styler.ColourTo(endPos, SCE_BAT_WORD); + stopLineProcessing=true; } - // Check for Regular Keyword in list - } else if ((keywords.InList(wordBuffer)) && - (continueProcessing)) { - // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking - if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || - (CompareCaseInsensitive(wordBuffer, "goto") == 0) || - (CompareCaseInsensitive(wordBuffer, "prompt") == 0) || - (CompareCaseInsensitive(wordBuffer, "set") == 0)) { - continueProcessing = false; + + // Check for Hide Command (@ECHO OFF/ON) + if (lineBuffer[offset] == '@') { + styler.ColourTo(startLine + offset, SCE_BAT_HIDE); + offset++; } - // Identify External Command / Program Location for ERRORLEVEL, and EXIST - if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || - (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip comparison - while ((cmdLoc < lengthLine) && - (!isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; + // Skip next spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + + // Read remainder of line word-at-a-time or remainder-of-word-at-a-time + while (offset < lengthLine && !stopLineProcessing) { + if (offset > startLine) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); } - // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH - } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || - (CompareCaseInsensitive(wordBuffer, "do") == 0) || - (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || - (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; + // Copy word from Line Buffer into Word Buffer + wbl = 0; + for (; offset < lengthLine && wbl < 80 && + !isspacechar(lineBuffer[offset]); wbl++, offset++) { + wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset])); } - } - // Colorize Regular keyword - styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); - // No need to Reset Offset - // Check for Special Keyword in list, External Command / Program, or Default Text - } else if ((wordBuffer[0] != '%') && - (wordBuffer[0] != '!') && - (!IsBOperator(wordBuffer[0])) && - (continueProcessing)) { - // Check for Special Keyword - // Affected Commands are in Length range 2-6 - // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected - sKeywordFound = false; - for (Sci_PositionU keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { + wordBuffer[wbl] = '\0'; wbo = 0; - // Copy Keyword Length from Word Buffer into Special Keyword Buffer - for (; wbo < keywordLength; wbo++) { - sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]); + + // Check for Comment - return if found + if ((CompareCaseInsensitive(wordBuffer, "rem") == 0) && continueProcessing) { + styler.ColourTo(endPos, SCE_BAT_COMMENT); + break; } - sKeywordBuffer[wbo] = '\0'; - // Check for Special Keyword in list - if ((keywords.InList(sKeywordBuffer)) && - ((IsBOperator(wordBuffer[wbo])) || - (IsBSeparator(wordBuffer[wbo])))) { - sKeywordFound = true; - // ECHO requires no further Regular Keyword Checking - if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { - continueProcessing = false; + // Check for Separator + if (IsBSeparator(wordBuffer[0])) { + // Check for External Command / Program + if ((cmdLoc == offset - wbl) && + ((wordBuffer[0] == ':') || + (wordBuffer[0] == '\\') || + (wordBuffer[0] == '.'))) { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Reset External Command / Program Location + cmdLoc = offset; + } else { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); } - // Colorize Special Keyword as Regular Keyword - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - } - // Check for External Command / Program or Default Text - if (!sKeywordFound) { - wbo = 0; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; + // Check for Regular Keyword in list + } else if ((keywords.InList(wordBuffer)) && + (continueProcessing)) { + // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking + if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || + (CompareCaseInsensitive(wordBuffer, "goto") == 0) || + (CompareCaseInsensitive(wordBuffer, "prompt") == 0)) { + continueProcessing = false; } - // Reset External Command / Program Location - cmdLoc = offset - (wbl - wbo); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // CHOICE requires no further Regular Keyword Checking - if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { + // SET requires additional processing for the assignment operator + if (CompareCaseInsensitive(wordBuffer, "set") == 0) { continueProcessing = false; + isNotAssigned=true; } - // Check for START (and its switches) - What follows is External Command \ Program - if (CompareCaseInsensitive(wordBuffer, "start") == 0) { + // Identify External Command / Program Location for ERRORLEVEL, and EXIST + if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || + (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { // Reset External Command / Program Location cmdLoc = offset; // Skip next spaces @@ -269,37 +250,284 @@ static void ColouriseBatchLine( (isspacechar(lineBuffer[cmdLoc]))) { cmdLoc++; } - // Reset External Command / Program Location if command switch detected - if (lineBuffer[cmdLoc] == '/') { - // Skip command switch - while ((cmdLoc < lengthLine) && - (!isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; + // Skip comparison + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH + } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || + (CompareCaseInsensitive(wordBuffer, "do") == 0) || + (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || + (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + // Colorize Regular keyword + styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); + // No need to Reset Offset + // Check for Special Keyword in list, External Command / Program, or Default Text + } else if ((wordBuffer[0] != '%') && + (wordBuffer[0] != '!') && + (!IsBOperator(wordBuffer[0])) && + (continueProcessing)) { + // Check for Special Keyword + // Affected Commands are in Length range 2-6 + // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected + sKeywordFound = false; + for (Sci_PositionU keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { + wbo = 0; + // Copy Keyword Length from Word Buffer into Special Keyword Buffer + for (; wbo < keywordLength; wbo++) { + sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]); + } + sKeywordBuffer[wbo] = '\0'; + // Check for Special Keyword in list + if ((keywords.InList(sKeywordBuffer)) && + ((IsBOperator(wordBuffer[wbo])) || + (IsBSeparator(wordBuffer[wbo])))) { + sKeywordFound = true; + // ECHO requires no further Regular Keyword Checking + if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { + continueProcessing = false; } - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; + // Colorize Special Keyword as Regular Keyword + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for External Command / Program or Default Text + if (!sKeywordFound) { + wbo = 0; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (((wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))))) { + wbo++; + } + // Reset External Command / Program Location + cmdLoc = offset - (wbl - wbo); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // CHOICE requires no further Regular Keyword Checking + if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { + continueProcessing = false; + } + // Check for START (and its switches) - What follows is External Command \ Program + if (CompareCaseInsensitive(wordBuffer, "start") == 0) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Reset External Command / Program Location if command switch detected + if (lineBuffer[cmdLoc] == '/') { + // Skip command switch + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + } + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); } + // No need to Reset Offset + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (((wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) + } else if (wordBuffer[0] == '%') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second % (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '%')) { + wbo++; + } + // Check for Argument (%n) or (%*) + if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && + (wordBuffer[wbo] != '%')) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 2); + } + // Colorize Argument + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Expanded Argument (%~...) / Variable (%%~...) + } else if (((wbl > 1) && (wordBuffer[1] == '~')) || + ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Expanded Argument / Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Environment Variable (%x...%) + } else if ((wordBuffer[1] != '%') && + (wordBuffer[wbo] == '%')) { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Local Variable (%%a) + } else if ( + (wbl > 2) && + (wordBuffer[1] == '%') && + (wordBuffer[2] != '%') && + (!IsBOperator(wordBuffer[2])) && + (!IsBSeparator(wordBuffer[2]))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 3); + } + // Colorize Local Variable + styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 3); + } + // Check for Environment Variable (!x...!) + } else if (wordBuffer[0] == '!') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second ! (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '!')) { + wbo++; + } + if (wordBuffer[wbo] == '!') { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); } - // Colorize External Command / Program - if (!keywords2) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else if (keywords2.InList(wordBuffer)) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + // Check for Operator + } else if (IsBOperator(wordBuffer[0])) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + // Check for Comparison Operator + if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { + // Identify External Command / Program Location for IF + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Comparison Operator + if (continueProcessing) + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); + else + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Pipe Operator + } else if ((wordBuffer[0] == '|') && + !(IsEscaped(lineBuffer,offset - wbl + wbo) || textQuoted(lineBuffer, offset - wbl) )) { + // Reset External Command / Program Location + cmdLoc = offset - wbl + 1; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Pipe Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + continueProcessing = true; + // Check for Other Operator } else { - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + // Check for Operators: >, |, & + if (((wordBuffer[0] == '>')|| + (wordBuffer[0] == ')')|| + (wordBuffer[0] == '(')|| + (wordBuffer[0] == '&' )) && + !(!continueProcessing && (IsEscaped(lineBuffer,offset - wbl + wbo) + || textQuoted(lineBuffer, offset - wbl) ))){ + // Turn Keyword and External Command / Program checking back on + continueProcessing = true; + isNotAssigned=false; + } + // Colorize Other Operators + // Do not Colorize Paranthesis, quoted text and escaped operators + if (((wordBuffer[0] != ')') && (wordBuffer[0] != '(') + && !textQuoted(lineBuffer, offset - wbl) && !IsEscaped(lineBuffer,offset - wbl + wbo)) + && !((wordBuffer[0] == '=') && !isNotAssigned )) + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + else + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + + if ((wordBuffer[0] == '=') && isNotAssigned ){ + isNotAssigned=false; + } } - // No need to Reset Offset // Check for Default Text } else { // Read up to %, Operator or Separator while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && + ((wordBuffer[wbo] != '%') && (wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { + (!IsBSeparator(wordBuffer[wbo])))) { wbo++; } // Colorize Default Text @@ -307,186 +535,31 @@ static void ColouriseBatchLine( // Reset Offset to re-process remainder of word offset -= (wbl - wbo); } - } - // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) - } else if (wordBuffer[0] == '%') { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - wbo++; - // Search to end of word for second % (can be a long path) - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Check for Argument (%n) or (%*) - if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && - (wordBuffer[wbo] != '%')) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - 2); - } - // Colorize Argument - styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - 2); - // Check for Expanded Argument (%~...) / Variable (%%~...) - } else if (((wbl > 1) && (wordBuffer[1] == '~')) || - ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Expanded Argument / Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // Check for Environment Variable (%x...%) - } else if ((wordBuffer[1] != '%') && - (wordBuffer[wbo] == '%')) { - wbo++; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Environment Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // Check for Local Variable (%%a) - } else if ( - (wbl > 2) && - (wordBuffer[1] == '%') && - (wordBuffer[2] != '%') && - (!IsBOperator(wordBuffer[2])) && - (!IsBSeparator(wordBuffer[2]))) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - 3); - } - // Colorize Local Variable - styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - 3); - } - // Check for Environment Variable (!x...!) - } else if (wordBuffer[0] == '!') { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - wbo++; - // Search to end of word for second ! (can be a long path) - while ((wbo < wbl) && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - if (wordBuffer[wbo] == '!') { - wbo++; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Environment Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - // Check for Operator - } else if (IsBOperator(wordBuffer[0])) { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - // Check for Comparison Operator - if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { - // Identify External Command / Program Location for IF - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Colorize Comparison Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 2); - // Check for Pipe Operator - } else if (wordBuffer[0] == '|') { - // Reset External Command / Program Location - cmdLoc = offset - wbl + 1; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; + // Skip next spaces - nothing happens if Offset was Reset + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; } - // Colorize Pipe Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Check for Other Operator - } else { - // Check for > Operator - if (wordBuffer[0] == '>') { - // Turn Keyword and External Command / Program checking back on - continueProcessing = true; - } - // Colorize Other Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - } - // Check for Default Text - } else { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - // Skip next spaces - nothing happens if Offset was Reset - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - } - // Colorize Default Text for remainder of line - currently not lexed - styler.ColourTo(endPos, SCE_BAT_DEFAULT); -} - -static void ColouriseBatchDoc( - Sci_PositionU startPos, - Sci_Position length, - int /*initStyle*/, - WordList *keywordlists[], - Accessor &styler) { + // Colorize Default Text for remainder of line - currently not lexed + styler.ColourTo(endPos, SCE_BAT_DEFAULT); - char lineBuffer[1024]; + // handle line continuation for SET and ECHO commands except the last line and an empty line + if (!continueProcessing && (i<startPos + length-1) && linePos>2) { + Sci_PositionU lineContinuationPos; + if (lineBuffer[linePos-2]=='\r') // Windows EOL + lineContinuationPos=linePos-3; + else + lineContinuationPos=linePos-2; // Unix or Mac EOL + if ((lineBuffer[lineContinuationPos]!='^') || // handle '^' line continuation + IsEscaped(lineBuffer, lineContinuationPos) + || textQuoted(lineBuffer, lineContinuationPos)) + continueProcessing=true; + } - styler.StartAt(startPos); - styler.StartSegment(startPos); - Sci_PositionU linePos = 0; - Sci_PositionU startLine = startPos; - for (Sci_PositionU i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler); linePos = 0; startLine = i + 1; } } - if (linePos > 0) { // Last line does not have ending characters - lineBuffer[linePos] = '\0'; - ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1, - keywordlists, styler); - } } static const char *const batchWordListDesc[] = { |