Page 1 of 1

Cooler multi line comments.

Posted: 04 Oct 2017 19:24
by npocmaka_
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
)

Re: Cooler multi line comments.

Posted: 16 Oct 2017 03:02
by jfl
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
)

Re: Cooler multi line comments.

Posted: 22 Dec 2017 13:31
by MicrosoftIsKillingMe
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.

Re: Cooler multi line comments.

Posted: 31 Jul 2018 10:52
by JoBe
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?

Re: Cooler multi line comments.

Posted: 31 Jul 2018 12:37
by dbenham
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

Re: Cooler multi line comments.

Posted: 31 Jul 2018 22:36
by siberia-man
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."

Re: Cooler multi line comments.

Posted: 01 Aug 2018 07:51
by dbenham
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

Re: Cooler multi line comments.

Posted: 01 Aug 2018 10:13
by siberia-man
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 :)

Re: Cooler multi line comments.

Posted: 01 Aug 2018 11:08
by JoBe
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