第一次近似

第一次近似

我想找到一种方法来水平对齐文档中的任意两个或多个随机位置(但可能在同一页上或彼此相距不太远)。这有点像表格的第二列,但是:

  1. “行”之间可以任意分隔。(表格可以拆分为行。)
  2. 要对齐的点并不总是可以被视为属于表格的行或单元格,因为它们可以出现在普通段落的中间,而段落的其余部分不会受到此对齐的影响。

在以下示例中,如何使所有项目符号对齐(用空格替换减号)?

(1)本句缺少X。---------∙本句缺少什么?

中间有一些评论/段落。

(2) X 缺少一个主题。-------------∙ 什么/谁缺少一个主题?

中间有一些评论/段落。

(3)我的朋友邀请X参加聚会。---∙我的朋友邀请了谁参加聚会?

中间有一些评论/段落。

(4)--------------------------∙ 我的朋友邀请了谁?

和以下段落中的情况一样吗(用空格代替减号)?

此段落出于某种原因在某个点水平跳转-------∙。其余文本可以跨越下一行。

本段希望其跳跃能够落在 ---∙ 与上一段的跳跃完全相同的绝对水平位置(这里执行得不太完美)。

在跳转 ∙ 之前到达位置时如何表现尚未定义,但可以通过跳转到下一行并在那里对齐来定义。

跳转也可以发生在段落的第二行,这样看起来更像 -------------------------------∙ 这个跳转。

我觉得我需要的是一种机制来记住某个水平位置(比如距左边距 30pt)(类似于标签既不记住最后生成的数字也不记住它所在的页面,而是记住它的绝对水平位置 - 也许是?tikz node),然后稍后在文档中恢复它并使用它来水平定位这个绝对位置(距左边距 30pt)上的某个东西。

我需要这样做的一个特定情况是,语言示例是并行构建的,但出现在文档的不同部分(见上文)。特别是如果它们在同一页上,通过这种对齐来显示它们属于一起将是很好的视觉语义。在那里,上面的第 2 点不成立,所以我在tabu最后的 MWE 中记住了一个表格序言。

此解决方案的一个问题是,如果示例的左侧部分比第一个示例的左侧部分长,则示例的左侧部分会断开。我需要\hspace在第一个单元格的末尾手动添加一些内容。但我可以接受,因为我很少需要对齐多个示例。

  This sentence misses X. \hspace*{4em} & What does this sentence miss?\\

第二个问题是,使用表格并不总是一种选择,如上面的第二个案例所示。请参阅 MWE 的结尾以了解第二个问题,通过手动调整所有\hspace命令解决了该问题:

\documentclass{article}
\usepackage{expex}
\usepackage{tabu}

\begin{document}

\ex \begin{tabu}[t]{X[-1]@{\hspace{1em}}X}\savetabu{mypreamble}
  This sentence misses X. & What does this sentence miss?\\
\end{tabu}
\xe

Comments in between.

\ex \begin{tabu}{\usetabu{mypreamble}}
  X misses a subject. & Who/what misses a subject?\\
\end{tabu}
\xe

Another comment.

\ex \begin{tabu}{\usetabu{mypreamble}}
  My friends invited X to the party. & Who did my Friends invite to the party?\\
\end{tabu}
\xe

This paragraph horizontally jumps \hspace*{3em} \textbullet\ at some 
point for some reason. The rest of the text can span other the next lines.

This paragraph wants its jumps to land \hspace*{.5em} \textbullet\ 
exactly at the same absolute horizontal position as the jump from the 
above paragraph (not quite perfectly executed here).

How to behave when the position is reached before jumping \textbullet\ is undefined.

The jump can also happen in the second line of the paragraph, so that it 
looks like \hspace*{16em} \textbullet\ this jump. 

\end{document}

我怎样才能以更加自动化的方式实现示例中的情况?

我怎样才能在段落内实现这一点?

通过示例和段落对齐项目符号

答案1

以下示例将问题放在\hbox右侧。框的宽度是使用最长的问题预先测量的:

\documentclass{article}
\usepackage[
  hmargin=1.5in,
]{geometry}
\usepackage{enumerate}

