Menu

#2304 Comment Style when second command on line in Win 10 Batch

Bug
closed-fixed
nobody
5
2022-02-09
2021-12-14
ebloch
No

When a comment is used as the second command in Batch it does not get the comment style applied using NotePad++

Example where comment style is Bold and Italics:
:: Increment
Set /A xxx=%xxx%+1 & :: Increment

Discussion

  • Neil Hodgson

    Neil Hodgson - 2021-12-14

    Is this valid, and is there any documentation for this usage? :: is a label start and is only indirectly used for comments. Labels only go at the start of lines.

    Styling is performed by the batch lexer which is now part of the Lexilla project.
    https://github.com/ScintillaOrg/lexilla

     
  • ebloch

    ebloch - 2021-12-16

    I am not familiar with all of Sourceforge/Github and have tried to add it to lexilla.

    Note that a label ":" uses one character but a comment is either "::" or "REM"

     
    • Neil Hodgson

      Neil Hodgson - 2021-12-16

      The batch file:

      echo ::text
      

      shows:

      >echo ::text 
      ::text
      >
      

      That is, :: is not a comment in this case.

       
  • rdipardo

    rdipardo - 2021-12-17

    According to Stack Overflow [1], prefixing :: or REM with & can simulate the "inline" comment style that @ebloch is looking for:

    inline-batch-comment

    Treating &:: and &REM as comment starters would be trivial to implement.
    A better question is whether such a blatant hack should be regarded as a language feature.


    [1] See also https://ss64.com/nt/rem.html

    You can add a comment to the end of a command line using &REM or &::
    C:> Echo This will work &:: Echo this will not show
    This will work
    This approach works because '&' introduces a new command on the same line.

     

    Last edit: rdipardo 2021-12-17
  • Neil Hodgson

    Neil Hodgson - 2021-12-17

    It is not just the literal tokens &:: and &REM as the initial request included a space & ::.

    This could be approached by understanding where there are multiple commands on a line and treating each command separately. So the state would be reset after & so : and :: would be recognised as label / comment. There may be more complex cases like command groups (goto end & :: Completed) .

     
  • ebloch

    ebloch - 2021-12-18

    I just did some more testing and I think REM does work as second command but :: does not. I never use REM in my batches so did not test before.

     
  • rdipardo

    rdipardo - 2021-12-18

    This could be approached by understanding where there are multiple commands on a line and treating each command separately. So the state would be reset after & [. . .]

    It looks to me like @zufuliu's Batch lexer for notepad2 already implements logic similar to this [1].

    Every instance of & updates an enumerated Command variable; the "inline" comment syntax results in Command::None, leading :: to take this path:

      if (sc.Match(':', ':') && command != Command::Echo) {
        sc.SetState(SCE_BAT_COMMENT);
        // ...
      }
    

    A sequence like & REM comment text ends up styled the same, by an indirect path:

      } else if ((logicalVisibleChars == 0 || command <= Command::Keyword) && IsFileNameChar(sc.ch)) {
        sc.SetState(SCE_BAT_IDENTIFIER);
      }
    
    • then a final switch to comment style inside the SCE_BAT_IDENTIFIER case block:
      } else if (!IsFileNameChar(sc.ch)) {
      // ...
        if (StrEqual(s, "rem")) {
          sc.ChangeState(SCE_BAT_COMMENT);
        } // ...
      }
    

    [1] https://github.com/zufuliu/notepad2/blob/05a39a943ba041a98d2c4997129fad415dacb9f8/scintilla/lexers/LexBatch.cxx

    notepad2-inline-Batch-comments

     
  • Michael Heath

    Michael Heath - 2021-12-18
    --- a/LexBatch.cxx
    +++ b/LexBatch.cxx
    @@ -194,9 +194,16 @@
                    Sci_PositionU wbo = 0;      // Word Buffer Offset - also Special Keyword Buffer Length
    
                    // Check for Comment - return if found
    
    -               if ((CompareCaseInsensitive(wordBuffer, "rem") == 0) && continueProcessing) {
    -                   styler.ColourTo(endPos, SCE_BAT_COMMENT);
    -                   break;
    +               if (continueProcessing) {
    +                   if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
    +                       styler.ColourTo(startLine + offset - 4, SCE_BAT_DEFAULT);
    +                       styler.ColourTo(endPos, SCE_BAT_COMMENT);
    +                       break;
    +                   } else if ((wordBuffer[0] == ':' && wordBuffer[1] == ':')) {
    +                       styler.ColourTo(startLine + offset - 3, SCE_BAT_DEFAULT);
    +                       styler.ColourTo(endPos, SCE_BAT_COMMENT);
    +                       break;
    +                   }
                    }
                    // Check for Separator
                    if (IsBSeparator(wordBuffer[0])) {
    

    Noticed existing code between the operator and rem was being coloured as comment so had to colour it as default before colouring the comment.

    This patch treats :: just like rem.

    This does comments as highlighted:

    set /a "xxx+=1" & :: comment
    set /a "xxx+=1" && :: comment
    set /a "xxx+=1" || :: comment

    set /a "xxx+=1" & rem comment
    set /a "xxx+=1" && rem comment
    set /a "xxx+=1" || rem comment

    (set /a "xxx+=1" & :: comment) & echo.

    The last example will colour the ) & echo. as comment and the interpreter will error as the :: consumes also the remainder of the line.

    I consider the updated styling as OK in general with my knowledge in Batch.

    I can post this at Lexilla repo if checks out OK. Looks OK in editor and tried TestLexer.exe on an updated testfile.

    Edit: Just tried Notepad2 as Robert mentioned. The comment styling matches this patch. So, that seems like a confirmation, else both of us has got it incorrect.

     

    Last edit: Michael Heath 2021-12-18
  • Neil Hodgson

    Neil Hodgson - 2021-12-18

    Mostly good but it doesn't work when there is no space after the :::

    echo b & ::comment
    echo b && ::comment
    
     
    • Michael Heath

      Michael Heath - 2021-12-19

      Nice spotting of a bug. The default styling is causing the issue.

      Seems the length of the wordBuffer needs to be in the calculation for the default styling.

      2nd try at patching:

      --- a/LexBatch.cxx
      +++ b/LexBatch.cxx
      @@ -194,9 +194,12 @@
                      Sci_PositionU wbo = 0;      // Word Buffer Offset - also Special Keyword Buffer Length
      
                      // Check for Comment - return if found
      
      -               if ((CompareCaseInsensitive(wordBuffer, "rem") == 0) && continueProcessing) {
      -                   styler.ColourTo(endPos, SCE_BAT_COMMENT);
      -                   break;
      +               if (continueProcessing) {
      +                   if ((CompareCaseInsensitive(wordBuffer, "rem") == 0) || (wordBuffer[0] == ':' && wordBuffer[1] == ':')) {
      +                       styler.ColourTo(startLine + offset - strlen(wordBuffer) - 1, SCE_BAT_DEFAULT);
      +                       styler.ColourTo(endPos, SCE_BAT_COMMENT);
      +                       break;
      +                   }
                      }
                      // Check for Separator
                      if (IsBSeparator(wordBuffer[0])) {
      

      This helps to avoid code duplication as fixed lengths not used like in the previous patch, which means less code is needed.

      Edit: Added the missing break;.
      Edit2: Removed excess pair of parentheses.

       

      Last edit: Michael Heath 2021-12-19
  • Neil Hodgson

    Neil Hodgson - 2021-12-19
    • labels: NPP Comment Batch --> NPP Comment Batch, lexilla, lexer
    • status: open --> open-fixed
     
  • Neil Hodgson

    Neil Hodgson - 2022-02-09
    • status: open-fixed --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB