如何根据字符串结尾设置切换

如何根据字符串结尾设置切换

编译

\documentclass{article}
\usepackage{etoolbox,xstring}

\newcommand{\strendswithfoo}{\IfEndWith{bar-foo}{foo}{true}{false}}

\newtoggle{strendswithfoo}
\settoggle{strendswithfoo}{\strendswithfoo}

\begin{document}

command \textbackslash strendswithfoo = \strendswithfoo

toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}

\end{document}

导致以下错误:

./test.tex:7: Missing \endcsname inserted.
<to be read again> 
                   \let 
l.7 \settoggle{strendswithfoo}{\strendswithfoo}

The control sequence marked <to be read again> should
not appear between \csname and \endcsname.


./test.tex:7: Argument of \reserved@a has an extra }.
<inserted text> 
                \par 
l.7 \settoggle{strendswithfoo}{\strendswithfoo}

I've run across a `}' that doesn't seem to match anything.
For example, `\def\a#1{...}' and `\a}' would produce
this error. If you simply proceed now, the `\par' that
I've just inserted will cause me to report a runaway
argument that might be the root of the problem. But if
your `}' was spurious, just type `2' and it will go away.

Runaway argument?
{\@firstoftwo {\let \@xs@assign \@xs@expand@and@detokenize \@xs@IfEndWith@@ \ETC.
./test.tex:7: Paragraph ended before \reserved@a was complete.
<to be read again> 
                   \par 
l.7 \settoggle{strendswithfoo}{\strendswithfoo}

I suspect you've forgotten a `}', causing me to apply this
control sequence to too much text. How can we recover?
My plan is to forget the whole thing and hope for the best.

./test.tex:7: Package etoolbox Error: Invalid boolean value '\let \reserved@d =*\def \par .
<recently read>  

l.7 \settoggle{strendswithfoo}{\strendswithfoo}

Valid boolean values are 'true' and 'false'.

输出文档包含:

command \strendswithfoo = true
toggle strendswithfoo = false

我希望切换strendswithfoo为真。如果有更好的解决方案,我很乐意放弃 xstring。

答案1

另一种方法是使用listofitems,其结果是可扩展的。也就是说,实际\readlist是不可扩展的,但它生成的数据数组是可扩展的。

在此实现中,我搜索测试字符串中所有出现的“foo”,并将其用作列表分隔符。不是“foo” 存储在\foosep数组、、\foosep[1]等中\foosep[2],其中索引1是最左边“foo”左边的文本,索引2是第 1 个和第二个“foo”之间的文本,等等。

负索引(例如)[-1]仅从最右边的“foo”开始向左计数。如果字符串以“foo”结尾,则\foosep[-1]表示最右边“foo”右侧文本的扩展将为空,因此我测试其是否为空以确定是否将切换设置为 true 或 false。

\documentclass{article}
\usepackage{etoolbox,listofitems}

\newtoggle{strendswithfoo}
\def\toggletmp{\settoggle{strendswithfoo}}

\newcommand{\teststrendswithfoo}[1]{%
  \setsepchar{foo}%
  \readlist\foosep{#1}%
  \edef\strendswithfoo{\if\relax\foosep[-1]\relax{true}\else{false}\fi}%
  \expandafter\toggletmp\strendswithfoo
}

\begin{document}
\teststrendswithfoo{bar-foo}
toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}

\teststrendswithfoo{foo-bar}
toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}
\end{document}

在此处输入图片描述

答案2

一种解决方案是将参数设为\IfEndWith \toggletrue\togglefalse。我发现这相当不令人满意,而且有点像意大利面条式的代码,虽然我喜欢,但它很短。

\documentclass{article}
\usepackage{etoolbox,xstring}

\newtoggle{strendswithfoo}

\IfEndWith{bar-foo}{foo}{\toggletrue}{\togglefalse}{strendswithfoo}

\begin{document}

toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}

\end{document}

相关内容