Changing the effect of a command in another
up vote
2
down vote
favorite
I'm currently trying to define commands such that:
x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}
This I can do fairly easily:
newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}
However, I would like to have
x{y{F}{b}}{a} gives F^{(y=b, x=a)}
And this, I am currently not able to do.
In practice, I have many such commands x
, y
, z
, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).
Does anyone know of a way to do this in TeX?
macros superscripts
add a comment |
up vote
2
down vote
favorite
I'm currently trying to define commands such that:
x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}
This I can do fairly easily:
newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}
However, I would like to have
x{y{F}{b}}{a} gives F^{(y=b, x=a)}
And this, I am currently not able to do.
In practice, I have many such commands x
, y
, z
, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).
Does anyone know of a way to do this in TeX?
macros superscripts
1
That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54
The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I'm currently trying to define commands such that:
x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}
This I can do fairly easily:
newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}
However, I would like to have
x{y{F}{b}}{a} gives F^{(y=b, x=a)}
And this, I am currently not able to do.
In practice, I have many such commands x
, y
, z
, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).
Does anyone know of a way to do this in TeX?
macros superscripts
I'm currently trying to define commands such that:
x{F}{a} gives F^{(x=a)}
y{F}{b} gives F^{(y=b)}
This I can do fairly easily:
newcommand{x}[2]{ensuremath{{#1}^{(x={#2})}}}
However, I would like to have
x{y{F}{b}}{a} gives F^{(y=b, x=a)}
And this, I am currently not able to do.
In practice, I have many such commands x
, y
, z
, ... and I would like to be able to automatically combine them intelligently such that there is only one superscript (see example).
Does anyone know of a way to do this in TeX?
macros superscripts
macros superscripts
edited Dec 6 at 6:04
siracusa
4,76011128
4,76011128
asked Dec 4 at 13:48
Serker
132
132
1
That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54
The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07
add a comment |
1
That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54
The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07
1
1
That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54
That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54
The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07
The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07
add a comment |
4 Answers
4
active
oldest
votes
up vote
3
down vote
accepted
Have fun with it. Nested use is only correctly handled in the first argument of x
, y
etc. Create other macros with newtransformation<name>{symbol}
.
documentclass{article}
usepackage{amsmath}
newcommandnewtransformation[2]%>>>
{%
newcommand*#1{Fof{#2}}%
}%<<<
makeatletter
defq@stop{q@stop}
longdefafterfi#1fi{fi#1}
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
#2%
}%<<<
newcommandFof@printpair[3]%>>>
{%
#1=#2%
ifxq@stop#3%
else
afterfi, Fof@printpair{#3}%
fi
}%<<<
newcommand*Fof@printpairs%>>>
{%
expandafterFof@printpairFof@pairsq@stop
}%<<<
newcommand*Fof@output%>>>
{%
Fof@second^{(Fof@printpairs)}%
}%<<<
newcommandFof[3]%>>>
{%
gdefFof@pairs{{#1}{#3}}%
gdefFof@second{#2}%
setboxz@hbox
{% code analog to mathaccentV from amsmath
letFofFof@test
letuse@mathgroup@gobbletwo
letselect@group@gobblethree
frozen@everymath{}%
$#2$%
}%
Fof@output
}%<<<
makeatother
newtransformationx{x}
newtransformationy{y}
begin{document}
$x{y{F}{c}}{b}$
end{document}
To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs
. This can be done by changing the definition of Fof@test
. Change its definition to the following:
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
#2%
}%<<<
Impressive code, I think it is intended for only two variables?$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).
– Marijn
Dec 4 at 14:25
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn found the issue, forgot a#2
. Should now work fine.
– Skillmon
Dec 4 at 14:31
it does work now :)
– Marijn
Dec 4 at 14:33
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
|
show 2 more comments
up vote
4
down vote
Here's a way you could define these transformations.
I defined a macro addtransform
that normally just prints {#1}^{#2}
, but if it used inside the first argument of another addtransform
it'll instead prepend #2,
to the list of things to be placed in the superscript of the outermost addtransform
(and then print #1
). (I hope that makes sense…)
The comments in the code below might be clearer.
documentclass{article}
letcurrtransformempty
newcommand*addtransform[2]{%
ifxcurrtransformempty %% <- if we are not inside an addtransform…
gdefcurrtransform{#2}% %% <- start a list of superscripts
{#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
globalletcurrtransformempty %% <- clear the list
else %% <- otherwise…
xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
unexpandedexpandafter{currtransform}}%
#1% %% <- then print #1
fi
}
newcommand*transx[2]{addtransform{#1}{x=#2}}
newcommand*transy[2]{addtransform{#1}{y=#2}}
newcommand*transz[2]{addtransform{#1}{z=#2}}
begin{document}
[
transx{F}{a},
qquad
transx{transy{F}{b}}{a},
qquad
transx{transy{transz{F}{c}}{b}}{a}
]
end{document}
Very elegant and simple, +1. Mine is overly complicated because it actually does everything yourelse
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
– Skillmon
Dec 4 at 18:57
add a comment |
up vote
1
down vote
The syntax you propose is very complicated to maintain, perhaps a simpler one such as
transform{x=a,y=b,z=c}{F}
is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
% simpler
NewDocumentCommand{transform}{mm}
{
seq_set_from_clist:Nn l_tmpa_seq { #1 }
seq_reverse:N l_tmpa_seq
#2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
}
% recursive
NewDocumentCommand{definetransform}{m}
{
clist_map_inline:nn { #1 }
{
cs_new_protected:cpn { ##1 } ####1 ####2
{
serker_transform:nnn { ##1 } { ####1 } { ####2 }
}
}
}
seq_new:N g__serker_transform_seq
cs_new_protected:Nn serker_transform:nnn
{
seq_if_empty:NTF g__serker_transform_seq
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
{#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
seq_gclear:N g__serker_transform_seq
}
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
#2
}
}
ExplSyntaxOff
definetransform{x,y,z} % add to the list
begin{document}
[
transform{x=a}{F},
qquad
transform{x=a,y=b}{F},
qquad
transform{x=a,y=b,z=c}{F}
]
[
x{F}{a},
qquad
x{y{F}{b}}{a},
qquad
x{y{z{F}{c}}{b}}{a}
]
end{document}
add a comment |
up vote
1
down vote
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (romannumeral expansion was introduced in order to overcome the
%% concerns and worries about improperly balanced
%% if..else..fi constructs.)
%%
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
}%
newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.
In edge cases this might cause problems.
The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.
Advantage:
This is more safe even in edge cases.
Disadvantages:
In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
the checking-mechanism (UD@MoreTransformationsFork
, UD@@MoreTransformationsFork
) as well as it does check on the presence of tokens and not on their meaning.
The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x
or y
or z
or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
newcommandUD@CheckWhetherBrace[1]{%
romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
string#1.}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
}%
%%==============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%..............................................................................
%% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
newcommandUD@CheckWhetherLeadingSpace[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
newcommandUD@CheckWhetherLeadingSpaceB{}%
longdefUD@CheckWhetherLeadingSpaceB#1 {%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument does not contain "!":
%%.............................................................................
newcommandUD@GobbleToExclam{}%
longdefUD@GobbleToExclam#1!{}%
newcommandUD@CheckWhetherNoExclam[1]{%
expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckForMoreTransformations[1]{%
romannumeral0UD@CheckWhetherBrace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherLeadingSpace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherNull{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
}%
}%
}%
}%
newcommandUD@MoreTransformationsFork[1]{%
UD@CheckWhetherNoExclam{#1}{%
UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
!U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
!U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
!U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
!U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
!U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
!U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
!!!!%
}{UD@Exchange{UD@secondoftwo}}% something else with !
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
newcommandUD@@MoreTransformationsFork{}%
longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
UD@CheckForMoreTransformations{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Have fun with it. Nested use is only correctly handled in the first argument of x
, y
etc. Create other macros with newtransformation<name>{symbol}
.
documentclass{article}
usepackage{amsmath}
newcommandnewtransformation[2]%>>>
{%
newcommand*#1{Fof{#2}}%
}%<<<
makeatletter
defq@stop{q@stop}
longdefafterfi#1fi{fi#1}
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
#2%
}%<<<
newcommandFof@printpair[3]%>>>
{%
#1=#2%
ifxq@stop#3%
else
afterfi, Fof@printpair{#3}%
fi
}%<<<
newcommand*Fof@printpairs%>>>
{%
expandafterFof@printpairFof@pairsq@stop
}%<<<
newcommand*Fof@output%>>>
{%
Fof@second^{(Fof@printpairs)}%
}%<<<
newcommandFof[3]%>>>
{%
gdefFof@pairs{{#1}{#3}}%
gdefFof@second{#2}%
setboxz@hbox
{% code analog to mathaccentV from amsmath
letFofFof@test
letuse@mathgroup@gobbletwo
letselect@group@gobblethree
frozen@everymath{}%
$#2$%
}%
Fof@output
}%<<<
makeatother
newtransformationx{x}
newtransformationy{y}
begin{document}
$x{y{F}{c}}{b}$
end{document}
To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs
. This can be done by changing the definition of Fof@test
. Change its definition to the following:
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
#2%
}%<<<
Impressive code, I think it is intended for only two variables?$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).
– Marijn
Dec 4 at 14:25
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn found the issue, forgot a#2
. Should now work fine.
– Skillmon
Dec 4 at 14:31
it does work now :)
– Marijn
Dec 4 at 14:33
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
|
show 2 more comments
up vote
3
down vote
accepted
Have fun with it. Nested use is only correctly handled in the first argument of x
, y
etc. Create other macros with newtransformation<name>{symbol}
.
documentclass{article}
usepackage{amsmath}
newcommandnewtransformation[2]%>>>
{%
newcommand*#1{Fof{#2}}%
}%<<<
makeatletter
defq@stop{q@stop}
longdefafterfi#1fi{fi#1}
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
#2%
}%<<<
newcommandFof@printpair[3]%>>>
{%
#1=#2%
ifxq@stop#3%
else
afterfi, Fof@printpair{#3}%
fi
}%<<<
newcommand*Fof@printpairs%>>>
{%
expandafterFof@printpairFof@pairsq@stop
}%<<<
newcommand*Fof@output%>>>
{%
Fof@second^{(Fof@printpairs)}%
}%<<<
newcommandFof[3]%>>>
{%
gdefFof@pairs{{#1}{#3}}%
gdefFof@second{#2}%
setboxz@hbox
{% code analog to mathaccentV from amsmath
letFofFof@test
letuse@mathgroup@gobbletwo
letselect@group@gobblethree
frozen@everymath{}%
$#2$%
}%
Fof@output
}%<<<
makeatother
newtransformationx{x}
newtransformationy{y}
begin{document}
$x{y{F}{c}}{b}$
end{document}
To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs
. This can be done by changing the definition of Fof@test
. Change its definition to the following:
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
#2%
}%<<<
Impressive code, I think it is intended for only two variables?$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).
– Marijn
Dec 4 at 14:25
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn found the issue, forgot a#2
. Should now work fine.
– Skillmon
Dec 4 at 14:31
it does work now :)
– Marijn
Dec 4 at 14:33
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
|
show 2 more comments
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Have fun with it. Nested use is only correctly handled in the first argument of x
, y
etc. Create other macros with newtransformation<name>{symbol}
.
documentclass{article}
usepackage{amsmath}
newcommandnewtransformation[2]%>>>
{%
newcommand*#1{Fof{#2}}%
}%<<<
makeatletter
defq@stop{q@stop}
longdefafterfi#1fi{fi#1}
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
#2%
}%<<<
newcommandFof@printpair[3]%>>>
{%
#1=#2%
ifxq@stop#3%
else
afterfi, Fof@printpair{#3}%
fi
}%<<<
newcommand*Fof@printpairs%>>>
{%
expandafterFof@printpairFof@pairsq@stop
}%<<<
newcommand*Fof@output%>>>
{%
Fof@second^{(Fof@printpairs)}%
}%<<<
newcommandFof[3]%>>>
{%
gdefFof@pairs{{#1}{#3}}%
gdefFof@second{#2}%
setboxz@hbox
{% code analog to mathaccentV from amsmath
letFofFof@test
letuse@mathgroup@gobbletwo
letselect@group@gobblethree
frozen@everymath{}%
$#2$%
}%
Fof@output
}%<<<
makeatother
newtransformationx{x}
newtransformationy{y}
begin{document}
$x{y{F}{c}}{b}$
end{document}
To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs
. This can be done by changing the definition of Fof@test
. Change its definition to the following:
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
#2%
}%<<<
Have fun with it. Nested use is only correctly handled in the first argument of x
, y
etc. Create other macros with newtransformation<name>{symbol}
.
documentclass{article}
usepackage{amsmath}
newcommandnewtransformation[2]%>>>
{%
newcommand*#1{Fof{#2}}%
}%<<<
makeatletter
defq@stop{q@stop}
longdefafterfi#1fi{fi#1}
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpandedexpandafter{Fof@pairs{#1}{#3}}}%
#2%
}%<<<
newcommandFof@printpair[3]%>>>
{%
#1=#2%
ifxq@stop#3%
else
afterfi, Fof@printpair{#3}%
fi
}%<<<
newcommand*Fof@printpairs%>>>
{%
expandafterFof@printpairFof@pairsq@stop
}%<<<
newcommand*Fof@output%>>>
{%
Fof@second^{(Fof@printpairs)}%
}%<<<
newcommandFof[3]%>>>
{%
gdefFof@pairs{{#1}{#3}}%
gdefFof@second{#2}%
setboxz@hbox
{% code analog to mathaccentV from amsmath
letFofFof@test
letuse@mathgroup@gobbletwo
letselect@group@gobblethree
frozen@everymath{}%
$#2$%
}%
Fof@output
}%<<<
makeatother
newtransformationx{x}
newtransformationy{y}
begin{document}
$x{y{F}{c}}{b}$
end{document}
To invert the order, you'd have to make sure that the new pairs are added to the front of Fof@pairs
. This can be done by changing the definition of Fof@test
. Change its definition to the following:
newcommandFof@test[3]%>>>
{%
gdefFof@second{#2}%
xdefFof@pairs{unexpanded{{#1}{#3}}unexpandedexpandafter{Fof@pairs}}%
#2%
}%<<<
edited Dec 4 at 18:47
answered Dec 4 at 14:17
Skillmon
20.7k11941
20.7k11941
Impressive code, I think it is intended for only two variables?$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).
– Marijn
Dec 4 at 14:25
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn found the issue, forgot a#2
. Should now work fine.
– Skillmon
Dec 4 at 14:31
it does work now :)
– Marijn
Dec 4 at 14:33
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
|
show 2 more comments
Impressive code, I think it is intended for only two variables?$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).
– Marijn
Dec 4 at 14:25
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn found the issue, forgot a#2
. Should now work fine.
– Skillmon
Dec 4 at 14:31
it does work now :)
– Marijn
Dec 4 at 14:33
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
Impressive code, I think it is intended for only two variables?
$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).– Marijn
Dec 4 at 14:25
Impressive code, I think it is intended for only two variables?
$q{x{y{F}{c}}{b}}{a}$
doesn't seem to work (outputs ! Double superscript).– Marijn
Dec 4 at 14:25
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn I never tested it with more than two because I thought it should work based on the code, but now it doesn't! I'll look into it.
– Skillmon
Dec 4 at 14:29
@Marijn found the issue, forgot a
#2
. Should now work fine.– Skillmon
Dec 4 at 14:31
@Marijn found the issue, forgot a
#2
. Should now work fine.– Skillmon
Dec 4 at 14:31
it does work now :)
– Marijn
Dec 4 at 14:33
it does work now :)
– Marijn
Dec 4 at 14:33
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
This is really impressive, I'll try and figure the code out but it works really well, thank you !
– Serker
Dec 4 at 14:43
|
show 2 more comments
up vote
4
down vote
Here's a way you could define these transformations.
I defined a macro addtransform
that normally just prints {#1}^{#2}
, but if it used inside the first argument of another addtransform
it'll instead prepend #2,
to the list of things to be placed in the superscript of the outermost addtransform
(and then print #1
). (I hope that makes sense…)
The comments in the code below might be clearer.
documentclass{article}
letcurrtransformempty
newcommand*addtransform[2]{%
ifxcurrtransformempty %% <- if we are not inside an addtransform…
gdefcurrtransform{#2}% %% <- start a list of superscripts
{#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
globalletcurrtransformempty %% <- clear the list
else %% <- otherwise…
xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
unexpandedexpandafter{currtransform}}%
#1% %% <- then print #1
fi
}
newcommand*transx[2]{addtransform{#1}{x=#2}}
newcommand*transy[2]{addtransform{#1}{y=#2}}
newcommand*transz[2]{addtransform{#1}{z=#2}}
begin{document}
[
transx{F}{a},
qquad
transx{transy{F}{b}}{a},
qquad
transx{transy{transz{F}{c}}{b}}{a}
]
end{document}
Very elegant and simple, +1. Mine is overly complicated because it actually does everything yourelse
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
– Skillmon
Dec 4 at 18:57
add a comment |
up vote
4
down vote
Here's a way you could define these transformations.
I defined a macro addtransform
that normally just prints {#1}^{#2}
, but if it used inside the first argument of another addtransform
it'll instead prepend #2,
to the list of things to be placed in the superscript of the outermost addtransform
(and then print #1
). (I hope that makes sense…)
The comments in the code below might be clearer.
documentclass{article}
letcurrtransformempty
newcommand*addtransform[2]{%
ifxcurrtransformempty %% <- if we are not inside an addtransform…
gdefcurrtransform{#2}% %% <- start a list of superscripts
{#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
globalletcurrtransformempty %% <- clear the list
else %% <- otherwise…
xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
unexpandedexpandafter{currtransform}}%
#1% %% <- then print #1
fi
}
newcommand*transx[2]{addtransform{#1}{x=#2}}
newcommand*transy[2]{addtransform{#1}{y=#2}}
newcommand*transz[2]{addtransform{#1}{z=#2}}
begin{document}
[
transx{F}{a},
qquad
transx{transy{F}{b}}{a},
qquad
transx{transy{transz{F}{c}}{b}}{a}
]
end{document}
Very elegant and simple, +1. Mine is overly complicated because it actually does everything yourelse
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
– Skillmon
Dec 4 at 18:57
add a comment |
up vote
4
down vote
up vote
4
down vote
Here's a way you could define these transformations.
I defined a macro addtransform
that normally just prints {#1}^{#2}
, but if it used inside the first argument of another addtransform
it'll instead prepend #2,
to the list of things to be placed in the superscript of the outermost addtransform
(and then print #1
). (I hope that makes sense…)
The comments in the code below might be clearer.
documentclass{article}
letcurrtransformempty
newcommand*addtransform[2]{%
ifxcurrtransformempty %% <- if we are not inside an addtransform…
gdefcurrtransform{#2}% %% <- start a list of superscripts
{#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
globalletcurrtransformempty %% <- clear the list
else %% <- otherwise…
xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
unexpandedexpandafter{currtransform}}%
#1% %% <- then print #1
fi
}
newcommand*transx[2]{addtransform{#1}{x=#2}}
newcommand*transy[2]{addtransform{#1}{y=#2}}
newcommand*transz[2]{addtransform{#1}{z=#2}}
begin{document}
[
transx{F}{a},
qquad
transx{transy{F}{b}}{a},
qquad
transx{transy{transz{F}{c}}{b}}{a}
]
end{document}
Here's a way you could define these transformations.
I defined a macro addtransform
that normally just prints {#1}^{#2}
, but if it used inside the first argument of another addtransform
it'll instead prepend #2,
to the list of things to be placed in the superscript of the outermost addtransform
(and then print #1
). (I hope that makes sense…)
The comments in the code below might be clearer.
documentclass{article}
letcurrtransformempty
newcommand*addtransform[2]{%
ifxcurrtransformempty %% <- if we are not inside an addtransform…
gdefcurrtransform{#2}% %% <- start a list of superscripts
{#1}^{(currtransform)}% %% <- output (N.B. #1 may change currtransform!)
globalletcurrtransformempty %% <- clear the list
else %% <- otherwise…
xdefcurrtransform{unexpanded{#2},% %% <- prepend #2 and a comma
unexpandedexpandafter{currtransform}}%
#1% %% <- then print #1
fi
}
newcommand*transx[2]{addtransform{#1}{x=#2}}
newcommand*transy[2]{addtransform{#1}{y=#2}}
newcommand*transz[2]{addtransform{#1}{z=#2}}
begin{document}
[
transx{F}{a},
qquad
transx{transy{F}{b}}{a},
qquad
transx{transy{transz{F}{c}}{b}}{a}
]
end{document}
edited Dec 4 at 19:41
answered Dec 4 at 18:49
Circumscribe
4,2571429
4,2571429
Very elegant and simple, +1. Mine is overly complicated because it actually does everything yourelse
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
– Skillmon
Dec 4 at 18:57
add a comment |
Very elegant and simple, +1. Mine is overly complicated because it actually does everything yourelse
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).
– Skillmon
Dec 4 at 18:57
Very elegant and simple, +1. Mine is overly complicated because it actually does everything your
else
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).– Skillmon
Dec 4 at 18:57
Very elegant and simple, +1. Mine is overly complicated because it actually does everything your
else
branch does inside of a box. Yours should also be more robust if the first argument of any nested one contains more than just another nested one or something without one of those macros (mine would discard stuff in that case).– Skillmon
Dec 4 at 18:57
add a comment |
up vote
1
down vote
The syntax you propose is very complicated to maintain, perhaps a simpler one such as
transform{x=a,y=b,z=c}{F}
is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
% simpler
NewDocumentCommand{transform}{mm}
{
seq_set_from_clist:Nn l_tmpa_seq { #1 }
seq_reverse:N l_tmpa_seq
#2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
}
% recursive
NewDocumentCommand{definetransform}{m}
{
clist_map_inline:nn { #1 }
{
cs_new_protected:cpn { ##1 } ####1 ####2
{
serker_transform:nnn { ##1 } { ####1 } { ####2 }
}
}
}
seq_new:N g__serker_transform_seq
cs_new_protected:Nn serker_transform:nnn
{
seq_if_empty:NTF g__serker_transform_seq
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
{#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
seq_gclear:N g__serker_transform_seq
}
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
#2
}
}
ExplSyntaxOff
definetransform{x,y,z} % add to the list
begin{document}
[
transform{x=a}{F},
qquad
transform{x=a,y=b}{F},
qquad
transform{x=a,y=b,z=c}{F}
]
[
x{F}{a},
qquad
x{y{F}{b}}{a},
qquad
x{y{z{F}{c}}{b}}{a}
]
end{document}
add a comment |
up vote
1
down vote
The syntax you propose is very complicated to maintain, perhaps a simpler one such as
transform{x=a,y=b,z=c}{F}
is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
% simpler
NewDocumentCommand{transform}{mm}
{
seq_set_from_clist:Nn l_tmpa_seq { #1 }
seq_reverse:N l_tmpa_seq
#2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
}
% recursive
NewDocumentCommand{definetransform}{m}
{
clist_map_inline:nn { #1 }
{
cs_new_protected:cpn { ##1 } ####1 ####2
{
serker_transform:nnn { ##1 } { ####1 } { ####2 }
}
}
}
seq_new:N g__serker_transform_seq
cs_new_protected:Nn serker_transform:nnn
{
seq_if_empty:NTF g__serker_transform_seq
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
{#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
seq_gclear:N g__serker_transform_seq
}
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
#2
}
}
ExplSyntaxOff
definetransform{x,y,z} % add to the list
begin{document}
[
transform{x=a}{F},
qquad
transform{x=a,y=b}{F},
qquad
transform{x=a,y=b,z=c}{F}
]
[
x{F}{a},
qquad
x{y{F}{b}}{a},
qquad
x{y{z{F}{c}}{b}}{a}
]
end{document}
add a comment |
up vote
1
down vote
up vote
1
down vote
The syntax you propose is very complicated to maintain, perhaps a simpler one such as
transform{x=a,y=b,z=c}{F}
is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
% simpler
NewDocumentCommand{transform}{mm}
{
seq_set_from_clist:Nn l_tmpa_seq { #1 }
seq_reverse:N l_tmpa_seq
#2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
}
% recursive
NewDocumentCommand{definetransform}{m}
{
clist_map_inline:nn { #1 }
{
cs_new_protected:cpn { ##1 } ####1 ####2
{
serker_transform:nnn { ##1 } { ####1 } { ####2 }
}
}
}
seq_new:N g__serker_transform_seq
cs_new_protected:Nn serker_transform:nnn
{
seq_if_empty:NTF g__serker_transform_seq
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
{#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
seq_gclear:N g__serker_transform_seq
}
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
#2
}
}
ExplSyntaxOff
definetransform{x,y,z} % add to the list
begin{document}
[
transform{x=a}{F},
qquad
transform{x=a,y=b}{F},
qquad
transform{x=a,y=b,z=c}{F}
]
[
x{F}{a},
qquad
x{y{F}{b}}{a},
qquad
x{y{z{F}{c}}{b}}{a}
]
end{document}
The syntax you propose is very complicated to maintain, perhaps a simpler one such as
transform{x=a,y=b,z=c}{F}
is better. So I propose an implementation along this line (the argument is then printed from right to left), but also a rewriting of Circumscribe's very fine answer in expl3
.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
% simpler
NewDocumentCommand{transform}{mm}
{
seq_set_from_clist:Nn l_tmpa_seq { #1 }
seq_reverse:N l_tmpa_seq
#2^{ ( seq_use:Nn l_tmpa_seq {,} ) }
}
% recursive
NewDocumentCommand{definetransform}{m}
{
clist_map_inline:nn { #1 }
{
cs_new_protected:cpn { ##1 } ####1 ####2
{
serker_transform:nnn { ##1 } { ####1 } { ####2 }
}
}
}
seq_new:N g__serker_transform_seq
cs_new_protected:Nn serker_transform:nnn
{
seq_if_empty:NTF g__serker_transform_seq
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
{#2}^{ ( seq_use:Nn g__serker_transform_seq {,} ) }
seq_gclear:N g__serker_transform_seq
}
{
seq_gput_left:Nn g__serker_transform_seq { #1 = #3 }
#2
}
}
ExplSyntaxOff
definetransform{x,y,z} % add to the list
begin{document}
[
transform{x=a}{F},
qquad
transform{x=a,y=b}{F},
qquad
transform{x=a,y=b,z=c}{F}
]
[
x{F}{a},
qquad
x{y{F}{b}}{a},
qquad
x{y{z{F}{c}}{b}}{a}
]
end{document}
answered Dec 5 at 13:21
egreg
704k8618753154
704k8618753154
add a comment |
add a comment |
up vote
1
down vote
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (romannumeral expansion was introduced in order to overcome the
%% concerns and worries about improperly balanced
%% if..else..fi constructs.)
%%
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
}%
newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.
In edge cases this might cause problems.
The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.
Advantage:
This is more safe even in edge cases.
Disadvantages:
In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
the checking-mechanism (UD@MoreTransformationsFork
, UD@@MoreTransformationsFork
) as well as it does check on the presence of tokens and not on their meaning.
The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x
or y
or z
or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
newcommandUD@CheckWhetherBrace[1]{%
romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
string#1.}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
}%
%%==============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%..............................................................................
%% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
newcommandUD@CheckWhetherLeadingSpace[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
newcommandUD@CheckWhetherLeadingSpaceB{}%
longdefUD@CheckWhetherLeadingSpaceB#1 {%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument does not contain "!":
%%.............................................................................
newcommandUD@GobbleToExclam{}%
longdefUD@GobbleToExclam#1!{}%
newcommandUD@CheckWhetherNoExclam[1]{%
expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckForMoreTransformations[1]{%
romannumeral0UD@CheckWhetherBrace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherLeadingSpace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherNull{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
}%
}%
}%
}%
newcommandUD@MoreTransformationsFork[1]{%
UD@CheckWhetherNoExclam{#1}{%
UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
!U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
!U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
!U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
!U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
!U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
!U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
!!!!%
}{UD@Exchange{UD@secondoftwo}}% something else with !
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
newcommandUD@@MoreTransformationsFork{}%
longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
UD@CheckForMoreTransformations{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
add a comment |
up vote
1
down vote
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (romannumeral expansion was introduced in order to overcome the
%% concerns and worries about improperly balanced
%% if..else..fi constructs.)
%%
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
}%
newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.
In edge cases this might cause problems.
The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.
Advantage:
This is more safe even in edge cases.
Disadvantages:
In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
the checking-mechanism (UD@MoreTransformationsFork
, UD@@MoreTransformationsFork
) as well as it does check on the presence of tokens and not on their meaning.
The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x
or y
or z
or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
newcommandUD@CheckWhetherBrace[1]{%
romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
string#1.}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
}%
%%==============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%..............................................................................
%% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
newcommandUD@CheckWhetherLeadingSpace[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
newcommandUD@CheckWhetherLeadingSpaceB{}%
longdefUD@CheckWhetherLeadingSpaceB#1 {%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument does not contain "!":
%%.............................................................................
newcommandUD@GobbleToExclam{}%
longdefUD@GobbleToExclam#1!{}%
newcommandUD@CheckWhetherNoExclam[1]{%
expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckForMoreTransformations[1]{%
romannumeral0UD@CheckWhetherBrace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherLeadingSpace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherNull{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
}%
}%
}%
}%
newcommandUD@MoreTransformationsFork[1]{%
UD@CheckWhetherNoExclam{#1}{%
UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
!U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
!U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
!U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
!U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
!U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
!U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
!!!!%
}{UD@Exchange{UD@secondoftwo}}% something else with !
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
newcommandUD@@MoreTransformationsFork{}%
longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
UD@CheckForMoreTransformations{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
add a comment |
up vote
1
down vote
up vote
1
down vote
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (romannumeral expansion was introduced in order to overcome the
%% concerns and worries about improperly balanced
%% if..else..fi constructs.)
%%
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
}%
newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.
In edge cases this might cause problems.
The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.
Advantage:
This is more safe even in edge cases.
Disadvantages:
In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
the checking-mechanism (UD@MoreTransformationsFork
, UD@@MoreTransformationsFork
) as well as it does check on the presence of tokens and not on their meaning.
The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x
or y
or z
or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
newcommandUD@CheckWhetherBrace[1]{%
romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
string#1.}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
}%
%%==============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%..............................................................................
%% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
newcommandUD@CheckWhetherLeadingSpace[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
newcommandUD@CheckWhetherLeadingSpaceB{}%
longdefUD@CheckWhetherLeadingSpaceB#1 {%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument does not contain "!":
%%.............................................................................
newcommandUD@GobbleToExclam{}%
longdefUD@GobbleToExclam#1!{}%
newcommandUD@CheckWhetherNoExclam[1]{%
expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckForMoreTransformations[1]{%
romannumeral0UD@CheckWhetherBrace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherLeadingSpace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherNull{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
}%
}%
}%
}%
newcommandUD@MoreTransformationsFork[1]{%
UD@CheckWhetherNoExclam{#1}{%
UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
!U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
!U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
!U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
!U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
!U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
!U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
!!!!%
}{UD@Exchange{UD@secondoftwo}}% something else with !
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
newcommandUD@@MoreTransformationsFork{}%
longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
UD@CheckForMoreTransformations{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (romannumeral expansion was introduced in order to overcome the
%% concerns and worries about improperly balanced
%% if..else..fi constructs.)
%%
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckWhetherLeadingUD@CollectMore[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingUD@CollectMoreB.#1UD@CollectMore}{}}%
}%
newcommandUD@CheckWhetherLeadingUD@CollectMoreB{}%
longdefUD@CheckWhetherLeadingUD@CollectMoreB#1UD@CollectMore{%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
expandafterUD@CheckWhetherLeadingUD@CollectMoreexpandafter{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
With the example above, the routine for checking for another nested transformation does attempt top-level-expansion to the first token of a transformation-macro's first argument in any case.
In edge cases this might cause problems.
The example below includes a checking routine with some brace-hacks which does the check without attempting to top-level-expand the first token of a transformation-macro's first argument and which applies top-level-expansion to that token only in case it is one of the tokens that are used as transformation-macros.
Advantage:
This is more safe even in edge cases.
Disadvantages:
In case you wish to rename some of the transformation-macros or wish to add some transformation-macros, you need to adjust
the checking-mechanism (UD@MoreTransformationsFork
, UD@@MoreTransformationsFork
) as well as it does check on the presence of tokens and not on their meaning.
The load of code is a bit larger: When grabbing the first token of an argument for checking whether it is either x
or y
or z
or the like, you also need to take into account that the very first token of the argument could as well be a space-token or a curly opening-brace or that the argument might be empty, and as you check on the presence of one of several tokens, you need code for cranking out several cases.
documentclass{article}
makeatletter
%%----------------------------------------------------------------------
%% Paraphernalia
%%----------------------------------------------------------------------
newcommandUD@firstoftwo[2]{#1}%
newcommandUD@secondoftwo[2]{#2}%
newcommandUD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
newcommandUD@CheckWhetherNull[1]{%
romannumeral0expandafterUD@secondoftwostring{expandafter
UD@secondoftwoexpandafter{expandafter{string#1}expandafter
UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
newcommandUD@CheckWhetherBrace[1]{%
romannumeral0expandafterUD@secondoftwoexpandafter{expandafter{%
string#1.}expandafterUD@firstoftwoexpandafter{expandafter
UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
UD@firstoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
}%
%%==============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%..............................................................................
%% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
newcommandUD@CheckWhetherLeadingSpace[1]{%
romannumeral0UD@CheckWhetherNull{#1}%
{expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
{expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
newcommandUD@CheckWhetherLeadingSpaceB{}%
longdefUD@CheckWhetherLeadingSpaceB#1 {%
expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
{UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument does not contain "!":
%%.............................................................................
newcommandUD@GobbleToExclam{}%
longdefUD@GobbleToExclam#1!{}%
newcommandUD@CheckWhetherNoExclam[1]{%
expandafterUD@CheckWhetherNullexpandafter{UD@GobbleToExclam#1!}%
}%
%%----------------------------------------------------------------------
%% UD@CheckWhetherLeadingUD@CollectMore{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is
%% UD@CollectMore>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% UD@CollectMore>}%
%%----------------------------------------------------------------------
newcommandUD@CheckForMoreTransformations[1]{%
romannumeral0UD@CheckWhetherBrace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherLeadingSpace{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
UD@CheckWhetherNull{#1}{%
expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo
}{%
expandafterUD@secondoftwostring{UD@MoreTransformationsFork#1}{}%
}%
}%
}%
}%
newcommandUD@MoreTransformationsFork[1]{%
UD@CheckWhetherNoExclam{#1}{%
UD@@MoreTransformationsFork!#1!V!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% U
!U!#1!W!x!y!z!{UD@Exchange{UD@firstoftwo}}% V
!U!V!#1!x!y!z!{UD@Exchange{UD@firstoftwo}}% W
!U!V!W!#1!y!z!{UD@Exchange{UD@firstoftwo}}% x
!U!V!W!x!#1!z!{UD@Exchange{UD@firstoftwo}}% y
!U!V!W!x!y!#1!{UD@Exchange{UD@firstoftwo}}% z
!U!V!W!x!y!z!{UD@Exchange{UD@secondoftwo}}% something else without !
!!!!%
}{UD@Exchange{UD@secondoftwo}}% something else with !
{UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter}expandafterexpandafter
expandafter}expandafterUD@secondoftwoexpandafter{string}%
}%
newcommandUD@@MoreTransformationsFork{}%
longdefUD@@MoreTransformationsFork#1!U!V!W!x!y!z!#2#3!!!!{#2}%
%%......................................................................
newcommandUD@CollectMore{UD@CollectMore@B{}}%
newcommandUD@CollectMore@B[3]{%
UD@CheckForMoreTransformations{#2}{%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter{%
expandafterUD@firstoftwoexpandafter{expandafter}#2}{UD@CollectMore@B{, #3#1}}%
}{%
ensuremath{{#2}^{(#3#1)}}%
}%
}%
%%......................................................................
newcommandx[2]{UD@CollectMore{#1}{x=#2}}%
newcommandy[2]{UD@CollectMore{#1}{y=#2}}%
newcommandz[2]{UD@CollectMore{#1}{z=#2}}%
newcommandU[2]{UD@CollectMore{#1}{u=#2}}%
newcommandV[2]{UD@CollectMore{#1}{v=#2}}%
newcommandW[2]{UD@CollectMore{#1}{w=#2}}%
makeatother
begin{document}
verb|x{F}{a}|: % yields F^{(x=a)}
x{F}{a}% gives F^{(x=a)}
verb|y{F}{b}|: % yields F^{(y=b)}
y{F}{b}% gives F^{(y=b)}
verb|z{F}{c}|: % yields F^{(z=b)}
z{F}{c}% gives F^{(z=b)}
verb|x{y{F}{b}}{a}|: % yields F^{(y=b, x=a)}
x{y{F}{b}}{a}% gives F^{(y=b, x=a)}
verb|x{y{z{F}{c}}{b}}{a}|: % yields F^{(z=c, y=b, x=a)}
x{y{z{F}{c}}{b}}{a}% gives F^{(z=c, y=b, x=a)}
verb|U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}|: % yields F^{(z=f, y=e, x=d, w=c, v=b, u=a)}
U{V{W{x{y{z{F}{f}}{e}}{d}}{c}}{b}}{a}
end{document}
edited Dec 6 at 12:23
answered Dec 4 at 23:37
Ulrich Diez
3,920615
3,920615
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f463149%2fchanging-the-effect-of-a-command-in-another%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
That syntax seems strange. Are you sure you want that (it is possible and I can post something, but it seems strange).
– Skillmon
Dec 4 at 13:54
The idea is that I have several parametrized possible transformations on F, and I would like to say that x{F}{a} is F transformed by transformation x with argument a. The problem is that I can also apply a transformation on something which has been transformed by another. The key thing, is that I do not want to have more than one superscript, which makes it non readable, and I can have the order of the transformations just by reading from left to right.
– Serker
Dec 4 at 14:07