在当前行之后的每一行开头插入一个字符?

在当前行之后的每一行开头插入一个字符?

我正在寻找一种方法来自动获取以下法语“连续 guillemets”布局,这种布局在旧印刷术中用于当引用包含另一个跨越多行的引用时(好吧,乍一看这可能看起来很奇怪):

“当比尔来到门口时,他
看见了他。男孩说:“你好,我是约翰
,今年 10 岁。我
和父母住在城里。
你想干什么?”比尔很惊讶
,但还是回答了男孩。»

我想使用 XeLaTeX 自动执行此操作。LaTeX 代码可能如下所示:

« When Bill arrived at the door, he saw him. The boy said: \continuousguil{Hello, I'm John and I'm 10 years old. I live with my parents in town. What do you want?} Bill was surprised but answered the boy. »

这几乎是 David 在这篇文章中给出的精彩回答: 环境在每行输出的开头打印相同的字符

但是还是存在一些差异,我无法自己调整代码...事实上,David 的环境必须从新行开始(而我可能希望从一行的中间开始),结尾处也是如此:我希望能够在同一行继续...

当我尝试修改代码时,遇到一个错误:“不正确的 \prevdepth”。

你知道怎样做吗?

提前致谢!


按照大卫卡莱尔的回答进行编辑:

当我尝试您的解决方案时,我得到了如下结果: 嵌套引用示例

这里有两个问题:嵌套引用的第一行没有对齐,并且嵌套引用的最后一行之前有一些额外的垂直空间......但最后一个难题并不总是发生。

为了完整起见,我应该提到我»用 替换了代码中的“前缀” \nospace{»}\hspace{.25em},其中nospace命令禁用了 polyglossia 包的自动法语间距。以下是完整代码(我几乎没有对 David 的代码进行任何更改;\phantom{}命令开头的 是一个丑陋的 hack,以便在 guillemet 之后有适当的间距):

\documentclass[12pt]{article} % Essai de guillemets continus

\usepackage{fontspec}
\defaultfontfeatures{Mapping=tex-text}
\setmainfont[Ligatures={TeX}, Numbers={OldStyle}]{Adobe Garamond Pro}

\usepackage{polyglossia}
\setdefaultlanguage{french}
\renewcommand\labelitemi{---}

\usepackage{microtype}

\setlength\textwidth{10cm}