\newdimen\QuestionLength
\newcommand*{\QuestionFormat}[1]{\textbullet~#1}%
\settowidth{\QuestionLength}{%
  \QuestionFormat{Who did my friends invite to the party?}%
}
\newcommand*{\question}[1]{%
  \leavevmode
  \unskip
  \hspace*{1em plus 1fill}\hbox to \QuestionLength{%
    \QuestionFormat{#1}\hfill
  }%
  \par
}

\begin{document}
\begin{enumerate}[(1)]
\item
  This sentence is missing X.
  \question{What is this sentence missing?}

  Some comment/paragraph(s) in between.

\item
  X is missing a subject.
  \question{What/Who is missing a subject?}

  Some comment/paragraph(s) in between.

\item
  My friends invited X to the party.
  \question{Who did my friends invite to the party?}

  Some comment/paragraph(s) in between.

\item
  \question{Who did my friends invite?}
\end{enumerate}
\end{document}

结果

修复了左侧空格的版本

将左侧最大文本的宽度放入\LeftPartLength。然后使用当前行宽减去左侧部分的长度和一些分隔空间来计算问题的宽度。如果没有足够的空间容纳问题,则会抛出错误。

\documentclass{article}
\usepackage[
  hmargin=1.5in,
]{geometry}
\usepackage{enumerate}

\newcommand*{\QuestionFormat}[1]{\textbullet~#1}%
\newdimen\QuestionLength
\newdimen\LeftPartLength
\newdimen\MiddleSep
\setlength{\MiddleSep}{1em}
\settowidth{\QuestionLength}{%
  \QuestionFormat{Who did my friends invite to the party?}%
}
\settowidth{\LeftPartLength}{%
   Some comment/paragraph(s) in between.%
}

\newcommand*{\question}[1]{%
  \leavevmode
  \unskip
  \begingroup
    \dimen0=\dimexpr\linewidth - \LeftPartLength - \MiddleSep\relax
    \ifdim\dimen0<\QuestionLength
      \errmessage{Question is large by %
        \the\dimexpr\QuestionLength-\dimen0\relax.}%
    \fi
    \hspace*{\MiddleSep plus 1fill}%
    \hbox to \dimen0{%
      \QuestionFormat{#1}\hfill
    }%
  \endgroup
  \par
}

\begin{document}
\begin{enumerate}[(1)]
\item
  This sentence is missing X.
  \question{What is this sentence missing?}

  Some comment/paragraph(s) in between.

\item
  X is missing a subject.
  \question{What/Who is missing a subject?}

  Some comment/paragraph(s) in between.

\item
  My friends invited X to the party.
  \question{Who did my friends invite to the party?}

  Some comment/paragraph(s) in between.

\item
  \question{Who did my friends invite?}
\end{enumerate}
\end{document}

结果

答案2

感谢 touhami 的建议,我找到了更通用的解决方案zref-savepos。请参阅软件包的文档以获取一些解释。一个困难似乎是绝对位置很难处理,而相对位置还可以。它最多需要5 合辑把事情做好!

这是注释的代码:

\documentclass[a4paper,10pt,DIV13]{scrartcl}
\usepackage{expex}
\usepackage{tabu}
\usepackage{ifthen}
\usepackage{calc}
\usepackage{zref-user}
\usepackage{zref-savepos}

\begin{document}

% because the bullets where here only to explicit what I wanted to align
% I didn't include them in the macros

% first the more general solution for paragraphs

\newlength{\tab}% the length of the jumps
\newcommand{\banchor}[1]{\zsaveposx{#1}}% choose the reference point

\newcommand{\balign}[2]{% the 1st argument is the anchorname of the current jump
                        % the 2nd argument is the name of the general anchor chosen
                        % through \banchor
\rule{0pt}{0pt}% to avoid trouble at the beginning of lines
\zsaveposx{#1}\zrefused{#1}% set the reference point from where you want to jump
\setlength{\tab}{\zposx{#2}sp-\zposx{#1}sp}% calculate the length of the jump
\ifthenelse{\lengthtest{\tab<0pt}}% if it's a negative jump,
  {\\\rule{0pt}{0pt}\zsaveposx{#1improbablename}%
    % then begin a new line and set the reference at its beginning
    % with a new anchor name
  \setlength{\tab}{\zposx{#2}sp-\zposx{#1improbablename}sp}% recalculate the jump
  } %
  {}%
\parbox[l]{\tab}{\rule{0pt}{0pt}}% use a \parbox to jump a exact unstrechtable length
% \hspace*{\tab} doesn't work here, because it's strechtable
}

This paragraph horizontally jumps\hspace*{4em}\banchor{B}\textbullet\ at  some point
for some reason. The rest of the text can span other the next lines. 
% this jump is arbitrary, the next ones (previous ones would also work)
% will adapt and align with it

This paragraph wants its jump to land\balign{Ba}{B}\textbullet\ exactly at the same
absolute horizontal position as the jump from the above paragraph (quite perfectly
executed here).

\balign{Bb}{B}\textbullet\ jumping directly to the point is also an option.

How to behave when the position is reached before jumping\balign{Bc}{B}\textbullet\ could
be defined by jumping to the next line.

The jump can also happen The jump can also happen The jump can also happen in the second
line of the paragraph, so that it looks like
\balign{Be}{B}\textbullet\ this jump. 

\bigskip
\hrule

% now to the linguistic examples, following the same principles, 
% but a bit adapted for the more specific needs of the linguistic  examples:
% compile and detect where to put the aligning anchor with \bmark
% use \btab to align the other right parts with it

\newlength{\tabmin}\setlength{\tabmin}{1em}

\newcommand{\bmark}[1]{%
\zsaveposx{#1}\zrefused{#1}\hspace*{\tabmin}}

\newcommand{\btab}[2]{%
\zsaveposx{#1}\zrefused{#1}%
\setlength{\tab}{\tabmin+\zposx{#2}sp-\zposx{#1}sp}%
\hspace*{\tab}}% \hspace* is ok, because wrapped lines are unexpected

\ex This sentence misses X.\btab{Aa}{A}\textbullet\ What does this sentence  miss?
\xe

Comments/explanations/paragraphs in between.

\ex X misses a subject.\btab{Ab}{A}\textbullet\ Who/what misses a subject?
\xe

Another comment.

\ex My friends invited X to the party.\bmark{A}\textbullet\ Who
did my friends invite to the party?
\xe

Another comment.

\ex \btab{Ac}{A}\textbullet\ Who did my friends invite?
\xe

\end{document}

不同段落的文本对齐

编辑

现在我用一条简单的规则替换了\parbox[l]{\tab}{\rule{0pt}{0pt}}\hspace*{\tab},如果设置非零高度,它可以帮助可视化精确的跳跃\rule{\tab}{0pt}

仍有待改进:我的方法需要用户在文档中找到尽可能多的不同名称,以便跳转。也许计数器可以自动完成这部分工作,这样命令\balign\btab需要一个参数。

在其他地方测试这些宏(在表格中,或处理图形时等)可能会显示出一些严重的限制。

就目前而言,这个解决方案是我最喜欢的。

答案3

第一次近似

\parbox解决方案仅适用于非常短的文本。这是一个更复杂的程序:

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

\makeatletter

\def\do#1{\@ifdefinable #1{\newdimen #1}}
% the above is because \newlength allocates a \skip
\do\JumpIndentation
\do\JPprevpardepth

% To allow customization:
\@ifdefinable\EveryJumpingPar{
    \newtoks\EveryJumpingPar \EveryJumpingPar={}
}

\newcommand*\StartJumpingPar{\par
    \JPprevpardepth \prevdepth
    \setbox\z@ \vbox\bgroup
        \color@begingroup % not sure it's really necessary
        \parfillskip \@flushglue
        \prevdepth \JPprevpardepth
        \indent \the\EveryJumpingPar
}
\newcommand*\Jump{%
        \par
        \color@endgroup
    \egroup
    \setbox\tw@ \vbox{%
        \unvcopy\z@
        \setbox\tw@ \lastbox % note that "\indent\par" yields at least one box
        \global \setbox\@ne \hbox{\unhbox\tw@}%
        \global \dimen@i \lastskip % should be -- finger crossed! -- the 
                                  % interline glue above the last box
        \unskip \unpenalty % remove interline glue and widow penalty
        \setbox\tw@ \lastbox % if non-void, assume it is penultimate line
        \global \dimen3 \ifvoid\tw@
            \JPprevpardepth
        \else
            \dp\tw@
        \fi
    }%
    \unvbox\z@
    \ifdim \wd\@ne<\JumpIndentation
        % backspace vertically by one line
        \skip@ \parskip
        \advance \skip@ \ht\@ne
        \advance \skip@ \dp\@ne
        \advance \skip@ \dimen@i
        \vskip -\skip@
        \prevdepth \dimen3
    \else
        \prevdepth \dp\@ne
    \fi
    {\parindent \JumpIndentation \indent}%
    \ignorespaces
}

\makeatother

\setlength{\JumpIndentation}{.57\textwidth} % set as desired



\begin{document}

Let's begin with an ordinart paragraph.

\lipsum[1]

\StartJumpingPar
Now a ``jumping paragraph''.
\lipsum*[1]\Jump\lipsum*[2]

Another ordinary (\emph{i.e.}, ``non-jumping'') paragraph in between, consisting
of at least two lines of text.

\StartJumpingPar
Note that all ``jump'' positions\Jump are vertically aligned, as required.

\StartJumpingPar
If the horizontal position to jump to has already been passed,\Jump the
\verb|\Jump| commands jumps to the next line, as required too.

\StartJumpingPar
Let's try, this time, to get aaaaalmost to\Jump the point!  Now we try again, 
with just one more~``a''.

\StartJumpingPar
Let's try, this time, to get aaaaaalmost to\Jump the point!  Are you satisfied?

\EveryJumpingPar{\textbullet\ }

\StartJumpingPar
Moreover, you can use the token register \verb|\EveryJumpingPar| to customize 
the appearance of\Jump your ``jumping paragraphs''.

That's all, folks!

\end{document}

该代码产生的输出是:

第一次近似的输出

这应该被视为对答案的初步近似:我将等待 OP 的评论,然后再介绍可能的增强功能。


第二次近似

这次我们定义一个名为的环境JumpingParagraphs。此环境必须包含仅有的普通段落,仅此而已。在此环境所包含的每个段落内,\Jump可以使用该命令将表格移动到由\JumpIndentation固定长度指定的水平位置。\Jump在同一段落内,可以无限次使用该命令。

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

\makeatletter

\def\do#1{\@ifdefinable #1{\newdimen #1}}
% the above is because \newlength allocates a \skip
\do\JumpIndentation
\do\@JP@normal@indent
\do\@JP@prevpardepth

% To allow customization:
\@ifdefinable\EveryJumpingPar{
    \newtoks\EveryJumpingPar \EveryJumpingPar={}
}

\@ifdefinable\@JP@saved@par{} % just check that the name can be used
\newenvironment*{JumpingParagraphs}{%
    \@JP@normal@indent \parindent
    \let\@JP@saved@par\par
    \def\par{\@JP@par@close\@JP@start@paragraph}%
    \@JP@start@paragraph
}{%
    \@JP@par@close
}
\newcommand*\@JP@start@paragraph{%
    \@JP@par@open\@JP@normal@indent{\the\EveryJumpingPar}%
}
\newcommand*\@JP@par@open[2]{%
    \@JP@prevpardepth \prevdepth
    \setbox\z@ \vbox\bgroup
        \color@begingroup % not sure it's really necessary
        \parfillskip \@flushglue
        \prevdepth \@JP@prevpardepth
        {\parindent #1\indent #2}%
        \ignorespaces
}
\newcommand*\@JP@par@close{%
        \@JP@saved@par
        \global \dimen@i \prevdepth
        \color@endgroup
    \egroup
    \unvcopy\z@
    \prevdepth \dimen@i % for the moment
}
\newcommand*\Jump{%
    \@JP@par@close
    \setbox\z@ \vbox{%
        \unvbox\z@
        \setbox\z@ \lastbox % note that "\indent\par" yields at least one box
        \global \setbox\@ne \hbox{\unhbox\z@}%
        \global \dimen@i \lastskip % should be -- finger crossed! -- the 
                                   % interline glue above the last box
        \unskip \unpenalty % remove interline glue and widow penalty
        \setbox\z@ \lastbox % if non-void, assume it is penultimate line
        \global \dimen3 \ifvoid\z@
            \@JP@prevpardepth
        \else
            \dp\z@
        \fi
    }%
    \ifdim \wd\@ne<\JumpIndentation
        % backspace vertically by one line
        \skip@ \parskip
        \advance \skip@ \ht\@ne
        \advance \skip@ \dp\@ne
        \advance \skip@ \dimen@i
        \vskip -\skip@
        \prevdepth \dimen3
        \dimen@ \ht\@ne
    \else
        \prevdepth \dp\@ne
        \dimen@ \z@
    \fi
    \@JP@par@open\JumpIndentation{\vrule \@width\z@ \@height\dimen@}%
}

\makeatother

\setlength{\JumpIndentation}{.57\textwidth} % set as desired



\begin{document}

Let's begin with an ordinary paragraph.

\lipsum[1]

\begin{JumpingParagraphs}
% No empty lines here!
Now a ``jumping paragraph''.
\lipsum*[1]\Jump\lipsum*[2]
\Jump Regrettably, \verb|Overfull \hbox|'es might occur: this is almost
inevitable, given the fact that a line containing a ``jump'' places a double
constraint on the choice of the breakpoints.

Another ordinary (\emph{i.e.}, ``non-jumping'') paragraph in between, consisting
of at least two lines of text.  Note that it occurs \emph{within} a 
\texttt{JumpingParagraphs} environment.

Note that all ``jump'' positions\Jump are vertically aligned, as required.

If the horizontal position to jump to has already been passed,\Jump the
\verb|\Jump| commands jumps to the next line, as required too.

Let's try, this time, to get aaaaalmost to\Jump the point!  Now we try again, 
with just one more~``a''.

Let's try, this time, to get aaaaaalmost to\Jump the point!  Are you satisfied?

Moreover, you can use the token register \verb|\EveryJumpingPar| to customize 
the appearance of\Jump your ``jumping paragraphs''.  However, it must be set 
\emph{outside} of the \texttt{JumpingParagraphs} environment.

The \verb|\Jump| command can also be used\Jump several times\Jump within a
single paragraph.  And in-line mathematics (say, \( y=\sin(x) \)) may\Jump
occur, too.  As it is quite obvious, you can both jump \emph{to} math\Jump\(
y=\frac{1}{x} \), and \emph{from} math (the last equation is better
written as \( y=1/x \),\Jump isn't it?).  It is also possible to use unusually
high formulas, as in \( \displaystyle
\biggl(\frac{1}{x}+\frac{1}{y}\biggr)\biggl(\frac{1}{x}-\frac{1}{y}\biggr) \),
and, even in case of a\Jump jump, the spacing will be correct!

But alas, \( \displaystyle \frac{x}{y}+\frac{y}{x}=\frac{x^{2}+y^{2}}{xy} \)
\Jump fails miserably: the spacing is correct for the second half of the line,
but not for the first.  You should keep in mind this limitation.  On the other
hand,\Jump \( \displaystyle \frac{x}{y}+\frac{y}{x}=\frac{x^{2}+y^{2}}{xy} \)
works in a more or less acceptable way, as you can see.

\textbf{Main limitation:} a \texttt{JumpingParagraphs} environment cannot
contain \emph{anything} but ordinary paragraphs.
% No empty lines here!
\end{JumpingParagraphs}

This paragraph is outside the \texttt{JumpingParagraphs} environment.  Note 
that line spacing is correct

\bigbreak

\EveryJumpingPar = {\textbullet\ }

We have just set \verb|\EveryJumpingPar| to contain \verb*|\textbullet\ |.  Now 
we start another \texttt{JumpingParagraphs} environment.

\begin{JumpingParagraphs}
    $X$~misses something.
    \Jump What is $X$ missing?

    This sentence misses~$X$.
    \Jump What is missing?

    This sentence $X$ something.
    \Jump What is missing?
\end{JumpingParagraphs}

That's all, folks!

\end{document}

第三次(和第四次)近似

\par第二个近似值无法正确处理输入中出现多个标记的情况,因为这可能是由额外的空行引起的。第三个近似值通过求助于\everypar触发\@JP@start@paragraph宏来纠正此缺陷,并且还添加了\EveryJump标记寄存器:

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

\definecolor{subdued}{gray}{.75}

\makeatletter

\def\do#1{\@ifdefinable #1{\newdimen #1}}
% the above is because \newlength allocates a \skip
\do\JumpIndentation
\do\@JP@normal@indent
\do\@JP@prevpardepth

% To allow customization:
\def\do#1{\@ifdefinable #1{\newtoks #1#1{}}}
\do\EveryJumpingPar
\do\EveryJump

\@ifdefinable\@JP@saved@par{} % just check that the name can be used
\@ifdefinable\@JP@next{}
\newenvironment*{JumpingParagraphs}{%
    \everypar{\@JP@start@paragraph}%
}{%
    \par
}
\newcommand*\@JP@start@paragraph{%
    \@JP@normal@indent \parindent
    \let\@JP@saved@par\par
    \setbox\z@ \lastbox % get indentation box
    \@@par % return to vertical mode with an empty paragraph
    \ifvoid\z@
        \let \@JP@next \noindent
    \else
        \let \@JP@next \indent
    \fi
    \@JP@par@open\@JP@next\@JP@normal@indent{\the\EveryJumpingPar}%
}
\newcommand*\@JP@par@open[3]{%
    % #1 <- either "\indent" or "\noindent"
    % #2 <- indentation amount
    % #3 <- tokens to insert at the beginning of the paragraph
    \@JP@prevpardepth \prevdepth
    \setbox\z@ \vbox\bgroup
        \color@begingroup % not sure it's really necessary
        \parfillskip \@flushglue
        \everypar{}%
        \let\par\@JP@par@close
        \prevdepth \@JP@prevpardepth
        {\parindent #2#1#3}%
        \ignorespaces
}
\newcommand*\@JP@par@close{%
        \@JP@saved@par
        \global \dimen@i \prevdepth
        \color@endgroup
    \egroup
    \unvcopy\z@
    \prevdepth \dimen@i % for the moment
}
\newcommand*\Jump{%
    \@JP@par@close
    \setbox\z@ \vbox{%
        \unvbox\z@
        \setbox\z@ \lastbox % note that "\indent\par" yields at least one box
        \global \setbox\@ne \hbox{\unhbox\z@}%
        \global \skip\@ne \lastskip % should be -- finger crossed! -- the 
                                    % interline glue above the last box
        \unskip \unpenalty % remove interline glue and widow penalty
        \setbox\z@ \lastbox % if non-void, assume it is penultimate line
        \global \dimen@i \ifvoid\z@
            \@JP@prevpardepth
        \else
            \dp\z@
        \fi
    }%
    \ifdim \wd\@ne<\JumpIndentation
        % backspace vertically by one line
        % Note: no "\parskip" glue is added in internal vertical mode when the
        %       current list is empty, so we don't need to compensate for it!
        \skip@ \skip\@ne
        \advance \skip@ \ht\@ne
        \advance \skip@ \dp\@ne
        \vskip -\skip@
        \prevdepth \dimen@i
        \dimen@   \ht\@ne
        \dimen@ii \dp\@ne
    \else
        \prevdepth \dp\@ne
        \dimen@   \z@
        \dimen@ii \z@
    \fi
    \@JP@par@open\indent\JumpIndentation{%
        % It was trivial to fix this one!
        \vrule \@width\z@ \@height\dimen@ \@depth\dimen@ii \relax
        % Now "\relax" is no longer necessary, actually.
        \the\EveryJump
    }%
}

\makeatother

\setlength{\JumpIndentation}{.57\textwidth} % set as desired



\begin{document}

Let's begin with an ordinary paragraph.

\lipsum[1]

\begin{JumpingParagraphs}

% Empty lines are now allowed here.

Now a ``jumping paragraph''.
\lipsum*[1]\Jump\lipsum*[2]
\Jump Regrettably,\hfil\verb|Overfull \hbox|'es might occur: this is almost
inevitable, given the fact that a line containing a ``jump'' places a double
constraint on the choice of the breakpoints.

% Multiple blank lines in the input are now handled correctly:


Another ordinary (\emph{i.e.}, ``non-jumping'') paragraph in between, consisting
of at least two lines of text.  Note that it occurs \emph{within} a 
\texttt{JumpingParagraphs} environment.

Note that all ``jump'' positions\Jump are vertically aligned, as required.

If the horizontal position to jump to has already been passed,\Jump the
\verb|\Jump| commands jumps to the next line, as required too.

Let's try, this time, to get aaaaalmost to\Jump the point!  Now we try again, 
with just one more~``a''.

Let's try, this time, to get aaaaaalmost to\Jump the point!  Are you satisfied?

\EveryJumpingPar = {\textbullet\ }

Moreover, you can use the token register \verb|\EveryJumpingPar| to customize 
the appearance of\Jump your ``jumping paragraphs''.

\EveryJump = {\textasteriskcentered\ }

In the same way, the \verb|\EveryJump| tokens\Jump are inserted each time a
\verb|\Jump| command\Jump is executed, as it is exemplified by this same\Jump
paragraph.

These token registers can now also be set inside the \texttt{JumpingParagraphs}
environment itself.

\EveryJumpingPar = {}
\EveryJump = {}

The \verb|\Jump| command can also be used\Jump several times\Jump within a
single paragraph.  And in-line mathematics (say, \( y=\sin(x) \)) may\Jump
occur, too.  As it is quite obvious, you can both jump \emph{to} math\Jump\(
y=\frac{1}{x} \), and \emph{from} math (the last equation is better
written as \( y=1/x \),\Jump isn't it?).  It is also possible to use unusually
high formulas, as in \( \displaystyle
\biggl(\frac{1}{x}+\frac{1}{y}\biggr)\biggl(\frac{1}{x}-\frac{1}{y}\biggr) \),
and, even in case of a\Jump jump, the spacing will be correct!

And now, also \( \displaystyle \frac{x}{y}+\frac{y}{x}=\frac{x^{2}+y^{2}}{xy} \)
\rlap{\color{subdued}sminnief}\Jump functions with absolute perfection: line
spacing is correct both for the first half of the line and for the second one.
On the other hand,\Jump \( \displaystyle
\frac{x}{y}+\frac{y}{x}=\frac{x^{2}+y^{2}}{xy} \) works in a less satisfactory
way, as you can see.  You should keep in mind this limitation.

\textbf{Main limitation:} a \texttt{JumpingParagraphs} environment cannot
contain \emph{anything} but ordinary paragraphs.

\noindent Note that \verb|\noindent| commands\Jump \emph{are} honored: indeed,
this has now been corrected (in an update).

\begingroup

\setlength{\parindent}{4em}

Also, \verb|\parindent| may now vary\Jump from one paragraph\Jump to another:
I~had completely overlooked this in the previous versions!

Another paragraph with the same\Jump different indentation.

\endgroup

Back to previous indentation,\Jump with a jump.

One last paragraph without jumps.

% Empty lines are now allowed here.

\end{JumpingParagraphs}

This paragraph is outside the \texttt{JumpingParagraphs} environment.  Note 
that line spacing is correct.

\bigbreak

\newcounter{sentence}
\renewcommand*{\thesentence}{{\normalfont (\textit{\alph{sentence}})}}
\EveryJumpingPar = {\refstepcounter{sentence}\llap{\thesentence\ }}
\EveryJump = {\textbullet\ }

We have just set \verb|\EveryJumpingPar| to contain a numbered label, which is
automatically stepped, and \verb|\EveryJump| to contain \verb*|\textbullet\ |.
Now we start another \texttt{JumpingParagraphs} environment.

\begin{JumpingParagraphs}
    \setlength{\parskip}{\medskipamount}

    $X$~misses something.
    \Jump What is $X$ missing?

    This sentence misses~$X$.
    \Jump What is missing?

    This sentence $X$ something.
    \Jump What is missing?

    Now, get close to the jump destination...
    \Jump to be sure that the baselines are lined up properly.
\end{JumpingParagraphs}

That's all, folks!

\end{document}

这次我也将显示输出:

3/4 次近似的输出

采用的解决方案zref-savepos确实比这更灵活;但是,我认为展示如何完全使用好的“纯 TeX 风格”方法实现目标可能会很有趣:不依赖于当时\pdfsavepos操作的和相关原语\shipout,不需要两遍编译,只需要使用盒子和胶水就可以了。


我必须坦白地承认,这个问题抓住我了!我正在反复完善我的答案,最后我可能会发布一个完整的答案……

答案4

对于段落的情况,我找到了一种使用\parbox跳过其文本的解决方案。我不知道这是否\hbox是一个更好的想法。这解决了跳转发生在段落第一行的情况。

\newlength{\jumplength}
\setlength{\jumplength}{20em} % adjust manually
\newcommand{\jumping}[1]{\parbox[l]{\jumplength}{#1}}

\jumping{This paragraph horizontally jumps}\textbullet\ at some point
for some reason. The rest of the text can span other the next lines.

\jumping{This paragraph wants its jump to land}\textbullet\ exactly at  
the same absolute horizontal position as the jump from the above paragraph.

\jumping{~}\textbullet\ jumping directly to the point is also an option.

不同段落中要点的对齐

为了准确起见,Heiko 的第二个答案应该是

\settowidth{\LeftPartLength}{%
My friends invited X to the party.%
}

完全符合我的需要,但结果略有不同:

在此处输入图片描述

相关内容