是否有一个包或宏可以让我轻松排版音乐音调,如下所示:
? 我确实希望八度音程有下标。假设
$\mathrm{E}\flat_3$
当调用以下宏时,我该如何编写一个产生此输出的宏:
\note{Eb3}
喜欢:
\newcommand{\note}[1]{???}
我必须将字符串拆开,第一个字符放入\mathrm
,然后是可选的第二个字符#
或b
,后面跟着一个数字。
答案1
唯一的怪癖是您必须使用括号[]
而不是大括号{}
来括起参数。
\documentclass{article}
\def\note[#1#2#3]{#1\if b#2$\flat_#3$\else\if#2##$\sharp_#3$\else$_#2$\fi\fi}
\begin{document}
\note[Eb3]
\note[A2]
\note[F#4]
\end{document}
如果您更喜欢使用大括号而不是方括号,那么可以进行以下修改。它将\note
上述代码中的重命名为\xnote
并创建一个新命令\note
来执行参数转换。
\documentclass{article}
\newcommand\note[1]{\xnote[#1]}
\def\xnote[#1#2#3]{#1\if b#2$\flat_#3$\else\if#2##$\sharp_#3$\else$_#2$\fi\fi}
\begin{document}
\note{Eb3}
\note{A2}
\note{F#4}
\end{document}
由于 egreg 的回答似乎超出了 OP 的要求,在缺少参数 2、参数 3 或参数 2 和 3 时提供合理的行为,因此我觉得有责任做同样的事情(使用 Qrrbrrbr...brbrbrl 的建议进行编辑,将下标定义括在括号中,这将有助于显示两位数的八度数字,如输出的最后一行所示):
\documentclass{article}
\newcommand\note[1]{\xnote#1\relax\relax\relax}
\def\xnote#1#2#3\relax{#1\if#2\relax\else\if b#2$\flat\if#3\relax%
\else_{#3}\fi$\else\if###2$\sharp\if#3\relax\else_{#3}\fi$\else$_{#2}$\fi\fi\fi}
\begin{document}
\note{Eb3}
\note{A2}
\note{C#}
\note{A}
\note{Eb}
\note{F#4}
\note{F{14}}
\note{F#{14}}
\end{document}
答案2
需要对该论点进行一些缓慢的扫描:
\documentclass{article}
\usepackage{fixltx2e} % for \textsubscript
\makeatletter
\newcommand{\note}[1]{\emit@note#1\@nil}
\def\emit@note#1#2\@nil{%
\textup{#1}%
\if\relax\detokenize{#2}\relax
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\emit@@note#2\@nil}%
}
\def\emit@@note{\@ifnextchar##{\emit@sharp}{\emit@@@note}}
\def\emit@sharp#1{$\sharp$\emit@@@note}
\def\emit@@@note{\@ifnextchar b{$\flat$\emit@@@@note}{\emit@@@@note{}}}
\def\emit@@@@note#1#2\@nil{\textsubscript{#2}}
\makeatother
\begin{document}
\note{A}
\note{A#}
\note{Ab}
\note{A2}
\note{A#2}
\note{Ab2}
\end{document}
根据请求,这里有一个可能的 LaTeX3 实现:
\documentclass{article}
\usepackage{fixltx2e} % for \textsubscript
\usepackage{xparse}
\ExplSyntaxOn
% user level command
\NewDocumentCommand{\note}{m}
{
\emit_note:n { #1 }
}
% a variable
\tl_new:N \l_emit_specs_tl
% internal main function
\cs_new_protected:Npn \emit_note:n #1
{% Get the first token
\emit_textup:x { \tl_head:n { #1 } }
% Get the rest and pass control to \emit_do_specs:n
\tl_set:Nx \l_emit_specs_tl { \tl_tail:n { #1 } }
\tl_if_empty:NF \l_emit_specs_tl
{
\emit_do_specs:o { \l_emit_specs_tl \q_stop }
}
}
% We can't use \textup{ \tl_head:n { #1 } } because of possible #
\cs_new_protected:Npn \emit_textup:n #1
{
\textup { #1 }
}
\cs_generate_variant:Nn \emit_textup:n { x }
% Check if the first token is # or b
% and take appropriate actions
% Then hand the remainder to \emit_range:w
\cs_new_protected:Npn \emit_do_specs:n #1
{
\peek_charcode_remove:NTF ##
{ $\sharp$ \emit_range:w }
{
\peek_charcode_remove:NTF b
{ $\flat$ \emit_range:w }
{ \emit_range:w }
}
#1
}
\cs_generate_variant:Nn \emit_do_specs:n { o }
\cs_new_protected:Npn \emit_range:w #1 \q_stop
{
\tl_if_empty:nF { #1 } { \textsubscript{#1} }
}
\ExplSyntaxOff
\begin{document}
\note{A}
\note{A#}
\note{Ab}
\note{A2}
\note{A#2}
\note{Ab2}
\end{document}
一种利用其拆分功能的新实现l3regex
。可以针对格式错误的输入实施某种错误检查。
临时记号取自 MusixTeX 字体,采用的方法与clemens 的回答
\documentclass{article}
\usepackage{xparse,l3regex}
\DeclareFontFamily{U}{musix}{}
\DeclareFontShape{U}{musix}{m}{n}{
<-12> s * [1.5] musix11
<12-15> s * [1.5] musix13
<15-18> s * [1.5] musix16
<18-23> s * [1.5] musix20
<23-> s * [1.5] musix29
}{}
\NewDocumentCommand{\musixsym}{m}{%
\raisebox{.6ex}{\normalfont\usefont{U}{musix}{m}{n}\symbol{#1}}%
}
\newcommand\mflat{\musixsym{'62}}
\newcommand\mdoubleflat{\musixsym{'63}}
\newcommand\msharp{\musixsym{'64}}
\newcommand\mdoublesharp{\musixsym{'65}}
\newcommand\mnatural{\musixsym{'66}}
\ExplSyntaxOn
\NewDocumentCommand{\note}{m}
{
\tl_set:Nn \l_emit_note_tl { #1 }
\regex_replace_all:nnN { \# } { S } \l_emit_note_tl
\regex_split:nVN { ([A-G]+) ([Sbn]*) (\d*) } \l_emit_note_tl \l_emit_note_seq
\seq_item:Nn \l_emit_note_seq { 2 }
\str_case_x:nn { \seq_item:Nn \l_emit_note_seq { 3 } }
{
{S}{\msharp}
{SS}{\,\mdoublesharp}
{b}{\mflat}
{bb}{\mdoubleflat}
{n}{\mnatural}
}
\textsubscript{\seq_item:Nn \l_emit_note_seq { 4 }}
}
\cs_generate_variant:Nn \regex_split:nnN { nVN }
\tl_new:N \l_emit_note_tl
\seq_new:N \l_emit_note_seq
\ExplSyntaxOff
\begin{document}
\note{A}
\note{B#}
\note{C##}
\note{Db}
\note{Ebb}
\note{F2}
\note{G#2}
\note{A##2}
\note{Bb2}
\note{Cbb2}
\note{Dn1}
\end{document}
请注意,自 2015/01/01 版本起,LaTeX\textsubscript
已被纳入内核。