以下使用等宽字体的 ascii-art 表示显示了我实际上想要使用比例字体获得的结果:
20 «Ἀτρεΐδαι τε καὶ ἄλλοι ἐϋκνήμιδες Ἀχαιοί,
ὑμῖν μὲν θεοὶ δοῖεν Ὀλύμπια δώματ᾽ ἔχοντες
ἐκπέρσαι Πριάμοιο πόλιν, εὖ δ᾽ οἴκαδ᾽ ἱκέσθαι·
παῖδα δ᾽ ἐμοὶ λύσαιτε φίλην, τὰ δ᾽ ἄποινα δέχεσθαι,
ἁζόμενοι Διὸς υἱὸν ἑκηβόλον Ἀπόλλωνα.»
25 Ἔνθ᾽ ἄλλοι μὲν πάντες ἐπευφήμησαν Ἀχαιοὶ
αἰδεῖσθαί θ᾽ ἱερῆα καὶ ἀγλαὰ δέχθαι ἄποινα·
ἀλλ᾽ οὐκ Ἀτρεΐδῃ Ἀγαμέμνονι ἥνδανε θυμῷ,
ἀλλὰ κακῶς ἀφίει, κρατερὸν δ᾽ ἐπὶ μῦθον ἔτελλε·
这个想法是,这是一篇以诗歌形式呈现的文本,并且由于我以一种不寻常的方式呈现它(在右页上有一组几何形状相似的注释),我希望布局与标准布局略有不同。通常,人们会将文本左对齐地放在左边距,行号放在右侧的空白处。我想要做的是在左侧留出一些额外的空白 x,比如 20 毫米,并且我希望行号放在该空白处,如图所示,而不是在右侧。
我实际上会通过反复试验来设置 x 的值,以便 99% 的行都足够短以适合。但是,会有 1% 的行(例如示例中的第 23 行)太长,在这种情况下,我希望文本尽可能向左移动以使其适合。这非常难看,但这种情况很少发生,所以我不介意。(这是 Homer,由于米制,这些行的长度实际上相当均匀。)
有没有什么简单的方法可以在乳胶中做到这一点?
就这个问题而言,有两个有问题的情况我不太关心:
(1) 如果行数非常非常长(即使占据了整个左侧空白,也太长了,无法容纳),那么我猜如果有某种优雅的后备行为(例如拆分行),那将是一个加分项,但实际上,这种文本不太可能出现这种情况。我在页面上留出的空间非常大,例如,在文本的前 500 行中,只有两行的长度为 53 个字符或更长。
(2) 还存在这样的情况:文本中有行号,但文本会与行号重叠。理想情况下,软件会检测到这种情况并自动忽略行号,但同样,我认为这种情况不太可能经常发生,不值得担心。
如果我能得到一个在这些边缘情况不发生时有效的建议,我就可以开始尝试它并看看以后如何适应这些边缘情况。
因此,理想情况下,我正在寻找一种方法来定义要使用的命令:
\homer{20}{«Ἀτρεΐδαι τε καὶ ἄλλοι ἐϋκνήμιδες Ἀχαιοί,}
...
\homer{}{παῖδα δ᾽ ἐμοὶ λύσαιτε φίλην, τὰ δ᾽ ἄποινα δέχεσθαι,}
我目前没有使用任何诗歌类型环境,并且我认为我不需要或不想使用它们。
答案1
一个简单的解决方案,并使用\homer{20}{...}
您在问题中要求的语法:
\documentclass{article}
\usepackage[greek]{babel}
\begin{document}
\newcommand{\homer}[2]{\noindent\rlap{#1}\hskip 20mm minus 20mm \hbox{#2}\par}
\hsize=265pt % Setting a smaller width for illustration.
% Just to show the allowed text width
\noindent \rule{\hsize}{0.4pt}
\homer{20}{«Ἀτρεΐδαι τε καὶ ἄλλοι ἐϋκνήμιδες Ἀχαιοί,}
\homer{}{ὑμῖν μὲν θεοὶ δοῖεν Ὀλύμπια δώματ᾽ ἔχοντες}
\homer{}{ἐκπέρσαι Πριάμοιο πόλιν, εὖ δ᾽ οἴκαδ᾽ ἱκέσθαι·}
\homer{23}{παῖδα δ᾽ ἐμοὶ λύσαιτε φίλην, τὰ δ᾽ ἄποινα δέχεσθαι,}
\homer{}{ἁζόμενοι Διὸς υἱὸν ἑκηβόλον Ἀπόλλωνα.»}
\homer{25}{Ἔνθ᾽ ἄλλοι μὲν πάντες ἐπευφήμησαν Ἀχαιοὶ}
\homer{}{αἰδεῖσθαί θ᾽ ἱερῆα καὶ ἀγλαὰ δέχθαι ἄποινα·}
\homer{}{ἀλλ᾽ οὐκ Ἀτρεΐδῃ Ἀγαμέμνονι ἥνδανε θυμῷ,}
\homer{}{ἀλλὰ κακῶς ἀφίει, κρατερὸν δ᾽ ἐπὶ μῦθον ἔτελλε·}
\noindent \rule{\hsize}{0.4pt}
\end{document}
(我给第 23 行编号以表明它也能正常工作,因为这个答案的第一个版本对于这样的行做了一些不正确的事情。)
怎么运行的:
\newcommand{\homer}[2]{\noindent\rlap{#1}\hskip 20mm minus 20mm \hbox{#2}\par}
注意,这与将 each 定义为包含以下内容的段落\rlap{#1}
相同:\hbox to 0pt{#1\hss}
\homer{…}{…}
#1
假装宽度为零的框中的可选行号( ),- 水平跳跃默认为 20 毫米,但可以缩小,
- a
hbox
是您的文本行。
当最后一个框足够长以至于总长度(20 毫米 + 您的文本行)超出线宽时,允许的收缩就会\hskip
发挥作用,并根据需要减少跳过。
在您提到的两个有问题的边缘情况下,这可以合理地失败:
(2) 为了防止行号与数字重叠,可以将最大收缩量调小。例如,改为可确保行号至少有 4mm。(对于此字体中的两位数字
\hskip 20mm minus 20mm
来说\hskip 20mm minus 16mm
,这正好足够了;也许4 是最宽的数字使用其他字体。)(1) 在极少数情况下,即使
\hskip
已缩小到其最大量(无论是满量20mm
还是较小的量,如16mm
,无论您选择哪种),一行仍然太长,您会收到过满框警告,因此您可以手动处理它。
答案2
以下代码是否接近您的要求?
\documentclass{article}
\usepackage[greek]{babel}
\begin{document}
\begin{tabbing}
20\=\quad\=«Ἀτρεΐδαι τε καὶ ἄλλοι ἐϋκνήμιδες Ἀχαιοί,\\
\>\>ὑμῖν μὲν θεοὶ δοῖεν Ὀλύμπια δώματ᾽ ἔχοντες\\
\>\>ἐκπέρσαι Πριάμοιο πόλιν, εὖ δ᾽ οἴκαδ᾽ ἱκέσθαι·\\
\>παῖδα δ᾽ ἐμοὶ λύσαιτε φίλην, τὰ δ᾽ ἄποινα δέχεσθαι,\\
\>\>ἁζόμενοι Διὸς υἱὸν ἑκηβόλον Ἀπόλλωνα.»\\
25\>\>Ἔνθ᾽ ἄλλοι μὲν πάντες ἐπευφήμησαν Ἀχαιοὶ\\
\>\>αἰδεῖσθαί θ᾽ ἱερῆα καὶ ἀγλαὰ δέχθαι ἄποινα·\\
\>\>ἀλλ᾽ οὐκ Ἀτρεΐδῃ Ἀγαμέμνονι ἥνδανε θυμῷ,\\
\>\>ἀλλὰ κακῶς ἀφίει, κρατερὸν δ᾽ ἐπὶ μῦθον ἔτελλε·
\end{tabbing}
\end{document}
答案3
已编辑以解决不计算文本空白行的问题。此答案还重点关注了 OP 所希望的边距。
环境justifly
使用\makebox
es 实现边缘化,并重新定义\\
以继续该过程。除了简单的\end{justifly}
,还需要使用双 , 来结束该过程\\\\
,以停止自引用迭代。
\buffwd
是要求的默认缩进(当前设置为 20mm),而\linewd
是正常尺寸行的默认允许宽度。
\documentclass{article}
\newcounter{stanzaline}
\newlength\linewd
\setlength\linewd{50mm}
\newlength\buffwd
\setlength\buffwd{20mm}
\let\endtest\empty
\makeatletter
\newcommand\fitline[1]{%
\ifnum\testblank#1\endtest\endtest=0\relax
\makebox[\buffwd][l]{}%
\else
\stepcounter{stanzaline}%
\makebox[\buffwd][l]{\tiny\thestanzaline}%
\fi
\sbox0{#1}%
\ifdim\wd0>\linewd\relax
\makebox[\linewd][r]{\ignorespaces#1}%
\else
\makebox[\linewd][l]{\ignorespaces#1}%
\fi}
\makeatother
\def\testblank#1#2\endtest{\ifx\endtest#10\else1\fi}
\let\svbbs\\
\newenvironment{justifly}
{\setcounter{stanzaline}{0}%
\bgroup\def\\##1\\{\ifx\relax##1\relax\else\mbox{}\svbbs
\fitline{##1}\expandafter\\\fi}\\}{\egroup}
\begin{document}
Here is normal text\\
Now for the poetry margins:
\noindent\rule{\buffwd}{1pt}\rule{\linewd}{3pt}
\begin{justifly}
aaa\\
This is a test\\
This is a longer test than the margin\\
\\
New verse\\
This is a test\\
This is a longer test that exceeds margin\\\\
\end{justifly}
\end{document}
为了让大卫更高兴,我们提供了希腊语版本(边距不同)
\documentclass{article}
\usepackage[english,greek]{babel}
\newcounter{stanzaline}
\newlength\linewd
\setlength\linewd{70mm}
\newlength\buffwd
\setlength\buffwd{30mm}
\let\endtest\empty
\makeatletter
\newcommand\fitline[1]{%
\ifnum\testblank#1\endtest\endtest=0\relax
\makebox[\buffwd][l]{}%
\else
\stepcounter{stanzaline}%
\makebox[\buffwd][l]{\tiny\thestanzaline}%
\fi
\sbox0{#1}%
\ifdim\wd0>\linewd\relax
\makebox[\linewd][r]{\ignorespaces#1}%
\else
\makebox[\linewd][l]{\ignorespaces#1}%
\fi}
\makeatother
\def\testblank#1#2\endtest{\ifx\endtest#10\else1\fi}
\let\svbbs\\
\newenvironment{justifly}
{\setcounter{stanzaline}{0}%
\bgroup\def\\##1\\{\ifx\relax##1\relax\else\mbox{}\svbbs
\fitline{##1}\expandafter\\\fi}\\}{\egroup}
\begin{document}
\begin{otherlanguage}{english}
Here is normal text\\
Now for the poetry margins:
\end{otherlanguage}
\noindent\rule{\buffwd}{1pt}\rule{\linewd}{3pt}
\begin{justifly}
«Ἀτρεΐδαι τε καὶ ἄλλοι ἐϋκνήμιδες Ἀχαιοί,\\
ὑμῖν μὲν θεοὶ δοῖεν Ὀλύμπια δώματ᾽ ἔχοντες\\
ἐκπέρσαι Πριάμοιο πόλιν, εὖ δ᾽ οἴκαδ᾽ ἱκέσθαι·\\
παῖδα δ᾽ ἐμοὶ λύσαιτε φίλην, τὰ δ᾽ ἄποινα δέχεσθαι,\\
ἁζόμενοι Διὸς υἱὸν ἑκηβόλον Ἀπόλλωνα.»\\
Ἔνθ᾽ ἄλλοι μὲν πάντες ἐπευφήμησαν Ἀχαιοὶ\\
αἰδεῖσθαί θ᾽ ἱερῆα καὶ ἀγλαὰ δέχθαι ἄποινα·\\
ἀλλ᾽ οὐκ Ἀτρεΐδῃ Ἀγαμέμνονι ἥνδανε θυμῷ,\\
ἀλλὰ κακῶς ἀφίει, κρατερὸν δ᾽ ἐπὶ μῦθον ἔτελλε·\\\\
\end{justifly}
\end{document}
答案4
因此,可能对你有用的简单、幼稚的方法就是用¹定义这条线
\newlength{\homermargin}
\setlength{\homermargin}{20mm}
\NewDocumentCommand{\homer}{ m m }{% ❖
\ifvmode\else\endgraf\fi % ❶
\hbox to\linewidth{%
\hbox to\homermargin{#1\hfil}% ❷
\hskip 0pt minus \homermargin % ❸
#2\strut\hfil
} % ❖
}
我使用来定义,因为这样就变成了一个简单的问题,只需\NewDocumentCommand
将第一个改为,就可以让你写m
O{}
\homer[20]{«Ἀτρεΐδαι τε καὶ ἄλλοι ἐϋκνήμιδες Ἀχαιοί,}
\homer{παῖδα δ᾽ ἐμοὶ λύσαιτε φίλην, τὰ δ᾽ ἄποινα δέχεσθαι,}
而不必在每一行没有数字的地方都放置空括号。
因此,这里的方法是手动为每一行创建一个框。LaTeX\mbox
有一些我想要避免的魔法,所以我使用 TeX 原语\hbox
并进行检查以确保我们以垂直模式而不是水平模式开始❶。
我们在左侧留出空间用于数字,并使用\hfil
填充该空间 ❷ 然后我们告诉 LaTeX,在该空间之后,我们有 0pt 的空间可以缩小边距宽度 ❸ ,这样文本就可以在需要时进入左边距。否则,它会整齐地放在左边距上。
但这很简单。让我们让它更有趣。如果行号不合适,则需要转储行号;如果绝对必要,则需要换行。
所以我们要测量我们想要设置的线条的宽度。²
为此,我们可以使用 LaTeX 的\sbox
机制保存参数 2 的内容。我们还将进入一个组,这样我们所有的更改都是本地的。
{%
\sbox0{#2}%
我们还将保存行号的宽度
\sbox1{#1}%
现在我们需要考虑三种情况:
- 线路合适,并且有空间容纳号码。
- 该行适合文本宽度,但我们需要减少数字
- 线不太合适,我们需要将其换行。
\wd0
我们可以通过比较(我们保存的框的宽度\sbox0
与\linewidth
情况\wd0>\linewidth
3 的宽度)来区分 3 和 1/2 。
\ifdim\wd0 > \linewidth
在这种情况下,我们将重新设置参数并#2
进行一些轻微的格式更改(我们不会进入左边距,我们将通过 em 缩进连续行,并使所有内容都正确排列)。 \hbox to\linewidth{% \hbox to\homermargin{#1\hfil}% \vtop{% ❹ \hsize\linewidth \addtolength{\hsize}{-\homermargin}% ❺ \parindent-10pt \leftskip 10pt \rightskip 0pt plus1fil #2\strut % ❻ }% }
❹\vtop
是 的一种特殊形式,\vbox
它与内容的第一条基线对齐³。我们将调整 hsize 以包含足够的空间用于左侧边距。❺ 我们需要\strut
在末尾添加 ❻,因为由于我们将比正常深度更大的内容放入垂直列表中,如果最后一行不包含降部,LaTeX 将不知道我们实际上需要更多空间,并且间距会偏离。放置\strut
一个具有足够高度和深度的隐形规则,以确保我们的行距保持一致。
现在我们可以考虑其他的可能性。我们将框的宽度与线条相加,框的宽度与线条号相加。
\else
\dimen0=\wd0
\advance\dimen0\wd1
\advance\dimen0 0.25em % ❼
标记为 ❼ 的行是可选的,但它确保文本和数字之间至少有一点空白,我选择了 ¼em,这是罗伯特·莫里斯 (Robert Morris) 之后的精细排版从业人员使用的标准空格宽度。⁴ 然后我们可以比较\dimen0
一下\linewidth
是否合适:
\ifdim\dimen0 < \linewidth
如果确实合适,我们就可以放心地设置我们的线路。我们将重新使用上面创建的框来设置输出
\hbox to \linewidth{%
\hbox to \homermargin{%
\box1\hfil
}%
\hskip 0pt minus\homermargin
\box0\hfil
}
如果不适合,我们会做几乎相同的事情,但不设置数字。我们也可以删除整个第一个框,只使用更宽的\hskip
左缩进:
\else
\hbox to \linewidth{%
\hskip \homermargin
\hskip 0pt minus\homermargin % ❽
}
我们必须写两个\hskip
s ❽,因为虽然我们可以在 后面使用长度minus
来表示可收缩性,但如果我们试图minus
在 后面添加\hskip\homermargin
,TeX 将无法意识到它是为了修改 的长度\homermargin
。我们必须做一些粘合算术来结合固定宽度和可收缩性,坦率地说,在这里写两个 s 更容易\hskip
。
最后,我们结束了所有的如果和我们开始的小组。
\fi
\fi
}
我正在考虑添加额外的修改来自动编号行,但我将其留给读者作为练习。
您没有指定,所以我假设您使用的是 LaTeX。如果不是,请在评论中告诉我,我会调整为 TeX 基元定义。其中大部分已经使用 TeX 基元定义,因为实际上并没有足够的复杂性来从 expl3 甚至一些 LaTeX 私有命令中获得简化。
以下所有内容将替换标有 ❖ 的行之间的所有内容,包括这些行。
事实上,这要复杂一些,但这就是我们在这里使用它的原因。
Computer Modern 使用 ⅓em 间距,这种间距相当宽,但符合 19 世纪建立的间距标准,当时排字员是按行获得报酬的,因此他们认为用宽间距填充他们的作品是合理的。
可以这么说。