T3RRYT3RR0R

Macro template with argument and switch handling

Apr 7th, 2021 (edited)
791
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ::: Author : T3RRY : Created 08/04/2021 : Version : 1.0.5
  2. ::: Version changes:
  3. ::: ADDED inbuilt substitution of {EQ} = ; {AS} * ; {FS} / and {DQ} "" for all args and switches
  4. ::: EXPANDED assessment of switch == true to support switches up to 3 characters long when switch is last switch used.
  5. ::: CORRECTED placement of substring removal of doublequotes to after assignment of leading.args
  6. :::
  7. ::: Use search / replace to substitute $Macroname for your desired macro name.
  8. ::: All macro internal variables are prefixed with $Macroname to prevent conflict with other script variables
  9.  
  10. ::: PURPOSE: Template for handling multiple arguments and switches within batch macros.
  11. :::          Batch macros perform much more efficiently than functions ; and can accept parameters [args]
  12. :::          just as a function can using a for loop to catch the assignment of the parameter value.
  13. :::          Batch macros are a scripting technique, not an innate part of cmd's command syntax and therefor
  14. :::          lack metavriables such as "%*" or "%1" or commands such as "SHIFT" to assist in the processing of arguments
  15. :::          The macro template below provides a ready to use structure for splitting macro arguments into a usable form.
  16.  
  17. ::: For advanced usage example see: https://pastebin.com/GL87S8fF
  18.  
  19. ::: Defines an array for arguments recieved : 'arg[i]' where 'i' is a 1 indexed integer
  20. ::: Defines an array for switches  used     : 'switch[l]' where 'l' is a letter / string defined as a valid switch.
  21. ::: If switch is plain [ has no subvalue ], switch[l] returns true ; else switch[l] returns value provided.
  22.  
  23. ::: Notes on arg / switch structure. As with typical cmd commands SWITCHES MUST FOLLOW ARGS.
  24. ::: - Arg order can be rigid or flexible depending on the use case and how you script assessment of the arg array.
  25. ::: - Rigid arg order is recommended for values that cant easily be distinguished as belonging to a given arg type.
  26. ::: - Switch order is flexible
  27. :::
  28. ::: As with normal batch arguments, args containing poison characters or standard delimiters must be doublequoted.
  29. :::
  30. ::: Permits switch usage structures:
  31. :::  /Switch
  32. :::  /Switch value
  33. :::  /Switch "quoted values"
  34.  
  35. :::
  36. ::: Args or Switch values containing poison characters must be doublequoted
  37. ::: Args are delimited using whitespaces except when encased in doublequotes.
  38. :::
  39. ::: Escaping: arg or switch values containing '!' shoud escape '!' and enclose in doublequotes: "SomeString^!"
  40. :::  - IE: %$Macroname% arg1 "arg 2" /C "poison & | ^! < > %:~%" /D
  41.  
  42. @Echo off
  43.  
  44. (Set \n=^^^
  45.  
  46. %= \n macro newline variable. Do not modify =%)
  47. (Set LF=^
  48.  
  49.  
  50. %= LF newline variable. Do not modify =%)
  51.  
  52. :# Example Switches for demonstrating concept. List used twice within macro switch handling. Define outside macro to
  53. :# simplify maintainance.
  54.  Set $MacroName_Switches="A" "B" "C" "D" "E" "Def"
  55.  
  56.  Set $MacroName=For %%n in (1 2)Do if %%n==2 (%\n%
  57.   For /F "Tokens=1,2 Delims==" %%G in ('Set "$Macroname_Arg[" 2^^^> nul')Do Set "%%~G="%\n%
  58.   For %%G in ( %$MacroName_Switches% )Do Set "$MacroName_Switch[%%~G]="%\n%
  59.   If not "!$MacroName_args:* /=!" == "!$MacroName_args!" (%\n: build $MacroName.Args[!$MacroName_arg[i]!] array if args present =%
  60.    Set "$MacroName_leading.args=!$MacroName_args:*/=!"%\n%
  61.    For /F "Delims=" %%G in ("!$MacroName_leading.args!")Do Set "$MacroName_leading.args=!$MacroName_args:/%%G=!"%\n%
  62.    Set ^"$MacroName_args=!$MacroName_args:"=!"%\n%
  63.    Set "$MacroName_arg[i]=0"%\n%
  64.    For %%G in (!$MacroName_leading.args!)Do (%\n%
  65.     Set /A "$MacroName_arg[i]+=1"%\n%
  66.     Set "$MacroName_arg[!$MacroName_arg[i]!]=%%~G"%\n%
  67.     For %%i in ("!$MacroName_arg[i]!")Do (%\n%
  68.      Set "$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{FS}=/!"%\n%
  69.      Set "$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{AS}=*!"%\n%
  70.      Set "$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{EQ}==!"%\n%
  71.      Set ^"$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{DQ}="!"%\n%
  72.     )%\n%
  73.    )%\n%
  74.   ) Else (%\n: remove doublequotes from args before switch processing switches =%
  75.    Set ^"$MacroName_args=!$MacroName_args:"=!"%\n%
  76.   )%\n%
  77.   Set "$MacroName_LastSwitch="%\n%
  78.   For /L %%L in (2 1 4)Do If "!$MacroName_LastSwitch!" == "" (%\n%
  79.    If "!$MacroName_Args:~-%%L,1!" == " " Set "$MacroName_LastSwitch=_"%\n%
  80.    If "!$MacroName_Args:~-%%L,1!" == "/" (%\n: Flag last switch true if no subargs; Works for character switches of up to 3 characters =%
  81.     For /F "Delims=" %%v in ('Set /A "%%L-1"')Do Set "$MacroName_Switch[!$MacroName_Args:~-%%v!]=true"%\n%
  82.     If not "!$MacroName_Args:/?=!." == "!$MacroName_Args!." Set "$MacroName_Switch[help]=true"%\n%
  83.     Set "$MacroName_Args=!$MacroName_Args:~0,-%%L!"%\n%
  84.     Set "$MacroName_LastSwitch=_"%\n%
  85.    )%\n%
  86.   )%\n%
  87.   For %%G in ( %$MacroName_Switches% )Do If not "!$MacroName_args:/%%~G =!" == "!$MacroName_args!" (%\n%
  88.    Set "$MacroName_Switch[%%~G]=!$MacroName_Args:*/%%~G =!"%\n%
  89.    If not "!$MacroName_Switch[%%~G]:*/=!" == "!$MacroName_Switch[%%~G]!" (%\n%
  90.     Set "$MacroName_Trail[%%~G]=!$MacroName_Switch[%%~G]:*/=!"%\n%
  91.     For %%v in ("!$MacroName_Trail[%%~G]!")Do (%\n%
  92.      Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]: /%%~v=!"%\n%
  93.      Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:/%%~v=!"%\n%
  94.     )%\n%
  95.     Set "$MacroName_Trail[%%~G]="%\n%
  96.     If "!$MacroName_Switch[%%~G]:~-1!" == " " Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:~0,-1!"%\n%
  97.     If "!$MacroName_Switch[%%~G]!" == "" Set "$MacroName_Switch[%%~G]=true"%\n%
  98.     If not "!$MacroName_Switch[%%~G]!" == "" If not "!$MacroName_Switch[%%~G]!" == "true" (%\n%
  99.      Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{FS}=/!"%\n%
  100.      Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{AS}=*!"%\n%
  101.      Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{EQ}==!"%\n%
  102.      Set ^"$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{DQ}="!"%\n%
  103.     )%\n%
  104.    )%\n%
  105.   )%\n: Insert Switch Assessment Below. Use conditional testing of valid switches to enact macro functions before $MacroName_args assignment =%
  106.  REM INSERT COMMANDS BETWEEN THE ABOVE AND BELOW LINES TERMINATING EACH WITH \n VARIABLE %\n%
  107.   %= EXAMPLE. Remove this line. =% Echo(!LF!Example: %%$Macroname%%!$Macroname_args!%\n%
  108.   %= EXAMPLE. Remove this line. =% Set $Macroname_Arg[%\n%
  109.   %= EXAMPLE. Remove this line. =% Set $Macroname_Switch[%\n%
  110.  %= ESCAPE AMPERSANDS AND REDIRECTION CHARACTERS.  =%) Else Set $MacroName_args=
  111.  
  112. Setlocal enableDelayedExpansion
  113.  
  114. :# For Testing from command line
  115.  if not "%~1" == ""  (
  116.   %$MacroName% %*
  117.   Goto :Eof
  118.  )
  119.  
  120. :# Proof of concept
  121. %$Macroname% "{AS} param 1 {EQ} {DQ}https:{FS}{FS}stackoverflow.com{FS}posts{FS}60793679{DQ}" "param 2" /C one /D 12 /Def
  122. %$Macroname% /B a b /E /Def "hello world & ^! > < | %%" /A 1 + 2 {EQ} 3 /Undefined switch
  123.  
  124. pause
  125. Goto :eof
  126.  
RAW Paste Data