环境尊重换行符并在空行前添加内容

环境尊重换行符并在空行前添加内容

我需要一个环境,在这个环境中,换行符被视为换行符,并且在行尾添加一些内容,后面跟着一个空行。Alltt改变了太多东西,甚至字体,因此我不使用它。

我提供了我的 mwe 和一幅用 lowirit 画的插图。由于我不知道该怎么做,所以我没有为新环境做任何事情。

\documentclass[a4paper]{article}
\usepackage{fancyhdr}
\setlength{\parindent}{0pt}

\fancyhead[C]{lipsum text (dummy text)}

\begin{document}
lipsum text \\ (dummy text)
\begin{myenv}
Laborum molestias nam
possimus omnis. Libero sit
maiores quas asperiores nobis
est nulla. Culpa sequi iste deserunt. ||

Adipisci fuga et quis dicta est et
odit. Illo aut nulla qui incidunt
necessitatibus nulla qui. Sunt
cumque voluptatem quasi quam  ||

\textbf{the peacock says ...}
commodi culpa quaerat sunt.
Debitis accusantium et porro et
libero nulla ut est. Asperiores sed
exercitationem aut. Ex sapiente  ||

\textbf{the elephant says ...}
Debitis nobis fugiat doloremque
voluptates enim ratione. Unde ||

magni beatae magni. Unde
voluptatum qui odio corporis quia.  ||

\end{myenv}
\end{document}

\z 如此处定义,我需要在每行末尾添加的内容,后跟一个空行:

\newcounter{versenum}\setcounter{versenum}{1}
\newcommand{\z}{\arabic{versenum}\addtocounter{versenum}{1}}

在此处输入图片描述

答案1

我通过制作一个自定义\obeylines宏来实现这一点,它会提前寻找空行并在userverse环境完成时处理特殊情况。

特征

  • 使用 LaTeX\list环境控制其他列表环境中的上下垂直间距和缩进。
  • 将每节经文放在一个\vtox框中,以防止经文内出现分页符。
  • 用于\devanagaridigits打印诗句编号
% TeX Program = xelatex
\documentclass{article}
\usepackage{lipsum}
\usepackage{multicol}
\usepackage{fontspec}
\usepackage{polyglossia}
\setmainlanguage{english}
\setotherlanguage{hindi}
\setmainfont{Noto Serif}
\newfontfamily\hindifont[Script=Devanagari]{Noto Serif Devanagari}
\ExplSyntaxOn
% Configuration
\dim_new:N \l__user_verse_left_margin_dim
\dim_set:Nn \l__user_verse_left_margin_dim { 3em }
\dim_new:N \l__user_verse_indent_dim
\dim_set:Nn \l__user_verse_indent_dim { 2em }
\skip_new:N \l__user_verse_skip
\skip_set:Nn \l__user_verse_skip { \medskipamount }
% Box to hold each verse to so page breaks are suppressed
\box_new:N \l__user_verse_box
% Counter to hold the verse number
\int_new:N \g__user_verse_number_int
% Increment verse number and output in required format
\cs_new_protected:Nn \__user_number_verse:
  {
    \int_gincr:N \g__user_verse_number_int
    \quad $\|$ ~
    \texthindi
      {
        \devanagaridigits { \int_use:N \g__user_verse_number_int }
      }
  }
% Set up custom \obeylines macro which calls \_user_do_obeylines:
\group_begin:
  \char_set_catcode_active:N \^^M
  \cs_gset_protected_nopar:Nn \__user_obeylines: %
    {%
      \char_set_catcode_active:N \^^M%
      \cs_set_eq:NN ^^M \__user_do_obeylines:%
    }%
\group_end:
\cs_new_protected:Npn \__user_vbox_set_top:Nw #1
  {
    \tex_setbox:D #1 \tex_vtop:D
      \c_group_begin_token
        \color_group_begin:
  }