% Enlever espace avant ponctuation
\makeatletter
\newcommand{\nospace}[1]{\nofrench@punctuation#1\french@punctuation}
\makeatother


% Commande guilcont

\makeatletter
%https://tex.stackexchange.com/questions/107726/how-to-get-the-natural-width-of-the-last-box-in-a-paragraph/107727#107727
\def\lastlinelength{%
{\abovedisplayshortskip\z@\abovedisplayskip\z@
    \belowdisplayshortskip\z@\belowdisplayskip\z@
$$\global\dimen\@ne\dimexpr\predisplaysize-2em\relax
 \xdef\tmp{%
      \predisplaysize\the\predisplaysize
      \prevgraf\the\prevgraf\relax}%
$$\vskip\dimexpr-\parskip-\baselineskip\relax}\tmp}


% The code for the start of  environment
\def\guilcont#1{«\phantom{}%
\lastlinelength
% save the depth of the previous line (Normally
% TeX uses this automatically but would lose the
% informatiom due to the boxing/reboxing)
\dimen0\prevdepth
% Save the prefix text from `#1` in box 0.
% In this version make it red, probably real code
% should not do that and should just have `#1` you
% could always add colour or font changes in the argument.
\setbox0\hbox{\nospace{»}\hspace{.25em}}%
% start saving the paragraph in box 2
\setbox2\vbox\bgroup\bgroup\vskip94sp
% by resetting the prevdepth to the saved value
% Tex will automatically insert glue to maintain even spacing
% before the first line.
\prevdepth\dimen0
% Reduce the width for line breaking by the width of box 0 to allow for
% the insertion of the prefix string later.
\advance\hsize-\wd0 
% end of begin environment code
\noindent\vadjust{\penalty123}\kern\dimen1 #1%
% close off the saving of box 2 started above.
\endgraf\egroup\egroup
% So at those point box 2 contains the body of the environment
% with lines broken to a short line length.
%
% Clear box 1 ready to start collecting the modified lines
\global\setbox1\vbox{}%
% Use unbox box2 (onto itself)
\setbox2\vbox{%
\unvbox2
\global\setbox5\lastbox
\unskip
% at this point we are at the end of box 2 now
% loop backwards up the vertical list copying glue and penalties
% but modifying boxes to add the prefix.
\loop
%
% an e-tex primitive that reports the last item in the vertical list.
% type 1 is a box, so remove the box (a line of text) and then
% put into box 1 a box that is this box together with the prefix which
% was saved in box 0
\ifnum\lastnodetype=1
\global\setbox3\lastbox
\global\setbox1\vbox{%
\hbox{\copy0\box3}%
\unvbox1}%
\fi
%
% type 11 is glue so remove it from this list and add
% equivalent glue to box 1
\ifnum\lastnodetype=11
\skip0\lastskip\unskip
\global\setbox1\vbox{\vskip\skip0\unvbox1}%
\fi
%
% same for penalty
\ifnum\lastnodetype=13
\count0\lastpenalty\unpenalty
\ifnum\count0=123
\setbox0\hbox{}%
\else
\global\setbox1\vbox{\penalty\count0 \unvbox1}%
\fi
\fi
%
% other node types are not handled here: either they won't happen
% or they can't be removed anyway so would break the loop \special
% for example would be bad.
%
% -1 means the vertical list is empty: we have reached the top of the box.
\ifnum\lastnodetype=-1
\else
\repeat}%
% Tip the modified box back onto the main list for the page, unbox
% it so that page breaking may still happen (if it could happen in the
% original context).
\vskip-\baselineskip
\unvbox1
\noindent\nospace{»}\hspace{.25em}\unhbox5\unskip\unskip\ »%
}


\begin{document}

«Il y a huit ans que je suis avec vous, n'est-ce pas? Eh bien, dès le premier
jour, je me suis dit : \guilcont{Dès que j'aurai amassé cinq mille francs, je
  m'en retournerai là-bas; j'achèterai la maison à Lagache, et je vivrai bien
  heureuse…} C'est une promesse que je me suis faite, vous comprenez.»

\end{document}

有什么办法可以解决这两个小问题吗?谢谢!

答案1

在此处输入图片描述

\documentclass{article}

\setlength\textwidth{3.5cm}
\usepackage[T1]{fontenc}% not for xetex
\usepackage[utf8]{inputenc}% not for xetex
\makeatletter
%http://tex.stackexchange.com/questions/107726/how-to-get-the-natural-width-of-the-last-box-in-a-paragraph/107727#107727
\def\lastlinelength{%
{\abovedisplayshortskip\z@\abovedisplayskip\z@
    \belowdisplayshortskip\z@\belowdisplayskip\z@
$$\global\dimen\@ne\dimexpr\predisplaysize-2em\relax
 \xdef\tmp{%
      \predisplaysize\the\predisplaysize
      \prevgraf\the\prevgraf\relax}%
$$\vskip\dimexpr-\parskip-\baselineskip\relax}\tmp}


