csname in newenviromentWhy can't the end code of an environment contain an argument?Setup a newenviroment for...

Why is a weak base more able to deprotonate a strong acid than a weak acid?

Was murdering a slave illegal in American slavery, and if so, what punishments were given for it?

Does the fact that we can only measure the two-way speed of light undermine the axiom of invariance?

Can a UK national work as a paid shop assistant in the USA?

Anatomically correct Guivre

What pc resources are used when bruteforcing?

VHDL: Why is it hard to desgin a floating point unit in hardware?

nginx conf: http2 module not working in Chrome in ubuntu 18.04

Are there historical examples of audiences drawn to a work that was "so bad it's good"?

What is this dime sized black bug with white on the segments near Loveland Colorodao?

Adobe Illustrator: How can I change the profile of a dashed stroke?

Why is this integration method not valid?

Three knights or knaves, three different hair colors

Make the `diff` command look only for differences from a specified range of lines

Which values for voltage divider

Is the default 512 byte physical sector size appropriate for SSD disks under Linux?

Is it OK to look at the list of played moves during the game to determine the status of the 50 move rule?

Proto-Indo-European (PIE) words with IPA

One word for 'the thing that attracts me'?

How to tease a romance without a cat and mouse chase?

Are clauses with "который" restrictive or non-restrictive by default?

Split into three!

csname in newenviroment

Efficient Algorithms for Destroyed Document Reconstruction



csname in newenviroment


Why can't the end code of an environment contain an argument?Setup a newenviroment for figure with includegraphics and captionCompiler Error when Creating a Macro/EnvironmentDefinition of a macro with multiple arguments and usage of csname













1















I defined a newenvironment with this code (sample):



documentclass{article}
usepackage[utf8]{inputenc}
usepackage{amsthm}

