How to perform a globalrenewenvironment

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
5
down vote

favorite












I need to execute a renewenvironment within a group. Using globalrenewenvironment is not sufficient.



What changes do I need to make to the DisableMyEnvironment macro in the MWE below so as to achieve the equivalent of globalrenewenvironment?



Currently, the MWE yields:



enter image description here



Once this is working as desired, the second line in blue should be in black.



Notes:



  • There are two test cases. The default one is within a foreach and commenting out defForeachTestCase uses a simple group.

References:




  • globalrenewcommand equivalent of globaldef.

Code:



defForeachTestCase%

documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz

newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%

newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%

newcommand*MyTestText[1]%
Some before text

beginMyEnvironment
This should be in #1.
endMyEnvironment

Some after text%


begindocument

MyTestTextblue

%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%

else
begingroup
DisableMyEnvironment
endgroup
fi

medskippar
MyTestTextblack

enddocument









share|improve this question























  • I don't know your real application, but one option is to use aftergroupDisableMyEnvironment. I don't know if this will do what you want, though.
    – Phelype Oleinik
    Aug 28 at 18:47











  • @PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a fpreach). Will look into it and try to figure it out.
    – Peter Grill
    Aug 28 at 18:50










  • I read somewhere that a foreach does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment should do. Not the prettiest code there is though :P
    – Phelype Oleinik
    Aug 28 at 18:52










  • @PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the environement and endenvironment separately.
    – Peter Grill
    Aug 28 at 19:16










  • It's a bit hacky, but would work: letdefgdefrenewenvironmentMyEnvironment[1] and it's global!
    – Andreas Storvik Strauman
    Aug 28 at 19:29















up vote
5
down vote

favorite












I need to execute a renewenvironment within a group. Using globalrenewenvironment is not sufficient.



What changes do I need to make to the DisableMyEnvironment macro in the MWE below so as to achieve the equivalent of globalrenewenvironment?



Currently, the MWE yields:



enter image description here



Once this is working as desired, the second line in blue should be in black.



Notes:



  • There are two test cases. The default one is within a foreach and commenting out defForeachTestCase uses a simple group.

References:




  • globalrenewcommand equivalent of globaldef.

Code:



defForeachTestCase%

documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz

newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%

newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%

newcommand*MyTestText[1]%
Some before text

beginMyEnvironment
This should be in #1.
endMyEnvironment

Some after text%


begindocument

MyTestTextblue

%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%

else
begingroup
DisableMyEnvironment
endgroup
fi

medskippar
MyTestTextblack

enddocument









share|improve this question























  • I don't know your real application, but one option is to use aftergroupDisableMyEnvironment. I don't know if this will do what you want, though.
    – Phelype Oleinik
    Aug 28 at 18:47











  • @PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a fpreach). Will look into it and try to figure it out.
    – Peter Grill
    Aug 28 at 18:50










  • I read somewhere that a foreach does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment should do. Not the prettiest code there is though :P
    – Phelype Oleinik
    Aug 28 at 18:52










  • @PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the environement and endenvironment separately.
    – Peter Grill
    Aug 28 at 19:16










  • It's a bit hacky, but would work: letdefgdefrenewenvironmentMyEnvironment[1] and it's global!
    – Andreas Storvik Strauman
    Aug 28 at 19:29













up vote
5
down vote

favorite









up vote
5
down vote

favorite











I need to execute a renewenvironment within a group. Using globalrenewenvironment is not sufficient.



What changes do I need to make to the DisableMyEnvironment macro in the MWE below so as to achieve the equivalent of globalrenewenvironment?



Currently, the MWE yields:



enter image description here



Once this is working as desired, the second line in blue should be in black.



Notes:



  • There are two test cases. The default one is within a foreach and commenting out defForeachTestCase uses a simple group.

References:




  • globalrenewcommand equivalent of globaldef.

Code:



defForeachTestCase%

documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz

newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%

newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%

newcommand*MyTestText[1]%
Some before text

beginMyEnvironment
This should be in #1.
endMyEnvironment

Some after text%


begindocument

MyTestTextblue

%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%

else
begingroup
DisableMyEnvironment
endgroup
fi

medskippar
MyTestTextblack

enddocument









share|improve this question















I need to execute a renewenvironment within a group. Using globalrenewenvironment is not sufficient.



