我定义了一个新命令,该命令在我想要的任何内容周围显示一个框,并希望它根据其参数是纯文本还是其他命令(例如\includegraphics
)采取不同的行动。
为此,我认为检查参数的第一个字符是否为 会很简单\
。我尝试过使用包\StrChar
中的xstring
,但它似乎对此不太满意。
\newcommand{\extractFirst}[1]{
\StrChar{#1}{1}[\FirstChar]
The first character is: '\FirstChar'\par
}
这能做到吗?
答案1
在这里,我利用了tokcycle
包中的一个内部宏。
宏\count@stringtoks
用于计算组成参数\string
的标记。我们依赖这样一个事实:\string
字符标记的 长度为一个字节,而\string
任何宏标记的 长度至少为两个字节。使用此标准,我们可以区分宏和字符。
最重要的是,\count@stringtoks
完全可扩展。
\documentclass{article}
\usepackage{tokcycle}
\makeatletter
\newcommand\extractFirst[1]{\testfirst#1\relax\relax}
\def\testfirst#1#2\relax{\tctestifnum{\count@stringtoks{#1}>1}{Macro}{Character}}
\makeatother
\begin{document}
\extractFirst{abc}
\extractFirst{a}
\extractFirst{\abc ab\c}
\extractFirst{\a ab\c}
\end{document}
如果您想避免加载包,重新创建\count@stringtoks
宏所需的提取代码如下:
\documentclass{article}
\makeatletter
\newcommand\extractFirst[1]{\testfirst#1\relax\relax}
\def\testfirst#1#2\relax{\tctestifnum{\count@stringtoks{#1}>1}{Macro}{Character}}
% FROM TOKCYCLE:
\long\def\count@stringtoks#1{\tc@earg\count@toks{\string#1}}
\long\def\count@toks#1{\the\numexpr-1\count@@toks#1.\tc@endcnt}
\long\def\count@@toks#1#2\tc@endcnt{+1\tc@ifempty{#2}{\relax}{\count@@toks#2\tc@endcnt}}
\def\tc@ifempty#1{\tc@testxifx{\expandafter\relax\detokenize{#1}\relax}}
\long\def\tc@earg#1#2{\expandafter#1\expandafter{#2}}
\long\def\tctestifnum#1{\tctestifcon{\ifnum#1\relax}}
\long\def\tctestifcon#1{#1\expandafter\tc@exfirst\else\expandafter\tc@exsecond\fi}
\long\def\tc@testxifx{\tc@earg\tctestifx}
\long\def\tctestifx#1{\tctestifcon{\ifx#1}}
\long\def\tc@exfirst#1#2{#1}
\long\def\tc@exsecond#1#2{#2}
\makeatother
\begin{document}
\extractFirst{abc}
\extractFirst{a}
\extractFirst{\abc ab\c}
\extractFirst{\a ab\c}
\end{document}
答案2
您可以使用函数检查输入expl3
。
\documentclass{article}
\usepackage{xparse,xcolor}
\NewDocumentCommand{\mycommandmacro}{m}{%
\fcolorbox{red}{white}{#1}%
}
\NewDocumentCommand{\mycommandnomacro}{m}{%
\fcolorbox{blue}{black!10}{#1}%
}
\ExplSyntaxOn
\NewDocumentCommand{\mycommand}{m}
{
\tl_if_blank:nF { #1 }
{
\peek_catcode:NTF \c_group_begin_token
{% argument starts with brace
\ballu_mycommand_nomacro:w
}
{
\ballu_mycommand_test:Nw
}
#1 \q_stop
}
}
\cs_new:Npn \ballu_mycommand_nomacro:w #1 \q_stop
{
\mycommandnomacro{#1}
}
\cs_new:Npn \ballu_mycommand_test:Nw #1 #2 \q_stop
{
\token_if_cs:NTF #1
{
\mycommandmacro{#1#2}
}
{
\mycommandnomacro{#1#2}
}
}
\ExplSyntaxOff
\begin{document}
\mycommand{abc}
\mycommand{{ab}c}
\mycommand{\mbox{abc}}
\mycommand{{\mbox{abc}}def}
X\mycommand{}X
X\mycommand{ }X
\end{document}
空白(空或仅有空格)参数什么也不做;这可能会被改变,这里它用于防御性编程。
初始支撑会触发“nomacro”变体。