4

The MWE below produces the desired results:

enter image description here

via the \ProcessLastPara{} which applies a desired \parshape to the given (last) paragraph.

Questions:

The MWE below required me to manually identify both the start and end of the last paragraph so it could be passed on to the \ProcessLastPara{} macro.

  1. Is it possible to achieve the effect of \ProcessLastPara{<text>} by simply identifying the beginning of the last paragraph. That is, can I change the call to \SetMyText to be of the form:

    \SetMyText{%
       Other Text... 
    
       \LastParaBeginsHere
       Last Para Text%
    }%
    

    so that \LastParaBeginsHere invokes\ProcessLastPara{Last Para Text}.

    This would need some error checking to make sure that \LastParaBeginsHere really was indeed the last paragraph defined by \SetMyText.

  2. Is it possible to auto detect where the last paragraph begins and ends so that I do not need to manually invoke \ProcessLastPara{} and identify the text of the last paragraph?

Notes:

  • This needs to work for the case where the text is defined in a macro before it is typeset.
  • The solution of \def\LastParaBeginsHere{\LastParShape} won't work as I need to process the last paragraph text to determine the appropriate \parshape to apply. That is, this is a 2 step process, the details of which are not included here to simplify the test case.

Code:

\documentclass{article}

\usepackage[paperwidth=15cm]{geometry}

\makeatletter
    \newcommand{\@MyText}{}
    \newcommand{\SetMyText}[1]{\def\@MyText{#1}}%
    \newcommand*{\OutputMyText}{\@MyText}%
\makeatother

\newcommand*{\LastParShape}{%
    \parshape 5
    0.10\hsize 0.80\hsize
    0.15\hsize 0.70\hsize
    0.20\hsize 0.60\hsize
    0.25\hsize 0.50\hsize
    0.30\hsize 0.40\hsize
}%


\newcommand*{\ProcessLastPara}[1]{%
    \LastParShape
    #1}%

\begin{document}
\SetMyText{%
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 
    incididunt ut labore et dolore magna aliqua. 

    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut 
    aliquip ex ea commodo consequat. 

    \ProcessLastPara{%
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore 
    eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia 
    deserunt mollit anim id est laborum.}%
}%
%% ----------------
\OutputMyText%
\end{document}
  • do you want the para indent on the first line of your triangle, I cancelled it out (not quite correctly) in my answer but I could remove it to get the same shape that you and egreg show... – David Carlisle Dec 12 '18 at 9:15
  • @DavidCarlisle: Removing indentation of the last para is preferrable. – Peter Grill Dec 12 '18 at 17:59
5
\documentclass{article}

\usepackage[paperwidth=15cm]{geometry}

\makeatletter
    \newcommand{\@MyText}{}
    \newcommand{\SetMyText}[1]{\def\@MyText{#1\LastParShape\par}}%
    \newcommand*{\OutputMyText}{\@MyText}%
\makeatother

\newcommand*{\LastParShape}{%
    \parshape 5
    \dimexpr0.10\hsize-\parindent\relax \dimexpr0.80\hsize+\parindent\relax
    0.15\hsize 0.70\hsize
    0.20\hsize 0.60\hsize
    0.25\hsize 0.50\hsize
    0.30\hsize 0.40\hsize
}%



\begin{document}
\SetMyText{%
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 
    incididunt ut labore et dolore magna aliqua. 

    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut 
    aliquip ex ea commodo consequat. 

    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore 
    eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia 
    deserunt mollit anim id est laborum.%
}%
%% ----------------
\OutputMyText%
\end{document}

enter image description here

  • 1
    I didn't even need egreg's hat. – David Carlisle Dec 12 '18 at 9:10
  • What kind of sorcery is this? You can specify the \parhsape after the paragraph (ie, after the #1 in \SetMyText)? However, this won't work as per second point in the Notes. I need the content of the last paragraph to be passed to \ProcessLastPara{} as a parameter so that I can determine the correct \parshape to apply. – Peter Grill Dec 12 '18 at 17:58
  • @PeterGrill I saw that note but decided just to answer the question as asked, as I wanted to demonstrate this (which uses a few orders of magnitude fewer macro expansions than egreg's:-) (you could of course add a \noindent to the code in your question and egreg's answer to get the full length top row. – David Carlisle Dec 12 '18 at 18:45
  • 1
    @DavidCarlisle Very nice and concise answer, but I'm really confused by putting the \LastParShape after #1. I wish you would have time to explain more about it. – javadr Dec 12 '18 at 19:12
  • 2
    @javadr paragraph settings, whether \parshape or \centering etc use the settings in force at the end of the paragraph, which is why you often see on this site warnings that {\centering hello} does not center as the settings are discarded but {\centering hello\par} does center, as does {\noindent hello\centering\par} setting the parshape is the same, it sets the linebreaking but is not consulted until tex starts linebreaking which is at the end of the paragraph. – David Carlisle Dec 12 '18 at 19:44
3

It's quite easy with expl3: collect the text, split it at \par, then detach the last paragraph and typeset it separately.

\documentclass{article}
\usepackage[paperwidth=15cm]{geometry}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\SetMyText}{s+m}
 {
  \IfBooleanTF{#1}
   {
    \seq_set_split:NnV \l_peter_mytext_seq { \par } #2
   }
   {
    \seq_set_split:Nnn \l_peter_mytext_seq { \par } { #2 }
   }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { NnV }
\seq_new:N \l_peter_mytext_seq
\tl_new:N \l_peter_mytext_tl

\NewDocumentCommand{\OutputMyText}{}
 {
  \seq_pop_right:NN \l_peter_mytext_seq \l_peter_mytext_tl
  \seq_use:Nn \l_peter_mytext_seq { \par } \par
  \LastParShape \l_peter_mytext_tl
 }
\ExplSyntaxOff

\newcommand*{\LastParShape}{%
    \parshape 5
    0.10\hsize 0.80\hsize
    0.15\hsize 0.70\hsize
    0.20\hsize 0.60\hsize
    0.25\hsize 0.50\hsize
    0.30\hsize 0.40\hsize
}

\begin{document}

\SetMyText{
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 
    incididunt ut labore et dolore magna aliqua. 

    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut 
    aliquip ex ea commodo consequat. 

    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore 
    eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia 
    deserunt mollit anim id est laborum.
}

\OutputMyText

\end{document}

enter image description here

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.