What changes do I need to make to the DisableMyEnvironment macro in the MWE below so as to achieve the equivalent of globalrenewenvironment?



Currently, the MWE yields:



enter image description here



Once this is working as desired, the second line in blue should be in black.



Notes:



  • There are two test cases. The default one is within a foreach and commenting out defForeachTestCase uses a simple group.

References:




  • globalrenewcommand equivalent of globaldef.

Code:



defForeachTestCase%

documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz

newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%

newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%

newcommand*MyTestText[1]%
Some before text

beginMyEnvironment
This should be in #1.
endMyEnvironment

Some after text%


begindocument

MyTestTextblue

%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%

else
begingroup
DisableMyEnvironment
endgroup
fi

medskippar
MyTestTextblack

enddocument






macros environments grouping






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 28 at 19:22

























asked Aug 28 at 18:38









Peter Grill

161k24427733




161k24427733











  • I don't know your real application, but one option is to use aftergroupDisableMyEnvironment. I don't know if this will do what you want, though.
    – Phelype Oleinik
    Aug 28 at 18:47











  • @PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a fpreach). Will look into it and try to figure it out.
    – Peter Grill
    Aug 28 at 18:50










  • I read somewhere that a foreach does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment should do. Not the prettiest code there is though :P
    – Phelype Oleinik
    Aug 28 at 18:52










  • @PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the environement and endenvironment separately.
    – Peter Grill
    Aug 28 at 19:16










  • It's a bit hacky, but would work: letdefgdefrenewenvironmentMyEnvironment[1] and it's global!
    – Andreas Storvik Strauman
    Aug 28 at 19:29

















  • I don't know your real application, but one option is to use aftergroupDisableMyEnvironment. I don't know if this will do what you want, though.
    – Phelype Oleinik
    Aug 28 at 18:47











  • @PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a fpreach). Will look into it and try to figure it out.
    – Peter Grill
    Aug 28 at 18:50










  • I read somewhere that a foreach does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment should do. Not the prettiest code there is though :P
    – Phelype Oleinik
    Aug 28 at 18:52










  • @PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the environement and endenvironment separately.
    – Peter Grill
    Aug 28 at 19:16










  • It's a bit hacky, but would work: letdefgdefrenewenvironmentMyEnvironment[1] and it's global!
    – Andreas Storvik Strauman
    Aug 28 at 19:29
















I don't know your real application, but one option is to use aftergroupDisableMyEnvironment. I don't know if this will do what you want, though.
– Phelype Oleinik
Aug 28 at 18:47





I don't know your real application, but one option is to use aftergroupDisableMyEnvironment. I don't know if this will do what you want, though.
– Phelype Oleinik
Aug 28 at 18:47













@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a fpreach). Will look into it and try to figure it out.
– Peter Grill
Aug 28 at 18:50




@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a fpreach). Will look into it and try to figure it out.
– Peter Grill
Aug 28 at 18:50












I read somewhere that a foreach does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment should do. Not the prettiest code there is though :P
– Phelype Oleinik
Aug 28 at 18:52




I read somewhere that a foreach does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment should do. Not the prettiest code there is though :P
– Phelype Oleinik
Aug 28 at 18:52












@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the environement and endenvironment separately.
– Peter Grill
Aug 28 at 19:16




@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the environement and endenvironment separately.
– Peter Grill
Aug 28 at 19:16












It's a bit hacky, but would work: letdefgdefrenewenvironmentMyEnvironment[1] and it's global!
– Andreas Storvik Strauman
Aug 28 at 19:29





It's a bit hacky, but would work: letdefgdefrenewenvironmentMyEnvironment[1] and it's global!
– Andreas Storvik Strauman
Aug 28 at 19:29











3 Answers
3






active

oldest

votes

















up vote
5
down vote



accepted










Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment, and then in the DisableMyEnvironment macro, globally reassign by way of



globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%


MWE:



documentclassarticle
usepackagexcolor
newenvironmentXEnvironment[1]%
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%

newcommand*DisableMyEnvironment%
%% How make this global??
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
%

newcommand*MyTestText[1]%
Some before text

beginMyEnvironment
This should be in #1.
endMyEnvironment

Some after text%


begindocument

MyTestTextblue

%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
begingroup
DisableMyEnvironment
endgroup

medskippar
MyTestTextblack


enddocument


enter image description here






