Use newcommand in newenvironment - content of environment is argument of newcommand
I want to create an environment, that generates a new command. There are some similar examples on google, but nothing fits exactly.
The minimal (not) working example shows best, what I want:
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
setlength{parindent}{0pt}
%Thats my environment:
newenvironment{LHZZ}[1]{
newcommand{csname LH#1endcsname }[1]bgroup
}{egroup}
%Thats the use of it. It is very important, that I can use arguments:
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
The environment above should (but doesnt) equal the following:
% not part of the code !!!!!
newcommand{LHXY}[1]{
write stuff here
refer to #1
}
The following is the call in the document.
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
The output should be:
write stuff here
refer to parameter
It doesnt work. It says csname
is already defined. But I dont want to define csname
. It is just the first command inside the argument. What do I have to change, to make this work?
Edit: There is a purpose for this, what seems to be code golfing. This should lead into a package which can be used by people who are not Tex-safe. The package is for making brochures for marriages, church service, etc. easily.
Edit 2:
I sticked to one of the given solutions as far as possible and far as I understood it. Unfortunately, I need one optional parameter. To understand, what is the meaning of this quirky code, have a look at the example songbook and the call of it. The almost final version as a still not working MWE:
%Business as usual
documentclass[12pt,a4paper]{book}
usepackage[utf8]{inputenc}
usepackage[german]{babel}
usepackage{environ}
%This sets a default value
newcommand{LHliederStandard}{n}
%This calls the environment(s)
newcommand{LHsong}[3][LHliederStandard]{
csname LH#2endcsname[#1]#3 %indirect call of what is defined in Liederbuch environment
}
makeatletter
%This is the Liederbuch environment (Liederbuch = songbook)
NewEnviron{Liederbuch}[1]{
xdefLB@my@temp{
noexpandnewcommand{csname LH#1endcsname}[2][relax]{
unexpandedexpandafter{BODY}
}
}
aftergroupLB@my@temp
}
makeatother
%This is the Lied environment (Lied = song)
NewEnviron{Lied}[2]{
ifnumnumexpr#2=numexpr##3 %the double # refers to parameter of the level above, or doesnt it.
ifnumpdfstrcmp{#1}{##2}=0
BODY
fi
fi
}
%example for a songbook
begin{Liederbuch}{songbook}
begin{Lied}{n}{1}
song 1 mode n
end{Lied}
begin{Lied}{nt}{2}
song 2 mode nt
end{Lied}
end{Liederbuch}
%call of the songbook
begin{document}
LHsong{songbook}{1} %calls song 1 mode n
LHsong[nt]{songbook}{2} %calls song 2 mode nt
%hypothetical other songbook
LHsong[n]{childrensongs}{35}
end{document}
macros environments
add a comment |
I want to create an environment, that generates a new command. There are some similar examples on google, but nothing fits exactly.
The minimal (not) working example shows best, what I want:
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
setlength{parindent}{0pt}
%Thats my environment:
newenvironment{LHZZ}[1]{
newcommand{csname LH#1endcsname }[1]bgroup
}{egroup}
%Thats the use of it. It is very important, that I can use arguments:
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
The environment above should (but doesnt) equal the following:
% not part of the code !!!!!
newcommand{LHXY}[1]{
write stuff here
refer to #1
}
The following is the call in the document.
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
The output should be:
write stuff here
refer to parameter
It doesnt work. It says csname
is already defined. But I dont want to define csname
. It is just the first command inside the argument. What do I have to change, to make this work?
Edit: There is a purpose for this, what seems to be code golfing. This should lead into a package which can be used by people who are not Tex-safe. The package is for making brochures for marriages, church service, etc. easily.
Edit 2:
I sticked to one of the given solutions as far as possible and far as I understood it. Unfortunately, I need one optional parameter. To understand, what is the meaning of this quirky code, have a look at the example songbook and the call of it. The almost final version as a still not working MWE:
%Business as usual
documentclass[12pt,a4paper]{book}
usepackage[utf8]{inputenc}
usepackage[german]{babel}
usepackage{environ}
%This sets a default value
newcommand{LHliederStandard}{n}
%This calls the environment(s)
newcommand{LHsong}[3][LHliederStandard]{
csname LH#2endcsname[#1]#3 %indirect call of what is defined in Liederbuch environment
}
makeatletter
%This is the Liederbuch environment (Liederbuch = songbook)
NewEnviron{Liederbuch}[1]{
xdefLB@my@temp{
noexpandnewcommand{csname LH#1endcsname}[2][relax]{
unexpandedexpandafter{BODY}
}
}
aftergroupLB@my@temp
}
makeatother
%This is the Lied environment (Lied = song)
NewEnviron{Lied}[2]{
ifnumnumexpr#2=numexpr##3 %the double # refers to parameter of the level above, or doesnt it.
ifnumpdfstrcmp{#1}{##2}=0
BODY
fi
fi
}
%example for a songbook
begin{Liederbuch}{songbook}
begin{Lied}{n}{1}
song 1 mode n
end{Lied}
begin{Lied}{nt}{2}
song 2 mode nt
end{Lied}
end{Liederbuch}
%call of the songbook
begin{document}
LHsong{songbook}{1} %calls song 1 mode n
LHsong[nt]{songbook}{2} %calls song 2 mode nt
%hypothetical other songbook
LHsong[n]{childrensongs}{35}
end{document}
macros environments
You need toexpandafter
thenewcommand
relative to the stuff which comes next. Not sure whether this works withnewcommand
, though. But probably you want to look at theenviron
package.
– cfr
Apr 9 '16 at 12:49
This can't work this way -- you can't grab the environment content like this.
– user31729
Apr 9 '16 at 12:49
I usedexpandafter
in some tries, but it didn't work.
– MaestroGlanz
Apr 9 '16 at 12:51
That's why I said you should look atenviron
.
– cfr
Apr 9 '16 at 23:02
add a comment |
I want to create an environment, that generates a new command. There are some similar examples on google, but nothing fits exactly.
The minimal (not) working example shows best, what I want:
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
setlength{parindent}{0pt}
%Thats my environment:
newenvironment{LHZZ}[1]{
newcommand{csname LH#1endcsname }[1]bgroup
}{egroup}
%Thats the use of it. It is very important, that I can use arguments:
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
The environment above should (but doesnt) equal the following:
% not part of the code !!!!!
newcommand{LHXY}[1]{
write stuff here
refer to #1
}
The following is the call in the document.
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
The output should be:
write stuff here
refer to parameter
It doesnt work. It says csname
is already defined. But I dont want to define csname
. It is just the first command inside the argument. What do I have to change, to make this work?
Edit: There is a purpose for this, what seems to be code golfing. This should lead into a package which can be used by people who are not Tex-safe. The package is for making brochures for marriages, church service, etc. easily.
Edit 2:
I sticked to one of the given solutions as far as possible and far as I understood it. Unfortunately, I need one optional parameter. To understand, what is the meaning of this quirky code, have a look at the example songbook and the call of it. The almost final version as a still not working MWE:
%Business as usual
documentclass[12pt,a4paper]{book}
usepackage[utf8]{inputenc}
usepackage[german]{babel}
usepackage{environ}
%This sets a default value
newcommand{LHliederStandard}{n}
%This calls the environment(s)
newcommand{LHsong}[3][LHliederStandard]{
csname LH#2endcsname[#1]#3 %indirect call of what is defined in Liederbuch environment
}
makeatletter
%This is the Liederbuch environment (Liederbuch = songbook)
NewEnviron{Liederbuch}[1]{
xdefLB@my@temp{
noexpandnewcommand{csname LH#1endcsname}[2][relax]{
unexpandedexpandafter{BODY}
}
}
aftergroupLB@my@temp
}
makeatother
%This is the Lied environment (Lied = song)
NewEnviron{Lied}[2]{
ifnumnumexpr#2=numexpr##3 %the double # refers to parameter of the level above, or doesnt it.
ifnumpdfstrcmp{#1}{##2}=0
BODY
fi
fi
}
%example for a songbook
begin{Liederbuch}{songbook}
begin{Lied}{n}{1}
song 1 mode n
end{Lied}
begin{Lied}{nt}{2}
song 2 mode nt
end{Lied}
end{Liederbuch}
%call of the songbook
begin{document}
LHsong{songbook}{1} %calls song 1 mode n
LHsong[nt]{songbook}{2} %calls song 2 mode nt
%hypothetical other songbook
LHsong[n]{childrensongs}{35}
end{document}
macros environments
I want to create an environment, that generates a new command. There are some similar examples on google, but nothing fits exactly.
The minimal (not) working example shows best, what I want:
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
setlength{parindent}{0pt}
%Thats my environment:
newenvironment{LHZZ}[1]{
newcommand{csname LH#1endcsname }[1]bgroup
}{egroup}
%Thats the use of it. It is very important, that I can use arguments:
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
The environment above should (but doesnt) equal the following:
% not part of the code !!!!!
newcommand{LHXY}[1]{
write stuff here
refer to #1
}
The following is the call in the document.
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
The output should be:
write stuff here
refer to parameter
It doesnt work. It says csname
is already defined. But I dont want to define csname
. It is just the first command inside the argument. What do I have to change, to make this work?
Edit: There is a purpose for this, what seems to be code golfing. This should lead into a package which can be used by people who are not Tex-safe. The package is for making brochures for marriages, church service, etc. easily.
Edit 2:
I sticked to one of the given solutions as far as possible and far as I understood it. Unfortunately, I need one optional parameter. To understand, what is the meaning of this quirky code, have a look at the example songbook and the call of it. The almost final version as a still not working MWE:
%Business as usual
documentclass[12pt,a4paper]{book}
usepackage[utf8]{inputenc}
usepackage[german]{babel}
usepackage{environ}
%This sets a default value
newcommand{LHliederStandard}{n}
%This calls the environment(s)
newcommand{LHsong}[3][LHliederStandard]{
csname LH#2endcsname[#1]#3 %indirect call of what is defined in Liederbuch environment
}
makeatletter
%This is the Liederbuch environment (Liederbuch = songbook)
NewEnviron{Liederbuch}[1]{
xdefLB@my@temp{
noexpandnewcommand{csname LH#1endcsname}[2][relax]{
unexpandedexpandafter{BODY}
}
}
aftergroupLB@my@temp
}
makeatother
%This is the Lied environment (Lied = song)
NewEnviron{Lied}[2]{
ifnumnumexpr#2=numexpr##3 %the double # refers to parameter of the level above, or doesnt it.
ifnumpdfstrcmp{#1}{##2}=0
BODY
fi
fi
}
%example for a songbook
begin{Liederbuch}{songbook}
begin{Lied}{n}{1}
song 1 mode n
end{Lied}
begin{Lied}{nt}{2}
song 2 mode nt
end{Lied}
end{Liederbuch}
%call of the songbook
begin{document}
LHsong{songbook}{1} %calls song 1 mode n
LHsong[nt]{songbook}{2} %calls song 2 mode nt
%hypothetical other songbook
LHsong[n]{childrensongs}{35}
end{document}
macros environments
macros environments
edited Apr 12 '16 at 12:46
MaestroGlanz
asked Apr 9 '16 at 12:44
MaestroGlanzMaestroGlanz
1,177315
1,177315
You need toexpandafter
thenewcommand
relative to the stuff which comes next. Not sure whether this works withnewcommand
, though. But probably you want to look at theenviron
package.
– cfr
Apr 9 '16 at 12:49
This can't work this way -- you can't grab the environment content like this.
– user31729
Apr 9 '16 at 12:49
I usedexpandafter
in some tries, but it didn't work.
– MaestroGlanz
Apr 9 '16 at 12:51
That's why I said you should look atenviron
.
– cfr
Apr 9 '16 at 23:02
add a comment |
You need toexpandafter
thenewcommand
relative to the stuff which comes next. Not sure whether this works withnewcommand
, though. But probably you want to look at theenviron
package.
– cfr
Apr 9 '16 at 12:49
This can't work this way -- you can't grab the environment content like this.
– user31729
Apr 9 '16 at 12:49
I usedexpandafter
in some tries, but it didn't work.
– MaestroGlanz
Apr 9 '16 at 12:51
That's why I said you should look atenviron
.
– cfr
Apr 9 '16 at 23:02
You need to
expandafter
the newcommand
relative to the stuff which comes next. Not sure whether this works with newcommand
, though. But probably you want to look at the environ
package.– cfr
Apr 9 '16 at 12:49
You need to
expandafter
the newcommand
relative to the stuff which comes next. Not sure whether this works with newcommand
, though. But probably you want to look at the environ
package.– cfr
Apr 9 '16 at 12:49
This can't work this way -- you can't grab the environment content like this.
– user31729
Apr 9 '16 at 12:49
This can't work this way -- you can't grab the environment content like this.
– user31729
Apr 9 '16 at 12:49
I used
expandafter
in some tries, but it didn't work.– MaestroGlanz
Apr 9 '16 at 12:51
I used
expandafter
in some tries, but it didn't work.– MaestroGlanz
Apr 9 '16 at 12:51
That's why I said you should look at
environ
.– cfr
Apr 9 '16 at 23:02
That's why I said you should look at
environ
.– cfr
Apr 9 '16 at 23:02
add a comment |
4 Answers
4
active
oldest
votes
The command form is easier:
documentclass{article}
newcommand{LHZZ}[2]{%
expandafternewcommandcsname LH#1endcsname[1]{#2}}%
}
begin{document}
LHZZ{XY}{%
write stuff here
refer to #1%
}
LHXY{parameter}
end{document}
If you really insist in using an environment, use environ
:
documentclass{article}
usepackage{environ}
makeatletter
NewEnviron{LHZZ}[1]{%
edefmaestroglanz@temp{%
unexpanded{expandaftergdefcsname LH#1endcsname}####1{unexpandedexpandafter{BODY}}%
}%
maestroglanz@temp
}
makeatother
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
end{document}
An implementation using xparse
and expl3
; the largest part of the code is the definition of the error messages in case the environment is called twice with the same argument.
documentclass{article}
usepackage{environ,xparse}
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Without the error check, the code part would look like
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
ExplSyntaxOff
Update
With xparse
released 2019-05-03 the code can become
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentEnvironment{LHZZ}{m +b}
{
cs_set_protected:cn { LH#1:n } { #2 }
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}{}
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Could you explain briefly (if this is possible) when to usecs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.
– cfr
Apr 9 '16 at 23:09
@cfr Basically, you always use_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable inx
arguments. For instance, the analog ofthesection
should not be protected.
– egreg
Apr 9 '16 at 23:12
@cfr Yes, but it wasn't right. Your impression aboutNewDocumentCommand
is wrong as well.
– egreg
Apr 9 '16 at 23:30
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
So I just went through one file addingprotected
s and things still seem to work, which I guess means they should beprotected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first:% includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?
– cfr
Apr 10 '16 at 0:23
|
show 1 more comment
Here is your minimal example turned into a working one:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary{} % check availability of the name
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary{%
newcommand{csname LH#1endcsname}[1]{BODY}}%
aftergroup@my@temporary
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1 % sorry, doubling "#" is necessary here
end{LHZZ}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Edit: I think using newcommand
instead of globaledef
(see Christian’s answer; note, however, that globaledef
is exactly the same as xdef
) does have some added value, because one retains, for example, the ability to define a default argument:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary@x{%
newcommand{csname LH#1endcsname}[1]{BODY}
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
protected@xdef@my@temporary@y{%
newcommand*{csname MG#1endcsname}[1][default]{BODY}
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1par % sorry, doubling "#" is necessary here
end{LHZZ}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
end{document}
Edit 2: Always double-check that the brain is connected before writing to TeX.SX! (Will it be, now?) Here is a cleaner implementation of the same basic idea:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
xdef@my@temporary@x{%
noexpandnewcommand{csname LH#1endcsname}[1]{%
unexpandedexpandafter{BODY}%
}%
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
xdef@my@temporary@y{%
noexpandnewcommand*{csname MG#1endcsname}[1][default]{%
unexpandedexpandafter{BODY}%
}%
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
% Obviously, in a real application you'd choose only one of the two
% possibiities.
}
makeatother
begin{document}
begingroup % to show that normal scoping is obeyed
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to texttt{#1}par % doubling the "#" is no longer necessary
end{LHZZ}
Now verb|LHXY| is
begin{flushleft}
ttfamily meaningLHXY
end{flushleft}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
endgroup
Here verb|LHXY| is textbf{%
ifdefined LHXY definedelse not definedfi
}.
end{document}
But I’d better follow @egreg’s solicitation… (see comments ;-)
No##1
is actually necessary; more important, you should useprotected@xdef
, notxdef
.
– egreg
Apr 9 '16 at 13:54
@egreg:protected@xdef
, yes, of course! Thanks for noticing. But concerning the##
, if I try with a single#
, it doesn’t work.
– GuM
Apr 9 '16 at 14:04
You have to work harder, for that.;-)
– egreg
Apr 9 '16 at 14:05
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
1
@MaestroGlanz:csname LH#1endcsname
(resp.,csname MG#1endcsname
) andBODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if#1
is, say,XY
, the macro@my@temporary@y
will be (globally) defined asnewcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when theLHZZ
environment is over (aftergroup
), so that theMGXY
command will be defined in the right scope. Try insertingshow@my@temporary@x
and/orshow@my@temporary@y
before the twoaftergroup
s.
– GuM
Apr 13 '16 at 9:42
|
show 3 more comments
I think this is code golfing however...
expandafternewcommandcsname ....endcsname{...
won't work outside -- it's a local definition.
globalexpandafternewcommand...won't work neither due to expansion, but globalexpandafterdefcsname...
would work, but since the environment body shall be grabbed, the BODY
macro must be expanded first, otherwise it would be undefined outside of the environment, so either use expandafterxdefcsname....
or globalexpandafteredefcsname...
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
usepackage{environ}
setlength{parindent}{0pt}
NewEnviron{LHZZ}[1]{%
longglobalexpandafteredefcsname LH#1endcsname##1{BODY ##1}
}
begin{LHZZ}{XY}
write stuff here
Other stuff here
end{LHZZ}
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
add a comment |
If you are using environ
package then you can write something like this:
NewEnviron{LHZZ}[1]{%
expandaftergdefcsname LH#1expandafterendcsname
expandafter##expandafter1expandafter{BODY}}
Note, that the code is much more compact than the usage of eTeX's unexpanded
, four hashes, etc...
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f303354%2fuse-newcommand-in-newenvironment-content-of-environment-is-argument-of-newc%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
The command form is easier:
documentclass{article}
newcommand{LHZZ}[2]{%
expandafternewcommandcsname LH#1endcsname[1]{#2}}%
}
begin{document}
LHZZ{XY}{%
write stuff here
refer to #1%
}
LHXY{parameter}
end{document}
If you really insist in using an environment, use environ
:
documentclass{article}
usepackage{environ}
makeatletter
NewEnviron{LHZZ}[1]{%
edefmaestroglanz@temp{%
unexpanded{expandaftergdefcsname LH#1endcsname}####1{unexpandedexpandafter{BODY}}%
}%
maestroglanz@temp
}
makeatother
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
end{document}
An implementation using xparse
and expl3
; the largest part of the code is the definition of the error messages in case the environment is called twice with the same argument.
documentclass{article}
usepackage{environ,xparse}
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Without the error check, the code part would look like
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
ExplSyntaxOff
Update
With xparse
released 2019-05-03 the code can become
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentEnvironment{LHZZ}{m +b}
{
cs_set_protected:cn { LH#1:n } { #2 }
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}{}
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Could you explain briefly (if this is possible) when to usecs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.
– cfr
Apr 9 '16 at 23:09
@cfr Basically, you always use_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable inx
arguments. For instance, the analog ofthesection
should not be protected.
– egreg
Apr 9 '16 at 23:12
@cfr Yes, but it wasn't right. Your impression aboutNewDocumentCommand
is wrong as well.
– egreg
Apr 9 '16 at 23:30
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
So I just went through one file addingprotected
s and things still seem to work, which I guess means they should beprotected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first:% includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?
– cfr
Apr 10 '16 at 0:23
|
show 1 more comment
The command form is easier:
documentclass{article}
newcommand{LHZZ}[2]{%
expandafternewcommandcsname LH#1endcsname[1]{#2}}%
}
begin{document}
LHZZ{XY}{%
write stuff here
refer to #1%
}
LHXY{parameter}
end{document}
If you really insist in using an environment, use environ
:
documentclass{article}
usepackage{environ}
makeatletter
NewEnviron{LHZZ}[1]{%
edefmaestroglanz@temp{%
unexpanded{expandaftergdefcsname LH#1endcsname}####1{unexpandedexpandafter{BODY}}%
}%
maestroglanz@temp
}
makeatother
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
end{document}
An implementation using xparse
and expl3
; the largest part of the code is the definition of the error messages in case the environment is called twice with the same argument.
documentclass{article}
usepackage{environ,xparse}
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Without the error check, the code part would look like
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
ExplSyntaxOff
Update
With xparse
released 2019-05-03 the code can become
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentEnvironment{LHZZ}{m +b}
{
cs_set_protected:cn { LH#1:n } { #2 }
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}{}
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Could you explain briefly (if this is possible) when to usecs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.
– cfr
Apr 9 '16 at 23:09
@cfr Basically, you always use_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable inx
arguments. For instance, the analog ofthesection
should not be protected.
– egreg
Apr 9 '16 at 23:12
@cfr Yes, but it wasn't right. Your impression aboutNewDocumentCommand
is wrong as well.
– egreg
Apr 9 '16 at 23:30
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
So I just went through one file addingprotected
s and things still seem to work, which I guess means they should beprotected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first:% includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?
– cfr
Apr 10 '16 at 0:23
|
show 1 more comment
The command form is easier:
documentclass{article}
newcommand{LHZZ}[2]{%
expandafternewcommandcsname LH#1endcsname[1]{#2}}%
}
begin{document}
LHZZ{XY}{%
write stuff here
refer to #1%
}
LHXY{parameter}
end{document}
If you really insist in using an environment, use environ
:
documentclass{article}
usepackage{environ}
makeatletter
NewEnviron{LHZZ}[1]{%
edefmaestroglanz@temp{%
unexpanded{expandaftergdefcsname LH#1endcsname}####1{unexpandedexpandafter{BODY}}%
}%
maestroglanz@temp
}
makeatother
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
end{document}
An implementation using xparse
and expl3
; the largest part of the code is the definition of the error messages in case the environment is called twice with the same argument.
documentclass{article}
usepackage{environ,xparse}
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Without the error check, the code part would look like
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
ExplSyntaxOff
Update
With xparse
released 2019-05-03 the code can become
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentEnvironment{LHZZ}{m +b}
{
cs_set_protected:cn { LH#1:n } { #2 }
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}{}
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
The command form is easier:
documentclass{article}
newcommand{LHZZ}[2]{%
expandafternewcommandcsname LH#1endcsname[1]{#2}}%
}
begin{document}
LHZZ{XY}{%
write stuff here
refer to #1%
}
LHXY{parameter}
end{document}
If you really insist in using an environment, use environ
:
documentclass{article}
usepackage{environ}
makeatletter
NewEnviron{LHZZ}[1]{%
edefmaestroglanz@temp{%
unexpanded{expandaftergdefcsname LH#1endcsname}####1{unexpandedexpandafter{BODY}}%
}%
maestroglanz@temp
}
makeatother
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
end{document}
An implementation using xparse
and expl3
; the largest part of the code is the definition of the error messages in case the environment is called twice with the same argument.
documentclass{article}
usepackage{environ,xparse}
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
Without the error check, the code part would look like
ExplSyntaxOn
NewEnviron{LHZZ}[1]
{
cs_set_protected:cV { LH#1:n } BODY
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
cs_generate_variant:Nn cs_set_protected:Nn { cV }
ExplSyntaxOff
Update
With xparse
released 2019-05-03 the code can become
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentEnvironment{LHZZ}{m +b}
{
cs_set_protected:cn { LH#1:n } { #2 }
cs_if_free:cTF { LH#1 }
{
cs_gset_eq:cc { LH#1 }{ LH#1:n }
}
{
msg_error:nnn { maestroglanz/LH } { already-defined } { #1 }
}
}{}
msg_new:nnnn { maestroglanz/LH } { already-defined }
{
LH#1~already~defined
}
{
You~used~token_to_str:N begin{LHZZ}{#1}~before
}
ExplSyntaxOff
begin{document}
begin{LHZZ}{XY}
write stuff here
refer to #1
end{LHZZ}
LHXY{parameter}
begin{LHZZ}{XY}aend{LHZZ}
end{document}
edited Mar 8 at 14:42
answered Apr 9 '16 at 13:45
egregegreg
727k8819223231
727k8819223231
Could you explain briefly (if this is possible) when to usecs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.
– cfr
Apr 9 '16 at 23:09
@cfr Basically, you always use_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable inx
arguments. For instance, the analog ofthesection
should not be protected.
– egreg
Apr 9 '16 at 23:12
@cfr Yes, but it wasn't right. Your impression aboutNewDocumentCommand
is wrong as well.
– egreg
Apr 9 '16 at 23:30
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
So I just went through one file addingprotected
s and things still seem to work, which I guess means they should beprotected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first:% includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?
– cfr
Apr 10 '16 at 0:23
|
show 1 more comment
Could you explain briefly (if this is possible) when to usecs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.
– cfr
Apr 9 '16 at 23:09
@cfr Basically, you always use_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable inx
arguments. For instance, the analog ofthesection
should not be protected.
– egreg
Apr 9 '16 at 23:12
@cfr Yes, but it wasn't right. Your impression aboutNewDocumentCommand
is wrong as well.
– egreg
Apr 9 '16 at 23:30
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
So I just went through one file addingprotected
s and things still seem to work, which I guess means they should beprotected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first:% includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?
– cfr
Apr 10 '16 at 0:23
Could you explain briefly (if this is possible) when to use
cs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.– cfr
Apr 9 '16 at 23:09
Could you explain briefly (if this is possible) when to use
cs_set_protected
in a way which doesn't assume an understanding of the corresponding TeX macros? If this query asks something unmanageably big, please just ignore it. I don't know enough to have a sense of whether the question is a reasonable one or not.– cfr
Apr 9 '16 at 23:09
@cfr Basically, you always use
_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable in x
arguments. For instance, the analog of thesection
should not be protected.– egreg
Apr 9 '16 at 23:12
@cfr Basically, you always use
_protected
, unless you have good reasons not to; the good reason is that you want the function is expandable in x
arguments. For instance, the analog of thesection
should not be protected.– egreg
Apr 9 '16 at 23:12
@cfr Yes, but it wasn't right. Your impression about
NewDocumentCommand
is wrong as well.– egreg
Apr 9 '16 at 23:30
@cfr Yes, but it wasn't right. Your impression about
NewDocumentCommand
is wrong as well.– egreg
Apr 9 '16 at 23:30
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
OK. I just wanted to make sure I wasn't (that) crazy.
– cfr
Apr 9 '16 at 23:31
So I just went through one file adding
protected
s and things still seem to work, which I guess means they should be protected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first: % includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?– cfr
Apr 10 '16 at 0:23
So I just went through one file adding
protected
s and things still seem to work, which I guess means they should be protected
s. But I'm wary of changing the last 3 cases because the first has a note saying that you gave me the code and the other 2 are modelled on the first: % includegraphics bit courtesy of egreg (chat 2015-01-08) cs_new:Npn cfr_includegraphics:nn #1 #2 { includegraphics[#1]{#2} }
. I don't know if you can tell from this why this shouldn't be protected?– cfr
Apr 10 '16 at 0:23
|
show 1 more comment
Here is your minimal example turned into a working one:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary{} % check availability of the name
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary{%
newcommand{csname LH#1endcsname}[1]{BODY}}%
aftergroup@my@temporary
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1 % sorry, doubling "#" is necessary here
end{LHZZ}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Edit: I think using newcommand
instead of globaledef
(see Christian’s answer; note, however, that globaledef
is exactly the same as xdef
) does have some added value, because one retains, for example, the ability to define a default argument:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary@x{%
newcommand{csname LH#1endcsname}[1]{BODY}
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
protected@xdef@my@temporary@y{%
newcommand*{csname MG#1endcsname}[1][default]{BODY}
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1par % sorry, doubling "#" is necessary here
end{LHZZ}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
end{document}
Edit 2: Always double-check that the brain is connected before writing to TeX.SX! (Will it be, now?) Here is a cleaner implementation of the same basic idea:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
xdef@my@temporary@x{%
noexpandnewcommand{csname LH#1endcsname}[1]{%
unexpandedexpandafter{BODY}%
}%
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
xdef@my@temporary@y{%
noexpandnewcommand*{csname MG#1endcsname}[1][default]{%
unexpandedexpandafter{BODY}%
}%
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
% Obviously, in a real application you'd choose only one of the two
% possibiities.
}
makeatother
begin{document}
begingroup % to show that normal scoping is obeyed
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to texttt{#1}par % doubling the "#" is no longer necessary
end{LHZZ}
Now verb|LHXY| is
begin{flushleft}
ttfamily meaningLHXY
end{flushleft}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
endgroup
Here verb|LHXY| is textbf{%
ifdefined LHXY definedelse not definedfi
}.
end{document}
But I’d better follow @egreg’s solicitation… (see comments ;-)
No##1
is actually necessary; more important, you should useprotected@xdef
, notxdef
.
– egreg
Apr 9 '16 at 13:54
@egreg:protected@xdef
, yes, of course! Thanks for noticing. But concerning the##
, if I try with a single#
, it doesn’t work.
– GuM
Apr 9 '16 at 14:04
You have to work harder, for that.;-)
– egreg
Apr 9 '16 at 14:05
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
1
@MaestroGlanz:csname LH#1endcsname
(resp.,csname MG#1endcsname
) andBODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if#1
is, say,XY
, the macro@my@temporary@y
will be (globally) defined asnewcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when theLHZZ
environment is over (aftergroup
), so that theMGXY
command will be defined in the right scope. Try insertingshow@my@temporary@x
and/orshow@my@temporary@y
before the twoaftergroup
s.
– GuM
Apr 13 '16 at 9:42
|
show 3 more comments
Here is your minimal example turned into a working one:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary{} % check availability of the name
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary{%
newcommand{csname LH#1endcsname}[1]{BODY}}%
aftergroup@my@temporary
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1 % sorry, doubling "#" is necessary here
end{LHZZ}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Edit: I think using newcommand
instead of globaledef
(see Christian’s answer; note, however, that globaledef
is exactly the same as xdef
) does have some added value, because one retains, for example, the ability to define a default argument:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary@x{%
newcommand{csname LH#1endcsname}[1]{BODY}
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
protected@xdef@my@temporary@y{%
newcommand*{csname MG#1endcsname}[1][default]{BODY}
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1par % sorry, doubling "#" is necessary here
end{LHZZ}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
end{document}
Edit 2: Always double-check that the brain is connected before writing to TeX.SX! (Will it be, now?) Here is a cleaner implementation of the same basic idea:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
xdef@my@temporary@x{%
noexpandnewcommand{csname LH#1endcsname}[1]{%
unexpandedexpandafter{BODY}%
}%
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
xdef@my@temporary@y{%
noexpandnewcommand*{csname MG#1endcsname}[1][default]{%
unexpandedexpandafter{BODY}%
}%
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
% Obviously, in a real application you'd choose only one of the two
% possibiities.
}
makeatother
begin{document}
begingroup % to show that normal scoping is obeyed
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to texttt{#1}par % doubling the "#" is no longer necessary
end{LHZZ}
Now verb|LHXY| is
begin{flushleft}
ttfamily meaningLHXY
end{flushleft}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
endgroup
Here verb|LHXY| is textbf{%
ifdefined LHXY definedelse not definedfi
}.
end{document}
But I’d better follow @egreg’s solicitation… (see comments ;-)
No##1
is actually necessary; more important, you should useprotected@xdef
, notxdef
.
– egreg
Apr 9 '16 at 13:54
@egreg:protected@xdef
, yes, of course! Thanks for noticing. But concerning the##
, if I try with a single#
, it doesn’t work.
– GuM
Apr 9 '16 at 14:04
You have to work harder, for that.;-)
– egreg
Apr 9 '16 at 14:05
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
1
@MaestroGlanz:csname LH#1endcsname
(resp.,csname MG#1endcsname
) andBODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if#1
is, say,XY
, the macro@my@temporary@y
will be (globally) defined asnewcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when theLHZZ
environment is over (aftergroup
), so that theMGXY
command will be defined in the right scope. Try insertingshow@my@temporary@x
and/orshow@my@temporary@y
before the twoaftergroup
s.
– GuM
Apr 13 '16 at 9:42
|
show 3 more comments
Here is your minimal example turned into a working one:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary{} % check availability of the name
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary{%
newcommand{csname LH#1endcsname}[1]{BODY}}%
aftergroup@my@temporary
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1 % sorry, doubling "#" is necessary here
end{LHZZ}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Edit: I think using newcommand
instead of globaledef
(see Christian’s answer; note, however, that globaledef
is exactly the same as xdef
) does have some added value, because one retains, for example, the ability to define a default argument:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary@x{%
newcommand{csname LH#1endcsname}[1]{BODY}
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
protected@xdef@my@temporary@y{%
newcommand*{csname MG#1endcsname}[1][default]{BODY}
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1par % sorry, doubling "#" is necessary here
end{LHZZ}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
end{document}
Edit 2: Always double-check that the brain is connected before writing to TeX.SX! (Will it be, now?) Here is a cleaner implementation of the same basic idea:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
xdef@my@temporary@x{%
noexpandnewcommand{csname LH#1endcsname}[1]{%
unexpandedexpandafter{BODY}%
}%
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
xdef@my@temporary@y{%
noexpandnewcommand*{csname MG#1endcsname}[1][default]{%
unexpandedexpandafter{BODY}%
}%
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
% Obviously, in a real application you'd choose only one of the two
% possibiities.
}
makeatother
begin{document}
begingroup % to show that normal scoping is obeyed
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to texttt{#1}par % doubling the "#" is no longer necessary
end{LHZZ}
Now verb|LHXY| is
begin{flushleft}
ttfamily meaningLHXY
end{flushleft}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
endgroup
Here verb|LHXY| is textbf{%
ifdefined LHXY definedelse not definedfi
}.
end{document}
But I’d better follow @egreg’s solicitation… (see comments ;-)
Here is your minimal example turned into a working one:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary{} % check availability of the name
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary{%
newcommand{csname LH#1endcsname}[1]{BODY}}%
aftergroup@my@temporary
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1 % sorry, doubling "#" is necessary here
end{LHZZ}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Edit: I think using newcommand
instead of globaledef
(see Christian’s answer; note, however, that globaledef
is exactly the same as xdef
) does have some added value, because one retains, for example, the ability to define a default argument:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
let newcommand relax
protected@xdef@my@temporary@x{%
newcommand{csname LH#1endcsname}[1]{BODY}
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
protected@xdef@my@temporary@y{%
newcommand*{csname MG#1endcsname}[1][default]{BODY}
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
}
makeatother
begin{document}
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to ##1par % sorry, doubling "#" is necessary here
end{LHZZ}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
end{document}
Edit 2: Always double-check that the brain is connected before writing to TeX.SX! (Will it be, now?) Here is a cleaner implementation of the same basic idea:
documentclass[a4paper]{article}
usepackage[T1]{fontenc}
usepackage[ascii]{inputenc}
usepackage{environ}
makeatletter
@ifdefinable@my@temporary@x{} % check availability of the names
@ifdefinable@my@temporary@y{}
% That's my environment:
NewEnviron{LHZZ}[1]{%
xdef@my@temporary@x{%
noexpandnewcommand{csname LH#1endcsname}[1]{%
unexpandedexpandafter{BODY}%
}%
}%
% ... but this one works too (the astersik is there only to illustrate
% another possibility: define a non-"long" command):
xdef@my@temporary@y{%
noexpandnewcommand*{csname MG#1endcsname}[1][default]{%
unexpandedexpandafter{BODY}%
}%
}%
aftergroup@my@temporary@x
aftergroup@my@temporary@y
% Obviously, in a real application you'd choose only one of the two
% possibiities.
}
makeatother
begin{document}
begingroup % to show that normal scoping is obeyed
% That's the use of it:
begin{LHZZ}{XY}
write stuff here
refer to texttt{#1}par % doubling the "#" is no longer necessary
end{LHZZ}
Now verb|LHXY| is
begin{flushleft}
ttfamily meaningLHXY
end{flushleft}
Text before.
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
MGXY[parameter]
MGXY
Text after.
endgroup
Here verb|LHXY| is textbf{%
ifdefined LHXY definedelse not definedfi
}.
end{document}
But I’d better follow @egreg’s solicitation… (see comments ;-)
edited Apr 9 '16 at 20:39
answered Apr 9 '16 at 13:40
GuMGuM
16.7k2458
16.7k2458
No##1
is actually necessary; more important, you should useprotected@xdef
, notxdef
.
– egreg
Apr 9 '16 at 13:54
@egreg:protected@xdef
, yes, of course! Thanks for noticing. But concerning the##
, if I try with a single#
, it doesn’t work.
– GuM
Apr 9 '16 at 14:04
You have to work harder, for that.;-)
– egreg
Apr 9 '16 at 14:05
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
1
@MaestroGlanz:csname LH#1endcsname
(resp.,csname MG#1endcsname
) andBODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if#1
is, say,XY
, the macro@my@temporary@y
will be (globally) defined asnewcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when theLHZZ
environment is over (aftergroup
), so that theMGXY
command will be defined in the right scope. Try insertingshow@my@temporary@x
and/orshow@my@temporary@y
before the twoaftergroup
s.
– GuM
Apr 13 '16 at 9:42
|
show 3 more comments
No##1
is actually necessary; more important, you should useprotected@xdef
, notxdef
.
– egreg
Apr 9 '16 at 13:54
@egreg:protected@xdef
, yes, of course! Thanks for noticing. But concerning the##
, if I try with a single#
, it doesn’t work.
– GuM
Apr 9 '16 at 14:04
You have to work harder, for that.;-)
– egreg
Apr 9 '16 at 14:05
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
1
@MaestroGlanz:csname LH#1endcsname
(resp.,csname MG#1endcsname
) andBODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if#1
is, say,XY
, the macro@my@temporary@y
will be (globally) defined asnewcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when theLHZZ
environment is over (aftergroup
), so that theMGXY
command will be defined in the right scope. Try insertingshow@my@temporary@x
and/orshow@my@temporary@y
before the twoaftergroup
s.
– GuM
Apr 13 '16 at 9:42
No
##1
is actually necessary; more important, you should use protected@xdef
, not xdef
.– egreg
Apr 9 '16 at 13:54
No
##1
is actually necessary; more important, you should use protected@xdef
, not xdef
.– egreg
Apr 9 '16 at 13:54
@egreg:
protected@xdef
, yes, of course! Thanks for noticing. But concerning the ##
, if I try with a single #
, it doesn’t work.– GuM
Apr 9 '16 at 14:04
@egreg:
protected@xdef
, yes, of course! Thanks for noticing. But concerning the ##
, if I try with a single #
, it doesn’t work.– GuM
Apr 9 '16 at 14:04
You have to work harder, for that.
;-)
– egreg
Apr 9 '16 at 14:05
You have to work harder, for that.
;-)
– egreg
Apr 9 '16 at 14:05
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
Don't you like the expl3 version?
– egreg
Apr 9 '16 at 14:40
1
1
@MaestroGlanz:
csname LH#1endcsname
(resp., csname MG#1endcsname
) and BODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if #1
is, say, XY
, the macro @my@temporary@y
will be (globally) defined as newcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when the LHZZ
environment is over (aftergroup
), so that the MGXY
command will be defined in the right scope. Try inserting show@my@temporary@x
and/or show@my@temporary@y
before the two aftergroup
s.– GuM
Apr 13 '16 at 9:42
@MaestroGlanz:
csname LH#1endcsname
(resp., csname MG#1endcsname
) and BODY
are expanded (the latter only by one level) when the temporary macros are defined. For example, if #1
is, say, XY
, the macro @my@temporary@y
will be (globally) defined as newcommand*MGXY[1][default]{<first-level expansion of BODY>}
. This temporary macro will be executed when the LHZZ
environment is over (aftergroup
), so that the MGXY
command will be defined in the right scope. Try inserting show@my@temporary@x
and/or show@my@temporary@y
before the two aftergroup
s.– GuM
Apr 13 '16 at 9:42
|
show 3 more comments
I think this is code golfing however...
expandafternewcommandcsname ....endcsname{...
won't work outside -- it's a local definition.
globalexpandafternewcommand...won't work neither due to expansion, but globalexpandafterdefcsname...
would work, but since the environment body shall be grabbed, the BODY
macro must be expanded first, otherwise it would be undefined outside of the environment, so either use expandafterxdefcsname....
or globalexpandafteredefcsname...
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
usepackage{environ}
setlength{parindent}{0pt}
NewEnviron{LHZZ}[1]{%
longglobalexpandafteredefcsname LH#1endcsname##1{BODY ##1}
}
begin{LHZZ}{XY}
write stuff here
Other stuff here
end{LHZZ}
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
add a comment |
I think this is code golfing however...
expandafternewcommandcsname ....endcsname{...
won't work outside -- it's a local definition.
globalexpandafternewcommand...won't work neither due to expansion, but globalexpandafterdefcsname...
would work, but since the environment body shall be grabbed, the BODY
macro must be expanded first, otherwise it would be undefined outside of the environment, so either use expandafterxdefcsname....
or globalexpandafteredefcsname...
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
usepackage{environ}
setlength{parindent}{0pt}
NewEnviron{LHZZ}[1]{%
longglobalexpandafteredefcsname LH#1endcsname##1{BODY ##1}
}
begin{LHZZ}{XY}
write stuff here
Other stuff here
end{LHZZ}
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
add a comment |
I think this is code golfing however...
expandafternewcommandcsname ....endcsname{...
won't work outside -- it's a local definition.
globalexpandafternewcommand...won't work neither due to expansion, but globalexpandafterdefcsname...
would work, but since the environment body shall be grabbed, the BODY
macro must be expanded first, otherwise it would be undefined outside of the environment, so either use expandafterxdefcsname....
or globalexpandafteredefcsname...
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
usepackage{environ}
setlength{parindent}{0pt}
NewEnviron{LHZZ}[1]{%
longglobalexpandafteredefcsname LH#1endcsname##1{BODY ##1}
}
begin{LHZZ}{XY}
write stuff here
Other stuff here
end{LHZZ}
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
I think this is code golfing however...
expandafternewcommandcsname ....endcsname{...
won't work outside -- it's a local definition.
globalexpandafternewcommand...won't work neither due to expansion, but globalexpandafterdefcsname...
would work, but since the environment body shall be grabbed, the BODY
macro must be expanded first, otherwise it would be undefined outside of the environment, so either use expandafterxdefcsname....
or globalexpandafteredefcsname...
documentclass[12pt,a4paper]{article}
usepackage[utf8]{inputenc}
usepackage{environ}
setlength{parindent}{0pt}
NewEnviron{LHZZ}[1]{%
longglobalexpandafteredefcsname LH#1endcsname##1{BODY ##1}
}
begin{LHZZ}{XY}
write stuff here
Other stuff here
end{LHZZ}
begin{document}
LHXY{parameter} %the command LHXY has been created indirectly by begin{LHZZ}
end{document}
answered Apr 9 '16 at 13:01
user31729
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
add a comment |
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
Oh, sorry, I hadn’t seen this answer before posting mine (I did not refresh the page).
– GuM
Apr 9 '16 at 13:44
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
@GustavoMezzetti: No worries, you provided a different answer
– user31729
Apr 9 '16 at 14:28
add a comment |
If you are using environ
package then you can write something like this:
NewEnviron{LHZZ}[1]{%
expandaftergdefcsname LH#1expandafterendcsname
expandafter##expandafter1expandafter{BODY}}
Note, that the code is much more compact than the usage of eTeX's unexpanded
, four hashes, etc...
add a comment |
If you are using environ
package then you can write something like this:
NewEnviron{LHZZ}[1]{%
expandaftergdefcsname LH#1expandafterendcsname
expandafter##expandafter1expandafter{BODY}}
Note, that the code is much more compact than the usage of eTeX's unexpanded
, four hashes, etc...
add a comment |
If you are using environ
package then you can write something like this:
NewEnviron{LHZZ}[1]{%
expandaftergdefcsname LH#1expandafterendcsname
expandafter##expandafter1expandafter{BODY}}
Note, that the code is much more compact than the usage of eTeX's unexpanded
, four hashes, etc...
If you are using environ
package then you can write something like this:
NewEnviron{LHZZ}[1]{%
expandaftergdefcsname LH#1expandafterendcsname
expandafter##expandafter1expandafter{BODY}}
Note, that the code is much more compact than the usage of eTeX's unexpanded
, four hashes, etc...
answered Apr 10 '16 at 20:48
wipetwipet
35.3k4983
35.3k4983
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f303354%2fuse-newcommand-in-newenvironment-content-of-environment-is-argument-of-newc%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You need to
expandafter
thenewcommand
relative to the stuff which comes next. Not sure whether this works withnewcommand
, though. But probably you want to look at theenviron
package.– cfr
Apr 9 '16 at 12:49
This can't work this way -- you can't grab the environment content like this.
– user31729
Apr 9 '16 at 12:49
I used
expandafter
in some tries, but it didn't work.– MaestroGlanz
Apr 9 '16 at 12:51
That's why I said you should look at
environ
.– cfr
Apr 9 '16 at 23:02