不确定这是否可能...
我想将(比如说)转换+
为一个不带括号的参数的命令。此参数应为以下所有内容:+
直到第一个非字母数字字符。 一个例子:
\documentclass{article}
\catcode`+\active
\def+{%
%do some magic tricks
}
\begin{document}
+ % + with an empty argument
+hello527world % + with the argument hello527world
+cool. This is nice. % + with the argument cool followed by ". This is nice."
+cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
换句话说,+
应该有点像\
,只是支持字母数字字符。此外,以下空格也需要输入。
我到底为什么要这样做?我正在尝试创建一个更简单的 LaTeX 前端,并且我想使用符号+blahblah
进行引用。
我尝试过xparse
,但没有找到任何方法来实现这一点。
答案1
引用其中一条评论:“欢迎使用非字母字符的解决方案”。因此,我提出了一个解决方案,提取完全由字母(\catcode
= 11)字符组成的参数,直到但不包括第一个非字母。原则上,代码可以调整为包括十个数字 0...9。
这个解决方案只需要 Knuth 的原始 TeX。
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\makeatletter
% Avoid using a critical character like +
\catcode`\! = \active
\def!{%
\toks@{}%
\@AN@scan@forward
}
\@ifdefinable\@AN@scan@forward{\def\@AN@scan@forward{%
\futurelet\next \@AN@test@next
}}
\@ifdefinable\@AN@test@next{\def\@AN@test@next{%
\ifcat A\noexpand\next
\expandafter\@AN@add@token
\else
\expandafter\@AN@call@payload
\fi
}}
\@ifdefinable\@AN@add@token{\def\@AN@add@token#1{%
\toks@ \expandafter{\the\toks@ #1}%
\@AN@scan@forward
}}
\@ifdefinable\@AN@call@payload{\def\@AN@call@payload{%
\ANPayload{\the\toks@}%
% (Or
% \expandafter\ANPayload \expandafter{\the\toks@}%
% if needed).
}}
\makeatother
\newcommand{\ANPayload}[1]{%
% Substitute the operations you want to perform on the argument:
\typeout{#1}%
\textbf{#1}%
}
\begin{document}
Reference text.
! % + with an empty argument
!hello527world % + with the argument hello followed by "527world"
!helloworld % + with the argument helloworld
!cool. This is nice. % + with the argument cool followed by ". This is nice."
!cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
我必须警告,可能,解析提供了更好的解决方案,我根本不知道:在看到大约两天没有提供其他答案后,我决定发布这个临时答案。
答案2
我建了一个图书馆...
%! TEX program = lualatex
\documentclass{article}
\usepackage{pythonimmediate}
\begin{pycode}
from pythonimmediate import newcommand, peek_next_char, get_next_char
from pythonimmediate import print as print_to_TeX
from string import ascii_letters, digits
@newcommand
def plussign():
s=""
while True:
ch=peek_next_char()
if ch!="" and (ch in ascii_letters or ch in digits):
get_next_char()
s+=ch
else:
break
print_to_TeX(r'(' + s + ')', end="") # need end="" to suppress the new line character being interpreted as a space, see documentation for details (did I remember to include it in the documentation?)
\end{pycode}
% currently there's no function to define active character yet...
\catcode `+\active
\let+\plussign
\begin{document}
+ % + with an empty argument
+hello527world % + with the argument hello527world
+cool. This is nice. % + with the argument cool followed by ". This is nice."
+cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
输出正如你所期望的:
话虽如此,这是一个“正常”的实现:
%! TEX program = lualatex
\documentclass{article}
\ExplSyntaxOn
\cs_new_protected:Npn \__gaussler_plus_sign:n #1 {
(#1)
}
\cs_new_protected:Npn \__gaussler_plus_sign:w {
\peek_regex_replace_once:nn {[A-Za-z0-9]*} {\c{__gaussler_plus_sign:n}{\0}}
}
\char_set_active_eq:NN + \__gaussler_plus_sign:w
\char_set_catcode_active:N +
\ExplSyntaxOff
\begin{document}
+ % + with an empty argument
+hello527world % + with the argument hello527world
+cool. This is nice. % + with the argument cool followed by ". This is nice."
+cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
所有的魔法都隐藏在函数后面。基本上,它 用\peek_regex_replace_once:nn
替换标记列表,然后函数本身完成工作。(在这个例子中,它用一对括号括起来)cool. This is nice
\__gaussler_plus_sign:n {cool}. This is nice.
答案3
这是一份工作\peek_regex_replace_once:nn
\documentclass{article}
\usepackage[T1]{fontenc}
\ExplSyntaxOn
\NewDocumentCommand{\+}{}
{
\gaussler_plus:
}
\cs_new_protected:Nn \gaussler_plus:
{
\peek_regex_replace_once:nn { ([[:alnum:]]*) } { \c{gaussler_plus_do:n}\cB\{\1\cE\} }
}
\cs_new:Nn \gaussler_plus_do:n
{
--Argument~was~|#1|--
}
% if you want to live dangerously
\char_gset_active_eq:NN + \gaussler_plus:
\char_set_catcode_active:N +
\ExplSyntaxOff
\begin{document}
\+ % + with an empty argument
\+Hello527World % + with the argument hello527world
\+cool. This is nice. % + with the argument cool followed by ". This is nice."
\+cool is nice. % + with the argument cool followed by a space and "is nice"
+ % + with an empty argument
+Hello527World % + with the argument hello527world
+cool. This is nice. % + with the argument cool followed by ". This is nice."
+cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
与搜索正则表达式(第一个参数)匹配的标记将按照替换正则表达式(第二个参数)的指示进行替换。在这里,它们作为参数输入\gaussler_plus:n
。
我还展示了如何激活+
。这不是一个好主意,因为+
catcode 12 的标准是 TeX 数字语法的一部分。
您可以制作一种变体,其中没有字母数字后续字符会触发其他操作。
\documentclass{article}
\usepackage[T1]{fontenc}
\ExplSyntaxOn
\NewDocumentCommand{\+}{}
{
\gaussler_plus:
}
\cs_new_protected:Nn \gaussler_plus:
{
\peek_regex_replace_once:nnF
{ ([[:alnum:]]+) } % search
{ \c{gaussler_plus_do:n}\cB\{\1\cE\} } % replace
{ Hey! } % no match
}
\cs_new:Nn \gaussler_plus_do:n
{
--Argument~was~|#1|--
}
\ExplSyntaxOff
\begin{document}
\+ % + with an empty argument
\+Hello527World % + with the argument hello527world
\+cool. This is nice. % + with the argument cool followed by ". This is nice."
\+cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
另一种变体是,只要后面跟着字母数字,就会忽略初始空格。
\documentclass{article}
\usepackage[T1]{fontenc}
\ExplSyntaxOn
\NewDocumentCommand{\+}{}
{
\gaussler_plus:
}
\cs_new_protected:Nn \gaussler_plus:
{
\peek_regex_replace_once:nnF
{ \s*([[:alnum:]]+) } % search
{ \c{gaussler_plus_do:n}\cB\{\1\cE\} } % replace
{ Hey! } % no match
}
\cs_new:Nn \gaussler_plus_do:n
{
--Argument~was~|#1|--
}
\ExplSyntaxOff
\begin{document}
\+ % + with an empty argument
\+ Hello527World % + with the argument hello527world
\+cool. This is nice. % + with the argument cool followed by ". This is nice."
\+ cool is nice. % + with the argument cool followed by a space and "is nice"
\end{document}
与之前相同的输出。