著者のリストを含むマクロ\printauthorsがあります。たとえば
John Doe, Barack Obama,...
この内容をファイルに書き込むにはどうすればいいでしょうかauthors.txt
。たとえば、コマンド
\immediate\write\myfile{\printauthors}
動作しません。何か間違っているのでしょうか、それとも別の方法を使うべきでしょうか?
答え1
\printauthors
私が提案したマクロが複数のエントリを持つ文字列をソートする場合機能を追加するのは簡単です。このバージョンでは、
\printauthors
名前だけを印刷し、
\printauthors[filename.ext]
指定されたファイルに同じデータを出力します:
\documentclass{article}
\usepackage{xparse,l3sort,pdftexcmds}
\ExplSyntaxOn
% a macro from pdftexcmds that works with all engines
\cs_set_eq:Nc \konewka_strcmp:nn { pdf@strcmp }
\NewDocumentCommand{\addauthor}{ o m m }
{
\IfNoValueTF{#1}
{
\konewka_add_author:nnn { #3 } { #2 } { #3 }
}
{
\konewka_add_author:nnn { #1 } { #2 } { #3 }
}
}
\NewDocumentCommand{\printauthors}{ o }
{
\IfNoValueTF { #1 }
{
\konewka_print_authors:
}
{
\konewka_print_authors_to_file:n { #1 }
}
}
\seq_new:N \g_konewka_authors_id_seq
\seq_new:N \l__konewka_authors_full_seq
\iow_new:N \g_konewka_write_authors_stream
\msg_new:nnn { konewka/authors } { author~exists }
{
The ~ author ~ #1 ~ already ~ exists; ~ it ~ won't ~ be ~ added ~ again
}
\cs_new_protected:Npn \konewka_add_author:nnn #1 #2 #3
{
\prop_if_exist:cTF { g_konewka_author_#1_prop }
{
\msg_warning:nnn { konewka/authors } { author~exists } { #1 }
}
{
\seq_gput_right:Nn \g_konewka_authors_id_seq { #1 }
\prop_new:c { g_konewka_author_#1_prop }
\prop_gput:cnn { g_konewka_author_#1_prop } { fname } { #2 }
\prop_gput:cnn { g_konewka_author_#1_prop } { lname } { #3 }
}
}
\cs_new_protected:Npn \konewka_print_authors:
{
\__konewka_sort_authors:
\seq_use:Nn \l__konewka_authors_full_seq { ,~ }
}
\cs_new_protected:Npn \konewka_print_authors_to_file:n #1
{
\iow_open:Nn \g_konewka_write_authors_stream { #1 }
\__konewka_sort_authors:
\iow_now:Nx \g_konewka_write_authors_stream
{
\seq_use:Nn \l__konewka_authors_full_seq { ,~ }
}
\iow_close:N \g_konewka_write_authors_stream
}
\cs_new_protected:Npn \__konewka_sort_authors:
{
\seq_gsort:Nn \g_konewka_authors_id_seq
{
\string_compare:nnnTF {##1} {>} {##2} {\sort_reversed:} {\sort_ordered:}
}
\seq_clear:N \l__konewka_authors_full_seq
\seq_map_inline:Nn \g_konewka_authors_id_seq
{
\seq_put_right:Nx \l__konewka_authors_full_seq
{
\prop_item:cn { g_konewka_author_##1_prop } { fname }
\c_space_tl
\prop_item:cn { g_konewka_author_##1_prop } { lname }
}
}
}
\prg_new_conditional:Npnn \string_compare:nnn #1 #2 #3 {TF}
{
\if_int_compare:w \konewka_strcmp:nn {#1}{#3} #2 \c_zero
\prg_return_true:
\else:
\prg_return_false:
\fi
}
\ExplSyntaxOff
\begin{document}
\addauthor{John}{Doe}
\addauthor{Harry}{Potter}
\addauthor[Uthor]{Archibald}{\"Uthor}
\addauthor{John}{Doe}
\addauthor{Bill}{Clinton}
\addauthor{Barack}{Obama}
\printauthors
\printauthors[\jobname.txt]
\end{document}
の内容\jobname.txt
は
Bill Clinton, John Doe, Barack Obama, Harry Potter, Archibald \"Uthor
注意: 私は\jobname
ファイルを上書きしないように使用しました。
答え2
これを使用している場合\printauthors
:複数のエントリを持つ文字列をソートする場合このマクロは拡張できないため、 では使用できません\immediate\write
。処理を準備と使用の 2 つのステップに分割する必要があります。「準備」ステップではソートを実行し、このマクロは拡張できません。「使用」ステップでは、準備ステップの結果のみを展開します。
私の例ではこの概念を示すことができますが、プレーン TeX を使用していないため、このコードを直接使用することはできません。
\input opmac
\def\sort{\begingroup\setprimarysorting\def\iilist{}\sortA}
\def\sortA#1#2{\ifx\relax#1\sortB\else
\expandafter\addto\expandafter\iilist\csname,#1\endcsname
\expandafter\preparesorting\csname,#1\endcsname
\expandafter\edef\csname,#1\endcsname{{\tmpb}{#2}}%
\expandafter\sortA\fi
}
\def\sortB{\def\message##1{}\dosorting
\def\act##1{\ifx##1\relax\else \seconddata##1\sortC \expandafter\act\fi}%
\gdef\tmpb{}\expandafter\act\iilist\relax
\endgroup
}
\def\sortC#1&{\global\addto\tmpb{{#1}}}
\def\sortauthors{\def\tmp{}\expandafter\sortauthorsA\authors [] {} {}; }
\def\sortauthorsA [#1] #2 #3; {%
\ifx^#1^\expandafter\sort\tmp\relax\relax \let\sortedauthors=\tmpb
\else\addto\tmp{{#1}{#2 #3}}\expandafter\sortauthorsA\fi
}
\def\printauthors{\expandafter\printauthorsB\sortedauthors\relax}
\def\printauthorsB#1{\ifx\relax#1\else #1, \expandafter\printauthorsB\fi}
\newwrite
\def\authors{[Doe] John Doe; [Potter] Harry Potter; [Clinton] Bill Clinton;
[Uthor] Archibald \"Uthor; [Obama] Barack Obama; }
\sortauthors
\immediate\write\myfile{\printauthors}
\bye
答え3
\printauthors
本当にが文字列に展開される単純なマクロである場合は、これで十分です。
\documentclass{article}
\newwrite\myfile
\newcommand{\printauthors}{John Doe, Barack Obama}
\begin{document}
\immediate\openout\myfile=authors.txt
\immediate\write\myfile{\printauthors}
\end{document}