自动格式化中间数据

自动格式化中间数据

中间诗是一种类似于首字母诗的诗歌/文本,只是“主干词”位于中间。Wiki 的文章对此进行了很好的解释。

这种格式是由作曲家约翰·凯奇首创的,随着时间的推移,他增加了更多的规则,并开始用它来“写”大段的文本(比如瓦尔登湖)创作了数百首或更多的中观诗歌。最终,他找到了一些人,通过软件将这一过程自动化。

我创建了自己的中观生成器。下面是使用 Poe 的乌鸦书脊上印有“Lenore”字样:

       nearLy napping,  
        camE a  
      tappiNg,  
        as Of  
    gently Rapping,  
at my chambEr door.  

大致来说,可以通过以下代码实现:

\documentclass[11pt]{memoir}
\usepackage{fancyvrb}
\usepackage{DejaVuSansMono}
\begin{document}
\begin{Verbatim}[xleftmargin=-35mm,commandchars=\\\{\}]
                                      near\textbf{L}y napping, 
                                       cam\textbf{E} a 
                                     tappi\textbf{N}g, 
                                       as \textbf{O}f 
                                   gently \textbf{R}apping, 
                               at my chamb\textbf{E}r door. 
\end{Verbatim}
\end{document}

我的中间生成器是用 Lua 编写的,可以自动在左侧添加足够的空间以使书脊沿着中心排列(另外我还添加了粗体内容)。

这对于等宽字体来说非常有效。当我浏览凯奇的书时,我发现他使用了比例字体,但仍然保留了书脊完美地位于中间的格式。我猜这是排字员手动完成的。

所以我想知道是否有人知道如何使用 TeX/LaTeX 中的比例字体自动格式化中间体?

几点说明:

  1. LuaLaTeX 中的解决方案就很好。

  2. 在 Cage 和我的 mesostics 中,所有字母都转换为小写,只有脊柱字母大写。这可以用来帮助格式化吗?

  3. Cage 的规则将一行中的字符总数限制为 90 个左右(书脊字母两侧限制为 45 个字符)。我在软件中遵循此规则。事实上,当行变长时,我会自动更改字体大小。

答案1

免责声明。 下面的代码并不以任何方式暗示我认可或以其他方式尊重约翰·凯奇的任何作品。


以下方法在 处分割输入\\,然后逐行构建,设置一个,\hbox其中测量中心字母的宽度;然后框将由

  1. 一个宽度为线宽的一半减去中心字母宽度的一半的框,右对齐;
  2. 中心字母;
  3. 类似于步骤 1 的盒子,但左对齐。
\documentclass{article}
\usepackage{environ,xparse}

\usepackage{kantlipsum} % for context

\ExplSyntaxOn
\NewEnviron{mesostic}
 {
  \par\addvspace{\topsep}
  \mesostic_build:V \BODY
  \addvspace{\topsep}
 }

\seq_new:N \l__mesostic_body_seq
\box_new:N \l__mesostic_center_box