% The code for the start of  environment
\def\continuousguil#1{ «%
\lastlinelength
% save the depth of the previous line (Normally
% TeX uses this automatically but would lose the
% informatiom due to the boxing/reboxing)
\dimen0\prevdepth
% Save the prefix text from `#1` in box 0.
% In this version make it red, probably real code
% should not do that and should just have `#1` you
% could always add colour or font changes in the argument.
\setbox0\hbox{» }%
% start saving the paragraph in box 2
\setbox2\vbox\bgroup\bgroup\vskip94sp
% by resetting the prevdepth to the saved value
% Tex will automatically insert glue to maintain even spacing
% before the first line.
\prevdepth\dimen0
% Reduce the width for line breaking by the width of box 0 to allow for
% the insertion of the prefix string later.
\advance\hsize-\wd0 
% end of begin environment code
\noindent\vadjust{\penalty123}\kern\dimen1 #1%
% close off the saving of box 2 started above.
\endgraf\egroup\egroup
% So at those point box 2 contains the body of the environment
% with lines broken to a short line length.
%
% Clear box 1 ready to start collecting the modified lines
\global\setbox1\vbox{}%
% Use unbox box2 (onto itself)
\setbox2\vbox{%
\unvbox2
\global\setbox5\lastbox
\unskip
% at this point we are at the end of box 2 now
% loop backwards up the vertical list copying glue and penalties
% but modifying boxes to add the prefix.
\loop
%
% an e-tex primitive that reports the last item in the vertical list.
% type 1 is a box, so remove the box (a line of text) and then
% put into box 1 a box that is this box together with the prefix which
% was saved in box 0
\ifnum\lastnodetype=1
\global\setbox3\lastbox
\global\setbox1\vbox{%
\hbox{\copy0\box3}%
\unvbox1}%
\fi
%
% type 11 is glue so remove it from this list and add
% equivalent glue to box 1
\ifnum\lastnodetype=11
\skip0\lastskip\unskip
\global\setbox1\vbox{\vskip\skip0\unvbox1}%
\fi
%
% same for penalty
\ifnum\lastnodetype=13
\count0\lastpenalty\unpenalty
\ifnum\count0=123
\setbox0\hbox{}%
\else
\global\setbox1\vbox{\penalty\count0 \unvbox1}%
\fi
\fi
%
% other node types are not handled here: either they won't happen
% or they can't be removed anyway so would break the loop \special
% for example would be bad.
%
% -1 means the vertical list is empty: we have reached the top of the box.
\ifnum\lastnodetype=-1
\else
\repeat}%
% Tip the modified box back onto the main list for the page, unbox
% it so that page breaking may still happen (if it could happen in the
% original context).
\vskip-\baselineskip
\unvbox1
\noindent » \unhbox5\unskip\unskip\ »
}


\begin{document}

\noindent
« When Bill arrived at the door, he saw him. The boy said:
\continuousguil{Hello, I'm John and I'm 10 years old. I live with my
  parents in town. What do you want?} Bill was surprised but answered
the boy. »

\end{document}

答案2

还有另一种方法更简单,但需要做出更多妥协。该解决方案使用\discretionary在每行之前插入所需的文本。

\hsize=3.6cm
\emergencystretch=2em

\def\guilpar#1\par{\bgroup \frenchspacing \hyphenpenalty=10000
   \rightskip=-\fontdimen2\the\font plus-\fontdimen3\the\font minus-\fontdimen4\the\font
   \guilparA#1 {}
}
\def\guilparA #1 #2 {#1\ifx\end#2\end \guilparE\else \guilparB \expandafter\guilparA \fi #2 }
\def\guilparB{\nobreak\space\penalty0 }
\def\guilparC{\nobreak\space\discretionary{}{»\kern3pt}{}}
\def\guilparE{\par\egroup}

\def\continuousguil#1{%
   {\let\guilparE=\ignorespaces \let\guilparB=\guilparC \guilparA «#1~» {} }}

\guilpar \noindent
« When Bill arrived at door, he saw him. The boy said:
\continuousguil{Hello, I'm John and I'm 10 years old. I live with my
parents in   town. What do you want?} Bill was surprised but answered
the boy. »

\bye

妥协方案如下:

  • 必须\frenchspacing在段落中使用(但我希望这不是真正的问题,因为这是针对法语的)。
  • 此类段落中的连字符必须关闭。

代码说明:段落中的每个空格\guilpar都由 -- 替换\nobreak\space\penalty0,换行已完成空间, 没有空格。包括\rightskip每行最后一个空格的补偿。参数\nobreak\space\discretionary中的每个空格都被替换为\continuousguil

相关内容