newenvironment{myEnv}[1][default]
{
pushQED{#1}
expandaftercsname x#1 endcsname
}
{ expandaftercsname endxpopQED endcsname }

newenvironment{xdefault}{}{}

begin{document}

begin{myEnv}
end{myEnv}

end{document}


I need this for some stuff later to call a specific environment using the argument. But I get the following error in Overleaf:



Missing endcsname inserted.

<to be read again>
begingroup
l.35 end{myEnv}

The control sequence marked <to be read again> should
not appear between csname and endcsname.
-----------
Extra endcsname.

endmyEnv ...after csname endxpopQED endcsname

l.35 end{myEnv}

I'm ignoring this, since I wasn't doing a csname.


As far as I can tell, the csname/endcsname's should be correct, I don't see an error, so I have no idea what causes this. When I searched the error I only found topics that were unrealated to my example.



Does someone know how to fix this?










share|improve this question

























  • My guess would be that the popQED within csname ... endcsname is a bit too much for LaTeX. I presume popQED does not expand to simple text, so LaTeX fails to make sense of it as part of a control sequence name. Maybe you just mean csname endx#1endcsnamepopQED? I'm also not quite sure if the expandafters are needed and the trailing space after #1 in csname x#1 endcsname might be too much. (But this is all speculation without a full example document where I can verify the definitions involved.)

    – moewe
    5 hours ago













  • @moewe Using pushQED was something I found searching for how to pass arguments to the end part. The space after #1 was from searching the error, removing them doesn't change that. moving popQED behind endscname causes the error to go, but then it prints 'default' and doesn't call endxdefault

    – Thorsten Schmitz
    4 hours ago













  • Ah, I see. I don't think popQED and pushQED can help you here. Try deftssavedarg{#1} and csname endxtssavedargendcsname instead.

    – moewe
    4 hours ago













  • expandaftercsname x expands x which is not expandable, so the expandafter is doing nothing.

    – David Carlisle
    4 hours ago
















1















I defined a newenvironment with this code (sample):



documentclass{article}
usepackage[utf8]{inputenc}
usepackage{amsthm}

newenvironment{myEnv}[1][default]
{
pushQED{#1}
expandaftercsname x#1 endcsname
}
{ expandaftercsname endxpopQED endcsname }

newenvironment{xdefault}{}{}

begin{document}

begin{myEnv}
end{myEnv}

end{document}


I need this for some stuff later to call a specific environment using the argument. But I get the following error in Overleaf:



Missing endcsname inserted.

<to be read again>
begingroup
l.35 end{myEnv}

The control sequence marked <to be read again> should
not appear between csname and endcsname.
-----------
Extra endcsname.

endmyEnv ...after csname endxpopQED endcsname

l.35 end{myEnv}

I'm ignoring this, since I wasn't doing a csname.


As far as I can tell, the csname/endcsname's should be correct, I don't see an error, so I have no idea what causes this. When I searched the error I only found topics that were unrealated to my example.



Does someone know how to fix this?










share|improve this question

























  • My guess would be that the popQED within csname ... endcsname is a bit too much for LaTeX. I presume popQED does not expand to simple text, so LaTeX fails to make sense of it as part of a control sequence name. Maybe you just mean csname endx#1endcsnamepopQED? I'm also not quite sure if the expandafters are needed and the trailing space after #1 in csname x#1 endcsname might be too much. (But this is all speculation without a full example document where I can verify the definitions involved.)

    – moewe
    5 hours ago













  • @moewe Using pushQED was something I found searching for how to pass arguments to the end part. The space after #1 was from searching the error, removing them doesn't change that. moving popQED behind endscname causes the error to go, but then it prints 'default' and doesn't call endxdefault

    – Thorsten Schmitz
    4 hours ago













  • Ah, I see. I don't think popQED and pushQED can help you here. Try deftssavedarg{#1} and csname endxtssavedargendcsname instead.

    – moewe
    4 hours ago













  • expandaftercsname x expands x which is not expandable, so the expandafter is doing nothing.

    – David Carlisle
    4 hours ago














1












1








1








I defined a newenvironment with this code (sample):



documentclass{article}
usepackage[utf8]{inputenc}
usepackage{amsthm}

newenvironment{myEnv}[1][default]
{
pushQED{#1}
expandaftercsname x#1 endcsname
}
{ expandaftercsname endxpopQED endcsname }

newenvironment{xdefault}{}{}

begin{document}

begin{myEnv}
end{myEnv}

end{document}


I need this for some stuff later to call a specific environment using the argument. But I get the following error in Overleaf:



Missing endcsname inserted.

<to be read again>
begingroup
l.35 end{myEnv}

The control sequence marked <to be read again> should
not appear between csname and endcsname.
-----------
Extra endcsname.

endmyEnv ...after csname endxpopQED endcsname

l.35 end{myEnv}

I'm ignoring this, since I wasn't doing a csname.


As far as I can tell, the csname/endcsname's should be correct, I don't see an error, so I have no idea what causes this. When I searched the error I only found topics that were unrealated to my example.



Does someone know how to fix this?










share|improve this question
















I defined a newenvironment with this code (sample):



documentclass{article}
usepackage[utf8]{inputenc}
usepackage{amsthm}

newenvironment{myEnv}[1][default]
{
pushQED{#1}
expandaftercsname x#1 endcsname
}
{ expandaftercsname endxpopQED endcsname }

newenvironment{xdefault}{}{}

begin{document}

begin{myEnv}
end{myEnv}

end{document}


I need this for some stuff later to call a specific environment using the argument. But I get the following error in Overleaf:



Missing endcsname inserted.

<to be read again>
begingroup
l.35 end{myEnv}

The control sequence marked <to be read again> should
not appear between csname and endcsname.
-----------
Extra endcsname.

endmyEnv ...after csname endxpopQED endcsname

l.35 end{myEnv}

I'm ignoring this, since I wasn't doing a csname.


As far as I can tell, the csname/endcsname's should be correct, I don't see an error, so I have no idea what causes this. When I searched the error I only found topics that were unrealated to my example.



Does someone know how to fix this?







environments






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 4 hours ago







Thorsten Schmitz

















asked 5 hours ago









Thorsten SchmitzThorsten Schmitz

62




62













  • My guess would be that the popQED within csname ... endcsname is a bit too much for LaTeX. I presume popQED does not expand to simple text, so LaTeX fails to make sense of it as part of a control sequence name. Maybe you just mean csname endx#1endcsnamepopQED? I'm also not quite sure if the expandafters are needed and the trailing space after #1 in csname x#1 endcsname might be too much. (But this is all speculation without a full example document where I can verify the definitions involved.)

    – moewe
    5 hours ago













  • @moewe Using pushQED was something I found searching for how to pass arguments to the end part. The space after #1 was from searching the error, removing them doesn't change that. moving popQED behind endscname causes the error to go, but then it prints 'default' and doesn't call endxdefault

    – Thorsten Schmitz
    4 hours ago













  • Ah, I see. I don't think popQED and pushQED can help you here. Try deftssavedarg{#1} and csname endxtssavedargendcsname instead.

    – moewe
    4 hours ago













  • expandaftercsname x expands x which is not expandable, so the expandafter is doing nothing.

    – David Carlisle
    4 hours ago



















  • My guess would be that the popQED within csname ... endcsname is a bit too much for LaTeX. I presume popQED does not expand to simple text, so LaTeX fails to make sense of it as part of a control sequence name. Maybe you just mean csname endx#1endcsnamepopQED? I'm also not quite sure if the expandafters are needed and the trailing space after #1 in csname x#1 endcsname might be too much. (But this is all speculation without a full example document where I can verify the definitions involved.)

    – moewe
    5 hours ago













  • @moewe Using pushQED was something I found searching for how to pass arguments to the end part. The space after #1 was from searching the error, removing them doesn't change that. moving popQED behind endscname causes the error to go, but then it prints 'default' and doesn't call endxdefault

    – Thorsten Schmitz
    4 hours ago













  • Ah, I see. I don't think popQED and pushQED can help you here. Try deftssavedarg{#1} and csname endxtssavedargendcsname instead.

    – moewe
    4 hours ago













  • expandaftercsname x expands x which is not expandable, so the expandafter is doing nothing.

    – David Carlisle
    4 hours ago

















My guess would be that the popQED within csname ... endcsname is a bit too much for LaTeX. I presume popQED does not expand to simple text, so LaTeX fails to make sense of it as part of a control sequence name. Maybe you just mean csname endx#1endcsnamepopQED? I'm also not quite sure if the expandafters are needed and the trailing space after #1 in csname x#1 endcsname might be too much. (But this is all speculation without a full example document where I can verify the definitions involved.)

– moewe
5 hours ago







My guess would be that the popQED within csname ... endcsname is a bit too much for LaTeX. I presume popQED does not expand to simple text, so LaTeX fails to make sense of it as part of a control sequence name. Maybe you just mean csname endx#1endcsnamepopQED? I'm also not quite sure if the expandafters are needed and the trailing space after #1 in csname x#1 endcsname might be too much. (But this is all speculation without a full example document where I can verify the definitions involved.)

– moewe
5 hours ago















@moewe Using pushQED was something I found searching for how to pass arguments to the end part. The space after #1 was from searching the error, removing them doesn't change that. moving popQED behind endscname causes the error to go, but then it prints 'default' and doesn't call endxdefault

– Thorsten Schmitz
4 hours ago







@moewe Using pushQED was something I found searching for how to pass arguments to the end part. The space after #1 was from searching the error, removing them doesn't change that. moving popQED behind endscname causes the error to go, but then it prints 'default' and doesn't call endxdefault

– Thorsten Schmitz
4 hours ago















Ah, I see. I don't think popQED and pushQED can help you here. Try deftssavedarg{#1} and csname endxtssavedargendcsname instead.

– moewe
4 hours ago







Ah, I see. I don't think popQED and pushQED can help you here. Try deftssavedarg{#1} and csname endxtssavedargendcsname instead.

– moewe
4 hours ago















expandaftercsname x expands x which is not expandable, so the expandafter is doing nothing.

– David Carlisle
4 hours ago





expandaftercsname x expands x which is not expandable, so the expandafter is doing nothing.

– David Carlisle
4 hours ago










2 Answers
2






active

oldest

votes


















3














Try something like



documentclass{article}
usepackage[utf8]{inputenc}

% make sure tssavedarg is not taken already
newcommand*{tssavedarg}{}
newenvironment{myEnv}[1][default]
{deftssavedarg{#1}%
csname x#1endcsname}
{csname endxtssavedargendcsname}

newenvironment{xdefault}{XX}{YY}

begin{document}

begin{myEnv}
A
end{myEnv}

end{document}


pushQED and popQED are specifically for QED handling in amsmath and they seem to implement a full QED stack, which you do not need. In particular popQED does not simply expand to the contents saved with pushQED, so it does not work within csname ... endcsname as expected.



In your case it is enough to just save the #1 in a normal macro with def and then retrieve the macro value by calling it.



Related Why can't the end code of an environment contain an argument?.



The xparse/LaTeX3 solution would be



usepackage{xparse}
NewDocumentEnvironment{myEnv}{O{default}}
{csname x#1endcsname}
{csname endx#1endcsname}


or maybe even more expl3-y



usepackage{xparse}
ExplSyntaxOn
NewDocumentEnvironment{myEnv}{O{default}}
{use:c{x#1}}
{use:c{endx#1}}
ExplSyntaxOff


because xparse's environments can access the arguments even in the end code.






share|improve this answer


























  • Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

    – Thorsten Schmitz
    4 hours ago











  • @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

    – moewe
    4 hours ago













  • mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

    – moewe
    4 hours ago



















1














Let's see how pushQED and popQED are defined in amsthm.sty:



    274 DeclareRobustCommand{qed}{%
275 ifmmode mathqed
276 else
277 leavevmodeunskippenalty9999 hbox{}nobreakhfill
278 quadhbox{qedsymbol}%
279 fi
280 }
281 letQED@stack@empty
282 letqed@eltrelax
283 newcommand{pushQED}[1]{%
284 toks@{qed@elt{#1}}@temptokenaexpandafter{QED@stack}%
285 xdefQED@stack{thetoks@the@temptokena}%
286 }
287 newcommand{popQED}{%
288 begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup
289 }
290 defpopQED@elt#1#2relax{#1gdefQED@stack{#2}}
291 newcommand{qedhere}{%
292 begingroup letmathqedmath@qedhere
293 letqed@eltsetQED@elt QED@stackrelaxrelax endgroup
294 }


The name clearly shows that this has to do with the typesetting of the QED marker in proofs, so I included the definition of qed.



There is a “stack”, actually a macro, called QED@stack, that's initialized to empty.



Suppose we call pushQED{foo} when the stack is empty. Two scratch token registers are set: first toks@ is set to qed@elt{foo}, then @temptokena is set to contain the current first level expansion of QED@stack (in this case, nothing). Next, QED@stack is redefined to contain the token lists in the two registers; with e-TeX extensions, this could be achieved with the single instruction



xdefQED@stack{unexpanded{qed@elt{#1}}unexpandedexpandafter{QED@stack}}


So now QED@stack will expand to qed@elt{foo}. If another pushQED{bar} follows, the expansion would become qed@elt{bar}qed@elt{foo}. But let's stay with the simple case.



What happens when popQED is called? The instructions at line 288 are executed, namely



begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup


The macro qed@elt (that normally is relax, see line 282) is set to mean popQED@elt inside a group and then QED@stackrelaxrelax is examined. In your case it is



qed@elt{foo}relaxrelax


Since the macro qed@elt has been redefined, this is the same as popQED@elt{foo}relaxrelax and, according to the definition of popQED@elt,



#1 <- {foo}
#2 <-


and therefore



foogdefQED@stack{}relax


would remain in the main token list (the braces are stripped off by rule of TeX). In case QED@stack had been qed@elt{bar}qed@elt{foo}, we'd have



#1 <- {bar}
#2 <- qed@elt{foo}


and bargdefQED@stack{qed@elt{foo}}relax would be pushed into the main input stream.



Just the fact that the expansion of popQED begins with begingroup disqualifies it from being legal inside csname...endcsname; moreover assignments cannot be performed in that context, so it's a lost battle to begin with.



The double relax is in case the stack is empty at the time popQED is called, that is without a matching pushQED command.



What's the main usage of the system? The standard proof environment in amsthm.sty is defined as



    432 newenvironment{proof}[1][proofname]{par
433 pushQED{qed}%
434 normalfont topsep6p@@plus6p@relax
435 trivlist
436 item[hskiplabelsep
437 itshape
438 #1@addpunct{.}]ignorespaces
439 }{%
440 popQEDendtrivlist@endpefalse
441 }


The idea is that a subordinate proof environment might define its own tombstone symbol and push it in the stack, so at end environment the right symbol would be used.





Can you use stacks for this purpose? Yes.



documentclass{article}
usepackage{xparse}

ExplSyntaxOn

NewDocumentCommand{newstack}{m}
{
seq_new:c { g_thorsten_#1_stack_seq }
}

NewDocumentCommand{push}{mm}
{% #1 is the stack's name, #2 the item to push
seq_gpush:cn { g_thorsten_#1_stack_seq } { #2 }
}

NewDocumentCommand{pop}{mo}
{% #1 is the stack's name, #2 what you should do with the top item
% reinitialize, in case it has been modified
cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
IfValueT{ #2 }
{
cs_set:Nn __thorsten_stack_exec:n { #2 }
}
seq_gpop:cNTF { g_thorsten_#1_stack_seq } l__thorsten_stack_item_tl
{% if the stack is not empty
__thorsten_stack_exec:V l__thorsten_stack_item_tl
}
{% if the stack is empty, issue an error
__thorsten_stack_exec:n { STACKEMPTYERROR }
}
}

tl_new:N l__thorsten_stack_item_tl
cs_new_protected:Nn __thorsten_stack_exec_default:n { #1 }
cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
cs_generate_variant:Nn __thorsten_stack_exec:n { V }

ExplSyntaxOff

newstack{env}

newenvironment{myEnv}[1][default]
{%
push{env}{#1}%
csname x#1endcsname
}
{%
pop{env}[csname endx##1endcsname]%
}

newenvironment{xdefault}{par start}{finishpar}
newenvironment{xinner}{par startinner}{finishinnerpar}

begin{document}

begin{myEnv}
begin{myEnv}[inner]
end{myEnv}
end{myEnv}

newstack{foo}

push{foo}{A}
push{foo}{B}
push{foo}{C}

pop{foo}[@@#1@@]
pop{foo}[??#1??]
pop{foo}[!!#1!!]
pop{foo}[---#1---]

end{document}


The push command takes as arguments the stack's name and the item to push. pop takes as mandatory argument the stack's name and the optional argument is a template for what to do with the popped item (default is to just deliver it) after removing the item from the top of the stack.



Be careful with spaces in your input: csname x#1 endcsname is not the same as csname x#1endcsname.



enter image description here



Since in the last example the pop operation is called on an empty stack, an error is produced



! Undefined control sequence.
<argument> STACKEMPTYERROR

l.69 pop{foo}[---#1---]





share|improve this answer


























    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
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f491651%2fcsname-in-newenviroment%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    Try something like



    documentclass{article}
    usepackage[utf8]{inputenc}

    % make sure tssavedarg is not taken already
    newcommand*{tssavedarg}{}
    newenvironment{myEnv}[1][default]
    {deftssavedarg{#1}%
    csname x#1endcsname}
    {csname endxtssavedargendcsname}

    newenvironment{xdefault}{XX}{YY}

    begin{document}

    begin{myEnv}
    A
    end{myEnv}

    end{document}


    pushQED and popQED are specifically for QED handling in amsmath and they seem to implement a full QED stack, which you do not need. In particular popQED does not simply expand to the contents saved with pushQED, so it does not work within csname ... endcsname as expected.



    In your case it is enough to just save the #1 in a normal macro with def and then retrieve the macro value by calling it.



    Related Why can't the end code of an environment contain an argument?.



    The xparse/LaTeX3 solution would be



    usepackage{xparse}
    NewDocumentEnvironment{myEnv}{O{default}}
    {csname x#1endcsname}
    {csname endx#1endcsname}


    or maybe even more expl3-y



    usepackage{xparse}
    ExplSyntaxOn
    NewDocumentEnvironment{myEnv}{O{default}}
    {use:c{x#1}}
    {use:c{endx#1}}
    ExplSyntaxOff


    because xparse's environments can access the arguments even in the end code.






    share|improve this answer


























    • Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

      – Thorsten Schmitz
      4 hours ago











    • @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

      – moewe
      4 hours ago













    • mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

      – moewe
      4 hours ago
















    3














    Try something like



    documentclass{article}
    usepackage[utf8]{inputenc}

    % make sure tssavedarg is not taken already
    newcommand*{tssavedarg}{}
    newenvironment{myEnv}[1][default]
    {deftssavedarg{#1}%
    csname x#1endcsname}
    {csname endxtssavedargendcsname}

    newenvironment{xdefault}{XX}{YY}

    begin{document}

    begin{myEnv}
    A
    end{myEnv}

    end{document}


    pushQED and popQED are specifically for QED handling in amsmath and they seem to implement a full QED stack, which you do not need. In particular popQED does not simply expand to the contents saved with pushQED, so it does not work within csname ... endcsname as expected.



    In your case it is enough to just save the #1 in a normal macro with def and then retrieve the macro value by calling it.



    Related Why can't the end code of an environment contain an argument?.



    The xparse/LaTeX3 solution would be



    usepackage{xparse}
    NewDocumentEnvironment{myEnv}{O{default}}
    {csname x#1endcsname}
    {csname endx#1endcsname}


    or maybe even more expl3-y



    usepackage{xparse}
    ExplSyntaxOn
    NewDocumentEnvironment{myEnv}{O{default}}
    {use:c{x#1}}
    {use:c{endx#1}}
    ExplSyntaxOff


    because xparse's environments can access the arguments even in the end code.






    share|improve this answer


























    • Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

      – Thorsten Schmitz
      4 hours ago











    • @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

      – moewe
      4 hours ago













    • mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

      – moewe
      4 hours ago














    3












    3








    3







    Try something like



    documentclass{article}
    usepackage[utf8]{inputenc}

    % make sure tssavedarg is not taken already
    newcommand*{tssavedarg}{}
    newenvironment{myEnv}[1][default]
    {deftssavedarg{#1}%
    csname x#1endcsname}
    {csname endxtssavedargendcsname}

    newenvironment{xdefault}{XX}{YY}

    begin{document}

    begin{myEnv}
    A
    end{myEnv}

    end{document}


    pushQED and popQED are specifically for QED handling in amsmath and they seem to implement a full QED stack, which you do not need. In particular popQED does not simply expand to the contents saved with pushQED, so it does not work within csname ... endcsname as expected.



    In your case it is enough to just save the #1 in a normal macro with def and then retrieve the macro value by calling it.



    Related Why can't the end code of an environment contain an argument?.



    The xparse/LaTeX3 solution would be



    usepackage{xparse}
    NewDocumentEnvironment{myEnv}{O{default}}
    {csname x#1endcsname}
    {csname endx#1endcsname}


    or maybe even more expl3-y



    usepackage{xparse}
    ExplSyntaxOn
    NewDocumentEnvironment{myEnv}{O{default}}
    {use:c{x#1}}
    {use:c{endx#1}}
    ExplSyntaxOff


    because xparse's environments can access the arguments even in the end code.






    share|improve this answer















    Try something like



    documentclass{article}
    usepackage[utf8]{inputenc}

    % make sure tssavedarg is not taken already
    newcommand*{tssavedarg}{}
    newenvironment{myEnv}[1][default]
    {deftssavedarg{#1}%
    csname x#1endcsname}
    {csname endxtssavedargendcsname}

    newenvironment{xdefault}{XX}{YY}

    begin{document}

    begin{myEnv}
    A
    end{myEnv}

    end{document}


    pushQED and popQED are specifically for QED handling in amsmath and they seem to implement a full QED stack, which you do not need. In particular popQED does not simply expand to the contents saved with pushQED, so it does not work within csname ... endcsname as expected.



    In your case it is enough to just save the #1 in a normal macro with def and then retrieve the macro value by calling it.



    Related Why can't the end code of an environment contain an argument?.



    The xparse/LaTeX3 solution would be



    usepackage{xparse}
    NewDocumentEnvironment{myEnv}{O{default}}
    {csname x#1endcsname}
    {csname endx#1endcsname}


    or maybe even more expl3-y



    usepackage{xparse}
    ExplSyntaxOn
    NewDocumentEnvironment{myEnv}{O{default}}
    {use:c{x#1}}
    {use:c{endx#1}}
    ExplSyntaxOff


    because xparse's environments can access the arguments even in the end code.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 4 hours ago

























    answered 4 hours ago









    moewemoewe

    98.8k10121372




    98.8k10121372













    • Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

      – Thorsten Schmitz
      4 hours ago











    • @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

      – moewe
      4 hours ago













    • mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

      – moewe
      4 hours ago



















    • Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

      – Thorsten Schmitz
      4 hours ago











    • @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

      – moewe
      4 hours ago













    • mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

      – moewe
      4 hours ago

















    Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

    – Thorsten Schmitz
    4 hours ago





    Thanks for your answer, I will lok into this. Btw could you tell me where you found the doc for pushQED/popQED? I couldn't find one, so I didn't really know, how they worked. Just did what was recommended in a thread I found.

    – Thorsten Schmitz
    4 hours ago













    @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

    – moewe
    4 hours ago







    @ThorstenSchmitz I didn't find a lot about the two. The amsthm documentation mentions the two only in a code example. But the source code shows that popQED does not simply expand to the saved test and suggests that the two implement a sort of stack. Where were those commands recommended for the job you had in mind, if I might ask?

    – moewe
    4 hours ago















    mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

    – moewe
    4 hours ago





    mirrors.ctan.org/macros/latex/required/amscls/doc/amsclass.pdf also has a little bit on the commands and their implementation

    – moewe
    4 hours ago











    1














    Let's see how pushQED and popQED are defined in amsthm.sty:



        274 DeclareRobustCommand{qed}{%
    275 ifmmode mathqed
    276 else
    277 leavevmodeunskippenalty9999 hbox{}nobreakhfill
    278 quadhbox{qedsymbol}%
    279 fi
    280 }
    281 letQED@stack@empty
    282 letqed@eltrelax
    283 newcommand{pushQED}[1]{%
    284 toks@{qed@elt{#1}}@temptokenaexpandafter{QED@stack}%
    285 xdefQED@stack{thetoks@the@temptokena}%
    286 }
    287 newcommand{popQED}{%
    288 begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup
    289 }
    290 defpopQED@elt#1#2relax{#1gdefQED@stack{#2}}
    291 newcommand{qedhere}{%
    292 begingroup letmathqedmath@qedhere
    293 letqed@eltsetQED@elt QED@stackrelaxrelax endgroup
    294 }


    The name clearly shows that this has to do with the typesetting of the QED marker in proofs, so I included the definition of qed.



    There is a “stack”, actually a macro, called QED@stack, that's initialized to empty.



    Suppose we call pushQED{foo} when the stack is empty. Two scratch token registers are set: first toks@ is set to qed@elt{foo}, then @temptokena is set to contain the current first level expansion of QED@stack (in this case, nothing). Next, QED@stack is redefined to contain the token lists in the two registers; with e-TeX extensions, this could be achieved with the single instruction



    xdefQED@stack{unexpanded{qed@elt{#1}}unexpandedexpandafter{QED@stack}}


    So now QED@stack will expand to qed@elt{foo}. If another pushQED{bar} follows, the expansion would become qed@elt{bar}qed@elt{foo}. But let's stay with the simple case.



    What happens when popQED is called? The instructions at line 288 are executed, namely



    begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup


    The macro qed@elt (that normally is relax, see line 282) is set to mean popQED@elt inside a group and then QED@stackrelaxrelax is examined. In your case it is



    qed@elt{foo}relaxrelax


    Since the macro qed@elt has been redefined, this is the same as popQED@elt{foo}relaxrelax and, according to the definition of popQED@elt,



    #1 <- {foo}
    #2 <-


    and therefore



    foogdefQED@stack{}relax


    would remain in the main token list (the braces are stripped off by rule of TeX). In case QED@stack had been qed@elt{bar}qed@elt{foo}, we'd have



    #1 <- {bar}
    #2 <- qed@elt{foo}


    and bargdefQED@stack{qed@elt{foo}}relax would be pushed into the main input stream.



    Just the fact that the expansion of popQED begins with begingroup disqualifies it from being legal inside csname...endcsname; moreover assignments cannot be performed in that context, so it's a lost battle to begin with.



    The double relax is in case the stack is empty at the time popQED is called, that is without a matching pushQED command.



    What's the main usage of the system? The standard proof environment in amsthm.sty is defined as



        432 newenvironment{proof}[1][proofname]{par
    433 pushQED{qed}%
    434 normalfont topsep6p@@plus6p@relax
    435 trivlist
    436 item[hskiplabelsep
    437 itshape
    438 #1@addpunct{.}]ignorespaces
    439 }{%
    440 popQEDendtrivlist@endpefalse
    441 }


    The idea is that a subordinate proof environment might define its own tombstone symbol and push it in the stack, so at end environment the right symbol would be used.





    Can you use stacks for this purpose? Yes.



    documentclass{article}
    usepackage{xparse}

    ExplSyntaxOn

    NewDocumentCommand{newstack}{m}
    {
    seq_new:c { g_thorsten_#1_stack_seq }
    }

    NewDocumentCommand{push}{mm}
    {% #1 is the stack's name, #2 the item to push
    seq_gpush:cn { g_thorsten_#1_stack_seq } { #2 }
    }

    NewDocumentCommand{pop}{mo}
    {% #1 is the stack's name, #2 what you should do with the top item
    % reinitialize, in case it has been modified
    cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
    IfValueT{ #2 }
    {
    cs_set:Nn __thorsten_stack_exec:n { #2 }
    }
    seq_gpop:cNTF { g_thorsten_#1_stack_seq } l__thorsten_stack_item_tl
    {% if the stack is not empty
    __thorsten_stack_exec:V l__thorsten_stack_item_tl
    }
    {% if the stack is empty, issue an error
    __thorsten_stack_exec:n { STACKEMPTYERROR }
    }
    }

    tl_new:N l__thorsten_stack_item_tl
    cs_new_protected:Nn __thorsten_stack_exec_default:n { #1 }
    cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
    cs_generate_variant:Nn __thorsten_stack_exec:n { V }

    ExplSyntaxOff

    newstack{env}

    newenvironment{myEnv}[1][default]
    {%
    push{env}{#1}%
    csname x#1endcsname
    }
    {%
    pop{env}[csname endx##1endcsname]%
    }

    newenvironment{xdefault}{par start}{finishpar}
    newenvironment{xinner}{par startinner}{finishinnerpar}

    begin{document}

    begin{myEnv}
    begin{myEnv}[inner]
    end{myEnv}
    end{myEnv}

    newstack{foo}

    push{foo}{A}
    push{foo}{B}
    push{foo}{C}

    pop{foo}[@@#1@@]
    pop{foo}[??#1??]
    pop{foo}[!!#1!!]
    pop{foo}[---#1---]

    end{document}


    The push command takes as arguments the stack's name and the item to push. pop takes as mandatory argument the stack's name and the optional argument is a template for what to do with the popped item (default is to just deliver it) after removing the item from the top of the stack.



    Be careful with spaces in your input: csname x#1 endcsname is not the same as csname x#1endcsname.



    enter image description here



    Since in the last example the pop operation is called on an empty stack, an error is produced



    ! Undefined control sequence.
    <argument> STACKEMPTYERROR

    l.69 pop{foo}[---#1---]





    share|improve this answer






























      1














      Let's see how pushQED and popQED are defined in amsthm.sty:



          274 DeclareRobustCommand{qed}{%
      275 ifmmode mathqed
      276 else
      277 leavevmodeunskippenalty9999 hbox{}nobreakhfill
      278 quadhbox{qedsymbol}%
      279 fi
      280 }
      281 letQED@stack@empty
      282 letqed@eltrelax
      283 newcommand{pushQED}[1]{%
      284 toks@{qed@elt{#1}}@temptokenaexpandafter{QED@stack}%
      285 xdefQED@stack{thetoks@the@temptokena}%
      286 }
      287 newcommand{popQED}{%
      288 begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup
      289 }
      290 defpopQED@elt#1#2relax{#1gdefQED@stack{#2}}
      291 newcommand{qedhere}{%
      292 begingroup letmathqedmath@qedhere
      293 letqed@eltsetQED@elt QED@stackrelaxrelax endgroup
      294 }


      The name clearly shows that this has to do with the typesetting of the QED marker in proofs, so I included the definition of qed.



      There is a “stack”, actually a macro, called QED@stack, that's initialized to empty.



      Suppose we call pushQED{foo} when the stack is empty. Two scratch token registers are set: first toks@ is set to qed@elt{foo}, then @temptokena is set to contain the current first level expansion of QED@stack (in this case, nothing). Next, QED@stack is redefined to contain the token lists in the two registers; with e-TeX extensions, this could be achieved with the single instruction



      xdefQED@stack{unexpanded{qed@elt{#1}}unexpandedexpandafter{QED@stack}}


      So now QED@stack will expand to qed@elt{foo}. If another pushQED{bar} follows, the expansion would become qed@elt{bar}qed@elt{foo}. But let's stay with the simple case.



      What happens when popQED is called? The instructions at line 288 are executed, namely



      begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup


      The macro qed@elt (that normally is relax, see line 282) is set to mean popQED@elt inside a group and then QED@stackrelaxrelax is examined. In your case it is



      qed@elt{foo}relaxrelax


      Since the macro qed@elt has been redefined, this is the same as popQED@elt{foo}relaxrelax and, according to the definition of popQED@elt,



      #1 <- {foo}
      #2 <-


      and therefore



      foogdefQED@stack{}relax


      would remain in the main token list (the braces are stripped off by rule of TeX). In case QED@stack had been qed@elt{bar}qed@elt{foo}, we'd have



      #1 <- {bar}
      #2 <- qed@elt{foo}


      and bargdefQED@stack{qed@elt{foo}}relax would be pushed into the main input stream.



      Just the fact that the expansion of popQED begins with begingroup disqualifies it from being legal inside csname...endcsname; moreover assignments cannot be performed in that context, so it's a lost battle to begin with.



      The double relax is in case the stack is empty at the time popQED is called, that is without a matching pushQED command.



      What's the main usage of the system? The standard proof environment in amsthm.sty is defined as



          432 newenvironment{proof}[1][proofname]{par
      433 pushQED{qed}%
      434 normalfont topsep6p@@plus6p@relax
      435 trivlist
      436 item[hskiplabelsep
      437 itshape
      438 #1@addpunct{.}]ignorespaces
      439 }{%
      440 popQEDendtrivlist@endpefalse
      441 }


      The idea is that a subordinate proof environment might define its own tombstone symbol and push it in the stack, so at end environment the right symbol would be used.





      Can you use stacks for this purpose? Yes.



      documentclass{article}
      usepackage{xparse}

      ExplSyntaxOn

      NewDocumentCommand{newstack}{m}
      {
      seq_new:c { g_thorsten_#1_stack_seq }
      }

      NewDocumentCommand{push}{mm}
      {% #1 is the stack's name, #2 the item to push
      seq_gpush:cn { g_thorsten_#1_stack_seq } { #2 }
      }

      NewDocumentCommand{pop}{mo}
      {% #1 is the stack's name, #2 what you should do with the top item
      % reinitialize, in case it has been modified
      cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
      IfValueT{ #2 }
      {
      cs_set:Nn __thorsten_stack_exec:n { #2 }
      }
      seq_gpop:cNTF { g_thorsten_#1_stack_seq } l__thorsten_stack_item_tl
      {% if the stack is not empty
      __thorsten_stack_exec:V l__thorsten_stack_item_tl
      }
      {% if the stack is empty, issue an error
      __thorsten_stack_exec:n { STACKEMPTYERROR }
      }
      }

      tl_new:N l__thorsten_stack_item_tl
      cs_new_protected:Nn __thorsten_stack_exec_default:n { #1 }
      cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
      cs_generate_variant:Nn __thorsten_stack_exec:n { V }

      ExplSyntaxOff

      newstack{env}

      newenvironment{myEnv}[1][default]
      {%
      push{env}{#1}%
      csname x#1endcsname
      }
      {%
      pop{env}[csname endx##1endcsname]%
      }

      newenvironment{xdefault}{par start}{finishpar}
      newenvironment{xinner}{par startinner}{finishinnerpar}

      begin{document}

      begin{myEnv}
      begin{myEnv}[inner]
      end{myEnv}
      end{myEnv}

      newstack{foo}

      push{foo}{A}
      push{foo}{B}
      push{foo}{C}

      pop{foo}[@@#1@@]
      pop{foo}[??#1??]
      pop{foo}[!!#1!!]
      pop{foo}[---#1---]

      end{document}


      The push command takes as arguments the stack's name and the item to push. pop takes as mandatory argument the stack's name and the optional argument is a template for what to do with the popped item (default is to just deliver it) after removing the item from the top of the stack.



      Be careful with spaces in your input: csname x#1 endcsname is not the same as csname x#1endcsname.



      enter image description here



      Since in the last example the pop operation is called on an empty stack, an error is produced



      ! Undefined control sequence.
      <argument> STACKEMPTYERROR

      l.69 pop{foo}[---#1---]





      share|improve this answer




























        1












        1








        1







        Let's see how pushQED and popQED are defined in amsthm.sty:



            274 DeclareRobustCommand{qed}{%
        275 ifmmode mathqed
        276 else
        277 leavevmodeunskippenalty9999 hbox{}nobreakhfill
        278 quadhbox{qedsymbol}%
        279 fi
        280 }
        281 letQED@stack@empty
        282 letqed@eltrelax
        283 newcommand{pushQED}[1]{%
        284 toks@{qed@elt{#1}}@temptokenaexpandafter{QED@stack}%
        285 xdefQED@stack{thetoks@the@temptokena}%
        286 }
        287 newcommand{popQED}{%
        288 begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup
        289 }
        290 defpopQED@elt#1#2relax{#1gdefQED@stack{#2}}
        291 newcommand{qedhere}{%
        292 begingroup letmathqedmath@qedhere
        293 letqed@eltsetQED@elt QED@stackrelaxrelax endgroup
        294 }


        The name clearly shows that this has to do with the typesetting of the QED marker in proofs, so I included the definition of qed.



        There is a “stack”, actually a macro, called QED@stack, that's initialized to empty.



        Suppose we call pushQED{foo} when the stack is empty. Two scratch token registers are set: first toks@ is set to qed@elt{foo}, then @temptokena is set to contain the current first level expansion of QED@stack (in this case, nothing). Next, QED@stack is redefined to contain the token lists in the two registers; with e-TeX extensions, this could be achieved with the single instruction



        xdefQED@stack{unexpanded{qed@elt{#1}}unexpandedexpandafter{QED@stack}}


        So now QED@stack will expand to qed@elt{foo}. If another pushQED{bar} follows, the expansion would become qed@elt{bar}qed@elt{foo}. But let's stay with the simple case.



        What happens when popQED is called? The instructions at line 288 are executed, namely



        begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup


        The macro qed@elt (that normally is relax, see line 282) is set to mean popQED@elt inside a group and then QED@stackrelaxrelax is examined. In your case it is



        qed@elt{foo}relaxrelax


        Since the macro qed@elt has been redefined, this is the same as popQED@elt{foo}relaxrelax and, according to the definition of popQED@elt,



        #1 <- {foo}
        #2 <-


        and therefore



        foogdefQED@stack{}relax


        would remain in the main token list (the braces are stripped off by rule of TeX). In case QED@stack had been qed@elt{bar}qed@elt{foo}, we'd have



        #1 <- {bar}
        #2 <- qed@elt{foo}


        and bargdefQED@stack{qed@elt{foo}}relax would be pushed into the main input stream.



        Just the fact that the expansion of popQED begins with begingroup disqualifies it from being legal inside csname...endcsname; moreover assignments cannot be performed in that context, so it's a lost battle to begin with.



        The double relax is in case the stack is empty at the time popQED is called, that is without a matching pushQED command.



        What's the main usage of the system? The standard proof environment in amsthm.sty is defined as



            432 newenvironment{proof}[1][proofname]{par
        433 pushQED{qed}%
        434 normalfont topsep6p@@plus6p@relax
        435 trivlist
        436 item[hskiplabelsep
        437 itshape
        438 #1@addpunct{.}]ignorespaces
        439 }{%
        440 popQEDendtrivlist@endpefalse
        441 }


        The idea is that a subordinate proof environment might define its own tombstone symbol and push it in the stack, so at end environment the right symbol would be used.





        Can you use stacks for this purpose? Yes.



        documentclass{article}
        usepackage{xparse}

        ExplSyntaxOn

        NewDocumentCommand{newstack}{m}
        {
        seq_new:c { g_thorsten_#1_stack_seq }
        }

        NewDocumentCommand{push}{mm}
        {% #1 is the stack's name, #2 the item to push
        seq_gpush:cn { g_thorsten_#1_stack_seq } { #2 }
        }

        NewDocumentCommand{pop}{mo}
        {% #1 is the stack's name, #2 what you should do with the top item
        % reinitialize, in case it has been modified
        cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
        IfValueT{ #2 }
        {
        cs_set:Nn __thorsten_stack_exec:n { #2 }
        }
        seq_gpop:cNTF { g_thorsten_#1_stack_seq } l__thorsten_stack_item_tl
        {% if the stack is not empty
        __thorsten_stack_exec:V l__thorsten_stack_item_tl
        }
        {% if the stack is empty, issue an error
        __thorsten_stack_exec:n { STACKEMPTYERROR }
        }
        }

        tl_new:N l__thorsten_stack_item_tl
        cs_new_protected:Nn __thorsten_stack_exec_default:n { #1 }
        cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
        cs_generate_variant:Nn __thorsten_stack_exec:n { V }

        ExplSyntaxOff

        newstack{env}

        newenvironment{myEnv}[1][default]
        {%
        push{env}{#1}%
        csname x#1endcsname
        }
        {%
        pop{env}[csname endx##1endcsname]%
        }

        newenvironment{xdefault}{par start}{finishpar}
        newenvironment{xinner}{par startinner}{finishinnerpar}

        begin{document}

        begin{myEnv}
        begin{myEnv}[inner]
        end{myEnv}
        end{myEnv}

        newstack{foo}

        push{foo}{A}
        push{foo}{B}
        push{foo}{C}

        pop{foo}[@@#1@@]
        pop{foo}[??#1??]
        pop{foo}[!!#1!!]
        pop{foo}[---#1---]

        end{document}


        The push command takes as arguments the stack's name and the item to push. pop takes as mandatory argument the stack's name and the optional argument is a template for what to do with the popped item (default is to just deliver it) after removing the item from the top of the stack.



        Be careful with spaces in your input: csname x#1 endcsname is not the same as csname x#1endcsname.



        enter image description here



        Since in the last example the pop operation is called on an empty stack, an error is produced



        ! Undefined control sequence.
        <argument> STACKEMPTYERROR

        l.69 pop{foo}[---#1---]





        share|improve this answer















        Let's see how pushQED and popQED are defined in amsthm.sty:



            274 DeclareRobustCommand{qed}{%
        275 ifmmode mathqed
        276 else
        277 leavevmodeunskippenalty9999 hbox{}nobreakhfill
        278 quadhbox{qedsymbol}%
        279 fi
        280 }
        281 letQED@stack@empty
        282 letqed@eltrelax
        283 newcommand{pushQED}[1]{%
        284 toks@{qed@elt{#1}}@temptokenaexpandafter{QED@stack}%
        285 xdefQED@stack{thetoks@the@temptokena}%
        286 }
        287 newcommand{popQED}{%
        288 begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup
        289 }
        290 defpopQED@elt#1#2relax{#1gdefQED@stack{#2}}
        291 newcommand{qedhere}{%
        292 begingroup letmathqedmath@qedhere
        293 letqed@eltsetQED@elt QED@stackrelaxrelax endgroup
        294 }


        The name clearly shows that this has to do with the typesetting of the QED marker in proofs, so I included the definition of qed.



        There is a “stack”, actually a macro, called QED@stack, that's initialized to empty.



        Suppose we call pushQED{foo} when the stack is empty. Two scratch token registers are set: first toks@ is set to qed@elt{foo}, then @temptokena is set to contain the current first level expansion of QED@stack (in this case, nothing). Next, QED@stack is redefined to contain the token lists in the two registers; with e-TeX extensions, this could be achieved with the single instruction



        xdefQED@stack{unexpanded{qed@elt{#1}}unexpandedexpandafter{QED@stack}}


        So now QED@stack will expand to qed@elt{foo}. If another pushQED{bar} follows, the expansion would become qed@elt{bar}qed@elt{foo}. But let's stay with the simple case.



        What happens when popQED is called? The instructions at line 288 are executed, namely



        begingroupletqed@eltpopQED@elt QED@stackrelaxrelaxendgroup


        The macro qed@elt (that normally is relax, see line 282) is set to mean popQED@elt inside a group and then QED@stackrelaxrelax is examined. In your case it is



        qed@elt{foo}relaxrelax


        Since the macro qed@elt has been redefined, this is the same as popQED@elt{foo}relaxrelax and, according to the definition of popQED@elt,



        #1 <- {foo}
        #2 <-


        and therefore



        foogdefQED@stack{}relax


        would remain in the main token list (the braces are stripped off by rule of TeX). In case QED@stack had been qed@elt{bar}qed@elt{foo}, we'd have



        #1 <- {bar}
        #2 <- qed@elt{foo}


        and bargdefQED@stack{qed@elt{foo}}relax would be pushed into the main input stream.



        Just the fact that the expansion of popQED begins with begingroup disqualifies it from being legal inside csname...endcsname; moreover assignments cannot be performed in that context, so it's a lost battle to begin with.



        The double relax is in case the stack is empty at the time popQED is called, that is without a matching pushQED command.



        What's the main usage of the system? The standard proof environment in amsthm.sty is defined as



            432 newenvironment{proof}[1][proofname]{par
        433 pushQED{qed}%
        434 normalfont topsep6p@@plus6p@relax
        435 trivlist
        436 item[hskiplabelsep
        437 itshape
        438 #1@addpunct{.}]ignorespaces
        439 }{%
        440 popQEDendtrivlist@endpefalse
        441 }


        The idea is that a subordinate proof environment might define its own tombstone symbol and push it in the stack, so at end environment the right symbol would be used.





        Can you use stacks for this purpose? Yes.



        documentclass{article}
        usepackage{xparse}

        ExplSyntaxOn

        NewDocumentCommand{newstack}{m}
        {
        seq_new:c { g_thorsten_#1_stack_seq }
        }

        NewDocumentCommand{push}{mm}
        {% #1 is the stack's name, #2 the item to push
        seq_gpush:cn { g_thorsten_#1_stack_seq } { #2 }
        }

        NewDocumentCommand{pop}{mo}
        {% #1 is the stack's name, #2 what you should do with the top item
        % reinitialize, in case it has been modified
        cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
        IfValueT{ #2 }
        {
        cs_set:Nn __thorsten_stack_exec:n { #2 }
        }
        seq_gpop:cNTF { g_thorsten_#1_stack_seq } l__thorsten_stack_item_tl
        {% if the stack is not empty
        __thorsten_stack_exec:V l__thorsten_stack_item_tl
        }
        {% if the stack is empty, issue an error
        __thorsten_stack_exec:n { STACKEMPTYERROR }
        }
        }

        tl_new:N l__thorsten_stack_item_tl
        cs_new_protected:Nn __thorsten_stack_exec_default:n { #1 }
        cs_set_eq:NN __thorsten_stack_exec:n __thorsten_stack_exec_default:n
        cs_generate_variant:Nn __thorsten_stack_exec:n { V }

        ExplSyntaxOff

        newstack{env}

        newenvironment{myEnv}[1][default]
        {%
        push{env}{#1}%
        csname x#1endcsname
        }
        {%
        pop{env}[csname endx##1endcsname]%
        }

        newenvironment{xdefault}{par start}{finishpar}
        newenvironment{xinner}{par startinner}{finishinnerpar}

        begin{document}

        begin{myEnv}
        begin{myEnv}[inner]
        end{myEnv}
        end{myEnv}

        newstack{foo}

        push{foo}{A}
        push{foo}{B}
        push{foo}{C}

        pop{foo}[@@#1@@]
        pop{foo}[??#1??]
        pop{foo}[!!#1!!]
        pop{foo}[---#1---]

        end{document}


        The push command takes as arguments the stack's name and the item to push. pop takes as mandatory argument the stack's name and the optional argument is a template for what to do with the popped item (default is to just deliver it) after removing the item from the top of the stack.



        Be careful with spaces in your input: csname x#1 endcsname is not the same as csname x#1endcsname.



        enter image description here



        Since in the last example the pop operation is called on an empty stack, an error is produced



        ! Undefined control sequence.
        <argument> STACKEMPTYERROR

        l.69 pop{foo}[---#1---]






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 hours ago

























        answered 2 hours ago









        egregegreg

        742k8919443277




        742k8919443277






























            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f491651%2fcsname-in-newenviroment%23new-answer', 'question_page');
            }
            );

            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







            Popular posts from this blog

            Hudson River Historic District Contents Geography History The district today Aesthetics Cultural...

            The number designs the writing. Feandra Aversely Definition: The act of ingrafting a sprig or shoot of one...

            Ayherre Geografie Demografie Externe links Navigatiemenu43° 23′ NB, 1° 15′ WL43° 23′ NB, 1°...