% Use box maintaining spacing
% Adapted from https://tex.stackexchange.com/a/463739/87678
\cs_new_protected:Nn \__user_box_use_drop:N
  {
    \vbox_set_top:Nn \l_tmpa_box { \vbox_unpack:N #1 }
    \vbox_set:Nn \l_tmpb_box { \vbox_unpack_drop:N #1 }
    \dim_set:Nn \l_tmpa_dim { \box_dp:N \l_tmpa_box - \box_dp:N \l_tmpb_box }
    \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpb_box }
    \box_use_drop:N \l_tmpa_box
    \vspace* \l_tmpa_dim
  }
% Look ahead at the end of each line
\cs_new_protected:Nn \__user_do_obeylines:
  {
    \peek_meaning:NTF \__user_do_obeylines:
      {
%       add verse number and extra space if blank line found
        \__user_number_verse:
        \vbox_set_end:
        \mode_leave_vertical:
        \__user_box_use_drop:N \l__user_verse_box
        \obeyedline
        \penalty \c_zero_int
        \vspace \l__user_verse_skip
        \__user_vbox_set_top:Nw \l__user_verse_box
        \dim_set_eq:NN \hsize \linewidth
      }
      {
%       no extra space if at end of verse environment, otherwise end paragraph
        \peek_meaning:NTF \end
          { \__user_number_verse: }
          { \obeyedline }
      }
  }
% Format verses
\NewDocumentEnvironment { userverse } { }
  {
    \int_gzero:N \g__user_verse_number_int
%   User a list environment to easily set indent and handle vertical spacing
    \list { }
      {
        \skip_zero:N \parsep
        \dim_set:Nn \leftmargin
          { \l__user_verse_left_margin_dim + \l__user_verse_indent_dim }
      }
    \item
    \relax
    \__user_obeylines:
    \__user_vbox_set_top:Nw \l__user_verse_box
    \dim_set_eq:NN \hsize \linewidth
  }
  {
    \vbox_set_end:
    \box_set_wd:Nn \l__user_verse_box \linewidth
    \mode_leave_vertical:
    \__user_box_use_drop:N \l__user_verse_box
    \endlist
  }
% Outdent and format verse intros 
\NewDocumentCommand \verseintro { m }
  {
    \hspace { -\l__user_verse_indent_dim }
    \textbf {#1}
  }
\ExplSyntaxOff
\begin{document}
\lipsum[11]

\begin{userverse}
  Laborum molestias nam
  possimus omnis. Libero sit
  maiores quas asperiores nobis
  est nulla. Culpa sequi iste deserunt.

  Adipisci fuga et quis dicta est et
  odit. Illo aut nulla qui incidunt
  necessitatibus nulla qui. Sunt
  cumque voluptatem quasi quam

  \verseintro{the peacock says\ldots}
  commodi culpa quaerat sunt.
  Debitis accusantium et porro et
  libero nulla ut est. Asperiores sed
  exercitationem aut. Ex sapiente 

  \verseintro{the elephant says\ldots}
  Debitis nobis fugiat doloremque
  voluptates enim ratione. Unde

  magni beatae magni. Unde
  voluptatum qui odio corporis quia.
\end{userverse}

\lipsum[11]

\selectlanguage{hindi}

\begin{multicols}{2}
  \begin{userverse}
    अअअअअअ
    अअअअअअ

    अअअअअअ
    अअअअअअ

    अअअअअअ
    अअअअअअ

    अअअअअअ
    अअअअअअ
  \end{userverse}
\end{multicols}

\selectlanguage{english}

\lipsum[11]

\end{document}

输出

答案2

您可以使用正则表达式替换来完成此操作。

我在读取参数之前\obeylines在环境中进行注入,因此每个结束行都会转变为活动的。myenv^^M

^^M然后删除初始标记;类似地,尾随标记^^M被替换为\addstanzanumber。接下来,将两个或更多个序列^^M替换为\addstanzanumber\par。其余的^^M被替换为\\,并将结果标记列表输入到verse

因此,初始或尾随的空行将myenv被忽略。

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}

\ExplSyntaxOn
% a trick to set a token list to the active endline character
\group_begin:
\char_set_catcode_active:n { 13 }
\tl_const:Nn \c_myenv_blank_line_tl { ^^M }
\group_end:

\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\tl_new:N \l_myenv_body_tl

\NewDocumentEnvironment{myenv}{+b}
 {
  \setcounter{stanzanumber}{0}
  \myenv_make:n { #1 }
  \begin{verse} \tl_use:N \l_myenv_body_tl \end{verse}  
 }
 {}

\cs_new_protected:Nn \myenv_make:n
 {
  \tl_set:Nn \l_myenv_body_tl { #1 }
  % remove any number of ^^M at the beginning
  \regex_replace_once:nnN { \A \u{c_myenv_blank_line_tl}* } { } \l_myenv_body_tl
  % replace any number of ^^M at the end with \addstanzanumber
  \regex_replace_once:nnN { \u{c_myenv_blank_line_tl}* \Z } { \c{addstanzanumber} } \l_myenv_body_tl
  % replace any number greater than two of ^^M with \addstanzanumber
  \regex_replace_all:nnN
   { \u{c_myenv_blank_line_tl}{2,} }% pairs ^^M^^M
   { \c{addstanzanumber}\c{par} } % replace with \addstanzanumber\par
   \l_myenv_body_tl
  % replace any remaining ^^M with \\
  \regex_replace_all:nnN
   { \u{c_myenv_blank_line_tl} } % single ^^M
   { \c{\\} } % replace with \\
   \l_myenv_body_tl
 }
\ExplSyntaxOff

\AtBeginEnvironment{myenv}{\obeylines}
\newcounter{stanzanumber}
\newcommand{\addstanzanumber}{~||~\stepcounter{stanzanumber}\thestanzanumber}
\newcommand{\says}[1]{\hspace{-2em}\textbf{#1}}

\begin{document}

\begin{myenv}
Laborum molestias nam
possimus omnis. Libero sit
maiores quas asperiores nobis
est nulla. Culpa sequi iste deserunt.

Adipisci fuga et quis dicta est et
odit. Illo aut nulla qui incidunt
necessitatibus nulla qui. Sunt
cumque voluptatem quasi quam 

\says{the peacock says\dots}
commodi culpa quaerat sunt.
Debitis accusantium et porro et
libero nulla ut est. Asperiores sed
exercitationem aut. Ex sapiente 

\says{the elephant says\dots}
Debitis nobis fugiat doloremque
voluptates enim ratione. Unde

magni beatae magni. Unde
voluptatum qui odio corporis quia. 
\end{myenv}

\end{document}

在此处输入图片描述

相关内容