これは非常に基本的な問題かもしれない(この質問) ですが、その方法がわかりません。1\mycmd{sometext}
つの引数の最初の文字に応じて文字列を生成するマクロが必要です。この結果の文字列は、後で で大文字にする必要があります\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}
私はpfgfor
ループ用のパッケージを使用してこれを実現し、その中で最初の文字をパッケージ\IfBeginWith
からのものと比較しようとしましたxstring
。しかし、これはどうやら展開できないコマンドにつながるようで、\makefirstuc
失敗します。この機能を使用して拡張可能なコマンドを実現するにはどうすればよいでしょうか?
これまでに、次の展開不可能なコマンドを作成しました。
\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%
}
答え1
これは非常に簡単に使用できますexpl3
(いくつかのアプローチが考えられます):
\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}
拡張がないので\makefirstuc
、バージョンを使用する必要がありますe
。拡張可能な (Unicode 対応) を使用して、この問題を回避することをお勧めします\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}
ケースの数によっては、最初に入力をすべて小文字にすることが望ましい場合があります。
\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
}
答え2
ここでのアプローチはexpl3
\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}
答え3
これは LuaLaTeX ベースのソリューションです。 と という 2 つの完全に展開可能な「ラッパー」マクロを定義し\mycmd
、それらの引数をと\mkfirstuc
という Lua 関数に渡します。Lua 関数は、それぞれ文字列の先頭に「an」または「a」を付ける作業と、文字列の最初の文字を大文字にする作業を実行します。mycmd
mkfirstuc
% !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}
答え4
これが意味することでしょうか? の最も効果的な使い方ではないことはexpl3
わかっています ;-)
\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}