'Calling a multi-line macro by using a dynamic name?

I'm back here for another question, this time about macros.

I'd want to call a multi-line macro by using !..! (if possible) in order to use dynamic macro names like in the following call for a single-line macro:

setlocal disabledelayedexpansion
:: Simple single-line macros for testing purpose.
set "_testA=echo A" & set "_testB=echo B"

setlocal enabledelayedexpansion
:: Choose macro _testA or _testB.
set /p char="Type A or B:"

:: Execute the chosen macro.
!_test%char%!
endlocal

endlocal

For example,

 setlocal disabledelayedexpansion
:: Line feed character.
(set CHR10=^
%=Do not remove this line, or you will be turned into a frog=%
)
 
:: End of line in a macro code.
set ^"\nmac=^^^%CHR10%%CHR10%^%CHR10%%CHR10%^^"

:: Simple multi-line macro for testing purpose, it could be replace with one receiving parameters obviously.
set _test=(echo A%\nmac%
echo B%\nmac%
echo C)

setlocal enabledelayedexpansion
:: Works as expected, displays A then B then C.
%_test%

:: Doesn't work... as expected also, displays `(echo Is Not Recognized as an Internal or External Command, Operable Program or Batch File.`
!_test!
endlocal

endlocal

The problem seems to comes from the definition of CHR10 when using with !..! (using %_test% works, obviously).

Any idea to solve this ? A solution could help me to refactor some code.

Thanks in advance for your answer.



Solution 1:[1]

The solution is easy, you always need percent expansion for the execution of a batch macro. Obviously you can't make the variable name dynamic for a percent expansion, but you can make the content dynamic.

@echo off
(set ^"$\n=^^^
%= Do not remove this line=%
)

set macro1=(echo #1 Line1 %$\n%
echo #1 Line2)

set macro2=(echo #2 Line1 %$\n%
echo #2 Line2)

setlocal EnableDelayedExpansion
%macro1%
%macro2%
set /p "macroNum=Select 1 or 2: "

set "macroName=macro%macroNum%"

REM *** Copy the content of the 'dynamic macro' to indirectMacro
set "indirectMacro=!%macroName%!"
%indirectMacro%

Btw. Your definition and use of \nmac is superfluous, because a single linefeed (with a single caret) is enough in batch macros, when they are enclosed in parenthesis.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1