songs 包中的 \gtabs 部分根据两个参数打印吉他和弦
\gtab{chord name}{guitar frets and strings}
第二个参数不接受 \pgfkeys 作为第二个参数
以下是说明该示例的代码:
\documentclass{article}
\RequirePackage{filecontents}% write the data file
\usepackage{pgfkeys}
\usepackage{xparse}
\usepackage{songs}
\begin{filecontents}{chords.csv}
A = { A,0022200}
A01 = { A,5:133211:143211}
B = { B,X24442}
C = { C,032010}
\end{filecontents}
% BEGIN Read Chord Definitions
\pgfkeys{/chords/.is family, chords,
.unknown/.code args={#1,#2}{ % Format is <name>,<capital>,<population>
\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname/c_name}{#1}
\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname/c_def}{#2}},
}
\newcommand\printchordnm[1]{% print the key if it is defined and ???Otherwise
\pgfkeysifdefined{/chords/#1/c_name}{\pgfkeysvalueof{/chords/#1/c_name}}{???}%
}
\newcommand\printchordef[1]{% print the key if it is defined and ???Otherwise
\pgfkeysifdefined{/chords/#1/c_def}{\pgfkeysvalueof{/chords/#1/c_def}}{???}%
}
\newcommand\AddState[1]{\expandafter\pgfkeys\expandafter{/chords, #1}}
\newread\statefile% file handler
\def\apar{\par}% \ifx\par won't work but \ifx\apar will
\newcommand\ReadStates[1]{% read file into [\pgfkeys{/state}
\openin\statefile=#1% open file for reading
\loop\unless\ifeof\statefile% loop until end of file
\read\statefile to \stateline% read line from file
\ifx\stateline\apar% test for \par
\else%
\ifx\stateline\empty\relax% skip over empty lines/comments
\else\expandafter\AddState\expandafter{\stateline}%
\fi%
\fi%
\repeat% end of file reading loop
\closein\statefile% close input file
}
\ReadStates{chords.csv}% read the file
\begin{document}
\def\hpvardef{\printchordef{A01}}
Hi \printchordnm{A01} and definition is \printchordef{A01}\par
the chord is represented as \gtab{A}{5:133211:143211}\par
Using macro as first parameter OK \gtab{\printchordnm{A01}}{5:133211:143211}\par
Now I want to use macro as second parameter \gtab{A02}{\printchordef{A01}}\par
which generates an error\par
What about local macro def hpvardef: \hpvardef\par
Let's try it \gtab{A02}{\hpvardef}
\begin{songs}{}
\end{songs}
\end{document}
答案1
根据 Elrich 提供的解释\gtab [歌曲包] 使用宏变量作为第二个参数 我修改了他的两个宏命令如下
\documentclass{article}
\RequirePackage{filecontents}% write the data file
\usepackage{pgfkeys}
\usepackage{xparse}
\usepackage{songs}
\begin{filecontents}{chords.csv}
A = { A,0022200}
A01 = { A,5:133211:143211}
B = { B,X24442}
C = { C,032010}
\end{filecontents}
% BEGIN Read US Chords Definitions
\pgfkeys{/chords/.is family, chords,
.unknown/.code args={#1,#2}{ % Format is <name>,<capital>,<population>
\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname/c_name}{#1}
\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname/c_def}{#2}},
}
\newcommand\AddChord[1]{\expandafter\pgfkeys\expandafter{/chords, #1}}
\newread\Chordfile% file handler
\def\apar{\par}% \ifx\par won't work but \ifx\apar will
\newcommand\ReadChords[1]{% read file into [\pgfkeys{/Chord}
\openin\Chordfile=#1% open file for reading
\loop\unless\ifeof\Chordfile% loop until end of file
\read\Chordfile to \Chordline% read line from file
\ifx\Chordline\apar% test for \par
\else%
\ifx\Chordline\empty\relax% skip over empty lines/comments
\else\expandafter\AddChord\expandafter{\Chordline}%
\fi%
\fi%
\repeat% end of file reading loop
\closein\Chordfile% close input file
}
\ReadChords{chords.csv}% read the file
\makeatletter
\newcommand\hpvarC[2]{\TotalExpandSecondFirst{\expandafter\gtab\@firstofone}{{#1}{#2}}}%
\newcommand\TotalExpandSecondFirst[2]{%
\begingroup
\protected@edef\mytempa{{#2}}%
\expandafter\PassFirstToSecond\mytempa{\endgroup#1}%
}%
\makeatother
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand\hptab[1]{% print the key if it is defined and ???Otherwise
\pgfkeysgetvalue{/chords/#1/c_name}\hpdeni
\pgfkeysgetvalue{/chords/#1/c_def}\hpdeff
Variant is: #1\par
Chord is: \hpdeni\par
Definition is: \hpdeff\par
Hello ``\hpvarC{\hpdeni}{\hpdeff}''
}
\begin{document}
My music book prints chords using macro definitions.\par
All I do is send the variant chord I want to hptab\par
Let's try it\par
\bigskip
Print First Variant of Chord A\par
\par
Let's call first hptab\{A01\} but take a look at hpvarC
\hptab{A01}
\end{document}