Passing arguments to a macro hidden in the text
Clash Royale CLAN TAG#URR8PPP
up vote
4
down vote
favorite
Context:
I'm trying to write a macro that behaves somewhat like C's printf
family of functions. For instance, the following C code:
#include <stdio.h>
int main()
printf("Hello %s! Today's a good day to write obscure %s macros.n",
"World","TeX");
prints
Hello World! Today's a good day to write obscure TeX macros.
by replacing the first %s
by "World"
and the second %s
by "TeX"
.
I'm trying to provide a similar syntax:
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
which should print the same sentence in TeX. Right now I'm failing because TeX is not C :)
The problem:
I can't find a way to pass the items in the second argument of Printf
to %
because the %
macro can be hidden anywhere in the middle of the text.
A simple definition for Printf
and %
would be:
defPrintf#1#2%
#1% What do I do with #2?
def%% How do I define this macro?
:(%
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
bye
then the output would be:
The question is: how do I define Printf
and %
such that it prints the correct sentence?
Requirements (because I'm picky :P
):
The strongest requirement is that I would like the
Printf
function to be expandable, so that:edeftempaPrintfObscure %space Macros.TeX
showtempawould print:
> tempa=macro:
->Obscure TeX Macros..It has to work inside brace groups. I tried a delimited macro approach that kind of worked, but failed miserably if the
%
appeared inside a brace pair1.I would also like engine independence.
The syntax, on the other hand, can change slightly. That is, the
Printftextreplacement
. I would like to keep the%
thingy:)
What I tried:
1Here's my attempt using %
delimited macros. I like this approach better because I don't have to redefine the %
control character anywhere. The downside is that it fails miserably when the %
token appears inside a braced group. What a bold...
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1 #2
__printf_step:nnn 0 #2 #1
cs_new:Npn __printf_step:nnn #1 #2 #3
__printf_step:nnw #1 #2 #3 % q_nil
cs_new:Npn __printf_step:nnw #1 #2 #3 % #4
#3
quark_if_nil:NF #4
exp_args:Nf __printf_percent:nn
int_eval:n #1 + 1 #2
exp_args:Nf __printf_step:nnw
int_eval:n #1 + 1 #2 #4
cs_new:Npn __printf_percent:nn #1 #2
clist_item:nn #2 #1
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
This prints:
macros expansion expl3
add a comment |Â
up vote
4
down vote
favorite
Context:
I'm trying to write a macro that behaves somewhat like C's printf
family of functions. For instance, the following C code:
#include <stdio.h>
int main()
printf("Hello %s! Today's a good day to write obscure %s macros.n",
"World","TeX");
prints
Hello World! Today's a good day to write obscure TeX macros.
by replacing the first %s
by "World"
and the second %s
by "TeX"
.
I'm trying to provide a similar syntax:
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
which should print the same sentence in TeX. Right now I'm failing because TeX is not C :)
The problem:
I can't find a way to pass the items in the second argument of Printf
to %
because the %
macro can be hidden anywhere in the middle of the text.
A simple definition for Printf
and %
would be:
defPrintf#1#2%
#1% What do I do with #2?
def%% How do I define this macro?
:(%
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
bye
then the output would be:
The question is: how do I define Printf
and %
such that it prints the correct sentence?
Requirements (because I'm picky :P
):
The strongest requirement is that I would like the
Printf
function to be expandable, so that:edeftempaPrintfObscure %space Macros.TeX
showtempawould print:
> tempa=macro:
->Obscure TeX Macros..It has to work inside brace groups. I tried a delimited macro approach that kind of worked, but failed miserably if the
%
appeared inside a brace pair1.I would also like engine independence.
The syntax, on the other hand, can change slightly. That is, the
Printftextreplacement
. I would like to keep the%
thingy:)
What I tried:
1Here's my attempt using %
delimited macros. I like this approach better because I don't have to redefine the %
control character anywhere. The downside is that it fails miserably when the %
token appears inside a braced group. What a bold...
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1 #2
__printf_step:nnn 0 #2 #1
cs_new:Npn __printf_step:nnn #1 #2 #3
__printf_step:nnw #1 #2 #3 % q_nil
cs_new:Npn __printf_step:nnw #1 #2 #3 % #4
#3
quark_if_nil:NF #4
exp_args:Nf __printf_percent:nn
int_eval:n #1 + 1 #2
exp_args:Nf __printf_step:nnw
int_eval:n #1 + 1 #2 #4
cs_new:Npn __printf_percent:nn #1 #2
clist_item:nn #2 #1
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
This prints:
macros expansion expl3
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
Context:
I'm trying to write a macro that behaves somewhat like C's printf
family of functions. For instance, the following C code:
#include <stdio.h>
int main()
printf("Hello %s! Today's a good day to write obscure %s macros.n",
"World","TeX");
prints
Hello World! Today's a good day to write obscure TeX macros.
by replacing the first %s
by "World"
and the second %s
by "TeX"
.
I'm trying to provide a similar syntax:
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
which should print the same sentence in TeX. Right now I'm failing because TeX is not C :)
The problem:
I can't find a way to pass the items in the second argument of Printf
to %
because the %
macro can be hidden anywhere in the middle of the text.
A simple definition for Printf
and %
would be:
defPrintf#1#2%
#1% What do I do with #2?
def%% How do I define this macro?
:(%
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
bye
then the output would be:
The question is: how do I define Printf
and %
such that it prints the correct sentence?
Requirements (because I'm picky :P
):
The strongest requirement is that I would like the
Printf
function to be expandable, so that:edeftempaPrintfObscure %space Macros.TeX
showtempawould print:
> tempa=macro:
->Obscure TeX Macros..It has to work inside brace groups. I tried a delimited macro approach that kind of worked, but failed miserably if the
%
appeared inside a brace pair1.I would also like engine independence.
The syntax, on the other hand, can change slightly. That is, the
Printftextreplacement
. I would like to keep the%
thingy:)
What I tried:
1Here's my attempt using %
delimited macros. I like this approach better because I don't have to redefine the %
control character anywhere. The downside is that it fails miserably when the %
token appears inside a braced group. What a bold...
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1 #2
__printf_step:nnn 0 #2 #1
cs_new:Npn __printf_step:nnn #1 #2 #3
__printf_step:nnw #1 #2 #3 % q_nil
cs_new:Npn __printf_step:nnw #1 #2 #3 % #4
#3
quark_if_nil:NF #4
exp_args:Nf __printf_percent:nn
int_eval:n #1 + 1 #2
exp_args:Nf __printf_step:nnw
int_eval:n #1 + 1 #2 #4
cs_new:Npn __printf_percent:nn #1 #2
clist_item:nn #2 #1
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
This prints:
macros expansion expl3
Context:
I'm trying to write a macro that behaves somewhat like C's printf
family of functions. For instance, the following C code:
#include <stdio.h>
int main()
printf("Hello %s! Today's a good day to write obscure %s macros.n",
"World","TeX");
prints
Hello World! Today's a good day to write obscure TeX macros.
by replacing the first %s
by "World"
and the second %s
by "TeX"
.
I'm trying to provide a similar syntax:
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
which should print the same sentence in TeX. Right now I'm failing because TeX is not C :)
The problem:
I can't find a way to pass the items in the second argument of Printf
to %
because the %
macro can be hidden anywhere in the middle of the text.
A simple definition for Printf
and %
would be:
defPrintf#1#2%
#1% What do I do with #2?
def%% How do I define this macro?
:(%
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
bye
then the output would be:
The question is: how do I define Printf
and %
such that it prints the correct sentence?
Requirements (because I'm picky :P
):
The strongest requirement is that I would like the
Printf
function to be expandable, so that:edeftempaPrintfObscure %space Macros.TeX
showtempawould print:
> tempa=macro:
->Obscure TeX Macros..It has to work inside brace groups. I tried a delimited macro approach that kind of worked, but failed miserably if the
%
appeared inside a brace pair1.I would also like engine independence.
The syntax, on the other hand, can change slightly. That is, the
Printftextreplacement
. I would like to keep the%
thingy:)
What I tried:
1Here's my attempt using %
delimited macros. I like this approach better because I don't have to redefine the %
control character anywhere. The downside is that it fails miserably when the %
token appears inside a braced group. What a bold...
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1 #2
__printf_step:nnn 0 #2 #1
cs_new:Npn __printf_step:nnn #1 #2 #3
__printf_step:nnw #1 #2 #3 % q_nil
cs_new:Npn __printf_step:nnw #1 #2 #3 % #4
#3
quark_if_nil:NF #4
exp_args:Nf __printf_percent:nn
int_eval:n #1 + 1 #2
exp_args:Nf __printf_step:nnw
int_eval:n #1 + 1 #2 #4
cs_new:Npn __printf_percent:nn #1 #2
clist_item:nn #2 #1
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
This prints:
macros expansion expl3
macros expansion expl3
asked 1 hour ago
Phelype Oleinik
19.5k54275
19.5k54275
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
5
down vote
Regular expressions are your friend! You can step through the clist
of arguments and use regex_replace_once:nnN
to replace each one in turn in a token list for the printed text to produce:
This approach is shorter too! Here's the code:
input expl3-generic.tex
ExplSyntaxOn
clist_new:N l_printf_args_clist
tl_new:N l_printf_tl
cs_new:Npn Printf #1 #2
tl_set:Nn l_printf_tl #1
clist_set:Nn l_printf_args_clist #2
clist_map_inline:Nn l_printf_args_clist
regex_replace_once:nnN c% ##1 l_printf_tl
tl_use:N l_printf_tl
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Hmm, although this may not fit the expandability requirement...
Hmmm... I didn't think of regular expressions. They do make things work. But theregex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)
â Phelype Oleinik
36 mins ago
add a comment |Â
up vote
4
down vote
Totally insane, of course, but doable! Here, I use the same approach as in for example tl_lower_case:n
. We step through the tokens, examining each one. There are three cases, a brace group, a space, and a 'normal' token. In the latter case, we split between %
and anything else. The only tricky part is tracking the substitution number inside brace groups. I do that by keeping the tracking number at the 'top level', and 'passing back' the number from inside any brace groups before they are added to the 'output'.
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1#2
__kernel_exp_not:w exp_after:wN
exp:w
exp_args:Nf __printf_outer:n __printf:nnn 1 #1 #2
cs_new:Npn __printf_outer:n #1
__printf_outer:nn #1
cs_new:Npn __printf_outer:nn #1#2
exp_end:
#1
cs_new:Npn __printf:nnn #1#2#3
group_align_safe_begin:
__printf_loop:w
#2 q_recursion_tail q_recursion_stop #3
__printf_result:nn #1
cs_new:Npn __printf_loop:w #1 q_recursion_stop
tl_if_head_is_N_type:nTF #1
__printf_N_type:N
tl_if_head_is_group:nTF #1
__printf_group:nw
__printf_space:w
#1 q_recursion_stop
cs_new:Npn __printf_N_type:N #1
quark_if_recursion_tail_stop_do:Nn #1
__printf_end:w
token_if_eq_meaning:NNTF #1 %
__printf_N_type:w
__printf_output:nw #1
__printf_loop:w
cs_new:Npn __printf_N_type:w #1 q_recursion_stop #2 __printf_result:nn #3#4
exp_args:Nff __printf_N_type:nnnnn
clist_item:nn #2 #4
int_eval:n #4 + 1
#1 #2 #3
cs_new:Npn __printf_N_type:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
cs_new:Npn __printf_group:nw #1#2 q_recursion_stop #3 __printf_result:nn #4#5
exp_args:Nf __printf_group:nnnn
__printf:nnn #5 #1 #3
#2 #3 #4
cs_new:Npn __printf_group:nnnn #1#2#3#4
__printf_group:nnnnn #1 #2 #3 #4
cs_new:Npn __printf_group:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
exp_last_unbraced:NNo cs_new:Npn __printf_space:w c_space_tl
__printf_output:nw ~
__printf_loop:w
cs_new:Npn __printf_output:nw #1#2 __printf_result:nn #3
#2 __printf_result:nn #3 #1
cs_new:Npn __printf_end:w #1 __printf_result:nn
group_align_safe_end:
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Basic idea here is from__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same astl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...
â Joseph Wrightâ¦
17 mins ago
Note: I've not worried about preventingf
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of addingTeX
), but I'll leave as an exercise for the reader :) [Hint: seetl_lower_case:n
]
â Joseph Wrightâ¦
16 mins ago
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
Regular expressions are your friend! You can step through the clist
of arguments and use regex_replace_once:nnN
to replace each one in turn in a token list for the printed text to produce:
This approach is shorter too! Here's the code:
input expl3-generic.tex
ExplSyntaxOn
clist_new:N l_printf_args_clist
tl_new:N l_printf_tl
cs_new:Npn Printf #1 #2
tl_set:Nn l_printf_tl #1
clist_set:Nn l_printf_args_clist #2
clist_map_inline:Nn l_printf_args_clist
regex_replace_once:nnN c% ##1 l_printf_tl
tl_use:N l_printf_tl
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Hmm, although this may not fit the expandability requirement...
Hmmm... I didn't think of regular expressions. They do make things work. But theregex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)
â Phelype Oleinik
36 mins ago
add a comment |Â
up vote
5
down vote
Regular expressions are your friend! You can step through the clist
of arguments and use regex_replace_once:nnN
to replace each one in turn in a token list for the printed text to produce:
This approach is shorter too! Here's the code:
input expl3-generic.tex
ExplSyntaxOn
clist_new:N l_printf_args_clist
tl_new:N l_printf_tl
cs_new:Npn Printf #1 #2
tl_set:Nn l_printf_tl #1
clist_set:Nn l_printf_args_clist #2
clist_map_inline:Nn l_printf_args_clist
regex_replace_once:nnN c% ##1 l_printf_tl
tl_use:N l_printf_tl
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Hmm, although this may not fit the expandability requirement...
Hmmm... I didn't think of regular expressions. They do make things work. But theregex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)
â Phelype Oleinik
36 mins ago
add a comment |Â
up vote
5
down vote
up vote
5
down vote
Regular expressions are your friend! You can step through the clist
of arguments and use regex_replace_once:nnN
to replace each one in turn in a token list for the printed text to produce:
This approach is shorter too! Here's the code:
input expl3-generic.tex
ExplSyntaxOn
clist_new:N l_printf_args_clist
tl_new:N l_printf_tl
cs_new:Npn Printf #1 #2
tl_set:Nn l_printf_tl #1
clist_set:Nn l_printf_args_clist #2
clist_map_inline:Nn l_printf_args_clist
regex_replace_once:nnN c% ##1 l_printf_tl
tl_use:N l_printf_tl
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Hmm, although this may not fit the expandability requirement...
Regular expressions are your friend! You can step through the clist
of arguments and use regex_replace_once:nnN
to replace each one in turn in a token list for the printed text to produce:
This approach is shorter too! Here's the code:
input expl3-generic.tex
ExplSyntaxOn
clist_new:N l_printf_args_clist
tl_new:N l_printf_tl
cs_new:Npn Printf #1 #2
tl_set:Nn l_printf_tl #1
clist_set:Nn l_printf_args_clist #2
clist_map_inline:Nn l_printf_args_clist
regex_replace_once:nnN c% ##1 l_printf_tl
tl_use:N l_printf_tl
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Hmm, although this may not fit the expandability requirement...
edited 37 mins ago
answered 42 mins ago
Andrew
28.6k34075
28.6k34075
Hmmm... I didn't think of regular expressions. They do make things work. But theregex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)
â Phelype Oleinik
36 mins ago
add a comment |Â
Hmmm... I didn't think of regular expressions. They do make things work. But theregex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)
â Phelype Oleinik
36 mins ago
Hmmm... I didn't think of regular expressions. They do make things work. But the
regex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)â Phelype Oleinik
36 mins ago
Hmmm... I didn't think of regular expressions. They do make things work. But the
regex
functions aren't expandable (as you noted yourself while I was writing this). But it's a nice idea nonetheless :)â Phelype Oleinik
36 mins ago
add a comment |Â
up vote
4
down vote
Totally insane, of course, but doable! Here, I use the same approach as in for example tl_lower_case:n
. We step through the tokens, examining each one. There are three cases, a brace group, a space, and a 'normal' token. In the latter case, we split between %
and anything else. The only tricky part is tracking the substitution number inside brace groups. I do that by keeping the tracking number at the 'top level', and 'passing back' the number from inside any brace groups before they are added to the 'output'.
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1#2
__kernel_exp_not:w exp_after:wN
exp:w
exp_args:Nf __printf_outer:n __printf:nnn 1 #1 #2
cs_new:Npn __printf_outer:n #1
__printf_outer:nn #1
cs_new:Npn __printf_outer:nn #1#2
exp_end:
#1
cs_new:Npn __printf:nnn #1#2#3
group_align_safe_begin:
__printf_loop:w
#2 q_recursion_tail q_recursion_stop #3
__printf_result:nn #1
cs_new:Npn __printf_loop:w #1 q_recursion_stop
tl_if_head_is_N_type:nTF #1
__printf_N_type:N
tl_if_head_is_group:nTF #1
__printf_group:nw
__printf_space:w
#1 q_recursion_stop
cs_new:Npn __printf_N_type:N #1
quark_if_recursion_tail_stop_do:Nn #1
__printf_end:w
token_if_eq_meaning:NNTF #1 %
__printf_N_type:w
__printf_output:nw #1
__printf_loop:w
cs_new:Npn __printf_N_type:w #1 q_recursion_stop #2 __printf_result:nn #3#4
exp_args:Nff __printf_N_type:nnnnn
clist_item:nn #2 #4
int_eval:n #4 + 1
#1 #2 #3
cs_new:Npn __printf_N_type:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
cs_new:Npn __printf_group:nw #1#2 q_recursion_stop #3 __printf_result:nn #4#5
exp_args:Nf __printf_group:nnnn
__printf:nnn #5 #1 #3
#2 #3 #4
cs_new:Npn __printf_group:nnnn #1#2#3#4
__printf_group:nnnnn #1 #2 #3 #4
cs_new:Npn __printf_group:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
exp_last_unbraced:NNo cs_new:Npn __printf_space:w c_space_tl
__printf_output:nw ~
__printf_loop:w
cs_new:Npn __printf_output:nw #1#2 __printf_result:nn #3
#2 __printf_result:nn #3 #1
cs_new:Npn __printf_end:w #1 __printf_result:nn
group_align_safe_end:
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Basic idea here is from__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same astl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...
â Joseph Wrightâ¦
17 mins ago
Note: I've not worried about preventingf
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of addingTeX
), but I'll leave as an exercise for the reader :) [Hint: seetl_lower_case:n
]
â Joseph Wrightâ¦
16 mins ago
add a comment |Â
up vote
4
down vote
Totally insane, of course, but doable! Here, I use the same approach as in for example tl_lower_case:n
. We step through the tokens, examining each one. There are three cases, a brace group, a space, and a 'normal' token. In the latter case, we split between %
and anything else. The only tricky part is tracking the substitution number inside brace groups. I do that by keeping the tracking number at the 'top level', and 'passing back' the number from inside any brace groups before they are added to the 'output'.
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1#2
__kernel_exp_not:w exp_after:wN
exp:w
exp_args:Nf __printf_outer:n __printf:nnn 1 #1 #2
cs_new:Npn __printf_outer:n #1
__printf_outer:nn #1
cs_new:Npn __printf_outer:nn #1#2
exp_end:
#1
cs_new:Npn __printf:nnn #1#2#3
group_align_safe_begin:
__printf_loop:w
#2 q_recursion_tail q_recursion_stop #3
__printf_result:nn #1
cs_new:Npn __printf_loop:w #1 q_recursion_stop
tl_if_head_is_N_type:nTF #1
__printf_N_type:N
tl_if_head_is_group:nTF #1
__printf_group:nw
__printf_space:w
#1 q_recursion_stop
cs_new:Npn __printf_N_type:N #1
quark_if_recursion_tail_stop_do:Nn #1
__printf_end:w
token_if_eq_meaning:NNTF #1 %
__printf_N_type:w
__printf_output:nw #1
__printf_loop:w
cs_new:Npn __printf_N_type:w #1 q_recursion_stop #2 __printf_result:nn #3#4
exp_args:Nff __printf_N_type:nnnnn
clist_item:nn #2 #4
int_eval:n #4 + 1
#1 #2 #3
cs_new:Npn __printf_N_type:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
cs_new:Npn __printf_group:nw #1#2 q_recursion_stop #3 __printf_result:nn #4#5
exp_args:Nf __printf_group:nnnn
__printf:nnn #5 #1 #3
#2 #3 #4
cs_new:Npn __printf_group:nnnn #1#2#3#4
__printf_group:nnnnn #1 #2 #3 #4
cs_new:Npn __printf_group:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
exp_last_unbraced:NNo cs_new:Npn __printf_space:w c_space_tl
__printf_output:nw ~
__printf_loop:w
cs_new:Npn __printf_output:nw #1#2 __printf_result:nn #3
#2 __printf_result:nn #3 #1
cs_new:Npn __printf_end:w #1 __printf_result:nn
group_align_safe_end:
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Basic idea here is from__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same astl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...
â Joseph Wrightâ¦
17 mins ago
Note: I've not worried about preventingf
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of addingTeX
), but I'll leave as an exercise for the reader :) [Hint: seetl_lower_case:n
]
â Joseph Wrightâ¦
16 mins ago
add a comment |Â
up vote
4
down vote
up vote
4
down vote
Totally insane, of course, but doable! Here, I use the same approach as in for example tl_lower_case:n
. We step through the tokens, examining each one. There are three cases, a brace group, a space, and a 'normal' token. In the latter case, we split between %
and anything else. The only tricky part is tracking the substitution number inside brace groups. I do that by keeping the tracking number at the 'top level', and 'passing back' the number from inside any brace groups before they are added to the 'output'.
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1#2
__kernel_exp_not:w exp_after:wN
exp:w
exp_args:Nf __printf_outer:n __printf:nnn 1 #1 #2
cs_new:Npn __printf_outer:n #1
__printf_outer:nn #1
cs_new:Npn __printf_outer:nn #1#2
exp_end:
#1
cs_new:Npn __printf:nnn #1#2#3
group_align_safe_begin:
__printf_loop:w
#2 q_recursion_tail q_recursion_stop #3
__printf_result:nn #1
cs_new:Npn __printf_loop:w #1 q_recursion_stop
tl_if_head_is_N_type:nTF #1
__printf_N_type:N
tl_if_head_is_group:nTF #1
__printf_group:nw
__printf_space:w
#1 q_recursion_stop
cs_new:Npn __printf_N_type:N #1
quark_if_recursion_tail_stop_do:Nn #1
__printf_end:w
token_if_eq_meaning:NNTF #1 %
__printf_N_type:w
__printf_output:nw #1
__printf_loop:w
cs_new:Npn __printf_N_type:w #1 q_recursion_stop #2 __printf_result:nn #3#4
exp_args:Nff __printf_N_type:nnnnn
clist_item:nn #2 #4
int_eval:n #4 + 1
#1 #2 #3
cs_new:Npn __printf_N_type:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
cs_new:Npn __printf_group:nw #1#2 q_recursion_stop #3 __printf_result:nn #4#5
exp_args:Nf __printf_group:nnnn
__printf:nnn #5 #1 #3
#2 #3 #4
cs_new:Npn __printf_group:nnnn #1#2#3#4
__printf_group:nnnnn #1 #2 #3 #4
cs_new:Npn __printf_group:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
exp_last_unbraced:NNo cs_new:Npn __printf_space:w c_space_tl
__printf_output:nw ~
__printf_loop:w
cs_new:Npn __printf_output:nw #1#2 __printf_result:nn #3
#2 __printf_result:nn #3 #1
cs_new:Npn __printf_end:w #1 __printf_result:nn
group_align_safe_end:
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
Totally insane, of course, but doable! Here, I use the same approach as in for example tl_lower_case:n
. We step through the tokens, examining each one. There are three cases, a brace group, a space, and a 'normal' token. In the latter case, we split between %
and anything else. The only tricky part is tracking the substitution number inside brace groups. I do that by keeping the tracking number at the 'top level', and 'passing back' the number from inside any brace groups before they are added to the 'output'.
input expl3-generic.tex
ExplSyntaxOn
cs_generate_variant:Nn clist_item:nn nf
cs_set_eq:NN clistItem clist_item:nf
cs_new:Npn Printf #1#2
__kernel_exp_not:w exp_after:wN
exp:w
exp_args:Nf __printf_outer:n __printf:nnn 1 #1 #2
cs_new:Npn __printf_outer:n #1
__printf_outer:nn #1
cs_new:Npn __printf_outer:nn #1#2
exp_end:
#1
cs_new:Npn __printf:nnn #1#2#3
group_align_safe_begin:
__printf_loop:w
#2 q_recursion_tail q_recursion_stop #3
__printf_result:nn #1
cs_new:Npn __printf_loop:w #1 q_recursion_stop
tl_if_head_is_N_type:nTF #1
__printf_N_type:N
tl_if_head_is_group:nTF #1
__printf_group:nw
__printf_space:w
#1 q_recursion_stop
cs_new:Npn __printf_N_type:N #1
quark_if_recursion_tail_stop_do:Nn #1
__printf_end:w
token_if_eq_meaning:NNTF #1 %
__printf_N_type:w
__printf_output:nw #1
__printf_loop:w
cs_new:Npn __printf_N_type:w #1 q_recursion_stop #2 __printf_result:nn #3#4
exp_args:Nff __printf_N_type:nnnnn
clist_item:nn #2 #4
int_eval:n #4 + 1
#1 #2 #3
cs_new:Npn __printf_N_type:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
cs_new:Npn __printf_group:nw #1#2 q_recursion_stop #3 __printf_result:nn #4#5
exp_args:Nf __printf_group:nnnn
__printf:nnn #5 #1 #3
#2 #3 #4
cs_new:Npn __printf_group:nnnn #1#2#3#4
__printf_group:nnnnn #1 #2 #3 #4
cs_new:Npn __printf_group:nnnnn #1#2#3#4#5
__printf_loop:w #3 q_recursion_stop
#4
__printf_result:nn #5 #1 #2
exp_last_unbraced:NNo cs_new:Npn __printf_space:w c_space_tl
__printf_output:nw ~
__printf_loop:w
cs_new:Npn __printf_output:nw #1#2 __printf_result:nn #3
#2 __printf_result:nn #3 #1
cs_new:Npn __printf_end:w #1 __printf_result:nn
group_align_safe_end:
ExplSyntaxOff
PrintfHello %! Today's a good day to write obscure % macros.
world,TeX
PrintfOh, %, my macro doesn't work bf with % text. What a %dots
drat,bold,shame
bye
answered 19 mins ago
Joseph Wrightâ¦
199k21549870
199k21549870
Basic idea here is from__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same astl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...
â Joseph Wrightâ¦
17 mins ago
Note: I've not worried about preventingf
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of addingTeX
), but I'll leave as an exercise for the reader :) [Hint: seetl_lower_case:n
]
â Joseph Wrightâ¦
16 mins ago
add a comment |Â
Basic idea here is from__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same astl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...
â Joseph Wrightâ¦
17 mins ago
Note: I've not worried about preventingf
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of addingTeX
), but I'll leave as an exercise for the reader :) [Hint: seetl_lower_case:n
]
â Joseph Wrightâ¦
16 mins ago
Basic idea here is from
__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same as tl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...â Joseph Wrightâ¦
17 mins ago
Basic idea here is from
__tl_act:NNNnn
, used internally in the kernel: one of Bruno's. You can't directly use that here, which is much the same as tl_lower_case:n
, due to the need to keep extra data on the stack. But it's fundamentally Bruno's approach ...â Joseph Wrightâ¦
17 mins ago
Note: I've not worried about preventing
f
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of adding TeX
), but I'll leave as an exercise for the reader :) [Hint: see tl_lower_case:n
]â Joseph Wrightâ¦
16 mins ago
Note: I've not worried about preventing
f
-type expansion of the replacement text. That would be doable (if for example you want to examine the tokens in the case of adding TeX
), but I'll leave as an exercise for the reader :) [Hint: see tl_lower_case:n
]â Joseph Wrightâ¦
16 mins ago
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f457787%2fpassing-arguments-to-a-macro-hidden-in-the-text%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password