9

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?

  • \long\def\par#1{\ifx#1\unpar\else\csname @firstofone\expandafter\endcsname\fi{\oldpar#1}} would work, if I'm not mistaken. – Manuel Nov 28 '15 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 Nov 28 '15 at 10:37
  • 1
    I see no way, unless you redefine \par to look for \enddemo – egreg Nov 28 '15 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. – David Carlisle Nov 28 '15 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. – barbara beeton Nov 28 '15 at 21:14
9

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.

  • 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 Nov 28 '15 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. – David Carlisle Nov 28 '15 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 Nov 30 '15 at 13:37
9

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.

  • Thank you! But why \def\unpar {\donothing{unpar}} \def\donothing#1{} instead of a simpler \def\unpar{}? – User Nov 30 '15 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 Nov 30 '15 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 Dec 1 '15 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 Dec 1 '15 at 7:52

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.