Cooler multi line comments.

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Cooler multi line comments.

#1 Post by npocmaka_ » 04 Oct 2017 19:24

Recently I saw the dbenham update here. The macro comments are cool ,but I was thinking about an improvement.

Here it is:

Code: Select all

@echo off
set "/:=goto :/%%"

%/:%
  multi
  line
  comment
%:/%

echo not commented 1

%/:%
   another
   multi
   line
   comment
%:/%

echo not commented 2


It uses one 'feature' of GOTO - you can put a single symbol (if it is not : ) in front of the label and the GOTO will still be able to find it (hope this is not something working only on my machine).Though the leading % in the closing comment can be skipped (and also the one at the end in the closing comment) it triggers my OCD with it's lack of symetry :-D .Also when ':' is the last symbol in the variable name substring or replacement are not started when the variable is used.
This looks almost like the comments in the "serious" programming languages. Even all kind of brackets can be used:



Code: Select all

@echo off
set "(:=goto :)%%"

echo not commented 1

%(:%
  multi
  line
  comment
%:)%


set "[:=goto :]%%"


%[:%
  another
  multi
  line
  comment
%:]%

echo not commented 2


This gives me a feeling of a something closed...


The negative conditional comment also can be improved a little bit (in case multi line comment in a brackets context is needed):


Code: Select all

@echo off

rem[||([

 multi line
 comment
 
])

echo not commented 1

rem/||(/
  another
  comment
/)

echo not commented 2


It also can be shorterened with a macros (and thus both techniques could be alligned with similar symbols):


Code: Select all

@echo off

::comment macros
set "[=rem/||(" & set "]=)"

for /f %%a in ('echo comment tests') do (
   echo not commented 1
   %[%
      multi
      line
      comment
   %]%
    echo not commented 2
)


Code: Select all

@echo off

::comment macros
set "(=rem/||(" & set ")=)"

for /f %%a in ('echo comment tests') do (
   echo not commented 1
   %(%
      multi
      line
      comment
   %)%
    echo not commented 2
)






Of course it is a matter of a personal taste , may be it's only me who find these more pleasing.


And the final result:

Code: Select all

@echo off

::GOTO comment macro
set "[:=goto :]%%"
::brackets comment macros
set "[=rem/||(" & set "]=)"

::testing
echo not commented 1

%[:%
  multi
  line
  comment outside of brackets
%:]%

echo not commented 2

%[:%
  second multi
  line
  comment outside of brackets
%:]%

::GOTO macro cannot be used inside for
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %[%
        multi line
        comment
    %]%
    echo second not commented line of the %%a execution
)

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: Cooler multi line comments.

#2 Post by jfl » 16 Oct 2017 03:02

A really great idea! It never ceases to amaze me that we can still make progress like this with this good old batch language.

Of course it is a matter of a personal taste

Indeed! I personally favor using :# for comments instead of ::, as the # character is used for comments by most other scripting languages. Using it in batch files like everywhere else, helps me when switching from one language to another.

It's easy to adapt your block comments to use the # character.
Note how I also changed the loop-specific ones to use parenthesis instead of brackets. I think this makes it more intuitive as to which macro is for goto comments, and which one is for use in (loops).

Code: Select all

@echo off

:# Goto comment macro
set "#:=goto :#%%"
:# Parentheses comment macros
set "#(=rem.||(" & set ")#=)"

:# testing
echo not commented 1

%#:%
  multi
  line
  comment outside of brackets
%:#%

echo not commented 2

%#:%
  second multi
  line
  comment outside of brackets
%:#%

echo not commented 3

:# GOTO macro cannot be used inside for loop
for %%a in (first second) do (
    echo first not commented line of the %%a execution
    %#(%
        multi line
        comment
    %)#%
    echo second not commented line of the %%a execution
)

MicrosoftIsKillingMe
Posts: 55
Joined: 11 Dec 2017 09:08

Re: Cooler multi line comments.

#3 Post by MicrosoftIsKillingMe » 22 Dec 2017 13:31

Hi npocmaka_, I like this. Thanks. A couple of minor comments...

I found that the closing % is in fact needed at the end of the block, as post #1 is currently written, otherwise giving
The system cannot find the batch label specified - /%

For the same reason, if the first block has the closing % but the second doesn't, infinite loop :) The second block keeps returning to the label in the first block. Recalling dbenham saying "Although it is generally recommended that :labels are unique within a batch script, it really is OK to embed multiple comments like this within the same batch script" I was curious how it might resolve the "ambiguity". It would appear (and seems logical) that goto looks "downward" for a label, then wraps around to the top of the file if not found below the goto, which is consistent with the infinite loop's progression.

OTOH I found, as you suggested, that the opening % can be omitted at the end of the block, though I agree with you in preference for "symmetry."

All of that is based on your definition
set "/:=goto :/%%"

IF instead the definition is
set "/:=goto :/%"
then you can (and should) omit the closing % at the end of blocks ( %:/ works ) but I agree with you to use the first set definition, and just close with %:/%.

I've been told that I write long posts and smart important people may grow weary reading them. I hope that everything above is of interest or is meaningful to someone, and if not, I apologize. I could have just said "Hey npoc, the closing % is actually needed on post 1" but thought I could add more value. Anyway, stop reading now :) However, for the intensely curious minds that enjoy trivial details and anecdotes:

