I took your comment
Almost. Thank you. \Command{\hbox{This box should be part of the paragraph, too} text text}{Left justified?}
does not work out...
on David Carlisle's answer into account:
The horizontal box of width \parindent
at the beginning of horizontal mode is produced and set without carrying out the hook \everyhbox
.
Thus you can create a mechanism for setting an \if...
-switch in case \everyhbox
/\everyvbox
is triggered before \everypar
:
Create a temporary vertical box from \Command
's first argument.
While creating that temporary vertical box prepend to the hooks \everyhbox
/\everyvbox
a macro-token which globally sets an \if...
-switch.
Prepend to each of the hooks \everyhbox
/\everyvbox
and \everypar
a directive to restore all these hooks.
Effect:
In case \everypar
is carried out before \everyvbox
or \everyhbox
, the hooks will be restored and thus the directive to change the \if..
-switch appended to \everyhbox
/\everyvbox
is gone and will never be carried out.
In case \everyvbox
or \everyhbox
is carried out before \everypar
, the directive to set the \if
-switch is carried out once and all the hooks are restored.
As three hooks (\everypar
, \everyvbox
, \everyhbox
) are involved, I defined a recursive routine \prependtorestorehooks
where you can provide a list of tuples, first component denoting a hook, second component denoting tokens for this hook to deliver before restoring all hooks in the tuple-list and delivering the tokens which the hook also delivered before redefining.
You also need some precautions in case the mechanism/\Command
is nested.
Caveats:
Appending to hooks/restoring hooks only works as long as the hooks themselves do not contain \outer
-tokens. E.g., the following code yields an error-message ! Forbidden control sequence found while scanning text of \everypar.
:
\begingroup
\everypar={\problem}%
\outer\def\problem{How to overcome the problem?}%
\everypar=\expandafter{\the\everypar Again: How to overcome the problem?}%
\endgroup
\bye
\everyhbox
/\everyvbox
is triggered when creating a \hbox
/\vbox
no matter if that box makes it into the output-file or goes into a box-register whose content will never make it into the output-file. Thus the mechanism can be fooled by placing, e.g., a \setbox
-assignment in the beginning of \Command
's argument.
A temporary \vbox
is created from \Command
's first argument for setting the \if...
-switch in case \everyhbox
/\everyvbox
is triggered before \everypar
. Thus the material of \Command
's first argument is processed twice: Once for creating the temporary box. Once for creating the paragraph that should go into the output-file. There might be things like \immediate\write
which you don't want to have carried out twice. Unfortunately there is no "get-box-properties"/"box-measuring"-mode where such things could be turned off.
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
%\prependtorestorehooks{%
% {{hook 1}{prepend 1}}%
% {{hook 2}{prepend 2}}%
% ...
%}%
\long\def\prependtorestorehooks#1{%
\prependtorestorehookscreraterestore{}{#1}#1\relax
}%
\long\def\prependtorestorehookscreraterestore#1#2#3{%
% #1 - Restore-List created so far
% #2 - entire list
% #3 - next element
\ifx\relax#3\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{\prependtorestorehooksprependtohooks{}{#1}#2\relax}%
{%
\prependtorestorehooksextract#3{#1}{#2}%
}%
}%
\long\def\prependtorestorehooksextract#1#2{%
\expandafter\prependtorestorehooksextractinner\expandafter{\the#1}{#1}%
}%
\long\def\prependtorestorehooksextractinner#1#2#3{%
\prependtorestorehookscreraterestore{#3#2={#1}}%
}%
\long\def\prependtorestorehooksprependtohooks#1#2#3{%
%#1 prepend-list-created so far
%#2 restore-list
%#3 {hook}{prepend}
\ifx\relax#3\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
{#1}{%
\prependtorestorehooksprependtohooksb#3{#1}{#2}%
}%
}%
\long\def\prependtorestorehooksprependtohooksb#1{%
\expandafter\prependtorestorehooksprependtohooksc\expandafter{\the#1}{#1}%
}%
\long\def\prependtorestorehooksprependtohooksc#1#2#3#4#5{%
\prependtorestorehooksprependtohooks{#4#2={#3#5#1}}{#5}%
}%
%------------------------------------------------------------------------------------
\newbox\MyBox
\newif\ifleadingbox
\newif\ifintestbox\intestboxfalse
\newif\ifhookdone\hookdonefalse
\def\firstindent{}%
\long\def\setifleadingboxandfirstindent#1{%
\begingroup
\ifintestbox\else\global\hookdonefalse\global\leadingboxfalse\fi
\setbox\MyBox=\vbox{%
\intestboxtrue
\prependtorestorehooks{%
{{\everypar}{\ifhookdone\else\setbox\MyBox=\lastbox\xdef\firstindent{\the\wd\MyBox}\box\MyBox\global\hookdonetrue\fi}}%
{{\everyhbox}{\ifhookdone\else\global\leadingboxtrue\global\hookdonetrue\fi}}%
{{\everyvbox}{\ifhookdone\else\global\leadingboxtrue\global\hookdonetrue\fi}}%
}%
#1%
}%
\endgroup
}%
\long\def\Command#1#2{%
\par
\setifleadingboxandfirstindent{#1}%
\prependtorestorehooks{{{\everypar}{\setbox\MyBox\lastbox\llap{#2}\box\MyBox}}}%
\ifleadingbox\leavevmode\else\noindent\hbox to\firstindent{\hfill}\fi#1%
}%
\leavevmode
\kern-1in
\noindent test \hfill test \hfill test
\setifleadingboxandfirstindent{a}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\setifleadingboxandfirstindent{\hbox{a}}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\setifleadingboxandfirstindent{\vbox{a}}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\setifleadingboxandfirstindent{\noindent\vbox{a}}%
\ifleadingbox some \else no \fi leading h-or vbox.
\ifleadingbox\else Paragraph is indented by: \firstindent\fi
\smallskip\hrule\smallskip
\noindent {\bf Test 1:}
\Command{The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 2:}
\Command{\noindent The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 3:}
\Command{\hbox to 5cm{The\hfill wide\hfill text} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 4:}
\Command{\noindent\hbox to 5cm{The\hfill wide\hfill text} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 5:}
\Command{\vtop{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 6:}
\Command{\noindent\vtop{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 7:}
\Command{\vbox{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 8:}
\Command{\noindent\vbox{\hbox to 5cm{The\hfill wide\hfill text}\hbox to 5cm{The\hfill wide\hfill text}} of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 9:}
\newdimen\MyDimen
\setbox\MyBox=\hbox{Left justified?}
\MyDimen=\wd\MyBox
\Command{\noindent\kern\MyDimen The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 10:}
\Command{\leavevmode\kern\MyDimen The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 11:}
\Command{\noindent\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\Command{\noindent The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 12:}
\Command{\noindent\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\Command{The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 13:}
\Command{\leavevmode\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\advance\hsize-\parindent\Command{\noindent The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 14:}
\Command{\leavevmode\kern\MyDimen \hbox{\vbox{\advance\hsize-\MyDimen\advance\hsize-\parindent\Command{The text of the paragraph.}{Left justified?}}}}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 15:}
\Command{\kern\MyDimen The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 16:}
% `\Command` starts with `\par`, i.e., by resorting to (restricted) vertical mode. Thus \kerns at the beginning of \Command's first argument in any case are vertical.
\Command{\kern\MyDimen\noindent The text of the paragraph.}{Left justified?}
\smallskip\hrule\smallskip
\noindent {\bf Test 17:}
% `\Command` starts with `\par`, i.e., by resorting to (restricted) vertical mode. Thus \kerns at the beginning of \Command's first argument in any case are vertical.
\Command{\kern\MyDimen\hbox{T}he text of the paragraph.}{Left justified?}
\smallskip\hrule\bigskip
\noindent {\bf Test 18:}
\Command{The text of the paragraph. \par The text of the paragraph. \par The text of the paragraph.\Command{\noindent The text of the paragraph. \par The text of the paragraph. \par The text of the paragraph.}{Left justified?}}{Left justified?}
\smallskip\hrule\bigskip
\noindent{\bf !!!! But: !!!}
\bigskip
\noindent {\bf Test 19:}
\Command{\setbox\MyBox=\hbox{Something to trigger the every-hook}\noindent This text is indented although it should not be indented. The reason is the triggering of {\tt\string\everyhbox} by {\tt\string\setbox...} right at the beginning of {\tt\string\Command}'s first argument.}{Left justified?}
\bye

To be honest:
I don't know why all this is needed. In the manual of \Command
just tell that TeX switches to vertical mode before processing #1
. The user can decide her-/himself if explicit \leavevmode
or \noindent
is needed for switching to horizontal-mode.
\parskip
-glue. Then initiating horizontal list by hbox of width\parindent
(unless horizontal mode was initiated by\noindent
), then the tokens held in\everypar
, then processing the...\everypar
you can "lay hands" on the\parindent
-box via\lastbox
which will remove the last box from the list and move it to the box-register of your choice. This is what David Carlisle did in his answer.