share|improve this answer




















  • Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
    – Peter Grill
    Aug 28 at 19:27











  • @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
    – Steven B. Segletes
    Aug 28 at 19:46







  • 1




    Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
    – Peter Grill
    Aug 28 at 20:56

















up vote
3
down vote













Edit: First approach didn't seem to work with optional arguments.



Edit 2: Found an easier way using globaldefs:



Final answer:



In spirit of answering how to do a renewenvironment global:



documentclassarticle
begindocument
newenvironmenttestHELLOWORLD
bgroup
globaldefs=1
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument


Second answer:



Two commands loosely inspired by makeatletter and makeatother: makerenewglobal and makerenewlocal. When makerenewglobal is called, renewenvironment do only global definitions. If makerenewlocal is called, it does the oposite: makes all renewenvironment-definitions local.



documentclassarticle
makeatletter
let@local@newenv@newenv
longdef@global@newenv#1#2#3#4%
@ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
l@ngrel@xexpandaftergdefcsname end#1endcsname#4%

gdefmakerenewglobalgloballet@newenv@global@newenv
gdefmakerenewlocalgloballet@newenv@local@newenv
begindocument
newenvironmenttestHELLOWORLD
bgroupmakerenewglobal
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument


First answer:



In spirit of semi-generality; a command, makeenvglobaltheenv, that makes a environment global:



documentclassarticle
gdefmakeenvglobal#1%
globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname

begindocument
newenvironmenttestHELLOWORLD
bgroup
renewenvironmenttestfoobar
makeenvglobaltest
egroup
begintest
endtest
enddocument


prints foo bar






share|improve this answer






















  • Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
    – Peter Grill
    Aug 28 at 19:17










  • @PeterGrill Oh. Yeah somethings going on. Give me a minute!
    – Andreas Storvik Strauman
    Aug 28 at 19:22










  • @PeterGrill See new answer!
    – Andreas Storvik Strauman
    Aug 28 at 19:40










  • Yep, revised answer works.
    – Peter Grill
    Aug 28 at 21:00

















up vote
1
down vote













As requested :)



I read somewhere here that foreach executes its commands inside two groups. You can check this statement with this (requires e-TeX):



documentclassarticle
usepackagepgffor
begindocument
foreach i in 0thecurrentgrouplevel
enddocument


which will print 2 :)



If you want to do a definition outside the scope of this foreach, then you can use a couple of aftergroups. In your case you want to run DisableMyEnvironment (one token) outside of two grouping levels.



If you do aftergroupDisableMyEnvironment, this will insert DisableMyEnvironment after the first group (one aftergroup per token). To make it reach the second level, you have to aftergroup that (two tokens), so aftergroupaftergroup aftergroupDisableMyEnvironment.



Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.




Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroups, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter =D



I made a (probably suboptimal) macro afterNgroups<N><token-list> that inserts the <token-list> after <N> groups:



makeatletter
defafterNgroups#1#2%
count@z@
toks@#2%
loop
ifnumcount@<#1 %
toks2%
expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
toks2
expandafterexpandafterexpandafter
expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
toks@expandafterthetoks2%
advancecount@@ne
repeat
thetoks@
makeatother


