我希望在 LATeX 中创建一个新环境,用于排版一首诗(非英语)的某些诗句。我希望每节诗句的文本都占据最长诗句的整个宽度。为了说明这一点,请考虑以下最小工作示例:
\documentclass{article}
\begin{document}
\newlength{\versewd}
\settowidth{\versewd}{adipiscing vitae, felis. Curabitur dictum gravida mauris.}
\begin{tabular}{p{\versewd}l}
\makebox[\versewd][s]{Lorem ipsum dolor sit amet} & \\
\makebox[\versewd][s]{consectetuer adipiscing elit} & (1) \\
\makebox[\versewd][s]{Ut purus elit, vestibulum ut, placerat ac} & \\
\makebox[\versewd][s]{adipiscing vitae, felis. Curabitur dictum gravida mauris.} & (2) \\
\end{tabular}
\end{document}
这正是我想要的,但我想创建一个可以做到这一点的环境。我希望代码看起来更简单,类似于:
\documentclass{article}
\begin{document}
\begin{verse}
\myitem{Lorem ipsum dolor sit amet}{consectetuer adipiscing elit}
\myitem{Ut purus elit, vestibulum ut, placerat ac}{adipiscing vitae, felis. Curabitur dictum gravida mauris.}
\end{verse}
\end{document}
我将非常感激任何关于这个方向的指点。我最初搜索了创建新环境,但没有找到任何足够有助于解决这个问题的方法。谢谢!
答案1
以下解决方案的作用是
- 吸收整首诗;
- 测量每节诗句的自然宽度,跟踪最大宽度;
- 将每节诗句打印在一个展开框中。
输入中,诗节之间用空行分隔,诗句之间用 分隔\\
。每节末尾添加数字。
\documentclass{article}
\usepackage{xparse,environ}
\ExplSyntaxOn
\NewEnviron{spreadverse}
{
\setlength{\parindent}{0pt} % no indent
\hbadness=\c_ten_thousand % don't show underfull box messages
\raman_spreadverse:V \BODY
}
%% variables
\dim_new:N \l_raman_spreadverse_width_dim
\int_new:N \l_raman_spreadverse_stanza_int
\seq_new:N \l_raman_spreadverse_stanzas_seq
\seq_new:N \l_raman_spreadverse_verses_seq
\seq_new:N \l_raman_spreadverse_printverses_seq
\box_new:N \l_raman_spreadverse_verse_box
\cs_new_protected:Nn \raman_spreadverse:n
{
\dim_zero:N \l_raman_spreadverse_width_dim
\int_zero:N \l_raman_spreadverse_stanza_int
\seq_set_split:Nnn \l_raman_spreadverse_stanzas_seq { \par } { #1 }
% measure the verses
\seq_map_inline:Nn \l_raman_spreadverse_stanzas_seq
{
\raman_spreadverse_measure:n { ##1 }
}
% typeset the verses
\seq_map_inline:Nn \l_raman_spreadverse_stanzas_seq
{
\raman_spreadverse_print:n { ##1 }
\int_incr:N \l_raman_spreadverse_stanza_int
\nolinebreak
\quad
( \int_to_arabic:n {\l_raman_spreadverse_stanza_int} )
\par
}
}
\cs_generate_variant:Nn \raman_spreadverse:n { V }
\cs_new_protected:Nn \raman_spreadverse_measure:n
{
\seq_set_split:Nnn \l_raman_spreadverse_verses_seq { \\ } { #1 }
\seq_map_inline:Nn \l_raman_spreadverse_verses_seq
{
\hbox_set:Nn \l_raman_spreadverse_verse_box { ##1 }
\dim_set:Nn \l_raman_spreadverse_width_dim
{
\dim_max:nn
{ \l_raman_spreadverse_width_dim }
{ \box_wd:N \l_raman_spreadverse_verse_box }
}
}
}
\cs_new_protected:Nn \raman_spreadverse_print:n
{
\seq_clear:N \l_raman_spreadverse_printverses_seq
\seq_set_split:Nnn \l_raman_spreadverse_verses_seq { \\ } { #1 }
\seq_map_inline:Nn \l_raman_spreadverse_verses_seq
{
\seq_put_right:Nn \l_raman_spreadverse_printverses_seq
{
\makebox[\l_raman_spreadverse_width_dim][s]{##1}
}
}
\seq_use:Nn \l_raman_spreadverse_printverses_seq { \\* }
}
\ExplSyntaxOff
\begin{document}
\begin{spreadverse}
Lorem ipsum dolor sit amet \\
consectetuer adipiscing elit
Ut purus elit, vestibulum ut, placerat ac \\
adipiscing vitae, felis. Curabitur dictum gravida mauris.
\end{spreadverse}
\end{document}
这是一个允许使用可选参数的版本,用于使用包含诗句的不同环境(默认center
)。
\documentclass{article}
\usepackage{xparse,environ}
\usepackage{lipsum,showframe} % just for the example
\ExplSyntaxOn
\NewEnviron{spreadverse}[1][center]
{
\begin{#1}
\hbadness=\c_ten_thousand
\raman_spreadverse:V \BODY
\end{#1}
}
%% variables
\dim_new:N \l_raman_spreadverse_width_dim
\int_new:N \l_raman_spreadverse_stanza_int
\seq_new:N \l_raman_spreadverse_stanzas_seq
\seq_new:N \l_raman_spreadverse_verses_seq
\seq_new:N \l_raman_spreadverse_printverses_seq
\box_new:N \l_raman_spreadverse_verse_box
\cs_new_protected:Nn \raman_spreadverse:n
{
\dim_zero:N \l_raman_spreadverse_width_dim
\int_zero:N \l_raman_spreadverse_stanza_int
\seq_set_split:Nnn \l_raman_spreadverse_stanzas_seq { \par } { #1 }
% measure the verses
\seq_map_inline:Nn \l_raman_spreadverse_stanzas_seq
{
\raman_spreadverse_measure:n { ##1 }
}
% typeset the verses
\seq_map_inline:Nn \l_raman_spreadverse_stanzas_seq
{
\raman_spreadverse_print:n { ##1 }
\int_incr:N \l_raman_spreadverse_stanza_int
\nolinebreak
\makebox[0pt][l]
{
\quad
( \int_to_arabic:n {\l_raman_spreadverse_stanza_int} )
}
\par
}
}
\cs_generate_variant:Nn \raman_spreadverse:n { V }
\cs_new_protected:Nn \raman_spreadverse_measure:n
{
\seq_set_split:Nnn \l_raman_spreadverse_verses_seq { \\ } { #1 }
\seq_map_inline:Nn \l_raman_spreadverse_verses_seq
{
\hbox_set:Nn \l_raman_spreadverse_verse_box { ##1 }
\dim_set:Nn \l_raman_spreadverse_width_dim
{
\dim_max:nn
{ \l_raman_spreadverse_width_dim }
{ \box_wd:N \l_raman_spreadverse_verse_box }
}
}
}
\cs_new_protected:Nn \raman_spreadverse_print:n
{
\seq_clear:N \l_raman_spreadverse_printverses_seq
\seq_set_split:Nnn \l_raman_spreadverse_verses_seq { \\ } { #1 }
\seq_map_inline:Nn \l_raman_spreadverse_verses_seq
{
\seq_put_right:Nn \l_raman_spreadverse_printverses_seq
{
\makebox[\l_raman_spreadverse_width_dim][s]{##1}
}
}
\seq_use:Nn \l_raman_spreadverse_printverses_seq { \\* }
}
\ExplSyntaxOff
\begin{document}
\lipsum[2]
\begin{spreadverse}
Lorem ipsum dolor sit amet \\
consectetuer adipiscing elit
Ut purus elit, vestibulum ut, placerat ac \\
adipiscing vitae, felis. Curabitur dictum gravida mauris.
\end{spreadverse}
\lipsum[2]
\begin{spreadverse}[flushleft]
Lorem ipsum dolor sit amet \\
consectetuer adipiscing elit
Ut purus elit, vestibulum ut, placerat ac \\
adipiscing vitae, felis. Curabitur dictum gravida mauris.
\end{spreadverse}
\lipsum[3]
\end{document}
请注意,在此版本中,数字不参与居中(可以进行修改以便参与)。
答案2
\documentclass{article}
\renewenvironment{verse}
{\par\addvspace{10pt}\hsize12cm\parindent0pt
\parfillskip0pt
\emergencystretch\maxdimen
\def\par{\ifhmode\unskip\rlap{\quad\refstepcounter{enumi} (\theenumi)}\fi
\endgraf}%
\def\\{\endgraf}}
{\par\let\par\endgraf\addvspace{10pt}}
\begin{document}
\noindent\rule{12cm}{2pt}
\begin{verse}
Lorem ipsum dolor sit amet\\
consectetuer adipiscing elit
Ut purus elit, vestibulum ut, placerat ac\\
adipiscing vitae, felis. Curabitur dictum gravida mauris.
\end{verse}
\end{document}