
Ich möchte einen erweiterbaren Befehl schreiben, der eine Zeichenfolge S1 am Anfang einer anderen Zeichenfolge S2 hinzufügt, wenn S2 nicht mit S1 beginnt, um sicherzustellen, dass meine Zeichenfolge immer mit S1 beginnt.
Ich habe derzeit diesen Code, der auf dem xstring-Paket basiert
\NewDocumentCommand\forcebeginwith{m m}{%
\edef\expandedstring{#1}%
\edef\expandedbeginning{#2}%
\IfBeginWith{
\expandedstring % String
}{
\expandedbeginning % Beginning
}{
\expandedstring % String
}{
\expandedbeginning\expandedstring % Beginning + String
}
}
Zum Beispiel :
\forcebeginwith{fancycolor}{fancy} % fancycolor
\forcebeginwith{color}{fancy} % fancycolor
Frage:Ich möchte diesen Befehl in einen erweiterbaren Befehl umwandeln NewExpandableDocumentCommand
, habe aber keine Ahnung, wie das geht (ich möchte, dass der resultierende Code mit Latex-Versionen funktioniert, die beispielsweise 5 Jahre alt sind, daher möchte ich superaktuelle Befehle/Pakete vermeiden).
Antwort1
Der Befehl \forcebeginwith
wird mit definiert \NewExpandableDocumentCommand
. Der Test wird mit durchgeführt \str_if_eq:eeTF
. Der Befehl \forcebeginwith
kann \edef
wie im folgenden Beispiel verwendet werden.
\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}
Antwort2
Wenn Sie verwenden pdflatex
, können Sie dies mit tun
\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}
Ich habe es bis TeX Live 2012 getestet.
Antwort3
Wenn nur TeX-Grundelemente verwendet werden, sollte der Code folgendermaßen aussehen:
\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
Beachten Sie, dass TeX nicht mit „Strings“ arbeitet, es gibt nur Token-Listen.
Antwort4
Die folgende, auf LuaLaTeX basierende Lösung definiert ein Benutzermakro namens \forcebeginwith
. Es sollte mit Versionen des LaTeX-Kernels funktionieren, die deutlich älter als ein Jahrzehnt sind, da sich die Eigenschaften des \directlua
Primitivs seit seinem ersten Erscheinen nicht wirklich geändert haben. Da \directlua
erweiterbar ist, ist auch erweiterbar \forcebeginwith
. Beachten Sie, dass die Argumente von \forcebeginwith
nicht ASCII-codiert sein müssen; sie können stattdessen UTF8-codiert sein.
% !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}