Community

    • Login
    • Search
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    flagging starting and ending parens in batch files

    General Discussion
    3
    6
    159
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • dshuman52
      dshuman52 last edited by dshuman52

      In the following code the use of command continuation character ^ causes the paren highlighting feature to break. The do ( maps to the incorrect closing paren and the else ( that include or follow the ^ character do not map at all. Replacing (delete and re-enter) the paren in either else ( results in a temporary incorrect mapping to the next closing paren regardless of nesting. Can anyone point out where in the code this pairing occurs? I would like to try to code and submit a fix.

      DO %%F IN (z y x) DO (
      IF %%F==x (
      ECHO ‘x’
      ) ELSE (
      IF %%F==y (
      ECHO ^
      ‘y’
      ) ELSE (
      IF %%F==z (
      ECHO ‘z’
      )
      )
      )
      )

      1 Reply Last reply Reply Quote 0
      • Alan Kilborn
        Alan Kilborn last edited by

        Batch syntax can be so crazy that I for one give Notepad++ (or any lexer) a total pass on it! :-)

        1 Reply Last reply Reply Quote 0
        • dshuman52
          dshuman52 last edited by dshuman52

          You may be correct. However if anyone can identify where this pairing is done (I could not find a ‘(’ or ‘\(’ literal in LexBatch.cxx in scintilla) so I am guessing not there. If the source code that contains this function can be identified I am willing to attempt to provide a fix (patch) for consideration, assuming I can fix it.

          1 Reply Last reply Reply Quote 0
          • dshuman52
            dshuman52 last edited by

            I attempted to create a user defined batch file editor.

                <UserLang name="bat" ext="bat cmd nt" udlVersion="2.1">
                    <Settings>
                        <Global caseIgnored="yes" allowFoldOfComments="no" foldCompact="no" forcePureLC="1" decimalSeparator="0" />
                        <Prefix Keywords1="no" Keywords2="no" Keywords3="no" Keywords4="no" Keywords5="no" Keywords6="no" Keywords7="no" Keywords8="no" />
                    </Settings>
                    <KeywordLists>
                        <Keywords name="Comments">00rem 01 02 03 04</Keywords>
                        <Keywords name="Numbers, prefix1">- + ~</Keywords>
                        <Keywords name="Numbers, prefix2"></Keywords>
                        <Keywords name="Numbers, extras1"></Keywords>
                        <Keywords name="Numbers, extras2"></Keywords>
                        <Keywords name="Numbers, suffix1"></Keywords>
                        <Keywords name="Numbers, suffix2"></Keywords>
                        <Keywords name="Numbers, range"></Keywords>
                        <Keywords name="Operators1">! = : \ @ . , / -</Keywords>
                        <Keywords name="Operators2">^</Keywords>
                        <Keywords name="Folders in code1, open">(</Keywords>
                        <Keywords name="Folders in code1, middle"></Keywords>
                        <Keywords name="Folders in code1, close">)</Keywords>
                        <Keywords name="Folders in code2, open"></Keywords>
                        <Keywords name="Folders in code2, middle"></Keywords>
                        <Keywords name="Folders in code2, close"></Keywords>
                        <Keywords name="Folders in comment, open"></Keywords>
                        <Keywords name="Folders in comment, middle"></Keywords>
                        <Keywords name="Folders in comment, close"></Keywords>
                        <Keywords name="Keywords1">assoc aux break call cd chcp chdir choice cls cmdextversion color con copy country ctty date defined del dir dpath echo endlocal erase errorlevel exit ftype goto loadfix loadhigh md mkdir mklink move path pause popd prn prompt pushd rd ren rename rmdir set setlocal shift start time title type ver verify vol</Keywords>
                        <Keywords name="Keywords2">com com1 com2 com3 com4 do else exist for if in lpt lpt1 lpt2 lpt3 lpt4 not nul on</Keywords>
                        <Keywords name="Keywords3"></Keywords>
                        <Keywords name="Keywords4"></Keywords>
                        <Keywords name="Keywords5"></Keywords>
                        <Keywords name="Keywords6">*</Keywords>
                        <Keywords name="Keywords7">%%a %%b %%c %%c %%d %%e %%f %%g %%h %%i %%j %%k %%l %%m %%n %%o %%p %%q %%r %%s %%t %%u %%v %%w %%x %%y %%z</Keywords>
                        <Keywords name="Keywords8">%1 %2 %3 %4 %5 %6 %7 %8 %9 %~1 %~2 %~3 %~4 %~5 %~6 %~7 %/~8 %~9</Keywords>
                        <Keywords name="Delimiters">00&quot; 01 02&quot; 03&apos; 04 05&apos; 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23</Keywords>
            <!--
                        <Keywords name="Delimiters">00&quot; 01 02&quot; 03&apos; 04 05&apos; 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21% 22 23%</Keywords>
            -->
                    </KeywordLists>
                    <Styles>
                        <WordsStyle name="DEFAULT" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="COMMENTS" fgColor="008000" bgColor="80FF80" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="LINE COMMENTS" fgColor="008000" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="NUMBERS" fgColor="FF80FF" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="KEYWORDS1" fgColor="0000FF" bgColor="A0FFFF" fontName="" fontStyle="7" nesting="0" />
                        <WordsStyle name="KEYWORDS2" fgColor="008000" bgColor="80FF80" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="KEYWORDS3" fgColor="0000FF" bgColor="A0FFFF" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="KEYWORDS4" fgColor="0000FF" bgColor="A0FFFF" fontName="" fontStyle="2" nesting="0" />
                        <WordsStyle name="KEYWORDS5" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="KEYWORDS6" fgColor="008000" bgColor="80FF80" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="KEYWORDS7" fgColor="FF8040" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="KEYWORDS8" fgColor="FF8040" bgColor="FFFFFF" fontName="" fontStyle="3" nesting="0" />
                        <WordsStyle name="OPERATORS" fgColor="0000FF" bgColor="FFC060" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="FOLDER IN CODE1" fgColor="000040" bgColor="FF8080" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="FOLDER IN CODE2" fgColor="0000FF" bgColor="A0FFFF" fontName="" fontStyle="3" nesting="0" />
                        <WordsStyle name="FOLDER IN COMMENT" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="DELIMITERS1" fgColor="008000" bgColor="FFFF00" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="DELIMITERS2" fgColor="008000" bgColor="FFFF80" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="DELIMITERS3" fgColor="008000" bgColor="FFFF80" fontName="" fontStyle="1" nesting="0" />
                        <WordsStyle name="DELIMITERS4" fgColor="E020E0" bgColor="E0C0E0" fontName="" fontStyle="0" nesting="67108864" />
                        ```
            <WordsStyle name="DELIMITERS5" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="256" />
                        <WordsStyle name="DELIMITERS6" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="DELIMITERS7" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" nesting="0" />
                        <WordsStyle name="DELIMITERS8" fgColor="FF8040" bgColor="FFFFFF" fontName="" fontStyle="1" nesting="83886080" />
                    </Styles>
                </UserLang>
            

            In the above keyword1 is a command list (incomplete)
            keyword2 is an operand list (probably incomplete)
            keyword6 is an operand the * in dir .
            (there may be a better way to do this)
            keyword7 is for FOR loop iteration variables
            keyword8 is for command line arguments
            The rest are fairly common

            Next consider the following bat file

            @ECHO   ON
            
            REM     LINKdir.bat
            REM
            REM     %1    = A99LINK
            REM     %2    = A99TARGET
            REM     %3    = A99FILTER
            REM
            SET             A99LINK=%~1
            SET             A99TARGET=%~2
            SET             A99FILTER=%~3
            REM
            REM     make directories and link files
            REM
            PUSHD           %A99TARGET:~0,-1%
            REM
            REM     make directories
            FOR   %%F   IN (DIR /ad /b) DO (
              SET           %A99FILE%=%%F
              IF            %A99FILE:~0,1%!='.' (
                MKDIR       %A99LINK%%A99FILE%
                %A01TESTbatPATH%LINKdir.bat ^
                            %A99LINK%%A99FILE% ^
                            %A99TARGET%%A99FILE%
              )
            )
            REM
            REM     link files
            REM
            FOR   %%T   IN (%A99FILTER%)       DO (
              FOR %%F   IN (DIR /a-d /b *.%%T)  DO (
                SET         %A99FILE%=%%F
                IF          %A99FILE:~0,1%!='.' (
                  MKLINK /h %A99LINK%%A99FILE% ^
                            %A99TARGET%%A99FILE%
                )
              )
            )
            POPD
            

            Quirk 1 the POPD command requires a space or CR/LF to color as a keyword – adding the CRLF is an easy workaround

            Desire 1 – to be able to use bold, italic and underline instead of background colors for most keywords. (This does not seem to work in the current portable version)

            Desire 2 a program change that would permit %…% to be added to the delimiters as in the commented code. This requires a program change (maybe easier said than done) to eliminate the keywords (list 7 and 8) starting with %% or % from being considered as a %…% delimited named variable resulting from a set command or an environment variable. Allowing numbers and operands (not space delimited) to be nested in this delimited value would support the substring construct of :~nn,snn inside a delimited named variable. (%{named variable:~nn,snn%) As a result the length value can be determined to be a number which does not work now. This would also allow named variables to be styled like keywords 7 and 8 which is also what I would do.

            Is there another way to do Desire 2 in UDL?

            Thanks for considering this.

            dshuman52 1 Reply Last reply Reply Quote 1
            • dshuman52
              dshuman52 @dshuman52 last edited by

              @dshuman52

              Desire 1 works when the stupid user (me) does not set the global overrides for BIU.

              1 Reply Last reply Reply Quote 1
              • guy038
                guy038 last edited by guy038

                Hello @dshuman52, @alan-kilborn and All,

                @dshuman52, Here is a method which could help you ! It works whatever the current language as it’s a recursive regular expression looking for well-balanced ( .... ) blocks, containing possible juxtaposed / nested other ( .... ) blocks !

                SEARCH \((?:[^()]++|(?0))*\) ( Select the Regular expression search mode )

                Notes :

                • From current location of the caret, this regex selects, automatically, the next longest well balanced ( .... ) block

                • If you prefer to get the ending parenthesis, only, simply change this regex as below :

                SEARCH \((?:[^()]++|(?0))*\K\)


                To explain this regex, the best is to use the free-spacing mode, which allows comments in regexes :

                (?x)             #  FREE-SPACING mode
                \(               #  STARTING parenthesis
                (?:              #  Start of the NON-CAPTURING group
                    [^()]++      #      Any NON-NULL ATOMIC range of ALLOWED characters
                    |            #      OR
                    (?0)         #      A RECURSION, using the WHOLE regex pattern ( group #0 )
                )*               #  End of the NON-CAPTURING group, repeated 0 or MORE times
                # \K             #  DELETE the initial '#' character, of that line, to match the ENDING parenthesis, ONLY
                \)               #  ENDING parenthesis
                

                Try this regex against your text, below :

                @ECHO   ON
                
                REM     LINKdir.bat
                REM
                REM     %1    = A99LINK
                REM     %2    = A99TARGET
                REM     %3    = A99FILTER
                REM
                SET             A99LINK=%~1
                SET             A99TARGET=%~2
                SET             A99FILTER=%~3
                REM
                REM     make directories and link files
                REM
                PUSHD           %A99TARGET:~0,-1%
                REM
                REM     make directories
                FOR   %%F   IN (DIR /ad /b) DO (
                  SET           %A99FILE%=%%F
                  IF            %A99FILE:~0,1%!='.' (
                    MKDIR       %A99LINK%%A99FILE%
                    %A01TESTbatPATH%LINKdir.bat ^
                                %A99LINK%%A99FILE% ^
                                %A99TARGET%%A99FILE%
                  )
                )
                REM
                REM     link files
                REM
                FOR   %%T   IN (%A99FILTER%)       DO (
                  FOR %%F   IN (DIR /a-d /b *.%%T)  DO (
                    SET         %A99FILE%=%%F
                    IF          %A99FILE:~0,1%!='.' (
                      MKLINK /h %A99LINK%%A99FILE% ^
                                %A99TARGET%%A99FILE%
                    )
                  )
                )
                POPD
                

                Notes :

                • Place the caret at different locations, of this batch file

                • Then do the search hitting, several times, the F3 shortcut

                Important :

                • Each time that a well-balanced ( .... ) block is selected :

                  • An hit on the Left Arrow key moves the caret right before the ( starting parenthesis

                  • An hit on the Right Arrow key moves the caret right after the ) ending parenthesis

                • The nice thing is that, when you hit the shift + F3 shortcut, it gets the inner ( ... ) block, closed to the end of the outer ( ... ) block !

                Try also, with your first sample text :

                DO %%F IN (z y x) DO (
                IF %%F==x (
                ECHO ‘x’
                ) ELSE (
                IF %%F==y (
                ECHO ^
                ‘y’
                ) ELSE (
                IF %%F==z (
                ECHO ‘z’
                )
                )
                )
                )
                

                Best Regards,

                guy038

                P.S. :

                In batch files , the & ampersand, the | vertical line and the ( and ) parentheses are special chars. So, they must be preceded with the escape character ^ or embedded inside double quotes.

                Thus, here’s a more elaborate version, where we suppose that the ^ symbol is the default escape character and any character, preceded with a ^ symbol, is just considered as a literal chars, including the syntaxes ^( and ^) !

                (?x)             #  FREE-SPACING mode
                (?<!\\)          #  NEXT character is NOT PRECEDED with a '\' symbol ( LOOK-BEHIND condition )
                \(               #  STARTING parenthesis
                (?:              #  Start of the 1st NON-CAPTURING group
                    (?:          #      Start of the 2nd NON-CAPTURING group
                        \^ [()]  #          STRINGS '^(' or '^)' are supposed to be ALLOWED characters     
                        |        #          OR
                        [^()]    #          Any ALLOWED character, even EOL ones, DIFFERENT of the PARENTHESES '(' and ')'
                    )++          #      End of the 2nd NON-CAPTURING group ( NON-NULL ATOMIC range of ALLOWED characters )
                    |            #      OR
                    (?0)         #      A RECURSION, using the WHOLE regex pattern ( group #0 )
                )*               #  End of the 1st NON-CAPTURING group, repeated 0 or MORE times
                (?<!\\)          #  NEXT character is NOT PREDECED with a '\' symbol ( LOOK-BEHIND condition )
                \)               #  ENDING parenthesis
                

                Here is its shortest syntax :

                SEARCH (?x)(?<!\\)\((?:(?:\^[()]|[^()])|(?0))*(?<!\\)\)

                Test it against this sample text :

                DO %%F IN (z y x) DO (
                IF %%F==x (
                ECHO ‘x’  ^(
                ) ELSE (
                IF %%F==y (
                ECHO ^
                ‘y’
                ) ELSE (
                IF %%F==z (
                ECHO ‘z’
                )
                )
                ^)
                )
                )
                
                1 Reply Last reply Reply Quote 2
                • First post
                  Last post
                Copyright © 2014 NodeBB Forums | Contributors