Erweiterbares Makro mit Schleifen und erweiterten String-Funktionen?

Erweiterbares Makro mit Schleifen und erweiterten String-Funktionen?

Dies könnte ein sehr grundlegendes Problem sein (als Folge vondiese Frage), aber ich weiß nicht, wie ich das machen soll: Ich brauche ein Makro \mycmd{sometext}, das einen String abhängig vom ersten Buchstaben seines Arguments erzeugt. Dieser resultierende String sollte anschließend mit groß geschrieben werden \makefirstuc.

\documentclass{article}
\usepackage{xparse}  % used in example below
\usepackage{pgffor}  % used in example below
\usepackage{xstring} % used in example below

\newcommand{\mycmd}[1]{
  % here, I define a list of letters {a,e,i,o,u,A,E,I,O,U}
  % that will lead to the output "an " in case
  % the argument string starts by one of them.
  % Otherwise the output shall be "a ".
}

\begin{document}
  \mycmd{somestring}                % should print "a "
  \makefirstuc{\mycmd{sometext}}    % should print "A "
  \mycmd{otherstring}               % should print "an "
  \makefirstuc{\mycmd{otherstring}} % should print "An "
\end{document}

Ich habe versucht, dies zu realisieren, indem ich das pfgforPaket für die Schleife verwende und dabei das erste Zeichen mit dem \IfBeginWithaus dem xstringPaket vergleiche. Dies führt jedoch anscheinend zu nicht erweiterbaren Befehlen, sodass dies \makefirstucfehlschlägt.Wie kann man einen erweiterbaren Befehl mit dieser Funktionalität erreichen?

Bisher habe ich den folgenden nicht erweiterbaren Befehl erstellt:

\NewDocumentCommand{\mycmd}{m}{%
  \def\undefart{a\space}%
  \foreach \c in {a,e,i,o,u,A,E,I,O,U}{%
    \IfBeginWith{#1}{\c}{\global\def\undefart{an\space}}{}%
  }%
  \undefart%
}

Antwort1

Dies ist ganz einfach mit expl3(es gibt mehrere mögliche Ansätze):

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand \mycmd { m }
  {
    \__mycmd_loop:nN {#1} aeiouAEIOU \q_recursion_tail \q_recursion_stop
  }
\cs_new:Npn \__mycmd_loop:nN #1#2
  {
    \quark_if_recursion_tail_stop_do:nn {#2} { a }
    \tl_if_head_eq_charcode:nNT {#1} #2
      {
        \use_i_delimit_by_q_recursion_stop:nw { an }
      }
    \__mycmd_loop:nN {#1}
  }
\ExplSyntaxOff
\usepackage{mfirstuc}
\begin{document}

  \mycmd{somestring}                % should print "a "
  \emakefirstuc{\mycmd{sometext}}    % should print "A "
  \mycmd{otherstring}               % should print "an "
  \emakefirstuc{\mycmd{otherstring}} % should print "An "
\end{document}

Da \makefirstuckeine Erweiterung vorhanden ist, musste ich die eVersion verwenden. Ich würde das wahrscheinlich lieber umgehen, indem ich die erweiterbare (und Unicode-fähige) Version verwende \text_titlecase:n:

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand \mycmd { m }
  {
    \__mycmd_loop:nN {#1} aeiouAEIOU \q_recursion_tail \q_recursion_stop
  }
\cs_new:Npn \__mycmd_loop:nN #1#2
  {
    \quark_if_recursion_tail_stop_do:nn {#2} { a }
    \tl_if_head_eq_charcode:nNT {#1} #2
      {
        \use_i_delimit_by_q_recursion_stop:nw { an }
      }
    \__mycmd_loop:nN {#1}
  }
\cs_new_eq:NN \Mymakefirstuc \text_uppercase:n
\ExplSyntaxOff
\begin{document}

  \mycmd{somestring}                % should print "a "
  \Mymakefirstuc{\mycmd{sometext}}    % should print "A "
  \mycmd{otherstring}               % should print "an "
  \Mymakefirstuc{\mycmd{otherstring}} % should print "An "
\end{document}

Abhängig von der Anzahl der Fälle kann es wünschenswert sein, alle Eingaben zunächst in Kleinbuchstaben zu schreiben.

\DeclareExpandableDocumentCommand \mycmd { m }
  {
    \exp_args:Nf \__mycmd:n { \text_lowercase:n {#1} }
  }
\cs_new:Npn \__mycmd:n #1
  {
    \__mycmd_loop:nN {#1} aeiou \q_recursion_tail \q_recursion_stop
  }

Antwort2

Hier ist ein Ansatz mitexpl3

\documentclass{article}
\usepackage{xparse,glossaries}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\indef}{m}
 {
  \str_case_x:nnF { \tl_head:f { \tl_lower_case:n { #1 } } }
   {
    {a}{an}
    {e}{an}
    {i}{an}
    {o}{an}
    {u}{an}
  }
  {a}~#1
 }
\ExplSyntaxOff

\begin{document}

\indef{abc} --- \indef{cde} --- \indef{ABC} --- \indef{CDE}

\emakefirstuc{\indef{abc}} --- \emakefirstuc{\indef{cde}} ---
\emakefirstuc{\indef{ABC}} --- \emakefirstuc{\indef{CDE}}

\end{document}

Bildbeschreibung hier eingeben

Antwort3

Hier ist eine LuaLaTeX-basierte Lösung. Sie definiert zwei vollständig erweiterbare „Wrapper“-Makros mit den Namen \mycmdund \mkfirstuc, die ihre Argumente an Lua-Funktionen mit den Namen mycmdund übergeben mkfirstuc. Die Lua-Funktionen führen die eigentliche Arbeit aus, indem sie einem String jeweils „an“ oder „a“ voranstellen und das erste Zeichen im String groß schreiben.

Bildbeschreibung hier eingeben

% !TEX TS-program = lualatex
\documentclass{article}

%% Lua-side code
\usepackage{luacode}
\begin{luacode}
function mycmd ( s )
  if string.match ( string.sub(s,1,1) , "[aeiouAEIOU]" ) then
    return tex.sprint ("an " .. s)
  else
    return tex.sprint ("a " .. s)
  end
end
function mkfirstuc ( s )
  return tex.sprint ( string.upper(string.sub(s,1,1)) .. string.sub(s,2) )
end
\end{luacode}

%% TeX-side code
\newcommand\mycmd[1]{\directlua{mycmd(\luastring{#1})}}
\newcommand\mkfirstuc[1]{\directlua{mkfirstuc(\luastring{#1})}}

\begin{document}
\mycmd{abc}, \mycmd{def}, \mycmd{ABC}, \mycmd{DEF}.

\mkfirstuc{\mycmd{abc}}, \mkfirstuc{\mycmd{def}}, 
\mkfirstuc{\mycmd{ABC}}, \mkfirstuc{\mycmd{DEF}}. 
\end{document}

Antwort4

Ist das gemeint? expl3Ich weiß, das ist nicht die effektivste Verwendung von ;-)

\documentclass{article}
\usepackage{xparse}  % used in example below
\usepackage{pgffor}  % used in example below
\usepackage{xstring} % used in example below

\ExplSyntaxOn

\clist_set:Nn \l_tinytot_lowercaseletters_clist {a,e,i,o,u}
\clist_set:Nn \l_tinytot_letters_clist {a,e,i,o,u,A,E,I,O,U}

\NewDocumentCommand{\makefirstuc}{m}{%
  \tl_to_uppercase:n {#1}
}

\NewDocumentCommand{\checkstart}{m}{%
  \tl_set:Nx \l_tmpa_tl {#1}
  \tl_trim_spaces:N \l_tmpa_tl
  \tl_set:Nx \l_tmpb_tl { \tl_item:Nn \l_tmpa_tl {1}}
  \clist_if_in:NVTF \l_tinytot_letters_clist {\l_tmpb_tl }{%
    \clist_if_in:NVTF \l_tinytot_lowercaseletters_clist {\l_tmpb_tl}
    {
      an
    }{
      An
    }
  }{
    \clist_if_in:NVTF \l_tinytot_lowercaseletters_clist {\l_tmpb_tl}
    {
      a
    }{
      A
    }
  }
}  
\ExplSyntaxOff

\newcommand{\mycmd}[1]{%
  \checkstart{#1}
  % here, I define a list of letters {a,e,i,o,u,A,E,I,O,U}
  % that will lead to the output "an " in case
  % the argument string starts by one of them.
  % Otherwise the output shall be "a ".
}

\begin{document}
\mycmd{somestring}                % should print "a "
\makefirstuc{\mycmd{sometext}}    % should print "A "
\mycmd{otherstring}               % should print "an "
\makefirstuc{\mycmd{otherstring}} % should print "An "
\end{document}

verwandte Informationen