# Dynamically Center Text above First Line Of Paragraph

I'm trying write a custom command that centers the text entered as the first parameter above the first line of the text entered as the second parameter.

\documentclass{article}
\newcommand{\centerCaption}[2]{
\textbf{#1}\par
#2
}
\parindent=0pt
\begin{document}
\centerCaption{Caption}{%
This is a short line.\\
This is a longer line with extra text.}
\end{document}


This should output something like this:

     Caption
This is a short line.
This is a longer line with extra text.


Is there a way to detect the width of only the first line of a given text? Or how else could this be done?

EDIT: I'm sorry If my question was unclear. I want the first argument to be centered relative to "This is a short line" in this example and in general centered relative to the first line of my second argument, no matter how many lines there are. That is why I asked for a way to determine the width of only the first line, disregarding subsequent lines.

I intend to use this in a script for a theatre play, to center the name of the character relative to the first spoken line, so there is no alternative captioning already implemented. I know that there are dedicated packages for screenplays, etc., but I've got everything set up correctly apart from this issue.

• Welcome to the site. Your question is not clear. Your "2nd line of text" (2nd argument) is actually multiple lines. Is "Caption" centered relative to "This is a short line" or centered relative to the longer line with extra text? Is this actually intended as part of a table or figure where actual captioning facilities exist? Jan 16 '20 at 11:11
• I edited my original post to answer your questions. Jan 16 '20 at 11:21
• You could also use a tabular, but you still would need to extract the second line separately. Jan 16 '20 at 14:48

The problem is greatly simplified if the line below "Caption" is its own argument. And while I retained the remainder of the caption as an argument (#3), there is (at least for this example) no compelling reason to do so...I could eliminate the use of #3 altogether.

\documentclass{article}
\usepackage{stackengine}
\newcommand{\centerCaption}[3]{%
\stackengine{\baselineskip}{#2}{\textbf{#1}}{O}{c}{F}{F}{L}\par
#3
}
\parindent=0pt
\begin{document}
\centerCaption{Caption}{%
This is a short line.}{
This is a longer line with extra text.}
\end{document}


Here is the version without the use of #3...same result.

\documentclass{article}
\usepackage{stackengine}
\newcommand{\centerCaption}[2]{%
\stackengine{\baselineskip}{#2}{\textbf{#1}}{O}{c}{F}{F}{L}\par
}
\parindent=0pt
\begin{document}
\centerCaption{Caption}{%
This is a short line.}
This is a longer line with extra text.
\end{document}


EXTRACTION TECHNIQUE

While it is easier to combine rather than extract text, here is a way the first line (prior to \\) can be extracted from a larger argument. Limitation: one occurrence of \\ in argument.

\documentclass{article}
\usepackage{stackengine,listofitems}
\newcommand\centerCaption[2]{%
\setsepchar{\\}%
\centerCaptionaux{#1}{\linesep[1]}{\linesep[2]}
}
\newcommand{\centerCaptionaux}[3]{%
\stackengine{\baselineskip}{#2}{\textbf{#1}}{O}{c}{F}{F}{L}\par
#3
}
\parindent=0pt
\begin{document}
\centerCaption{Caption}{%
This is a short line.\\
This is a longer line with extra text.}
\end{document}

• Thank you for your answer. Your suggestions work, but I was looking for a way to pass the text as a whole, rather than seperate the first line from the rest of the text. As I have to pass the whole text to another command which will then contain the code I am looking for and will additionally handle indentation and such, your second suggestion would not be an applicable solution, because I have to pass the whole text at once. Is there another solution which can work out the first line automatically? Jan 16 '20 at 12:15
• @SirTeddytheFirst Well, it is easier to combine than to extract text. One could add a line to the macro saying, \def\fulltext{#2\\#3} and then \fulltext would be available to pass to the next macro. On the other hand, if you insist on extraction, then you would need to insure that you use the prescribed separator between the first line and the rest of the argument, for example, \\. Then, a package like listofitems could easily extract what comes before the first \\ and what comes after. Jan 16 '20 at 12:31
• Well, then I'm going to thank you for your help, I think you've given me enough input to figure this out. I now have to decide how I'm going to do it. Jan 16 '20 at 12:36
• @SirTeddytheFirst I edited to show an extraction approach. Jan 16 '20 at 12:38