我想对角色进行@
如下定义:
\def @#1#2{\catcode`#1=13\def #1{#2}}
这样当我输入 时@xy x
,TeX 就会排版y
。但是,当我运行这个时,我收到一个错误。
我看过其他答案这里和这里询问有关更改命令中的 catcode 的问题。但是,给出的所有答案都不能以我想要的方式解决问题——它们只是将\catcode
宏移出。还有解决方案
\catcode`@=13
\def @#1{\catcode`#1=13\def}
@xx{y} x
其结果相同y
。但是,出于我自己的目的,我想用最少的字符 (3) 实现上述目标:@xy
。我尝试使用\expandafter
,但无济于事。这可能吗?
答案1
你必须使用\lowercase
技巧:
\def @#1#2{\catcode`#1=13 \bgroup \lccode`\~=`#1\lowercase{\egroup \def~}{#2}}
% test:
@ABA
~
在所有格式中默认处于活动状态,并将活动\lowercase
更改~
为您想要的活动字符。
答案2
wipet 的答案是获得你建议的语法的方法,但如果你改为使用双字符,那么@xxy ... x
你可以避免在字符激活之前访问定义的字符的问题,所以使用更简单的定义。这是在xii.tex
使用A
而不是@
但是例如AZZFLaLP
相当于您的建议 @Z{LaL}
但是Z
使用被定义为双倍。@ZZ{LaL}
\let~\catcode~`76~`A13~`F1~`j00~`P2jdefA71F~`7113jdefPALLF
PA''FwPA;;FPAZZFLaLPA//71F71iPAHHFLPAzzFenPASSFthP;A$$FevP
A@@FfPARR717273F737271P;ADDFRgniPAWW71FPATTFvePA**FstRsamP
AGGFRruoPAqq71.72.F717271PAYY7172F727171PA??Fi*LmPA&&71jfi
Fjfi71PAVVFjbigskipRPWGAUU71727374 75,76Fjpar71727375Djifx
:76jelse&U76jfiPLAKK7172F71l7271PAXX71FVLnOSeL71SLRyadR@oL
RrhC?yLRurtKFeLPFovPgaTLtReRomL;PABB71 72,73:Fjif.73.jelse
B73:jfiXF71PU71 72,73:PWs;AMM71F71diPAJJFRdriPAQQFRsreLPAI
I71Fo71dPA!!FRgiePBt'el@ lTLqdrYmu.Q.,Ke;vz vzLqpip.Q.,tz;
;Lql.IrsZ.eap,qn.i. i.eLlMaesLdRcna,;!;h htLqm.MRasZ.ilk,%
s$;z zLqs'.ansZ.Ymi,/sx ;LYegseZRyal,@i;@ TLRlogdLrDsW,@;G
LcYlaDLbJsW,SWXJW ree @rzchLhzsW,;WERcesInW qt.'oL.Rtrul;e
doTsW,Wk;Rri@stW aHAHHFndZPpqar.tridgeLinZpe.LtYer.W,:jbye
或者,如果您更喜欢\
使用转义字符而不是j
\catcode`\@13
\def\dodef#1#2{\def#1{#2}}
\def@#1{\catcode`#1=13 \dodef}
@xxy abc x
@ww{hello} hmmm what
\bye
\dodef
这里只是括号是可选的,你可以使用@xxy
而不是@xx{y}
。xii
版本直接使用\def
,所以你需要@xx{y}
,但你可以使用参数,这样例如@xx#1{(#1)} xq
会扩展为(q)
答案3
您显示的代码假定@
首先处于活动状态,因此\catcode`@=\active
需要在某处进行声明。
你的
\def @#1#2{\catcode`#1=13\def #1{#2}}
@xy x
尝试?TeX 会抱怨缺少控制序列,因为不的替换文本中的控制序列或活动字符@
,并x
使用其类别代码进行标记前任务\catcode
已完成。
您可以使用\lowercase
wipet 所示的技巧,或者采用不同的方法expl3
(可以与纯 TeX 一起使用,但只能在启用 e-TeX 扩展的情况下使用)。
\input expl3-generic
\ExplSyntaxOn
% first a generic function
\cs_new_protected:Nn \bshepard_catcode_def:nnn
{% #1 = character to be made active
% #2 = argument list, may be empty
% #3 = replacement text
\cs_new:cn { __bshepard_catcode_def_#1:#2 } { #3 }
\char_set_active_eq:nc { `#1 } { __bshepard_catcode_def_#1:#2 }
\char_set_catcode_active:n { `#1 }
}
%initialize @
\bshepard_catcode_def:nnn { @ } { nn } { \bshepard_catcode_def:nnn { #1 } { } { #2 } }
\ExplSyntaxOff
@xy x
\show x
\bye
控制台将显示
> x=\long macro:
->y.
l.22 \show x
发生了什么?通用函数有三个参数:要激活的字符、其激活值将查找的参数的规范以及替换文本。
这将根据角色定义一个内部函数,并将活动角色含义设置为等同于该内部函数,然后激活该角色。
线路
\bshepard_catcode_def:nnn { @ } { nn } { \bshepard_catcode_def:nnn { #1 } { } { #2 } }
激活@
并告诉 TeX 它的含义是寻找两个参数(其中第一个必须是一个字符)并将通用函数应用于这个字符。