you can use this macro for your case with afterNgroups2DisableMyEnvironment. It apparently works for trivial cases. Didn't test it extensively though.






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',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    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%2f448212%2fhow-to-perform-a-global-renewenvironment%23new-answer', 'question_page');

    );

    Post as a guest






























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    5
    down vote



    accepted










    Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment, and then in the DisableMyEnvironment macro, globally reassign by way of



    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%


    MWE:



    documentclassarticle
    usepackagexcolor
    newenvironmentXEnvironment[1]%
    newenvironmentMyEnvironment[1][blue]%
    begingroup
    color#1%
    %
    endgroup
    %

    newcommand*DisableMyEnvironment%
    %% How make this global??
    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%
    %

    newcommand*MyTestText[1]%
    Some before text

    beginMyEnvironment
    This should be in #1.
    endMyEnvironment

    Some after text%


    begindocument

    MyTestTextblue

    %DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
    begingroup
    DisableMyEnvironment
    endgroup

    medskippar
    MyTestTextblack


    enddocument


    enter image description here






    share|improve this answer




















    • Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
      – Peter Grill
      Aug 28 at 19:27











    • @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
      – Steven B. Segletes
      Aug 28 at 19:46







    • 1




      Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
      – Peter Grill
      Aug 28 at 20:56














    up vote
    5
    down vote



    accepted










    Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment, and then in the DisableMyEnvironment macro, globally reassign by way of



    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%


    MWE:



    documentclassarticle
    usepackagexcolor
    newenvironmentXEnvironment[1]%
    newenvironmentMyEnvironment[1][blue]%
    begingroup
    color#1%
    %
    endgroup
    %

    newcommand*DisableMyEnvironment%
    %% How make this global??
    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%
    %

    newcommand*MyTestText[1]%
    Some before text

    beginMyEnvironment
    This should be in #1.
    endMyEnvironment

    Some after text%


    begindocument

    MyTestTextblue

    %DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
    begingroup
    DisableMyEnvironment
    endgroup

    medskippar
    MyTestTextblack


    enddocument


    enter image description here






    share|improve this answer




















    • Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
      – Peter Grill
      Aug 28 at 19:27











    • @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
      – Steven B. Segletes
      Aug 28 at 19:46







    • 1




      Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
      – Peter Grill
      Aug 28 at 20:56












    up vote
    5
    down vote



    accepted







    up vote
    5
    down vote



    accepted






    Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment, and then in the DisableMyEnvironment macro, globally reassign by way of



    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%


    MWE:



    documentclassarticle
    usepackagexcolor
    newenvironmentXEnvironment[1]%
    newenvironmentMyEnvironment[1][blue]%
    begingroup
    color#1%
    %
    endgroup
    %

    newcommand*DisableMyEnvironment%
    %% How make this global??
    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%
    %

    newcommand*MyTestText[1]%
    Some before text

    beginMyEnvironment
    This should be in #1.
    endMyEnvironment

    Some after text%


    begindocument

    MyTestTextblue

    %DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
    begingroup
    DisableMyEnvironment
    endgroup

    medskippar
    MyTestTextblack


    enddocument


    enter image description here






    share|improve this answer












    Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment, and then in the DisableMyEnvironment macro, globally reassign by way of



    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%


    MWE:



    documentclassarticle
    usepackagexcolor
    newenvironmentXEnvironment[1]%
    newenvironmentMyEnvironment[1][blue]%
    begingroup
    color#1%
    %
    endgroup
    %

    newcommand*DisableMyEnvironment%
    %% How make this global??
    globalletMyEnvironmentXEnvironment%
    globalletendMyEnvironmentendXEnvironment%
    %

    newcommand*MyTestText[1]%
    Some before text

    beginMyEnvironment
    This should be in #1.
    endMyEnvironment

    Some after text%


    begindocument

    MyTestTextblue

    %DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
    begingroup
    DisableMyEnvironment
    endgroup

    medskippar
    MyTestTextblack


    enddocument


    enter image description here







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Aug 28 at 18:59









    Steven B. Segletes

    147k9186389




    147k9186389











    • Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
      – Peter Grill
      Aug 28 at 19:27











    • @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
      – Steven B. Segletes
      Aug 28 at 19:46







    • 1




      Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
      – Peter Grill
      Aug 28 at 20:56
















    • Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
      – Peter Grill
      Aug 28 at 19:27











    • @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
      – Steven B. Segletes
      Aug 28 at 19:46







    • 1




      Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
      – Peter Grill
      Aug 28 at 20:56















    Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
    – Peter Grill
    Aug 28 at 19:27





    Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new foreach case.
    – Peter Grill
    Aug 28 at 19:27













    @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
    – Steven B. Segletes
    Aug 28 at 19:46





    @PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
    – Steven B. Segletes
    Aug 28 at 19:46





    1




    1




    Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
    – Peter Grill
    Aug 28 at 20:56




    Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
    – Peter Grill
    Aug 28 at 20:56










    up vote
    3
    down vote













    Edit: First approach didn't seem to work with optional arguments.



    Edit 2: Found an easier way using globaldefs:



    Final answer:



    In spirit of answering how to do a renewenvironment global:



    documentclassarticle
    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    globaldefs=1
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    Second answer:



    Two commands loosely inspired by makeatletter and makeatother: makerenewglobal and makerenewlocal. When makerenewglobal is called, renewenvironment do only global definitions. If makerenewlocal is called, it does the oposite: makes all renewenvironment-definitions local.



    documentclassarticle
    makeatletter
    let@local@newenv@newenv
    longdef@global@newenv#1#2#3#4%
    @ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
    letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
    l@ngrel@xexpandaftergdefcsname end#1endcsname#4%

    gdefmakerenewglobalgloballet@newenv@global@newenv
    gdefmakerenewlocalgloballet@newenv@local@newenv
    begindocument
    newenvironmenttestHELLOWORLD
    bgroupmakerenewglobal
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    First answer:



    In spirit of semi-generality; a command, makeenvglobaltheenv, that makes a environment global:



    documentclassarticle
    gdefmakeenvglobal#1%
    globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
    globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname

    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    renewenvironmenttestfoobar
    makeenvglobaltest
    egroup
    begintest
    endtest
    enddocument


    prints foo bar






    share|improve this answer






















    • Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
      – Peter Grill
      Aug 28 at 19:17










    • @PeterGrill Oh. Yeah somethings going on. Give me a minute!
      – Andreas Storvik Strauman
      Aug 28 at 19:22










    • @PeterGrill See new answer!
      – Andreas Storvik Strauman
      Aug 28 at 19:40










    • Yep, revised answer works.
      – Peter Grill
      Aug 28 at 21:00














    up vote
    3
    down vote













    Edit: First approach didn't seem to work with optional arguments.



    Edit 2: Found an easier way using globaldefs:



    Final answer:



    In spirit of answering how to do a renewenvironment global:



    documentclassarticle
    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    globaldefs=1
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    Second answer:



    Two commands loosely inspired by makeatletter and makeatother: makerenewglobal and makerenewlocal. When makerenewglobal is called, renewenvironment do only global definitions. If makerenewlocal is called, it does the oposite: makes all renewenvironment-definitions local.



    documentclassarticle
    makeatletter
    let@local@newenv@newenv
    longdef@global@newenv#1#2#3#4%
    @ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
    letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
    l@ngrel@xexpandaftergdefcsname end#1endcsname#4%

    gdefmakerenewglobalgloballet@newenv@global@newenv
    gdefmakerenewlocalgloballet@newenv@local@newenv
    begindocument
    newenvironmenttestHELLOWORLD
    bgroupmakerenewglobal
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    First answer:



    In spirit of semi-generality; a command, makeenvglobaltheenv, that makes a environment global:



    documentclassarticle
    gdefmakeenvglobal#1%
    globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
    globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname

    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    renewenvironmenttestfoobar
    makeenvglobaltest
    egroup
    begintest
    endtest
    enddocument


    prints foo bar






    share|improve this answer






















    • Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
      – Peter Grill
      Aug 28 at 19:17










    • @PeterGrill Oh. Yeah somethings going on. Give me a minute!
      – Andreas Storvik Strauman
      Aug 28 at 19:22










    • @PeterGrill See new answer!
      – Andreas Storvik Strauman
      Aug 28 at 19:40










    • Yep, revised answer works.
      – Peter Grill
      Aug 28 at 21:00












    up vote
    3
    down vote










    up vote
    3
    down vote









    Edit: First approach didn't seem to work with optional arguments.



    Edit 2: Found an easier way using globaldefs:



    Final answer:



    In spirit of answering how to do a renewenvironment global:



    documentclassarticle
    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    globaldefs=1
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    Second answer:



    Two commands loosely inspired by makeatletter and makeatother: makerenewglobal and makerenewlocal. When makerenewglobal is called, renewenvironment do only global definitions. If makerenewlocal is called, it does the oposite: makes all renewenvironment-definitions local.



    documentclassarticle
    makeatletter
    let@local@newenv@newenv
    longdef@global@newenv#1#2#3#4%
    @ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
    letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
    l@ngrel@xexpandaftergdefcsname end#1endcsname#4%

    gdefmakerenewglobalgloballet@newenv@global@newenv
    gdefmakerenewlocalgloballet@newenv@local@newenv
    begindocument
    newenvironmenttestHELLOWORLD
    bgroupmakerenewglobal
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    First answer:



    In spirit of semi-generality; a command, makeenvglobaltheenv, that makes a environment global:



    documentclassarticle
    gdefmakeenvglobal#1%
    globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
    globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname

    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    renewenvironmenttestfoobar
    makeenvglobaltest
    egroup
    begintest
    endtest
    enddocument


    prints foo bar






    share|improve this answer














    Edit: First approach didn't seem to work with optional arguments.



    Edit 2: Found an easier way using globaldefs:



    Final answer:



    In spirit of answering how to do a renewenvironment global:



    documentclassarticle
    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    globaldefs=1
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    Second answer:



    Two commands loosely inspired by makeatletter and makeatother: makerenewglobal and makerenewlocal. When makerenewglobal is called, renewenvironment do only global definitions. If makerenewlocal is called, it does the oposite: makes all renewenvironment-definitions local.



    documentclassarticle
    makeatletter
    let@local@newenv@newenv
    longdef@global@newenv#1#2#3#4%
    @ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
    letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
    l@ngrel@xexpandaftergdefcsname end#1endcsname#4%

    gdefmakerenewglobalgloballet@newenv@global@newenv
    gdefmakerenewlocalgloballet@newenv@local@newenv
    begindocument
    newenvironmenttestHELLOWORLD
    bgroupmakerenewglobal
    renewenvironmenttest[1][world]foo #1bar
    egroup
    begintest[hello]
    endtest
    enddocument


    First answer:



    In spirit of semi-generality; a command, makeenvglobaltheenv, that makes a environment global:



    documentclassarticle
    gdefmakeenvglobal#1%
    globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
    globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname

    begindocument
    newenvironmenttestHELLOWORLD
    bgroup
    renewenvironmenttestfoobar
    makeenvglobaltest
    egroup
    begintest
    endtest
    enddocument


    prints foo bar







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 28 at 20:01

























    answered Aug 28 at 19:08









    Andreas Storvik Strauman

    2,267418




    2,267418











    • Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
      – Peter Grill
      Aug 28 at 19:17










    • @PeterGrill Oh. Yeah somethings going on. Give me a minute!
      – Andreas Storvik Strauman
      Aug 28 at 19:22










    • @PeterGrill See new answer!
      – Andreas Storvik Strauman
      Aug 28 at 19:40










    • Yep, revised answer works.
      – Peter Grill
      Aug 28 at 21:00
















    • Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
      – Peter Grill
      Aug 28 at 19:17










    • @PeterGrill Oh. Yeah somethings going on. Give me a minute!
      – Andreas Storvik Strauman
      Aug 28 at 19:22










    • @PeterGrill See new answer!
      – Andreas Storvik Strauman
      Aug 28 at 19:40










    • Yep, revised answer works.
      – Peter Grill
      Aug 28 at 21:00















    Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
    – Peter Grill
    Aug 28 at 19:17




    Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
    – Peter Grill
    Aug 28 at 19:17












    @PeterGrill Oh. Yeah somethings going on. Give me a minute!
    – Andreas Storvik Strauman
    Aug 28 at 19:22




    @PeterGrill Oh. Yeah somethings going on. Give me a minute!
    – Andreas Storvik Strauman
    Aug 28 at 19:22












    @PeterGrill See new answer!
    – Andreas Storvik Strauman
    Aug 28 at 19:40




    @PeterGrill See new answer!
    – Andreas Storvik Strauman
    Aug 28 at 19:40












    Yep, revised answer works.
    – Peter Grill
    Aug 28 at 21:00




    Yep, revised answer works.
    – Peter Grill
    Aug 28 at 21:00










    up vote
    1
    down vote













    As requested :)



    I read somewhere here that foreach executes its commands inside two groups. You can check this statement with this (requires e-TeX):



    documentclassarticle
    usepackagepgffor
    begindocument
    foreach i in 0thecurrentgrouplevel
    enddocument


    which will print 2 :)



    If you want to do a definition outside the scope of this foreach, then you can use a couple of aftergroups. In your case you want to run DisableMyEnvironment (one token) outside of two grouping levels.



    If you do aftergroupDisableMyEnvironment, this will insert DisableMyEnvironment after the first group (one aftergroup per token). To make it reach the second level, you have to aftergroup that (two tokens), so aftergroupaftergroup aftergroupDisableMyEnvironment.



    Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.




    Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroups, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter =D



    I made a (probably suboptimal) macro afterNgroups<N><token-list> that inserts the <token-list> after <N> groups:



    makeatletter
    defafterNgroups#1#2%
    count@z@
    toks@#2%
    loop
    ifnumcount@<#1 %
    toks2%
    expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
    toks2
    expandafterexpandafterexpandafter
    expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
    toks@expandafterthetoks2%
    advancecount@@ne
    repeat
    thetoks@
    makeatother


    you can use this macro for your case with afterNgroups2DisableMyEnvironment. It apparently works for trivial cases. Didn't test it extensively though.






    share|improve this answer


























      up vote
      1
      down vote













      As requested :)



      I read somewhere here that foreach executes its commands inside two groups. You can check this statement with this (requires e-TeX):



      documentclassarticle
      usepackagepgffor
      begindocument
      foreach i in 0thecurrentgrouplevel
      enddocument


      which will print 2 :)



      If you want to do a definition outside the scope of this foreach, then you can use a couple of aftergroups. In your case you want to run DisableMyEnvironment (one token) outside of two grouping levels.



      If you do aftergroupDisableMyEnvironment, this will insert DisableMyEnvironment after the first group (one aftergroup per token). To make it reach the second level, you have to aftergroup that (two tokens), so aftergroupaftergroup aftergroupDisableMyEnvironment.



      Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.




      Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroups, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter =D



      I made a (probably suboptimal) macro afterNgroups<N><token-list> that inserts the <token-list> after <N> groups:



      makeatletter
      defafterNgroups#1#2%
      count@z@
      toks@#2%
      loop
      ifnumcount@<#1 %
      toks2%
      expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
      toks2
      expandafterexpandafterexpandafter
      expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
      toks@expandafterthetoks2%
      advancecount@@ne
      repeat
      thetoks@
      makeatother


      you can use this macro for your case with afterNgroups2DisableMyEnvironment. It apparently works for trivial cases. Didn't test it extensively though.






      share|improve this answer
























        up vote
        1
        down vote










        up vote
        1
        down vote









        As requested :)



        I read somewhere here that foreach executes its commands inside two groups. You can check this statement with this (requires e-TeX):



        documentclassarticle
        usepackagepgffor
        begindocument
        foreach i in 0thecurrentgrouplevel
        enddocument


        which will print 2 :)



        If you want to do a definition outside the scope of this foreach, then you can use a couple of aftergroups. In your case you want to run DisableMyEnvironment (one token) outside of two grouping levels.



        If you do aftergroupDisableMyEnvironment, this will insert DisableMyEnvironment after the first group (one aftergroup per token). To make it reach the second level, you have to aftergroup that (two tokens), so aftergroupaftergroup aftergroupDisableMyEnvironment.



        Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.




        Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroups, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter =D



        I made a (probably suboptimal) macro afterNgroups<N><token-list> that inserts the <token-list> after <N> groups:



        makeatletter
        defafterNgroups#1#2%
        count@z@
        toks@#2%
        loop
        ifnumcount@<#1 %
        toks2%
        expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
        toks2
        expandafterexpandafterexpandafter
        expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
        toks@expandafterthetoks2%
        advancecount@@ne
        repeat
        thetoks@
        makeatother


        you can use this macro for your case with afterNgroups2DisableMyEnvironment. It apparently works for trivial cases. Didn't test it extensively though.






        share|improve this answer














        As requested :)



        I read somewhere here that foreach executes its commands inside two groups. You can check this statement with this (requires e-TeX):



        documentclassarticle
        usepackagepgffor
        begindocument
        foreach i in 0thecurrentgrouplevel
        enddocument


        which will print 2 :)



        If you want to do a definition outside the scope of this foreach, then you can use a couple of aftergroups. In your case you want to run DisableMyEnvironment (one token) outside of two grouping levels.



        If you do aftergroupDisableMyEnvironment, this will insert DisableMyEnvironment after the first group (one aftergroup per token). To make it reach the second level, you have to aftergroup that (two tokens), so aftergroupaftergroup aftergroupDisableMyEnvironment.



        Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.




        Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroups, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter =D



        I made a (probably suboptimal) macro afterNgroups<N><token-list> that inserts the <token-list> after <N> groups:



        makeatletter
        defafterNgroups#1#2%
        count@z@
        toks@#2%
        loop
        ifnumcount@<#1 %
        toks2%
        expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
        toks2
        expandafterexpandafterexpandafter
        expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
        toks@expandafterthetoks2%
        advancecount@@ne
        repeat
        thetoks@
        makeatother


        you can use this macro for your case with afterNgroups2DisableMyEnvironment. It apparently works for trivial cases. Didn't test it extensively though.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Aug 29 at 11:11

























        answered Aug 28 at 23:10









        Phelype Oleinik

        16.9k33769




        16.9k33769



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f448212%2fhow-to-perform-a-global-renewenvironment%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay