How to vertically align two or more random places of a document?

I would like to find a way to horizontally align any two or more random places of my document (but probably on the same page or not too far from each other). It's a bit like the second column of a tabular, but:

1. the "rows" can be separated by any amount of whatever. (The tabular can be splitted between the rows.)
2. the points to be aligned can't always be seen as belonging to a row or cell of a tabular, because they can appear in the middle of a normal paragraph without the rest of the paragraph being affected by this alignment.

How to obtain that all bullets be aligned in the following examples (replacing minuses with white space)?

(1) This sentence is missing X. ---------∙ What is this sentence missing?

Some comment/paragraph(s) in between.

(2) X is missing a subject. -------------∙ What/Who is missing a subject?

Some comment/paragraph(s) in between.

(3) My friends invited X to the party. ---∙ Who did my friends invite to the party?

Some comment/paragraph(s) in between.

(4) -------------------------------∙ Who did my friends invite?

And alike in the following paragraphs (replacing minuses with blank space)?

This paragraph horizontally jumps-------∙ at some point for some reason. The rest of the text can span other the next lines.

This paragraph wants its jumps to land ---∙ 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 ∙ is undefined but could be defined by jumping to the next line and aligning there.

The jump can also happen in the second line of the paragraph, so that it looks more like -------------------------------∙ this jump.

What (I think) I need is a mecanism to remember some horizontal position (for example 30pt from the left margin) (something like a label remembering neither the last produced number, nor the page it is in, but the absolute horizontal position it has-maybe a tikz node?), then recover it later in the document and use it to horizontally position something at this absolute position (30pt from the left margin).

One specific situation where I need this is with linguistic examples that are built parallel but appear at different parts of the document (see above). Espacially if they are on the same page, it would be good visual semantics to show their belonging together through this alignment. There, the point 2 above doesn't hold, so I used remembering a tabular preamble with tabu in the MWE at the end.

One problem with this solution is that any further left part of an example that is longer than the left part of the first example gets broken. I need to manually add some \hspace at the end of the first cell. But it's something I'm ok with, because I seldom have to align more than a few examples.

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


And the second problem is that using a tabular is not always an option as shown in my second case above. See the end of the MWE for that second problem, solved with manually ajusting all \hspace commands:

\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

\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}


How can I achieve the case in the examples in an even more automated fashion?

How can I achieve this at all within paragraphs?

• this question finally brought the tabto package to my attention. It seems to do (part of) the job I need pretty well. See also Werner's answer there. Dec 1 '16 at 9:03

The following example puts the question in a \hbox to the right. The width of the box is measured beforehand using the longest question:

\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}


Version with fixes space to the left

The width of the largest text on the left is put in \LeftPartLength. Then the width of the question is calculated by using the current line width minus the length of the left part and some separation space. An error is thrown, if there is not enough place for the question.

\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}


• Works almost fine. But it somehow pushes the right-hand parts of the examples (the questions) very far to the right if they are all quite short. To avoid these big spaces in the middle, the solution would be to calculate the width needed for the \hbox with something like \linewidth - length of longest left-part. Any ideas? If not, I will accept your answer for the first case. Mar 25 '16 at 20:11
• @benjamin See updated answer. Mar 25 '16 at 20:26
• I belive that a solution use zref-savepos package. Mar 25 '16 at 20:37

Thanks to touhami's suggestion, I found more general solutions using zref-savepos. Refer to the package's documentation for some explanations. One difficulty seems to be that absolute positions are hard to deal with, whereas relative positions are ok. It takes up to 5 compilations to get things right!

Here the commented code:

\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

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

\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}


Edit

Now I've replaced \parbox[l]{\tab}{\rule{0pt}{0pt}} and \hspace*{\tab} with a simple rule, which can help visualise the exact jump if set with non-zero height \rule{\tab}{0pt}.

Improvement still pending: my approach needs the user to find as many different names as jumps needed in the document. Maybe a counter could automatise this part of the job, so that the commands \balign and \btab only take one argument.

Testing these macros in other places (in tabulars, or when dealing with graphics, etc.) might show some serious limitations.

As for now, this solution is my favorite one.

• Be aware, however, that the insertion of the calculated horizontal space affects the paragraphing computations, so it might well happan that TeX finds different line breaks in the second run and moves the start of the jump to a different x-position. The length of the jump must therefore be recomputed, and there is no guarantee that the process converges. Indeed, I’ve been able to build an example in which the \balign commands keeps on alternatively understimating and overstimating the tabbing amount, and never gets to the right one.
– GuM
Mar 26 '16 at 20:09
• True! I tried and I too found a case where the process never converges. So a limitation is that it's not guaranteed if more than one jump appear in the same paragraph. And again: to those who want to use it, be patient, it sometimes converges after a lot of compilations (yes, maybe 10 or so). Mar 30 '16 at 12:16
• Well, actually my example that never converges involves a single paragraph that contains a single jump (a single \balign).
– GuM
Mar 31 '16 at 17:50

First approximation

The \parbox solution works only for very short texts. Here is a more elaborate program:

\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
\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
\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}


The output produced by this code is:

This should be regarded as a first approximation to the answer: I’ll wait for the OP’s comments before introducing possible enhancements.

Second approximation

This time we define an environment called JumpingParagraphs. This environment must contain only ordinary paragraphs, and nothing else. Within each paragraph encompassed by this environment, the \Jump command can be used to tabulate to the horizontal position specified by the \JumpIndentation rigid length. The \Jump command may be used an unlimited number of times within the same paragraph.

\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
\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.

\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}


Third (and fourth) approximation

The second approximation did not handle correctly the case of multiple \par tokens appearing in the input, as it could result from extra blank lines. The third approximation corrects this flaw, by having recourse to \everypar to trigger the \@JP@start@paragraph macro, and also adds the \EveryJump token register:

\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
\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
\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.

\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}

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...
\end{JumpingParagraphs}

That's all, folks!

\end{document}


This time I’ll show the output too:

The solution that employs zref-savepos is indeed more flexible than this; however, I think that it might be of some interest to show how the goal can be achived entirely with good ol’ “plain-TeX-style” methods: no dependence on the \pdfsavepos and related primitives operating at \shipout-time, no need for a two-pass compilation, just playing around with boxes and glue.

I must plainly admit it, this question has caught me! I am repeatedly refining my answer, and I’ll probably end up with posting a complete package…

• This does the job. Unfortunately, I don't understand the code so I can't really hope to make enhancements myself. One thing could be added, if possible with this approach: the exact \JumpIndentation could be automatically extracted from some anchored point in the document, like I did in my answer using zref-savepos. But because I found an answer that does it, don't waste time developing your approach further. Mar 26 '16 at 0:40
• @benjamin: Please refrain from accepting this answer yet: it’s still unfinished (I spoke of “first approximation”). To begin with, multiple \Jump commands within the same paragraph are not supported. This can be corrected, but I was awaiting input from you on how you are going to use the commands. For example, would it be acceptable for you to enclose every “jumping paragraph” in an environment? Or would you prefer an environment that encompasses several such paragraphs?
– GuM
Mar 26 '16 at 0:56
• as you will have seen in my own solution with zref-savepos, the mechanism I hoped to find was to deal with 2 commands: one to define a horizontal anchor point at any user-chosen position, and one to use this anchor when adding some tab command (\Jump) refering to this anchor anywhere else in the document, at best without having to define the paragraphs as anything special like JumpingParagraphs. Mar 26 '16 at 8:53

This one has long been, and still was, in my “to do” list…

I said that this question caught my imagination, and indeed I am here again with another proposal for a solution, based on a different approach; and exactly because the approach is different, I deem this is one of those rare cases in which it is more correct to post a new answer that to edit the one I have already given (all the more so, in that it would be the fifth major addition!). I am also going to keep my promise to supply, this time, a complete and independent package that provides the required functionality.

Analysis of the other solutions

Before presenting the new solution, however, I’d like to discuss briefly why I think that the ones that have already been given (including mine) are not completely satisfactory.

Drawbacks of my solution

The solution presented in the other answer I gave is based on a simple principle: in order to jump to a tab position, we do the following:

1. we interrupt the current paragraph, breaking into lines the part of it that comes before the tabbing command;

2. we measure the width of the last line, to see if it reached as far from the left margin as to have already gone past the tab position;

3. if it has not, we backspace by one line of text, in order to print the continuation line at the same vertical position as the line that came before the tab;

4. we typeset the continuation line starting with an indentation equal to the tab position.

The critical points in this algorithm are step 2 and 3: in step 2, in order to measure the width of the last line, that is, of the last box in the paragraph, you need to retrieve that box from the current vertical list; in step 3, in order to find out the exact amount of vertical backspace required to align perfectly the continuation line with the line that came before the tab, you need to inspect, and hence retrieve as well from the current vertical list, the so-called “interline glue” that TeX has inserted before the latter. But both of this operations are forbidden (leaving TeXnical details alone) in the normal mode of operation TeX is in when it is stacking paragraphs on the page: you need to enter “internal vertical mode”, and this accounts for the restrictions that had to be imposed on the contents of a JumpingParagraphs environment. These restrictions could be somewhat lifted by taking a slightly different approach (which, however, would increase the burden put on TeX’s memory), but even in this case two things would remain impossible:

• to include floats;

• to have footnotes and marginal notes.

These limitations could be acceptable, if they were effective; unfortunately, even with this method it cannot be guaranteed that the right alignment would be achieved in all cases, as the last example presented in my other answer shows.

The answer based on the use of zref-savepos measures, at \shipout-time, the horizontal position at which the “start” of the tabulation occurs, and uses this information to insert, during a subsequent LaTeX run, a horizontal space that is supposed to shift the ensuing text at the position one wants to tabulate to. However, the insertion of this space might alter TeX’s line-breaking decision, in such a way that, in the second run, the position of the “start” of the tabulation might change, thus invalidating the previous computation of the amount of horizontal space that should be inserted. Another LaTeX run is therefore required to compute a new value for this horizontal space, but the new value might again change TeX’s line-breaking decisions, and so on. Thus we see that the process is inherently iterative, and this has essentially one downside: there is no guarantee that this iterative process will come to an end, eventually finding a value for the horizontal space that remains the same on subsequent runs. Indeed, it is possible to build examples in which this process does not “converge”; even worse, since the exact horizontal position measured by zref-savepos depends on the computations for glue setting, that can be rounded differently on different machines, it is even possible that, for the same given input file, the process “converges” on some machines and not on others.

The approach used in this answer

This answer uses a hack based on a low-level feature of TeX which permits (provided that some conditions are met) to measure the length of the last line of a partial paragraph even in “outer” vertical mode, that is, in the mode TeX operates in while it is stacking paragraphs in the usual way: see The TeXbook, p. 188, second paragraph, description of \predisplaysize for details. Before measuring that line, the current partial paragraph is divided into lines (well, it wouldn’t make any sense to speak of its “last line”, otherwise!), and the line breaks that have been chosen are “frozen” so that they can no longer change. This approach has the following pros and cons:

1. It can be used in the normal mode LaTeX operates in, allowing all usual constructs (lists, floating objects, footnotes…) to intervene without disturbing the alignment mechanism.

2. It works in a single LaTeX run: therefore, it simply cannot suffer from any “convergence” problem.

3. On the other hand, since the low-level TeX feature on which it is based is not available under some circumstances, also this solution will not work under those same circumstances. Anyway, the code is capable of detecting when this happens, and will consequently issue an appropriate error message.

The package code

As already said above, this time I have written a complete package that implements the proposed solution, called ghoritab. Here is the code:

%%
%% This is file ghoritab.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% ghoritab.doc
%%
%% IMPORTANT NOTICE:
%%
%% For the copyright see the source file.
%%
%% Any modified versions of this file must be renamed
%% with new filenames distinct from ghoritab.sty.
%%
%% For distribution of the original source see the terms
%% for copying and modification in the file ghoritab.doc.
%%
%% This generated file may be distributed as long as the
%% original source files, as listed above, are part of the
%% same distribution. (The sources need not necessarily be
%% in the same archive or directory.)
%% \CharacterTable
%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%%   Digits        \0\1\2\3\4\5\6\7\8\9
%%   Exclamation   \!     Double quote  \"     Hash (number) \#

or more deeply nested position;


c) in your local (machine-wide) texmf tree, e.g.,

Well, it depends: for what concern the tab position
itself,\gotoghtab{\tabposB}it doesn't, as you can see here, and, continuing on
the next line,\gotoghtab{\tabposB}also here.  On the other hand, sooner or later
\verb|Overfull \hbox| warnings are guaranteed to appear, for the simple
reason\gotoghtab{\tabposB}that the line becomes too narrow for the tab
position\gotoghtab{\tabposB}that has been set.  But in this example we give
up\gotoghtab{\tabposB}before this happens, because we don't like such warnings!
In exchange, we \emph{set} a new tab stop right here:~\vissettab{\tabposC} we'll
use this new tab position after resuming the normal margins.

\endgroup

As you expect, the tab position\gotoghtab{\tabposC}set up inside the paragraph
having custom \verb|\parshape| is honored in normal'' paragraphs too, as you
can see again\gotoghtab{\tabposC}here, and also\gotoghtab{\tabposC}here.

\section{Setting the tab inside a list}
\label{S:Lists}

Generalizing what we saw in section~\ref{S:Basic}, we want to show that\ldots
%
\begin{itemize}
\item
\ldots you can also \emph{set} a tab stop inside a list\ldots

\item
\ldots also, let's say\ldots
\begin{itemize}
\item  \ldots at the second level, as we do here~\vissettab{\tabposC}
\item  (another item).
\end{itemize}

\item
then you can:
\begin{enumerate}
\item  use that stop\gotoghtab{\tabposC}at the same level
\item  (but with a different kind of list,\gotoghtab{\tabposC}as
here); \emph{or}
\item  use that tab at an inner level,
\begin{itemize}
\item  as it is done\gotoghtab{\tabposC}here
\item  (and here is another\gotoghtab{\tabposC}example);
\emph{or}
\end{itemize}
\end{enumerate}

\item
use always the same tab stop at\gotoghtab{\tabposC}an outer level;
\emph{or}, finally\ldots
\end{itemize}
%
\ldots use it at the level of normal text, that is,\gotoghtab{\tabposC}at the
outermost level.

Well, until now, everything seems fine, and our tab mechanism seems to perform
pretty well: you say Jump!'',\gotoghtab{\tabposC}and it jumps where you want;
you order Again!'',\gotoghtab{\tabposC}and it does it again, perhaps on the
next line; you can also set several tab positions within the same paragraph,
say, one here~\vissettab{\tabposA} and another one here~\vissettab{\tabposB}
(plus the one set inside the list, that, don't forget,
lies\gotoghtab{\tabposC}here); the tame printing head'' will
jump\gotoghtab{\tabposA}here,\gotoghtab{\tabposB}and
here,\gotoghtab{\tabposC}and here.  But the next section will reveal a drawback
of the algorithm\ldots

\section{Making up for incorrect line spacing}
\label{S:Interline}

When used without optional arguments, the \verb|\gotoghtab| and \verb|\setghtab|
commands assume that the line they occur on contains text with normal'' height
and depth.  If this is not the case, for example because of a tall in-line
formula like $$\displaystyle \frac{x}{y}-\frac{y}{x} = \frac{(x+y)(x-y)}{xy}$$, say,\gotoghtab{\tabposB}as you can see here the two halves of that line will
not be aligned.  Let us make another test using rules (a few more words, in
order to get to the next
line):~\rule[-5mm]{.4pt}{5mm}\gotoghtab{\tabposB}\rule{.4pt}{5mm}~The optional
arguments have been introduced exactly to provide a workaround for this.

When used without optional arguments, the \verb|\gotoghtab| and \verb|\setghtab|
commands assume that the line they occur on contains text with normal'' height
and depth.  If this is not the case, for example because of a tall in-line
formula \gotoghtab[like $$\displaystyle \frac{x}{y}-\frac{y}{x} = \frac{(x+y)(x-y)}{xy}$$, say,\rlap{\textcolor{subdued}{..\kern 1.6pt
aas}}]{\tabposB}as you can see here the two halves of that line will not be
aligned.  Let us make another test using rules (a few more words, in order to
get \gotoghtab[{to the next
line):~\rule[-5mm]{.4pt}{5mm}}\rlap{\textcolor{subdued}{.....\rule{.4pt}{5mm}}}]
[\rule{.4pt}{5mm}~The optional]{\tabposB} arguments have been introduced exactly
to provide a workaround for this.

\end{document}


The following pictures show the three pages you should obtain by typesetting it:

For the case of paragraphs, I found a solution using a \parbox to jump over its text. I can't tell if \hbox would be a better Idea. This solves the cases where the jump happens in the first line of a paragraph.

\newlength{\jumplength}
\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.


\settowidth{\LeftPartLength}{%