aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cppcheck.suppress1
-rw-r--r--doc/ScintillaHistory.html7
-rw-r--r--lexers/LexBatch.cxx835
-rw-r--r--lexilla/test/examples/batch/SciTE.properties2
-rw-r--r--lexilla/test/examples/batch/x.bat10
-rw-r--r--lexilla/test/examples/batch/x.bat.styled18
6 files changed, 484 insertions, 389 deletions
diff --git a/cppcheck.suppress b/cppcheck.suppress
index 8523b30f2..1d351d90b 100644
--- a/cppcheck.suppress
+++ b/cppcheck.suppress
@@ -139,7 +139,6 @@ constVariable:scintilla/lexers/LexAVE.cxx
constVariable:scintilla/lexers/LexAVS.cxx
constVariable:scintilla/lexers/LexAsn1.cxx
constVariable:scintilla/lexers/LexBibTeX.cxx
-constVariable:scintilla/lexers/LexBatch.cxx
constVariable:scintilla/lexers/LexCLW.cxx
constVariable:scintilla/lexers/LexCOBOL.cxx
constVariable:scintilla/lexers/LexCSS.cxx
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 027497e7b..201b2213a 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -573,6 +573,13 @@
Added Visual Studio project files for Lexilla and Scintilla with no lexers.
</li>
<li>
+ Fix brace styling in Batch lexer so that brace matching works.
+ <a href="https://sourceforge.net/p/scintilla/bugs/1624/">Bug #1624</a>,
+ <a href="https://sourceforge.net/p/scintilla/bugs/1906/">Bug #1906</a>,
+ <a href="https://sourceforge.net/p/scintilla/bugs/1997/">Bug #1997</a>,
+ <a href="https://sourceforge.net/p/scintilla/bugs/2065/">Bug #2065</a>.
+ </li>
+ <li>
Change Perl lexer to style all line ends of comment lines in comment line style.
Previously, the last character was in default style which made the characters in
\r\n line ends have mismatching styles.
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[] = {
diff --git a/lexilla/test/examples/batch/SciTE.properties b/lexilla/test/examples/batch/SciTE.properties
index 6c03c3f39..c3963bd1e 100644
--- a/lexilla/test/examples/batch/SciTE.properties
+++ b/lexilla/test/examples/batch/SciTE.properties
@@ -1,3 +1,3 @@
lexer.*.bat=batch
-keywords.*.bat=call do echo else errorlevel exist for goto if in set
+keywords.*.bat=call defined do echo else errorlevel exist exit for goto if in not set
diff --git a/lexilla/test/examples/batch/x.bat b/lexilla/test/examples/batch/x.bat
index ce061da0d..60eab1116 100644
--- a/lexilla/test/examples/batch/x.bat
+++ b/lexilla/test/examples/batch/x.bat
@@ -13,7 +13,9 @@ echo %ProgramFiles(x86)%
rem operator=7 '='
@set Q=A
-rem 2nd ')' in this construct is wrongly styled as default
+::comment=1
+
+:: Bug 1624: this construct produced inconsistent brackets in the past
if ERRORLEVEL 2 goto END
@if exist a (
echo exists
@@ -23,4 +25,10 @@ echo not
FOR /L %%G IN (2,1,4) DO (echo %%G)
+:: Bug 1997: keywords not recognized when preceded by '('
+IF NOT DEFINED var (SET var=1)
+
+:: Bug 2065: keywords not recognized when followed by ')'
+@if exist a ( exit)
+
:END
diff --git a/lexilla/test/examples/batch/x.bat.styled b/lexilla/test/examples/batch/x.bat.styled
index 9d1a14cdc..07f903338 100644
--- a/lexilla/test/examples/batch/x.bat.styled
+++ b/lexilla/test/examples/batch/x.bat.styled
@@ -13,14 +13,22 @@ rem 'echo' is word=2, 'a' is default=0
{1}rem operator=7 '='
{4}@{2}set{0} Q{7}={0}A
-{1}rem 2nd ')' in this construct is wrongly styled as default
+{1}::comment=1
+{0}
+{1}:: Bug 1624: this construct produced inconsistent brackets in the past
{2}if ERRORLEVEL{0} 2{2} goto{0} END
-{4}@{2}if exist{0} a{5} ({0}
+{4}@{2}if exist{0} a (
{2}echo{0} exists
-{5}){2} else{0} (
+){2} else{0} (
{2}echo{0} not
-{5}){0}
+)
-{2}FOR{0} /L {6}%%G{2} IN{0} (2,1,4){2} DO{5} (echo{0} {6}%%G{0})
+{2}FOR{0} /L {6}%%G{2} IN{0} (2,1,4){2} DO{0} ({2}echo{0} {6}%%G{0})
+
+{1}:: Bug 1997: keywords not recognized when preceded by '('
+{2}IF NOT DEFINED{0} var ({2}SET{0} var{7}={0}1)
+
+{1}:: Bug 2065: keywords not recognized when followed by ')'
+{4}@{2}if exist{0} a ({2} exit{0})
{3}:END