
Простой вопрос. У меня есть два макроса для отображения сокращенных дней недели, таких как MWF или TR. Я не уверен, почему первый макрос в моем MWE не работает, а второй работает. Я бы предпочел, чтобы работало что-то вроде первого макроса, потому что он короче.
\documentclass{article}
\usepackage{stix2}
\usepackage{suffix}
\WithSuffix\newcommand\textsc*[1]{%
\textsc{\MakeLowercase{#1}}%
}
\usepackage{tikz}
\newcommand{\Repeat}[2]{%\repeat already used
\foreach \n in {1,...,#1}{#2}%
}
\usepackage{xstring}
%\newcommand{\weekdays}[1]{%doesn't work
% \textsc*{%
% \IfSubStr{#1}{1}{N}{}%Sunday
% \IfSubStr{#1}{2}{M}{}%Monday
% \IfSubStr{#1}{3}{T}{}%Tuesday
% \IfSubStr{#1}{4}{W}{}%Wednesday
% \IfSubStr{#1}{5}{R}{}%Thursday
% \IfSubStr{#1}{6}{F}{}%Friday
% \IfSubStr{#1}{7}{S}{}%Saturday
% }%
%}
\newcommand{\weekdays}[1]{%
\IfSubStr{#1}{1}{\textsc*{N}}{}%Sunday
\IfSubStr{#1}{2}{\textsc*{M}}{}%Monday
\IfSubStr{#1}{3}{\textsc*{T}}{}%Tuesday
\IfSubStr{#1}{4}{\textsc*{W}}{}%Wednesday
\IfSubStr{#1}{5}{\textsc*{R}}{}%Thursday
\IfSubStr{#1}{6}{\textsc*{F}}{}%Friday
\IfSubStr{#1}{7}{\textsc*{S}}{}%Saturday
}
\begin{document}
\weekdays{246}\quad\weekdays{35}
\Repeat{7}{\par\weekdays{\n}}
\end{document}
решение1
Я не совсем понимаю, зачем все усложнять, \MakeLowercase
если можно просто использовать строчные буквы в определении.
В любом случае, xstring
команды не расширяются, и в этом ваша проблема.
Эту проблему можно решить с помощью xstring
, но есть гораздо лучший способ.
\documentclass{article}
\usepackage{stix2}
\usepackage{tikz}
\newcommand{\Repeat}[2]{%\repeat already used
\foreach \n in {1,...,#1}{#2}%
}
\ExplSyntaxOn
\NewDocumentCommand{\textsmallcaps}{m}
{
\textsc { \text_lowercase:n { #1 } }
}
\NewExpandableDocumentCommand{\weekdayinitial}{m}
{
\exp_args:Ne \str_map_function:nN { #1 } \egreg_weekday:n
}
\cs_new:Nn \egreg_weekday:n
{
\str_case:nn { #1 }
{
{1}{N}
{2}{M}
{3}{T}
{4}{W}
{5}{R}
{6}{F}
{7}{S}
}
}
\NewDocumentCommand{\weekdays}{m}
{
\textsmallcaps { \weekdayinitial { #1 } }
}
\ExplSyntaxOff
\begin{document}
\weekdays{246}\quad\weekdays{35}
\Repeat{7}{\par\weekdays{\n}}
\end{document}
Я бы не стал использовать suffix
.
решение2
С \textsc*
\MakeLowercase
внутренне делает полное расширение через \protected@edef
while \IfSubStr
не расширяется.
Вы можете использовать \unexpanded
для предотвращения расширения.
\documentclass{article}
\usepackage{stix2}
\usepackage{suffix}
\WithSuffix\newcommand\textsc*[1]{%
\textsc{\MakeLowercase{#1}}%
}
\usepackage{tikz}
\newcommand{\Repeat}[2]{%\repeat already used
\foreach \n in {1,...,#1}{#2}%
}
\usepackage{xstring}
\DeclareRobustCommand{\weekdays}[1]{%
\textsc*{%
\unexpanded{%
\IfSubStr{#1}{1}{N}{}%Sunday
\IfSubStr{#1}{2}{M}{}%Monday
\IfSubStr{#1}{3}{T}{}%Tuesday
\IfSubStr{#1}{4}{W}{}%Wednesday
\IfSubStr{#1}{5}{R}{}%Thursday
\IfSubStr{#1}{6}{F}{}%Friday
\IfSubStr{#1}{7}{S}{}%Saturday
}%
}%
}
\begin{document}
\weekdays{246}\quad\weekdays{35}
\Repeat{7}{\par\weekdays{\n}}
\end{document}
Таким образом, расширение аргумента откладывается до тех пор, пока не будет выполнено преобразование в нижний регистр. Когда преобразование в нижний регистр завершено, \IfSubStr
выполняются -директивы. \IfSubStr
также полностью расширяет аргумент.
Но при преобразовании в нижний регистр аргумента, расширение которого предотвращается во время преобразования в нижний регистр, передача \csname..\endcsname
-выражений, расширение которых на каком-то этапе дает последовательности цифр, может быть проблемой, поскольку преобразование в нижний регистр может изменить то, что находится между \csname
и , \endcsname
и, таким образом, может изменить то, какой токен управляющей последовательности формируется из \csname...\endcsname
-выражения.
Поэтомурешение эгрегапредпочитать.
В качестве альтернативы вы можете использовать только \noexpand
для предотвращения расширения токена \IfSubStr
.
\documentclass{article}
\usepackage{stix2}
\usepackage{suffix}
\WithSuffix\newcommand\textsc*[1]{%
\textsc{\MakeLowercase{#1}}%
}
\usepackage{tikz}
\newcommand{\Repeat}[2]{%\repeat already used
\foreach \n in {1,...,#1}{#2}%
}
\usepackage{xstring}
\DeclareRobustCommand{\weekdays}[1]{%
\textsc*{%
\noexpand\IfSubStr{#1}{1}{N}{}%Sunday
\noexpand\IfSubStr{#1}{2}{M}{}%Monday
\noexpand\IfSubStr{#1}{3}{T}{}%Tuesday
\noexpand\IfSubStr{#1}{4}{W}{}%Wednesday
\noexpand\IfSubStr{#1}{5}{R}{}%Thursday
\noexpand\IfSubStr{#1}{6}{F}{}%Friday
\noexpand\IfSubStr{#1}{7}{S}{}%Saturday
}%
}
\begin{document}
\weekdays{246}\quad\weekdays{35}
\Repeat{7}{\par\weekdays{\n}}
\par
\def\foobar{1357}
\weekdays{\foobar}
\end{document}
Тем не менее, не предотвращается преобразование аргумента в нижний регистр, что при использовании индивидуальных \lccode
настроек может привести к неожиданным результатам.