Расширяемая команда, которая добавляет строку к аргументу, если строка отсутствует.

Расширяемая команда, которая добавляет строку к аргументу, если строка отсутствует.

Я хотел бы написать расширяемую команду, которая добавляет строку S1 в начало другой строки S2, если S2 не начинается с S1, чтобы гарантировать, что моя строка всегда начинается с S1.

В настоящее время у меня есть этот код, который использует пакет xstring

\NewDocumentCommand\forcebeginwith{m m}{%
    \edef\expandedstring{#1}%
    \edef\expandedbeginning{#2}%
    \IfBeginWith{
        \expandedstring % String
    }{
        \expandedbeginning % Beginning
    }{
        \expandedstring % String
    }{
        \expandedbeginning\expandedstring % Beginning + String
    }
}

Например :

\forcebeginwith{fancycolor}{fancy} % fancycolor
\forcebeginwith{color}{fancy} % fancycolor

Вопрос:Я хотел бы преобразовать эту команду в расширяемую NewExpandableDocumentCommand, но понятия не имею, как это сделать (я хотел бы, чтобы полученный код работал в версиях latex, скажем, 5-летней давности, поэтому я хотел бы избежать супер-пупер последних команд/пакетов).

решение1

Команда \forcebeginwithопределяется с помощью \NewExpandableDocumentCommand. Тест выполняется с помощью \str_if_eq:eeTF. Команду \forcebeginwithможно использовать внутри, \edefкак в примере ниже.

введите описание изображения здесь

\documentclass[border=6pt,varwidth]{standalone}
\ExplSyntaxOn
\NewExpandableDocumentCommand { \forcebeginwith } { m m }
  {
    \str_if_eq:eeTF {#2} { \str_range:nnn {#1} { 1 } { \str_count:n {#2} } }
      {#1}
      { #2#1 }
  }
\ExplSyntaxOff
\begin{document}
\forcebeginwith{fancycolor}{fancy}\\% fancycolor
\forcebeginwith{color}{fancy}\\% fancycolor
\edef\testA{\forcebeginwith{LaTeX}{La}}\testA\\
\edef\testB{\forcebeginwith{TeX}{La}}\testB
\end{document}

решение2

Если вы используете pdflatex, то вы можете сделать это с помощью

\documentclass{article}

\newcommand{\forcebeginwith}[2]{%
  \ifnum\pdfmatch{^#2}{#1}=0 #2\fi#1%
}

\begin{document}

\forcebeginwith{fancycolor}{fancy}% fancycolor

\forcebeginwith{color}{fancy}% fancycolor

\edef\testA{\forcebeginwith{LaTeX}{La}}\testA

\edef\testB{\forcebeginwith{TeX}{La}}\testB

\end{document}

введите описание изображения здесь

Я тестировал его вплоть до TeX Live 2012.

решение3

Используя только примитивы TeX, код должен выглядеть следующим образом:

\def\forcebeginwith#1#2{\fbwA .#1\end .#2\end{#1}{#2}}
\def\fbwA #1#2\end #3#4\end #5#6{%
   \ifx #1#3%
      \ifx \end#4\end #5% S2 is included at the start of S1, print S1 only
      \else 
          \ifx \end#2\end {#5} shorter than {#6}, something wrong%
          \else \fbwB {#2\end #4\end {#5}{#6}}%
          \fi
      \fi
   \else #6#5% S2 isn't inluded at the start of S1, print S2S1.
   \fi
}
\def\fbwB #1\fi\fi#2\fi{\fi\fi\fi \fbwA #1}

% test:

\message{\forcebeginwith{fancycolor}{fancy}}

\message{\forcebeginwith{color}{fancy}}

\bye

Обратите внимание, что TeX не работает со «строками», есть только списки токенов.

решение4

Следующее решение на основе LuaLaTeX определяет пользовательский макрос с именем \forcebeginwith. Он должен работать с версиями ядра LaTeX, которым уже более десяти лет, поскольку свойства примитива \directluaна самом деле не изменились с момента его первого появления. Поскольку \directluaрасширяемый, то и \forcebeginwith. Обратите внимание, что аргументы \forcebeginwithне обязательно должны быть закодированы в ASCII; вместо этого они могут быть закодированы в UTF8.

введите описание изображения здесь

% !TEX program = lualatex
\documentclass{article} % or some other suitable document class
\directlua{% Define the Lua function 'forcebeginwith':
   function forcebeginwith ( s1 , s2 )
      if unicode.utf8.sub ( s1 , 1 , unicode.utf8.len ( s2 ) ) == s2 then
         return ( s1 )
      else
         return ( s2..s1 )
      end
   end
}
\newcommand\forcebeginwith[2]{%
   \directlua{ tex.sprint ( forcebeginwith ( "#1" , "#2" ) ) }}

\newcommand\Za{color}
\newcommand\Zb{fancy}

\begin{document}
\obeylines % just for this document
\forcebeginwith{fancycolor}{fancy}
\forcebeginwith{color}{fancy}

\smallskip
% Demonstrate that '\forcebeginwith' is expandable
\forcebeginwith{\Zb\Za}{\Zb}
\forcebeginwith{\Za}{\Zb}
\end{document}

Связанный контент