10

I would like to write an \unpar macro which removes last \par. For example, the TeX code

 This is a \par \unpar paragraph

should be equivalent to

 This is a paragraph

(Note that by equivalent I mean not that it has to produce exactly the last token list: I mean that it should have the same output as the one I will obtain using the last token list.)

A solution could be to redefine \par in the following way:

\let\oldpar\par
\def\unpar{}
\long\def\par#1{\ifx#1\unpar\else\oldpar#1\fi}

But this does not work if \bye is preceeded by a \par (I don't know why). Furthermore, a redefinition of \par could possibly break some macro package. So, I was wondering: Is there a way to define \unpar without modifying \par?

And what about an \Unpar macro which removes not just a single \par but all \pars preceeding it?

7
  • \long\def\par#1{\ifx#1\unpar\else\csname @firstofone\expandafter\endcsname\fi{\oldpar#1}} would work, if I'm not mistaken.
    – Manuel
    Commented Nov 28, 2015 at 10:04
  • You can't undo a \par (when the command has its primitive meaning). Can you please show a typical use case for your \unpar command?
    – egreg
    Commented Nov 28, 2015 at 10:37
  • 1
    I see no way, unless you redefine \par to look for \enddemo
    – egreg
    Commented Nov 28, 2015 at 11:14
  • 1
    @User but what if "the last line" has already been shipped out on the previous page? In general you need to set things up in advance, with \demo to redefine \par not to do a real \endgraf until it has looked ahead, or perhaps set the whole thing in a vbox, then unbox it \lastskip any vertical skip add your end marker then \unvbox` the contents on to the main list for the page. Commented Nov 28, 2015 at 11:18
  • 1
    @User -- it's simply better to avoid a blank line before \enddemo. if you want a visual gap in the input, put a % at the beginning of the otherwise empty line. Commented Nov 28, 2015 at 21:14

2 Answers 2

10

This is not possible.

TeX sees \par.

At this point the current horizontal list is split into a vertical list of horizontal boxes, hyphenation is applied if necessary, discardable glue is discarded and left and right glue is added. Then the output routine is invoked, which may output one or more pages, possibly taking stored inserts and footnotes, and adding them to the page, then control is returned to the input stream, in vertical mode.

It would be hard to define \unpar to undo all this.

3
  • But would redefine \par be that impossible? Of course you can't undo, but TeX inserts the token \par automatically when a blank line appears, but it doesn't need to be the primitive \par (or am I mistaken?).
    – Manuel
    Commented Nov 28, 2015 at 15:14
  • @Manuel macros redefine \par all the time that's why plain has \endgraf and latex has \@@par to save the original definition while \par is redefined. But the question was whether you could avoid that. Commented Nov 28, 2015 at 15:59
  • 1
    @Manuel In l3galley we set things up such that the 'real' \par is not inserted until we are sure there's been no look-ahead for more-or-less exactly the reason David gives: you can't remove a 'real' \par.
    – Joseph Wright
    Commented Nov 30, 2015 at 13:37
10

You can try something like this:

\def\par{\futurelet\next\dopar}
\def\dopar{\let\doparA=\endgraf
           \ifx\next\par \let\doparA\relax \fi
           \ifx\next\unpar \let\doparA\relax \fi
           \doparA}
\def\unpar{\donothing{unpar}} % any special macro with empty output
\def\donothing#1{}


This is paragraph.

Note more empty lines here:



\unpar
The paragraph is not finished.

\bye

Of course, you must redefine \par. There is no another possibility (it was explained by David Carlisle).

Your mistake was: you tried to scan next token by #1 (macro parameter), not by \futurelet, wich is much more robust. The \outer defined macros (like \bye) cannot be loaded to #1 but they can be tested using \futurelet. If the next token is { then #1 scanning does much more work than you need to do. But \futurelet keeps the { without any changing.

4
  • Thank you! But why \def\unpar {\donothing{unpar}} \def\donothing#1{} instead of a simpler \def\unpar{}?
    – User
    Commented Nov 30, 2015 at 20:35
  • 1
    @User because \unpar is equivalent to \empty after \def\unpar{}. And then \par \empty has the same behaviour as \par \unpar. This is not what you need.
    – wipet
    Commented Nov 30, 2015 at 21:13
  • @User For your application: You cannot include \unpar into \enddemo macro body because \futurelet does not look inside the expanded next token. Better is to add the test \ifx\next\enddemo \let\doparA\relax\fi to the \dopar definition. Then you need not the trick with \donothing because \unpar will never used by user (nor @User).
    – wipet
    Commented Dec 1, 2015 at 5:22
  • Yes, I already figured that out and comed to a solution similar to this even before you answered my question. Anyway, your answers are always welcome: There's always something to learn from you :)
    – User
    Commented Dec 1, 2015 at 7:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .