AutoMacro - a function for Macro code generation

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
T3RRY
Posts: 249
Joined: 06 May 2020 10:14

AutoMacro - a function for Macro code generation

#1 Post by T3RRY » 27 Jul 2024 08:42

After encountering a similar function earlier this week on SS64, and liking the apeal of improved readability without using %\n%,
I decided the idea could be expanded on to provide new functionality.

Ideas that got incorperated along the way:
* Switches to add common use structures to macro definitions IE:
- the for loop used to capture args
- Ability to append usage info to a macro for output if it doesnt recieve args
- Appension of a for loop to flush macro temp variables after execution
* Capacity to declare dependencies at the start of a macros definiton, with that declaration triggering the definition of any macros the macro-in-progress will use
* optional Generation of debugging data as each macro is defined to aid in macro creation.

the below code includes ample instructions and several examples of implementing the syntax.

Code: Select all

@Echo off & Setlocal EnableDelayedExpansion

1> nul Call:Automacro "%~f0" @Substring
CLS
Mode 80,30

If 0==1 (
  %help% @substring
  Timeout /T 2 /Nobreak
  Pause
  CLS
)

%@Substring:$Return=HW% /L "Hello World " /I '['$_ ' /M "$_" /I '['$_ ' /M "$_" /I '['$_ ' /M "$_" /I '['$_ ' /M "$_"

Set /a HW[%HW.i%].Len+=1
Set "Redraw=!$_!"
For /l %%i in (0 1 !HW[%HW.i%].Len!) do (
  %@Substring% /A /I '%%i'%\E%[32;7m^^^<^^^>%\E%[0m' "%$_%"
  Echo(%\E%[1;1H%\E%[K!$Return[0]!
)

%@Substring:$Return=Original% /A /L "<Hello World>"
%@Substring:$Return=Step% /I '1'%\E%[33m?%\E%[0m' "%$_%" /I '2'%\E%[33m?%\E%[0m' "%$_%" /I '3'%\E%[33m?%\E%[0m' "%$_%" /I '4'%\E%[33m?%\E%[0m' "%$_%" /I '5'%\E%[33m?%\E%[0m' "%$_%" /I '6'%\E%[33m?%\E%[0m' "%$_%" /I '7'%\E%[33m?%\E%[0m' "%$_%" /I '8'%\E%[33m?%\E%[0m' "%$_%" /I '9'%\E%[33m?%\E%[0m' "%$_%" /I '10'%\E%[33m?%\E%[0m' "%$_%" /I '11'%\E%[33m?%\E%[0m' "%$_%" /I '12'%\E%[33m?%\E%[0m' "%$_%"
For /L %%i in (1 1 !Step.i!)Do (
  <nul Set /p "=%\E%[6;1H!Step[%%i]!"
  For /l %%z in (1 1 75000)Do If 1==0 REM delay
)

Echo(%\E%[1;1H%\E%7

Set "$_=%Redraw% "
For /f %%L in ("!HW[%HW.i%].Len!")DO For /l %%i in (0 1 !HW[%HW.i%].Len!) do (
  %@Substring% /A /I '%%i' ' "!$_:~0,%%L! "
  Echo(%\E%[1;1H!$Return[0]!
)
Set "$_=%Redraw%"
Echo(%\E%[1;1H!$_!

 For %%G in ( B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C C A A A C C C C B B B C C C A A A E B B B B C C C C C C C C C STOP )Do (
  IF not %%G==STOP (
   %@Substring% /A /O /R 'Hello World= * ' /I '['%\E%8%\E%[5X%\E%[?25l%\E%[%%~G%\E%7' "!Original[0]!"
  )Else %@Substring% /A /O /R '!Original[0]!= ' /I '['%\E%8%\E%[5X%\E%[?25l%\E%7' "!Original[0]!"
 )

Echo(%\E%[7;1H%\E%[?25h

Endlocal & Goto:Eof


:AutoMacro <filepath> <macroname> [macroname]
REM :: Version 2.1 27/07/2024
REM :: Author T3RRY
REM :: Contributors: Einstein1969 Grub4K
REM :: inspired by https://ss64.org/viewtopic.php?t=65
REM :: https://discord.gg/batch
REM :: https://discord.com/channels/288498150145261568/1264550373126049813

Set "AutoMacro.debug=true"
REM :: if above variable is defined, macro lines will be outputted to the below file for debugging,
REM    where 'macro' is replaced with the macros name.
REM    in the following format, where # is the actual line number:
REM      raw.#: the raw text of the line
REM      exp.#: the line after expansions occur
REM      =====
REM      macroName=defined lines
REM      =====
Set "debug.file=%~dp0debug_%%~1.dat"
Set "append.debug.file=>> "!debug.file!""

If not "!!"=="" (
  2>&1 Echo(AutoMacro requires DelayedExpansion to be enabled
  Pause
  Exit /b 1
)
If  "%~1"=="" (
  2>&1 Echo(Usage: CALL %0 "path\to\macroLib.ext" macroname
  Pause
  Exit /b 1
)

REM Syntax for defining macros with AutoMacro:
REM @macroname { [ Dependencies: <@macroname> [@macroname] ]
REM   [ @macroname usage: <arginfo> ]
REM   <;
REM     multiline
REM     comments
REM   ;>
REM   macro function body
REM   ::  - a comment
REM   //  - a comment
REM   REM - a comment
REM } @macroname [/args] [/argRequired] [/selfRef] [/help] [/?] [/expand] [/flush]
REM 
REM note: 'macroname {' and '} macroname' are opening and closing tags.
REM        Each such tag MUST be positioned at the beginning of the line.
REM        All unremarked lines after the Opening tag (after the last instance of "@macroname usage:" until the mathcing
REM        closing tag will be defined to the macro.
REM        If usage info is provided on the line following the opening tag, it will be defined to macroname_usage
REM        /args : wraps the macro with a For loop to capture args in @macroname.args
REM /argRequired : Reject execution if no Args provided. requires /args usage; over-rules /help if both used.
REM     /selfRef : Substitutes @. in macros to macroname. - Do not use with variable names that contain "()<>" etc.
REM        /help : displays usage info if @macroname.args not defined. requires /args usage
REM .||       /? : creates a help file to be displayed by using the HELP macro, IE %Help% macroname
REM      /expand : expands metavariables: %~n0 %~x0 %~dp0 %~f0
REM       /flush : undefine all macro specific temp variables prefixed with @. or @macroname. after executing macro
REM Dependencies : Defines supplied macro Arguments to enable embedding in the Host macro definiton using
REM                Delayed Expansion. Dependencies are assumed to be in the same file as the host
REM       
REM *** comment lines: " :: " // ", or " REM ", or <; multiline comments ;> will be excluded from the macro definiton.
REM                     leading and trailing whitespace is expected for single line comments within macros.
REM multiline remarks:  initiate a multiline comment using: <;
REM                    terminate a multiline comment using: ;>
REM 
REM ! escaping:
REM            Single escape any expansion of delayed vairable you wish to expand at runtime, IE: ^!@.args^!
REM            Embedded macros should not be escaped. 
REM To pass arguments containing poison characters to a macro:
REM            double quote the argument string
REM            triple escape any ! characters
REM            example:
REM           %@macroname% "some ^^^ <> & posion ^^^!"
REM 
REM AutoMacro's can self reference [via string substitution] use: @. to automatically replace @. with the macroname.
REM AutoMacro's using vt sequences should not use the escape character directly. use !\E! in it's place.
REM or ^!\E^! in the case where the macro may be a dependency of another macro

Set HELP=For %%. in (1 2)Do if %%. EQU 2 (For %%H in (^^^!helpfiles^^^!)Do If exist "%TEMP%\%%H.hlp" More ^< "%TEMP%\%%H.hlp"^)Else Set helpfiles=

REM the below defines the escape character 0x1B to the variable \E
REM providing the FULL path to cmd ensures the definition doesn't fail if the CD command is used prior to
REM its definition. [ windows 11 issue ]
For /F %%a in ('Echo prompt $E^| %systemroot%\system32\cmd.exe')Do Set \E=%%a
(Set LF=^


%= above empty lines required =%)

If not exist "%~f1" (
  2>&1 Echo( Macro libary: "%~f1" not found.
  Exit /b 1
)
Set "AutoMacros=%*"
Set "AutoMacros=!AutoMacros:%1 =!"

  For %%1 in (!AutoMacros!)Do If "!%%~1!" == "" (
    Set "AutoMacro=%%~1"
    Set "!AutoMacro!="
    For /f "tokens=1,* Delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /blinc:"!AutoMacro! {" "%~f1"')Do (
      Set "!AutoMacro!.start=%%I"
      Set "%%~1_Dependencies=%%J"
      If not "!%%~1_Dependencies:Dependencies:=!" == "!%%~1_Dependencies!" (
        If not defined AutoMacro.Parent Set "AutoMacro.Parent=%%~1"
        Set "!AutoMacro!_Dependencies=!%%~1_Dependencies:*Dependencies:=!"
      )Else Set "!AutoMacro!_Dependencies="
      Set "!AutoMacro!_usage=!AutoMacro! Usage"
      For /f "tokens=1,* Delims=:" %%U in ('%SystemRoot%\System32\findstr.exe /linc:"!AutoMacro! usage:" "%~f1"')Do (
        Set "!AutoMacro!.start=%%U"
        Set "Line=%%V"
        Set "!AutoMacro!_usage=!%%~1_usage!!line:*:=!!LF!"
      )
    )
    If "!%%~1.start!" == "" (
      2>&1 Echo(macro: !AutoMacro! not found in "%~f1"
      Pause
      Exit
    )
    If not "!%%~1_Dependencies!" == "" For %%D in (!%%~1_Dependencies!)Do (
      Call:AutoMacro "%~1" %%D
      Set "AutoMacro=%%~1"
    )
    Set "!AutoMacro!.end="
    For /f "tokens=1,* Delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /NIRC:"^}\ !AutoMacro!\^>" "%~f1"')Do (
      Set "!AutoMacro!.end=%%I"
      Set "!AutoMacro!.switches=%%~J"
      Echo Defining: !Automacro!
      If not "!%%~1.switches:/=!" == "!%%~1.switches!" (Set "!AutoMacro!.switches=!%%~1.switches:*}=!")Else Set "!AutoMacro!.switches="
    )
    If defined !AutoMacro!_usage If not "!%%~1_switches:/?=!" == "!%%~1_switches!" (
      >"%TEMP%\!AutoMacro!.hlp" Echo(!%%~1_usage!
    )
    <"%~f0" (
      If defined AutoMacro.debug break > "%debug.file%"
      For /l %%i in (1 1 !%%~1.end!)Do (
        Set "line="
        Set /p "line="
        If defined line (
          If not "!line:<;=!" == "!line!" (
            Set "line="
            Set "remarking=active"
          )
          if defined line If not "!line:;>=!" == "!line!" (
            Set "line="
            Set "remarking="
          )
          If not "!line: :: =!" == "!line!" Set "line="
          If not "!line: // =!" == "!line!" Set "line="
          If not "!line: REM =!" == "!line!" Set "line="
        )
        If defined remarking Set "line="
        If defined line If %%i GTR !%%~1.start! If %%i LSS !%%~1.end! (
          If not "!%%1.switches:/expand=!" == "!%%~1.switches!" (
            Set "line=!line:%%~n0=%~n0!"
            Set "line=!line:%%~x0=%~x0!"
            Set "line=!line:%%~dp0=%~dp0!"
            Set "line=!line:%%~f0=%~f0!"
          )
          If defined line (
            If defined AutoMacro.Debug %append.debug.file% Echo(raw.%%i: !line!
            If defined AutoMacro.Debug For /f "delims=" %%G in ("!line!")Do (
              Set "AutoMacro.out=%%G"
              %append.debug.file% Echo(exp.%%i: !AutoMacro.out!!LF!
            )
            For /f "tokens=1,* delims= " %%G in (". !line!")Do Set "Line=%%H"
            Set "!AutoMacro!=!%%~1!!line![LF]"
          )
        )
      )
    )
    Set "!AutoMacro!=!%%~1:%%%%=%%!"

    If not "!%%~1.switches!" == "" (
      If not "!%%~1.switches:/flush=!" == "!%%~1.switches!" (
        Set "!AutoMacro!=!%%~1!For /f "tokens=1 Delims==" %%V in ('Set @.')Do Set "%%V="[LF]"
      )
      If not "!%%~1.switches:/argRequired=!" == "!%%~1.switches!" (
        Set "!AutoMacro!=If defined @.Args ([LF]!%%~1!"
        Set "!AutoMacro!=!%%~1!)[LF]"
      )
      If not "!%%~1.switches:/help=!" == "!%%~1.switches!" If "!%%~1.switches:/argRequired=!" == "!%%~1.switches!" (
        Set "!AutoMacro!=If not "^^^!@.Args^^^!"=="" ([LF]!%%~1!"
        Set "!AutoMacro!=!%%~1!)Else Echo(^!%%~1_usage^![LF]"
      )
      If not "!%%~1.switches:/args=!" == "!%%~1.switches!" (
        Set "!AutoMacro!=For %%. in (1 2)Do if %%.==2 ([LF]!%%~1!"
        Set "!AutoMacro!=!%%~1!)Else Set @.Args=[LF]"
      )
    )
    Set "!AutoMacro!=!%%~1:~0,-4!"
    If not "!%%~1.switches:/selfRef=!" == "!%%~1.switches!" Set "!AutoMacro!=!%%~1:@.=%%~1.!"
    Set ^"!AutoMacro!=!%%~1:[LF]=^%LF%%LF%!"
    If defined AutoMacro.debug %append.debug.file% (
       Echo(
       Echo(======================================================================================
       Set !AutoMacro!
       Echo(======================================================================================
       Echo(

    )
    Set "!AutoMacro!.start="
    Set "remarking="
    Set "!AutoMacro!.end="
    Set "!AutoMacro!.switches="
    Set "!AutoMacro!_Dependencies="
  )

Exit /b 0

@Strlen {
  @Strlen usage: <sourceVar> <returnVar>
  <;
    Macro Version: 2.0 27/07/2024
    Original Author: JEB
    Contributor [macro conversion]:  T3RRY
    Refernece: https://www.dostips.com/forum/viewtopic.php?t=1429&start=15#p6267
  ;>
  For /f "tokens=1,2,3" %%i in ("^!@.Args^!")Do (
    Set "@.t=^!%%i^!"
    If defined @.t (
      Set "%%j=1"
      For %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)Do (
        If not "^!@.t:~%%P,1^!" == "" (
          Set /a "%%j+=%%P"
          Set "@.t=^!@.t:~%%P^!"
        )
      )
    )Else set "%%j=0"
  )
} @strlen /args

@template { Dependencies: @strLen @print
  @template usage: --varname:"a string" --math.varname:"(sum)" /print /debug /len
  @template usage:                  --varname[#]:"a string" --varname[#]:"b string"
  @template usage:                  --:"a string" --math: ~ use Default returnvar: $return[i] ; where i = Arg index
  @template usage: 
  @template usage:  * Note:         Variable names containing [#] will self index with like variable names
  <;
    Macro Version: 2.0 27/07/2024
    Author: T3RRY aka T3RRYT3RR0R
    License: Creative Commons 4.0 international
             https://creativecommons.org/licenses/by/4.0/legalcode.en
  ;>
  For %%S in ("print" "len" "debug")Do If /I not "^!@.Args: /%%~S=^!" == "^!@.args^!" (
    Set "@.Args=^!@.Args: /%%~S=^!"
    Set "@.%%~S=1"
  )
  Set "@.Args=^!@.Args:"--=" --^!"
  Set "@.Args=^!@.Args::"=: "^!"
  Set "@.Args=^!@.Args: --=`--^!"
  Set "@.Args=^!@.Args:`--math:=`--math.$Return[#]:^!"
  Set "@.Args=^!@.Args:`--:=`--$Return[#]:^!"
  Set "@.Args=^!@.Args:--.=--VoidArg:.^!"
  Set "@.Args=^!@.Args::\=;\^!"
  Set "@.Args=^!@.Args: .--= .`--^!"
  Set "@.Args=^!@.Args: .`=:.`^!"
  !@StrLen! @.Args @.ArgCount
  Set "@.t=^!@.Args:--=^!"
  !@StrLen! @.t @.i
  Set /A "@.ArgCount=(@.ArgCount-@.i)/2"
  For /l %%i in (1 1 ^!@.ArgCount^!)do For /f "tokens=1,2 Delims=:`" %%1 in ("^!@.Args:*--=^!")Do (
    If not "%%1"=="VoidArg" (
      Set "@.type=%%1"
      If not "^!@.type:[#]=^!"=="^!@.type^!" (
        Set "@.type=^!@.type:[#]=[%%i]^!"
      )
      If "^!@.type:math=^!" == "^!@.type^!" (
        Set "@.%%i=^!@.type^!"
        If not "^!@.type:[%%i]=^!"=="^!@.type^!" For /f "delims=" %%V in ("^!@.%%i:[%%i]=^!")Do (
          Set /A "^!@.%%i:[%%i]=^![i]+=1","%%V[i].end=%%i"
          If "^!%%V[i].start^!"=="" Set "%%V[i].start=%%i"
        )
        Set "@.A.%%i=%%~2"
        Set "@.A.%%i=^!@.A.%%i:;\=:\^!"
        Set "^!@.type^!=%%~2"
        For /f "Delims=" %%V in ("^!@.type^!")Do Set "^!@.type^!=^!%%V:;\=:\^!"
      )Else (
        Set "@.%%i=^!@.type:math.=^!"
        If not "^!@.type:[%%i]=^!"=="^!@.type^!" For /f "delims=" %%V in ("^!@.%%i:[%%i]=^!")Do (
          Set /A "^!@.%%i:[%%i]=^![i]+=1","%%V[i].end=%%i"
          If "^!%%V[i].start^!"=="" Set "%%V[i].start=%%i"
        )
        2> nul Set /A "@.A.%%i=%%~2","^!@.%%i^!=@.A.%%i" || Set /A "^!@.%%i^!=0","@.A.%%i=0" && If not "^!@.debug^!"=="" (1>&2 Echo(invalid expression @ Arg.%%i: ^!@.type^!="%%~2")
      )
    )Else Set "@.%%i="
    Set "@.Args=^!@.Args:*--%%1:%%2=^!"
    If not "^!@.Len^!"=="" (
      !@StrLen! @.A.%%i ^!@.%%i^!.Len
    )
    If not "^!@.Print^!"=="" if "^!@.%%i:color=^!"=="^!@.%%i^!" !@print! 38;5;^!color^! ^!@.A.%%i^!
  )
} @template /args /help /flush /selfRef

@power {
  @power usage: <integer> <power> <returnVar>
  <;
    Macro Version: 2.0 24/07/2024
    Author: T3RRY aka T3RRYT3RR0R
    License: Creative Commons 4.0 international
             https://creativecommons.org/licenses/by/4.0/legalcode.en
  ;>
  If not defined power Set "power=p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p*p"
  For /f "tokens=1,2,3" %%1 in ("^!@.Args:* =^!")Do (
    Set /a "n=(%%2*2)-1","p=%%1"
    For %%n in (^!n^!)Do Set /A "%%3=^!power:~0,%%n^!"
  )
} @power /args

@log {
  @log usage: <base> <x> <returnVar>
  <;
    Macro Version: 2.0 24/07/2024
    Author: T3RRY aka T3RRYT3RR0R
    License: Creative Commons 4.0 international
             https://creativecommons.org/licenses/by/4.0/legalcode.en
  ;>
  For /f "tokens=1,2,3" %%1 in ("^!@.args^!")Do (
    Set /A "@.b=%%1"
    Set "%%3="
    For /l %%i in (1 1 16)Do if not defined %%3 For /l %%j in (1 1 16)Do if not defined %%3 (
      If not ^!@.b^! EQU %%2 (
        Set /A "@.b*=%%1"
      )Else Set /A "%%3=(%%j*%%i)"
    )
  ) 
} @log /args

@print {
  @print usage: <vtColor> <string>
  <;
    Macro Version: 2.0 26/07/2024
    Author: T3RRY aka T3RRYT3RR0R
    License: Creative Commons 4.0 international
             https://creativecommons.org/licenses/by/4.0/legalcode.en
  ;>
  For %%_ in (1 2)Do if %%_ == 2 (
    For /f "tokens=1,* Delims= " %%1 in ("^!@.Args^!")Do (
      Set "@.o=%%~2"
      Echo(^!\E^![%%~1m^!@.o^!^!\E^![0m
    )
  )Else Set @.Args=
} @print /selfRef

@_power2 {
  @_power2 usage: Set /a "result=!@power2:x=integer!"
    1073741824>>((29-x)+1)
  )
} @_power2

@substring { dependencies: @strlen
  @substring usage: [/A] [/O] [/N] [/L] [/P] [/K] [[/E] [option]] [/M] [/R 'search=replace'~int,-int'~int,-int'~int'~-int'] [/I 'INT'string'] Arg "or Arg phrase"
  @substring usage:  
  @substring usage:  Switches apply after their occurance, and do not affect
  @substring usage:  arguments or other switches which precede them.
  @substring usage:  [/SWITCH-] Use "-" after a switch to disable the switch
  @substring usage:  $* = Arg or "Arg phrase"
  @substring usage:  
  @substring usage:  /E /P /K optional switches for /I and /R use prior /I or /R
  @substring usage:      Default # of substring options supported by /I and /R is 5
  @substring usage:  /A Disable Array index incrementing.
  @substring usage:  /E extend number of substring options for /I and /R to 25
  @substring usage:  /E [INT] extend number of options for /I and /R to INT
  @substring usage:  /P print current string after each substring modification
  @substring usage:  /K keep original values in $Return[i].Raw + $Return.Raw.Len
  @substring usage:  /O output the processed argument string.
  @substring usage:  /N Emit a Newline after output from /O
  @substring usage:  /M mirror the argument {string reverse}
  @substring usage:  /R Replace - standard Substring modification syntax
  @substring usage:  /I 'INT'substring' Insert Substring at position INT
  @substring usage:  /I '['substring' Prepend substring to subsequent $*
  @substring usage:  /I ']'substring'  Append substring to subsequent $*
  @substring usage:     insertion ALWAYS precedes /R Substring Modifications
  @substring usage:  Unquoted $* following a switch or switch option
  @substring usage:    must be seperated using the backtick character '`'
  @substring usage:  "`" Backtick is the internal argument seperator and
  @substring usage:               cannot be contained within an argument or switch.
  @substring usage:  "'" Single Quote is the Switch option seperator
  @substring usage:               and cannot be contained within Switch options.
  @substring usage:  Arguments or /I options containing only "$_" will be
  @substring usage:  expanded to the modified state of the last argument.
  <;
    Macro Version: 2.0 27/07/2024
    Author: T3RRY aka T3RRYT3RR0R
    License: Creative Commons 4.0 international
             https://creativecommons.org/licenses/by/4.0/legalcode.en
  ;>
  If not defined $Return.i Set "$Return.i=0"
  Set "$*=^!@.Args^!"
  Set "$*=^!$*:" "=`^!"
  Set ^"$*=^!$*:"=`^!"
  Set "$*=^!$*: /=`/^!"
  Set "$*=^!$*: `=`^!"
  Set "$*=^!$*:``=`^!"
  IF "^!$*:~-1^!"==" " Set "$*=^!$*:~0,-1^!"
  IF "^!$*:~0,1^!"=="`" Set "$*=^!$*:~1^!"
  IF "^!$*:~-1^!"=="`" Set "$*=^!$*:~0,-1^!"
  Set "$?=^!$*^!"
  !@strlen! $? ${ArgC}
  Set "$?=^!$*:`=^!"
  !@StrLen! $? $`
  Set /A "${ArgC}-=$`"
  For /l %%i in (0 1 ^!${ArgC}^!)Do If defined $* For /f "tokens=1 Delims=`" %%G in ("^!$*^!")Do (
    Set "$?=%%G"
    Set "$@=%%G"
    If "^!$@^!" == "$_" If defined $_ Set "$@=^!$_^!"
    !@StrLen! $? $len
    Set "$*=^!$*:*`=^!"
    If not "^!$@:~0,1^!"=="/" (
      Set "$?=^!$@^!"
      If Defined $\S[M] (
        Set "$oLen=^!$Len^!"
        If "%%G"=="$_" (
           Set "$?=^!$_^!"
           !@StrLen! $? $oLen
        )
        Set "$.="
        For /l %%i in (^!$oLen^! -1 0)Do Set "$.=^!$.^!^!$@:~%%i,1^!"
        Set "$@=^!$.^!"
      )
      Set "$\Insert=^!$\S[I]^!"
      If Defined $\Insert If "^!$\Insert:''=^!" == "^!$\Insert^!" (
        Set "$\S\options.i=5"
        If defined $\S[E] Set "$\S\options.i=^!$\S[E]:true=25^!"
        For /l %%i in (1 1 ^!$\S\options.i^!)Do If defined $\Insert For /f "tokens=1,2 Delims='" %%V in ("^!$\Insert^!")Do (
          Set "$\S[I]pos=%%V"
          Set "$?=^!$@^!"
          !@StrLen! $? $cLen
          Set "$?=%%V'%%W"
          For /f "delims=" %%I in ("^!$cLen^!")Do (
            Set "$\S[I]pos=^!$\S[I]pos:]=%%I^!"
            Set "$\S[I]pos=^!$\S[I]pos:[=0^!"
            Set /A "$Lead=$\S[I]pos","$Tail=(^!$cLen^!-^!$\S[I]pos^!)"
          )
          If ^!$\S[I]pos^! EQU ^!$cLen^! For /f "delims=" %%I in ("^!$\S[I]pos^!")Do Set "$@=^!$@^!%%W"
          If ^!$\S[I]pos^! EQU 0 For /f "delims=" %%I in ("^!$\S[I]pos^!")Do Set "$@=%%W^!$@^!"
          If ^!$\S[I]pos^! GTR 0 If ^!$\S[I]pos^! LSS ^!$cLen^! For /f "tokens=1,2" %%I in ("^!$Lead^! ^!$Tail^!")Do Set "$@=^!$@:~0,%%I^!%%W^!$@:~-%%J^!"
          For /f "Delims=" %%E in ("^!$_^!")Do Set "$@=^!$@:$_=%%E^!"
          If "^!$\Insert:~0,1^!"=="'" Set "$\Insert=^!$\Insert:~1^!"
          If defined $\Insert Set "$\Insert=^!$\Insert:*'=^!"
          If defined $\Insert Set "$\Insert=^!$\Insert:*'=^!"
          If "^!$\S[P]^!"=="true" If /i not "^!$?^!" == "^!$@^!" Echo(^!$@^!
      )   )
      Set "$@.R=^!$\S[R]^!"
      If defined $@.R (
          Set "$\S\options.i=5"
          If defined $\S[E] Set "$\S\options.i=^!$\S[E]:true=25^!"
          If Defined $\S[R] For /l %%i in (1 1 ^!$\S\options.i^!)Do If defined $@.R For /f "tokens=1 Delims='" %%V in ("^!$@.R^!")Do (
        Set "$?=%%V
        For /f "delims=" %%R in ("^!$?^!")Do Set "$@=^!$@:%%R^!"
        If "^!$@.R:~0,1^!"=="'" Set "$@.R=^!$@.R:~1^!"
        If defined $@.R Set "$@.R=^!$@.R:*'=^!"
        If defined $@.R Set "$@.R=^!$@.R:*'=^!"
        If "^!$\S[P]^!"=="true" If /i "^!$?^!" NEQ "^!$@^!" Echo(^!$@^!
      )   )
      If /i not "^!$\S[A]^!"=="true" Set /A "$Return.i+=1"
      Set "$Return[^!$Return.i^!]=^!$@^!"
      If "^!$\S[l]^!"=="true" (
        set /a "$sLen=$Len"
        If not "^!$@^!" == "%%G" (
          If "^!$\S[K]^!"=="true" (
            Set "$Return[^!$Return.i^!].RAW.len=^!$Len^!"
            Set "$Return[^!$Return.i^!].RAW=%%G"
            If "%%G"=="$_" (
              Set "$?=^!$_^!"
              !@StrLen! $? $oLen
              Set "$Return[^!$Return.i^!].RAW.len=^!$oLen^!"
              Set "$Return[^!$Return.i^!].RAW=^!$_^!"
            )
          )
          Set "$?=^!$@^!"
          !@StrLen! $? $sLen
        )
        Set "$Return[^!$Return.i^!].len=^!$sLen^!"
      )
      Set "$_=^!$@^!"
      If "^!$\S[O]^!"=="true" <nul Set /p "=^!$@^! "
      If "^!$\S[N]^!" == "true" Echo(
    )Else (
      For /f "tokens=1,* delims=/ " %%1 in ("^!$@^!")Do (
        Set "$\S[%%1]=%%~2"
        if not defined $\S[%%1] Set "$\S[%%1]=true"
      )
    )
  )
  For %%G in (K P A I R M E L O N)Do Set "$\S[%%~G]="
} @substring /args /?

Post Reply