\cs_new_protected:Nn \mesostic_build:n
 {
  \seq_set_split:Nnn \l__mesostic_body_seq { \\ } { #1 }
  \seq_map_inline:Nn \l__mesostic_body_seq
   {
    \__mesostic_line:w ##1 \q_stop
   }
 }
\cs_generate_variant:Nn \mesostic_build:n { V }

\cs_new_protected:Npn \__mesostic_line:w #1 | #2 | #3 \q_stop
 {
  \hbox_set:Nn \l__mesostic_center_box { \textbf{#2} }
  \hbox_to_wd:nn { \linewidth }
   {
    \hbox_to_wd:nn { (\linewidth-\box_wd:N \l__mesostic_center_box)/2 }
     {
      \hss #1
     }
    \textbf{#2}
    \hbox_to_wd:nn { (\linewidth-\box_wd:N \l__mesostic_center_box)/2 }
     {
      #3 \hss
     }
   }
 }
\ExplSyntaxOff

\begin{document}

\kant[1]

\begin{mesostic}
         near|L|y napping, \\
          cam|E| a         \\
        tappi|N|g,         \\
          as |O|f          \\
      gently |R|apping,    \\
  at my chamb|E|r door.
\end{mesostic}

\kant[2]

\end{document}

在此处输入图片描述

改变字体可以通过进行试验性排版并测量每个部分来实现,以查看它是否满足包含在线宽的约束;如果失败,则停止,更改字体大小并重复。


允许使用可选参数来声明字体或字体大小(或两者)的变体;还添加了尾随检查\\。主要代码已简化(感谢 jfbu 的创意)。

\documentclass{article}
\usepackage{environ,xparse}

\usepackage{kantlipsum} % for context

\ExplSyntaxOn
\NewEnviron{mesostic}[1][]
 {
  #1
  \par\addvspace{\topsep}
  \mesostic_build:V \BODY
  \addvspace{\topsep}
 }

\seq_new:N \l__mesostic_body_seq
\cs_generate_variant:Nn \tl_if_empty:nT { x }

\cs_new_protected:Nn \mesostic_build:n
 {
  \seq_set_split:Nnn \l__mesostic_body_seq { \\ } { #1 }
  % check for a trailing \\
  \tl_if_empty:xT { \seq_item:Nn \l__mesostic_body_seq { -1 } }
   {
    \seq_pop_right:NN \l__mesostic_body_seq \l_tmpa_tl
   }
  \seq_map_inline:Nn \l__mesostic_body_seq
   {
    \__mesostic_line:w ##1 \q_stop
   }
 }
\cs_generate_variant:Nn \mesostic_build:n { V }

\cs_new_protected:Npn \__mesostic_line:w #1 | #2 | #3 \q_stop
 {
  \hbox_to_wd:nn { \linewidth }
   {
    \hss
    \hbox_to_wd:nn { 0pt } { \hss \tl_lower_case:n { #1 } }
    \textbf{\tl_upper_case:n { #2 }}
    \hbox_to_wd:nn { 0pt } { \tl_lower_case:n { #3 } \hss }
    \hss
   }
 }
\ExplSyntaxOff

\begin{document}

\kant[1]

\begin{mesostic}
         near|L|y napping, \\
          cam|E| a         \\
        tappi|N|g,         \\
          as |O|f          \\
      gently |R|apping,    \\
  at my chamb|E|r door.
\end{mesostic}

\kant[2]

\begin{mesostic}[\sffamily\footnotesize]
         NEAR|l|Y NAPPING \\
          CAM|e| A        \\
        TAPPI|n|G         \\
          AS |o|F         \\
      GENTLY |r|APPING    \\
  AT MY CHAMB|e|R DOOR    \\
\end{mesostic}

\kant[3]

\end{document}

在此处输入图片描述

答案2

\documentclass{article}

\makeatletter
  \def\mesostic@end{\end{mesostic}}
\begingroup\catcode`\^^M\active
  \gdef\mesostic@aux#1|#2|#3\mesostic@aux%
     {\noindent\hfill%
      \llap{\MakeLowercase{#1}}%
      \textbf{\MakeUppercase{#2}}%
      \rlap{\MakeLowercase{#3}}%
      \hfill\hbox{}\par%
      \expandafter^^M}%
\endgroup
\newenvironment{mesostic}{\parskip0pt\relax
   \obeylines
   \begingroup\lccode`~`\^^M 
   \lowercase{\endgroup\def~##1~}{%
     \def\mesostic@tmp{##1}%
     \ifx\mesostic@tmp\mesostic@end
       \expandafter\mesostic@end
     \else
       \mesostic@aux##1\mesostic@aux
     \fi}%
  }{}
\makeatother

\begin{document}

blah blah blah

\noindent X\dotfill X

\begin{mesostic}
  near|L|y napping,
  cam|E| a
  tappi|N|g,
  as |O|f
  gently |R|apping,
  at my chamb|E|r door.
\end{mesostic}

\noindent X\dotfill X

blah blah blah

\noindent X\dotfill X

\begin{mesostic}
  NEAR|l|Y NAPPING,
  CAM|e| A
  TAPPI|n|G,
  AS |o|F
  GENTLY |r|APPING,
  AT MY CHAMB|e|R DOOR.
\end{mesostic}


\noindent X\dotfill X

blah blah blah

\end{document}

在此处输入图片描述

并使用X\dotfill X\dotfill X额外的行来表示上下文:

在此处输入图片描述

答案3

在此处输入图片描述

 \documentclass{article}

\makeatletter
\let\zzfont\textbf
{\obeylines\everyeof{\noexpand}%
\gdef\zzz#1{%
\catcode`#1\active\scantokens{\def\zzzz{\gdef#1}}%
\zzzz##1^^M{\makebox[.5\textwidth][l]{\zzfont{\string#1}##1}\par}%
}}
\def\zz{\flushright\obeylines%
\let\or\zzz\@Alph{0\fi\iftrue}}%

\def\endzz{\endflushright}
\begin{document}

\begin{zz}
       nearLy napping,  
        camE a  
      tappiNg,  
        as Of  
    gently Rapping,  
at my chambEr door.  
\end{zz}

\renewcommand\zzfont[1]{\large$\mathcal{#1}$}
\begin{zz}
       nearLy napping,  
        camE a  
      tappiNg,  
        as Of  
    gently Rapping,  
at my chambEr door.  
\end{zz}


\end{document}

相关内容