Expansion of macro in environment argumentExpansion of command for language in otherlanguage...
Is there a low-level alternative to Animate Objects?
What are these green text/line displays shown during the livestream of Crew Dragon's approach to dock with the ISS?
Understanding Kramnik's play in game 1 of Candidates 2018
If nine coins are tossed, what is the probability that the number of heads is even?
How to properly claim credit for peer review?
I encountered my boss during an on-site interview at another company. Should I bring it up when seeing him next time?
GeometricMean definition
How to avoid being sexist when trying to employ someone to function in a very sexist environment?
It took me a lot of time to make this, pls like. (YouTube Comments #1)
Can you use a beast's innate abilities while polymorphed?
What is a term for a function that when called repeatedly, has the same effect as calling once?
How can I be pwned if I'm not registered on that site?
How can atoms be electrically neutral when there is a difference in the positions of the charges?
Can you 'upgrade' leather armor to studded leather armor without purchasing the new armor directly?
What is the difference between ashamed and shamed?
If a druid in Wild Shape swallows a creature whole, then turns back to her normal form, what happens?
Skis versus snow shoes - when to choose which for travelling the backcountry?
When should a commit not be version tagged?
Multiplication via squaring and addition
Significance and timing of "mux scans"
What's the difference between a cart and a wagon?
Is there a frame of reference in which I was born before I was conceived?
Did 5.25" floppies undergo a change in magnetic coating?
How would we write a misogynistic character without offending people?
Expansion of macro in environment argument
Expansion of command for language in otherlanguage environmentString variable with multiple valuesGeneralising a second-order macro with loopsStrange expansion of a macro inside an environmentEnvironment with delayed expansionPreventing argument expansionCompiler Error when Creating a Macro/EnvironmentAbstract page of babel[magyar] undefinedTricky expansion in macroifnum and expansion of macro argumentForce macro expansionA way to “execute” only latex procedural code (def, let) in a sequence ignoring the rest?Macro Substitution/Expansion in Environment Names
I'd like to generate an environment that changes a bit according to an argument given for it. The reason is having different locales in the document. I have defined a command, EmitLanguageStr
that determines the argument to otherlanguage
according to the argument that was passed. For example, EmitLanguageStr[en] -> english
. See these questions for further context: [ 1, 2 ]. Here's the environment stripped down.
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{otherlanguage}{EmitLanguageStr[#1]}
@authorpar
textbf{EmitTitle[#1]}par
}{%
end{otherlanguage}
}
Turns out other people have had the same problem (Q), but the solution did not quite work for me. The answer suggests that wrapping the environment in one of two ways would allow the argument to be expanded:
% Create a macro
newcommandtestlang{english}
% Expand the argument once:
newenvironment{Otherlanguage}[1]{%
expandafterotherlanguageexpandafter{#1}%
}{endotherlanguage}
% Alternative: argument is fully expanded
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
% usage
begin{Otherlanguage}{testlang}
...
end{Otherlangauge}
First, without these wrappers, babel gives an error message that the language EmitLanguageStr[en]
is not defined. That was addressed in the linked question. However, the solutions presented produce another kind of error: Use of EmitLanguageStr doesn't match its definition
.
How can the command be properly expanded?
Here's a complete example of the situation. This works, but by switching the argument of Otherlanguage
to the one in the comment the described error is thrown.
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
%newenvironment{Otherlanguage}[1]{%
% expandafterotherlanguageexpandafter{#1}%
%}{endotherlanguage}
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{Otherlanguage}{english}%EmitLanguageStr[#1]
@authorpar
textbf{EmitTitle[#1]}par
EmitYearpar
par
}{%
end{Otherlanguage}
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
macros environments expansion
New contributor
add a comment |
I'd like to generate an environment that changes a bit according to an argument given for it. The reason is having different locales in the document. I have defined a command, EmitLanguageStr
that determines the argument to otherlanguage
according to the argument that was passed. For example, EmitLanguageStr[en] -> english
. See these questions for further context: [ 1, 2 ]. Here's the environment stripped down.
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{otherlanguage}{EmitLanguageStr[#1]}
@authorpar
textbf{EmitTitle[#1]}par
}{%
end{otherlanguage}
}
Turns out other people have had the same problem (Q), but the solution did not quite work for me. The answer suggests that wrapping the environment in one of two ways would allow the argument to be expanded:
% Create a macro
newcommandtestlang{english}
% Expand the argument once:
newenvironment{Otherlanguage}[1]{%
expandafterotherlanguageexpandafter{#1}%
}{endotherlanguage}
% Alternative: argument is fully expanded
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
% usage
begin{Otherlanguage}{testlang}
...
end{Otherlangauge}
First, without these wrappers, babel gives an error message that the language EmitLanguageStr[en]
is not defined. That was addressed in the linked question. However, the solutions presented produce another kind of error: Use of EmitLanguageStr doesn't match its definition
.
How can the command be properly expanded?
Here's a complete example of the situation. This works, but by switching the argument of Otherlanguage
to the one in the comment the described error is thrown.
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
%newenvironment{Otherlanguage}[1]{%
% expandafterotherlanguageexpandafter{#1}%
%}{endotherlanguage}
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{Otherlanguage}{english}%EmitLanguageStr[#1]
@authorpar
textbf{EmitTitle[#1]}par
EmitYearpar
par
}{%
end{Otherlanguage}
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
macros environments expansion
New contributor
2
As always on this site please provide a full minimal example instead of sniplets. That makes it a lot easier for others to test your code and provide suggestions
– daleif
14 hours ago
SeemsEmitLanguageStr
processes an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This meansEmitLanguageStr
won't expand to tokens only that form the name of a language but it also delivers assignment-tokens like@ifnextchar
/futurelet
which are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly.
– Ulrich Diez
14 hours ago
@UlrichDiez Oh, that's good to know. Minimal example added.
– Felix
14 hours ago
add a comment |
I'd like to generate an environment that changes a bit according to an argument given for it. The reason is having different locales in the document. I have defined a command, EmitLanguageStr
that determines the argument to otherlanguage
according to the argument that was passed. For example, EmitLanguageStr[en] -> english
. See these questions for further context: [ 1, 2 ]. Here's the environment stripped down.
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{otherlanguage}{EmitLanguageStr[#1]}
@authorpar
textbf{EmitTitle[#1]}par
}{%
end{otherlanguage}
}
Turns out other people have had the same problem (Q), but the solution did not quite work for me. The answer suggests that wrapping the environment in one of two ways would allow the argument to be expanded:
% Create a macro
newcommandtestlang{english}
% Expand the argument once:
newenvironment{Otherlanguage}[1]{%
expandafterotherlanguageexpandafter{#1}%
}{endotherlanguage}
% Alternative: argument is fully expanded
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
% usage
begin{Otherlanguage}{testlang}
...
end{Otherlangauge}
First, without these wrappers, babel gives an error message that the language EmitLanguageStr[en]
is not defined. That was addressed in the linked question. However, the solutions presented produce another kind of error: Use of EmitLanguageStr doesn't match its definition
.
How can the command be properly expanded?
Here's a complete example of the situation. This works, but by switching the argument of Otherlanguage
to the one in the comment the described error is thrown.
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
%newenvironment{Otherlanguage}[1]{%
% expandafterotherlanguageexpandafter{#1}%
%}{endotherlanguage}
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{Otherlanguage}{english}%EmitLanguageStr[#1]
@authorpar
textbf{EmitTitle[#1]}par
EmitYearpar
par
}{%
end{Otherlanguage}
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
macros environments expansion
New contributor
I'd like to generate an environment that changes a bit according to an argument given for it. The reason is having different locales in the document. I have defined a command, EmitLanguageStr
that determines the argument to otherlanguage
according to the argument that was passed. For example, EmitLanguageStr[en] -> english
. See these questions for further context: [ 1, 2 ]. Here's the environment stripped down.
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{otherlanguage}{EmitLanguageStr[#1]}
@authorpar
textbf{EmitTitle[#1]}par
}{%
end{otherlanguage}
}
Turns out other people have had the same problem (Q), but the solution did not quite work for me. The answer suggests that wrapping the environment in one of two ways would allow the argument to be expanded:
% Create a macro
newcommandtestlang{english}
% Expand the argument once:
newenvironment{Otherlanguage}[1]{%
expandafterotherlanguageexpandafter{#1}%
}{endotherlanguage}
% Alternative: argument is fully expanded
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
% usage
begin{Otherlanguage}{testlang}
...
end{Otherlangauge}
First, without these wrappers, babel gives an error message that the language EmitLanguageStr[en]
is not defined. That was addressed in the linked question. However, the solutions presented produce another kind of error: Use of EmitLanguageStr doesn't match its definition
.
How can the command be properly expanded?
Here's a complete example of the situation. This works, but by switching the argument of Otherlanguage
to the one in the comment the described error is thrown.
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
%newenvironment{Otherlanguage}[1]{%
% expandafterotherlanguageexpandafter{#1}%
%}{endotherlanguage}
newenvironment{Otherlanguage}[1]{%
begingroup
edeftemp{endgroupnoexpandotherlanguage{#1}}%
temp
}{endotherlanguage}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[#1]}
begin{Otherlanguage}{english}%EmitLanguageStr[#1]
@authorpar
textbf{EmitTitle[#1]}par
EmitYearpar
par
}{%
end{Otherlanguage}
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
macros environments expansion
macros environments expansion
New contributor
New contributor
edited 14 hours ago
Felix
New contributor
asked 15 hours ago
FelixFelix
1265
1265
New contributor
New contributor
2
As always on this site please provide a full minimal example instead of sniplets. That makes it a lot easier for others to test your code and provide suggestions
– daleif
14 hours ago
SeemsEmitLanguageStr
processes an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This meansEmitLanguageStr
won't expand to tokens only that form the name of a language but it also delivers assignment-tokens like@ifnextchar
/futurelet
which are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly.
– Ulrich Diez
14 hours ago
@UlrichDiez Oh, that's good to know. Minimal example added.
– Felix
14 hours ago
add a comment |
2
As always on this site please provide a full minimal example instead of sniplets. That makes it a lot easier for others to test your code and provide suggestions
– daleif
14 hours ago
SeemsEmitLanguageStr
processes an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This meansEmitLanguageStr
won't expand to tokens only that form the name of a language but it also delivers assignment-tokens like@ifnextchar
/futurelet
which are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly.
– Ulrich Diez
14 hours ago
@UlrichDiez Oh, that's good to know. Minimal example added.
– Felix
14 hours ago
2
2
As always on this site please provide a full minimal example instead of sniplets. That makes it a lot easier for others to test your code and provide suggestions
– daleif
14 hours ago
As always on this site please provide a full minimal example instead of sniplets. That makes it a lot easier for others to test your code and provide suggestions
– daleif
14 hours ago
Seems
EmitLanguageStr
processes an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This means EmitLanguageStr
won't expand to tokens only that form the name of a language but it also delivers assignment-tokens like @ifnextchar
/futurelet
which are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly.– Ulrich Diez
14 hours ago
Seems
EmitLanguageStr
processes an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This means EmitLanguageStr
won't expand to tokens only that form the name of a language but it also delivers assignment-tokens like @ifnextchar
/futurelet
which are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly.– Ulrich Diez
14 hours ago
@UlrichDiez Oh, that's good to know. Minimal example added.
– Felix
14 hours ago
@UlrichDiez Oh, that's good to know. Minimal example added.
– Felix
14 hours ago
add a comment |
1 Answer
1
active
oldest
votes
MakeLocaleVar{LanguageStr}
causes EmitLanguageStr
to be defined as:
newcommandEmitLanguageStr[1][en]{@nameuse{LanguageStr:#1}}%
EmitLanguageStr
processes an optional argument.
If you look at EmitLanguageStr
via showEmitLanguageStr
, you'll find:
> EmitLanguageStr=macro:
->@protected@testopt EmitLanguageStr \EmitLanguageStr {en}.
Looking at @protected@testopt
yields:
> @protected@testopt=macro:
#1->ifx protect @typeset@protect expandafter @testopt else @x@protect #1
fi .
Looking at @testopt
yields:
> @testopt=long macro:
#1#2->kernel@ifnextchar [{#1}{#1[{#2}]}.
Looking at kernel@ifnextchar
yields:
> kernel@ifnextchar=long macro:
#1#2#3->let reserved@d =#1def reserved@a {#2}def reserved@b {#3}futurele
t @let@token @ifnch .
Looking at @ifnch
yields:
> @ifnch=macro:
->ifx @let@token @sptoken let reserved@c @xifnch else ifx @let@token
reserved@d let reserved@c reserved@a else let reserved@c reserved@b fi
fi reserved@c .
Looking at @xifnch
yields:
> @xifnch=macro:
->futurelet @let@token @ifnch .
As you can see a lot of playing around with non-expandable let
- and futurelet
-assignments is involved into the checking for the presence of the optional argument via kernel@ifnextchar [
.
Therefore EmitLanguageStr
does not only deliver those character tokens that form the name of the language. It also yields a lot of unexpandable assignment-tokens like let
and futurelet
for checking for the presence of the optional argument.
These tokens won't vanish within a pure-expansion-context while obtaining the name of the language for passing it as argument to an environment would be a pure expansion context.
After expansion these unexpandable assignment-tokens remain in the token-stream because while expansion takes place in (La)TeX's "gullet",
the carrying out of assignments takes place in (La)TeX's "stomach".
So in short:
As long as EmitLanguageStr
processes an optional argument whereby the techniques for detecting the presence of an optional argument themselves involve non-expandable assignment-tokens which don't vanish during expansion, you can't use EmitLanguageStr
in pure-expansion-contexts for obtaining only those tokens that form the name of the language.
But you can, e.g., create a variant of EmitLanguageStr
with an additional argument holding tokens to which the emitted string is to be passed as argument. I call that macro PassLanguageStrTo
:
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}%%%%
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
expandafternewcommandcsname Pass#2Toendcsname[2][en]{%
expandafterexpandafterexpandafterPassFirstToSecond
expandafterexpandafterexpandafter{csname#2:##1endcsname}{##2}%
}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[{#1}]}%%%%
PassLanguageStrTo[{#1}]{begin{otherlanguage}}%
@authorpar
textbf{EmitTitle[{#1}]}par
EmitYearpar
par
}{%
end{otherlanguage}%%%%
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Felix is a new contributor. Be nice, and check out our Code of Conduct.
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%2f477681%2fexpansion-of-macro-in-environment-argument%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
MakeLocaleVar{LanguageStr}
causes EmitLanguageStr
to be defined as:
newcommandEmitLanguageStr[1][en]{@nameuse{LanguageStr:#1}}%
EmitLanguageStr
processes an optional argument.
If you look at EmitLanguageStr
via showEmitLanguageStr
, you'll find:
> EmitLanguageStr=macro:
->@protected@testopt EmitLanguageStr \EmitLanguageStr {en}.
Looking at @protected@testopt
yields:
> @protected@testopt=macro:
#1->ifx protect @typeset@protect expandafter @testopt else @x@protect #1
fi .
Looking at @testopt
yields:
> @testopt=long macro:
#1#2->kernel@ifnextchar [{#1}{#1[{#2}]}.
Looking at kernel@ifnextchar
yields:
> kernel@ifnextchar=long macro:
#1#2#3->let reserved@d =#1def reserved@a {#2}def reserved@b {#3}futurele
t @let@token @ifnch .
Looking at @ifnch
yields:
> @ifnch=macro:
->ifx @let@token @sptoken let reserved@c @xifnch else ifx @let@token
reserved@d let reserved@c reserved@a else let reserved@c reserved@b fi
fi reserved@c .
Looking at @xifnch
yields:
> @xifnch=macro:
->futurelet @let@token @ifnch .
As you can see a lot of playing around with non-expandable let
- and futurelet
-assignments is involved into the checking for the presence of the optional argument via kernel@ifnextchar [
.
Therefore EmitLanguageStr
does not only deliver those character tokens that form the name of the language. It also yields a lot of unexpandable assignment-tokens like let
and futurelet
for checking for the presence of the optional argument.
These tokens won't vanish within a pure-expansion-context while obtaining the name of the language for passing it as argument to an environment would be a pure expansion context.
After expansion these unexpandable assignment-tokens remain in the token-stream because while expansion takes place in (La)TeX's "gullet",
the carrying out of assignments takes place in (La)TeX's "stomach".
So in short:
As long as EmitLanguageStr
processes an optional argument whereby the techniques for detecting the presence of an optional argument themselves involve non-expandable assignment-tokens which don't vanish during expansion, you can't use EmitLanguageStr
in pure-expansion-contexts for obtaining only those tokens that form the name of the language.
But you can, e.g., create a variant of EmitLanguageStr
with an additional argument holding tokens to which the emitted string is to be passed as argument. I call that macro PassLanguageStrTo
:
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}%%%%
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
expandafternewcommandcsname Pass#2Toendcsname[2][en]{%
expandafterexpandafterexpandafterPassFirstToSecond
expandafterexpandafterexpandafter{csname#2:##1endcsname}{##2}%
}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[{#1}]}%%%%
PassLanguageStrTo[{#1}]{begin{otherlanguage}}%
@authorpar
textbf{EmitTitle[{#1}]}par
EmitYearpar
par
}{%
end{otherlanguage}%%%%
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
add a comment |
MakeLocaleVar{LanguageStr}
causes EmitLanguageStr
to be defined as:
newcommandEmitLanguageStr[1][en]{@nameuse{LanguageStr:#1}}%
EmitLanguageStr
processes an optional argument.
If you look at EmitLanguageStr
via showEmitLanguageStr
, you'll find:
> EmitLanguageStr=macro:
->@protected@testopt EmitLanguageStr \EmitLanguageStr {en}.
Looking at @protected@testopt
yields:
> @protected@testopt=macro:
#1->ifx protect @typeset@protect expandafter @testopt else @x@protect #1
fi .
Looking at @testopt
yields:
> @testopt=long macro:
#1#2->kernel@ifnextchar [{#1}{#1[{#2}]}.
Looking at kernel@ifnextchar
yields:
> kernel@ifnextchar=long macro:
#1#2#3->let reserved@d =#1def reserved@a {#2}def reserved@b {#3}futurele
t @let@token @ifnch .
Looking at @ifnch
yields:
> @ifnch=macro:
->ifx @let@token @sptoken let reserved@c @xifnch else ifx @let@token
reserved@d let reserved@c reserved@a else let reserved@c reserved@b fi
fi reserved@c .
Looking at @xifnch
yields:
> @xifnch=macro:
->futurelet @let@token @ifnch .
As you can see a lot of playing around with non-expandable let
- and futurelet
-assignments is involved into the checking for the presence of the optional argument via kernel@ifnextchar [
.
Therefore EmitLanguageStr
does not only deliver those character tokens that form the name of the language. It also yields a lot of unexpandable assignment-tokens like let
and futurelet
for checking for the presence of the optional argument.
These tokens won't vanish within a pure-expansion-context while obtaining the name of the language for passing it as argument to an environment would be a pure expansion context.
After expansion these unexpandable assignment-tokens remain in the token-stream because while expansion takes place in (La)TeX's "gullet",
the carrying out of assignments takes place in (La)TeX's "stomach".
So in short:
As long as EmitLanguageStr
processes an optional argument whereby the techniques for detecting the presence of an optional argument themselves involve non-expandable assignment-tokens which don't vanish during expansion, you can't use EmitLanguageStr
in pure-expansion-contexts for obtaining only those tokens that form the name of the language.
But you can, e.g., create a variant of EmitLanguageStr
with an additional argument holding tokens to which the emitted string is to be passed as argument. I call that macro PassLanguageStrTo
:
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}%%%%
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
expandafternewcommandcsname Pass#2Toendcsname[2][en]{%
expandafterexpandafterexpandafterPassFirstToSecond
expandafterexpandafterexpandafter{csname#2:##1endcsname}{##2}%
}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[{#1}]}%%%%
PassLanguageStrTo[{#1}]{begin{otherlanguage}}%
@authorpar
textbf{EmitTitle[{#1}]}par
EmitYearpar
par
}{%
end{otherlanguage}%%%%
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
add a comment |
MakeLocaleVar{LanguageStr}
causes EmitLanguageStr
to be defined as:
newcommandEmitLanguageStr[1][en]{@nameuse{LanguageStr:#1}}%
EmitLanguageStr
processes an optional argument.
If you look at EmitLanguageStr
via showEmitLanguageStr
, you'll find:
> EmitLanguageStr=macro:
->@protected@testopt EmitLanguageStr \EmitLanguageStr {en}.
Looking at @protected@testopt
yields:
> @protected@testopt=macro:
#1->ifx protect @typeset@protect expandafter @testopt else @x@protect #1
fi .
Looking at @testopt
yields:
> @testopt=long macro:
#1#2->kernel@ifnextchar [{#1}{#1[{#2}]}.
Looking at kernel@ifnextchar
yields:
> kernel@ifnextchar=long macro:
#1#2#3->let reserved@d =#1def reserved@a {#2}def reserved@b {#3}futurele
t @let@token @ifnch .
Looking at @ifnch
yields:
> @ifnch=macro:
->ifx @let@token @sptoken let reserved@c @xifnch else ifx @let@token
reserved@d let reserved@c reserved@a else let reserved@c reserved@b fi
fi reserved@c .
Looking at @xifnch
yields:
> @xifnch=macro:
->futurelet @let@token @ifnch .
As you can see a lot of playing around with non-expandable let
- and futurelet
-assignments is involved into the checking for the presence of the optional argument via kernel@ifnextchar [
.
Therefore EmitLanguageStr
does not only deliver those character tokens that form the name of the language. It also yields a lot of unexpandable assignment-tokens like let
and futurelet
for checking for the presence of the optional argument.
These tokens won't vanish within a pure-expansion-context while obtaining the name of the language for passing it as argument to an environment would be a pure expansion context.
After expansion these unexpandable assignment-tokens remain in the token-stream because while expansion takes place in (La)TeX's "gullet",
the carrying out of assignments takes place in (La)TeX's "stomach".
So in short:
As long as EmitLanguageStr
processes an optional argument whereby the techniques for detecting the presence of an optional argument themselves involve non-expandable assignment-tokens which don't vanish during expansion, you can't use EmitLanguageStr
in pure-expansion-contexts for obtaining only those tokens that form the name of the language.
But you can, e.g., create a variant of EmitLanguageStr
with an additional argument holding tokens to which the emitted string is to be passed as argument. I call that macro PassLanguageStrTo
:
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}%%%%
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
expandafternewcommandcsname Pass#2Toendcsname[2][en]{%
expandafterexpandafterexpandafterPassFirstToSecond
expandafterexpandafterexpandafter{csname#2:##1endcsname}{##2}%
}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[{#1}]}%%%%
PassLanguageStrTo[{#1}]{begin{otherlanguage}}%
@authorpar
textbf{EmitTitle[{#1}]}par
EmitYearpar
par
}{%
end{otherlanguage}%%%%
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
MakeLocaleVar{LanguageStr}
causes EmitLanguageStr
to be defined as:
newcommandEmitLanguageStr[1][en]{@nameuse{LanguageStr:#1}}%
EmitLanguageStr
processes an optional argument.
If you look at EmitLanguageStr
via showEmitLanguageStr
, you'll find:
> EmitLanguageStr=macro:
->@protected@testopt EmitLanguageStr \EmitLanguageStr {en}.
Looking at @protected@testopt
yields:
> @protected@testopt=macro:
#1->ifx protect @typeset@protect expandafter @testopt else @x@protect #1
fi .
Looking at @testopt
yields:
> @testopt=long macro:
#1#2->kernel@ifnextchar [{#1}{#1[{#2}]}.
Looking at kernel@ifnextchar
yields:
> kernel@ifnextchar=long macro:
#1#2#3->let reserved@d =#1def reserved@a {#2}def reserved@b {#3}futurele
t @let@token @ifnch .
Looking at @ifnch
yields:
> @ifnch=macro:
->ifx @let@token @sptoken let reserved@c @xifnch else ifx @let@token
reserved@d let reserved@c reserved@a else let reserved@c reserved@b fi
fi reserved@c .
Looking at @xifnch
yields:
> @xifnch=macro:
->futurelet @let@token @ifnch .
As you can see a lot of playing around with non-expandable let
- and futurelet
-assignments is involved into the checking for the presence of the optional argument via kernel@ifnextchar [
.
Therefore EmitLanguageStr
does not only deliver those character tokens that form the name of the language. It also yields a lot of unexpandable assignment-tokens like let
and futurelet
for checking for the presence of the optional argument.
These tokens won't vanish within a pure-expansion-context while obtaining the name of the language for passing it as argument to an environment would be a pure expansion context.
After expansion these unexpandable assignment-tokens remain in the token-stream because while expansion takes place in (La)TeX's "gullet",
the carrying out of assignments takes place in (La)TeX's "stomach".
So in short:
As long as EmitLanguageStr
processes an optional argument whereby the techniques for detecting the presence of an optional argument themselves involve non-expandable assignment-tokens which don't vanish during expansion, you can't use EmitLanguageStr
in pure-expansion-contexts for obtaining only those tokens that form the name of the language.
But you can, e.g., create a variant of EmitLanguageStr
with an additional argument holding tokens to which the emitted string is to be passed as argument. I call that macro PassLanguageStrTo
:
documentclass[a4paper,12pt]{article}
usepackage{ifthen}
usepackage{pgffor}
makeatletter
newcommandSetDefaultValue[2]{%
global@namedef{#2:#1}{%
{scriptsize (Use {tttextbackslash #2[#1]} to replace this text.)}%
}%
}
newcommandPassFirstToSecond[2]{#2{#1}}%
newcommandMakeLocaleVar[2][en,fi]{%
foreach n in {#1}{%
expandafterSetDefaultValueexpandafter{n}{#2}%%%%
}%
expandafternewcommandcsname #2endcsname[2][]{%
ifthenelse{equal{##1}{}}{%
foreach n in {#1}{%
global@namedef{#2:n}{##2}%
}%
}{%
global@namedef{#2:##1}{##2}%
}%
}%
expandafternewcommandcsname Emit#2endcsname[1][en]{@nameuse{#2:##1}}%
expandafternewcommandcsname Pass#2Toendcsname[2][en]{%
expandafterexpandafterexpandafterPassFirstToSecond
expandafterexpandafterexpandafter{csname#2:##1endcsname}{##2}%
}%
}
% Variables set in document
MakeLocaleVar{Title}
MakeLocaleVar{Year}
MakeLocaleVar{AbstractStr}
AbstractStr[en]{ABSTRACT}
AbstractStr[fi]{TIIVISTELMÄ}
MakeLocaleVar{LanguageStr}
LanguageStr[en]{english}
LanguageStr[fi]{finnish}
renewenvironment{abstract}[1][en]{%
section*{EmitAbstractStr[{#1}]}%%%%
PassLanguageStrTo[{#1}]{begin{otherlanguage}}%
@authorpar
textbf{EmitTitle[{#1}]}par
EmitYearpar
par
}{%
end{otherlanguage}%%%%
}
makeatother
usepackage[utf8]{inputenc}
usepackage[T1]{fontenc}
usepackage[finnish, english]{babel}
author{Handsome Devil}
Year{2019}
Title[en]{Title in English}
Title[fi]{Otsikko suomeksi}
begin{document}
selectlanguage{english}
begin{abstract}
Abstract environment in English.
end{abstract}
begin{abstract}[fi]
Abstract environment in Finnish.
end{abstract}
end{document}
edited 13 hours ago
answered 13 hours ago
Ulrich DiezUlrich Diez
5,155619
5,155619
add a comment |
add a comment |
Felix is a new contributor. Be nice, and check out our Code of Conduct.
Felix is a new contributor. Be nice, and check out our Code of Conduct.
Felix is a new contributor. Be nice, and check out our Code of Conduct.
Felix is a new contributor. Be nice, and check out our Code of Conduct.
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.
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%2f477681%2fexpansion-of-macro-in-environment-argument%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
2
As always on this site please provide a full minimal example instead of sniplets. That makes it a lot easier for others to test your code and provide suggestions
– daleif
14 hours ago
Seems
EmitLanguageStr
processes an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This meansEmitLanguageStr
won't expand to tokens only that form the name of a language but it also delivers assignment-tokens like@ifnextchar
/futurelet
which are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly.– Ulrich Diez
14 hours ago
@UlrichDiez Oh, that's good to know. Minimal example added.
– Felix
14 hours ago