I tested the first /: example in post #1 above, saved as COMM_BLK.BAT and run from a command line.
A curious thing happened; after running, I typed the letter C and F8 key.
On Windows 7 it retrieves the command line normally.
On XP SP3 hitting C and F8 does not retrieve it. I wonder why. However you can still up-arrow to the command history item, and it does show in F7. (Microsoft Windows XP [Version 5.1.2600])
However if I renamed from COMM_BLK.BAT to COMM_BAK.BAT, then C and F8 gets it normally in XP. Just curious; maybe a small former bug.

JoBe
Posts: 2
Joined: 31 Jul 2018 10:25

Re: Cooler multi line comments.

#4 Post by JoBe » 31 Jul 2018 10:52

Hi,

an even shorter and completely symmetric solution for multi line comments outside of ()-blocks seems to be this:

Code: Select all

set :=goto %%

%:%
  comment lines
  ...
  a little weird that comment opening and closing symbol are identical,
  but you can do this also in C with /*/ ... /*/
%:%
This works because searching for a labels happens in a very early phase of the "parser" (for me, a too ambitious denomination in the context of cmd.exe).

Another comment related question: It seems to me that outside of ()-blocks a plain ')' at the beginning of a line works like '::' (with the same restrictions). Any experiences if this assumption is correct?

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Cooler multi line comments.

#5 Post by dbenham » 31 Jul 2018 12:37

Interesting idea, but I don't think I would use it. I like being able to differentiate comment begin from comment end.
JoBe wrote:
31 Jul 2018 10:52
Another comment related question: It seems to me that outside of ()-blocks a plain ')' at the beginning of a line works like '::' (with the same restrictions). Any experiences if this assumption is correct?
Absolutely, although the restrictions are quite different from those for ::

I've documented the behavior at How does the Windows Command Interpreter (CMD.EXE) parse scripts? in my Phase 2 edits.
StackOverflow wrote:
  • If the parenthesis counter is 0 and the parser is looking for a command, then ) functions similar to a REM statement as long as it is immediately followed by a token delimiter, special character, newline, or end-of-file
    • All special characters lose their meaning except ^ (line concatenation is possible)
    • Once the end of the logical line is reached, the entire "command" is discarded.
Here are examples of working "comments":

Code: Select all

@echo off
) This is a comment
)=This is a comment
),This is a comment
);This is a comment
)>This is a comment
)<This is a comment
)|This is a comment
)&This is a comment
echo OK & ) OK is printed and the rest is a comment

) This multiline comment^
  works just fine!
But the following attempt at a comment fails because the character following the ) is not acceptable:

Code: Select all

@echo off
)This gives a syntax error

Dave Benham

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: Cooler multi line comments.

#6 Post by siberia-man » 31 Jul 2018 22:36

Multiple-line comments in batch scripts is certainly the interesting topic. Time ago I was inspired to implement them using internal facilities of the batch interpreter. I have thoroughly read this thread and other links to SO pages. To be honest, all the options with macros like %[:% and %:]% and others are variations (or syntax sugar) of the basic structure. In my opinion this is the best attempt to enter multiline comments to batch script

Code: Select all

rem.||(
)
I found couple of limitations:
-- blank lines after :label within these structures are not allowed and throw error "The syntax of the command is incorrect."
-- some problems with closing parentheses if they are not consistent. The exception is the same "The syntax of the command is incorrect."

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Cooler multi line comments.

#7 Post by dbenham » 01 Aug 2018 07:51

There are additional restrictions to REM.||( ... )

The content within the brackets (the comment) is fully parsed through phase 3. So anything that can cause an error in those phases can be problematic with this technique.

Of particular concern is the fact that any IF or FOR command must have valid syntax, else you get a fatal syntax error.

For example:

Code: Select all

@echo off

rem.||(
  if a == b is a valid comment
)
echo The above comment works just fine

rem.||(
  if this is the comment then fatal error
)
echo Not excecuted
Also, a special character may be needed after a closing ), depending on whether the parens are parsed as a block

Code: Select all

@echo off

rem.||(
  This (is not a problem)
  (nor is this) & a problem
)
echo The above comment works just fine

rem.||(
  (but this) causes a fatal syntax error
)
echo Not excecuted

One potentially nice attribute of this technique is that the comments are all printed if ECHO is ON, which is consistent with normal REM behavior.


Dave Benham

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: Cooler multi line comments.

#8 Post by siberia-man » 01 Aug 2018 10:13

One think I can present here is pie - the Plain, Impressive, Executable documentation format. It looks pretty flexible and easy in use but described not very clear and not very popular even in my plate :)

JoBe
Posts: 2
Joined: 31 Jul 2018 10:25

Re: Cooler multi line comments.

#9 Post by JoBe » 01 Aug 2018 11:08

Hi Dave,
dbenham wrote:
31 Jul 2018 12:37
Interesting idea, but I don't think I would use it. I like being able to differentiate comment begin from comment end.
I agree. I only enjoyed that it is possible to use identical symbols for start and end of a comment :).

My proposal can also make problems when I use syntax highlighting im Vim: It's possible to define a syntax region with identical start and end symbols and even to replace them (by conceal) with different (!) characters (e. g. '{' and '}'). But the highlighting can fail depending on your position in the file, because Vim (and I think other editors too) only parse a limited part of the file for syntax recognition.

By the way, another possibility (in a sense similar to /* ... */) would be to use

Code: Select all

%:%
comment lines 
:%:
Maybe this prohibits these problems, because start and end symbol are unique and so Vim cannot mix them up.
dbenham wrote:
31 Jul 2018 12:37
I've documented the behavior at How does the Windows Command Interpreter (CMD.EXE) parse scripts? in my Phase 2 edits.
I looked there before, but obviously I read this hint over.

Johannes

Post Reply