AFAIK, LaTeX's comments are what is between a pair of characters with category code respectively:

  • 14 (normally a %),
  • 5 (normally an end of line).

Is it possible to define another pair of characters (say @*) such that all in between is discarded from the output? More explicitly, I want the output of:

foo @bar *baz

to be: "foo baz"

Note that my question is not how to define characters of categories 14 and 5: in particular, I don't want @ to be of category 14 since I don't want all what follows on the current line to be discarded from the output.

  • 1
    But you are explicitly saying that you want to remove everything in between but at the same time foo<space>@bar*<space>baz should convert to foo<space>baz rather than the logic foo<space><space>baz? – Manuel Mar 13 '18 at 15:10
  • @Manuel Indeed. I'll edit my question. – Denis Bitouzé Mar 13 '18 at 15:21
  • luatex a possibility? – David Carlisle Mar 13 '18 at 23:13

You can make the first character active (catcode 13) and define it as a macro.


TeX will match everything after @ up to the character * as #1, and then expand to the definition, which is blank. Use \long\def if you'd like to allow newlines between @ and *

For example, it works with foo @bar *baz as the question asks:




% Because I use \verb below for illustration and I'd like the character @ to be treated verbatim too.
\def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&\do\#\do\^\do\_\do\%\do\~\do\@}
% ^ The above is the standard definition of \dospecials, with "\do\@" appended. Could also write:
% \let \dospecialsOld = \dospecials
% \def\dospecials{\dospecialsOld\do\@}

foo baz (typed \verb|foo baz|)

foo %bar
baz (typed \verb|foo %bar<newline>baz|)

foo @bar
*baz (typed \verb|foo @bar<newline>*baz|)

foo @bar *baz (typed \verb|foo @bar *baz|)


foo @bar* baz (typed \verb|foo @bar* baz|)

foo {} baz (typed \verb|foo {} baz|)


Note that with this definition, the starting character @ cannot be used for anything else by default (without changing its catcode again), just as with the usual catcodes the character % cannot be used for anything other than comments. (Also, for the character @ in particular, note that using \makeatletter and \makeatother will clobber our definition and we'd have to set the catcode to \active again.)

Note also that the behaviour of skipping leading spaces on the next line, that you get with from-%–to-end-of-line comments, is different (to get it, you have to put the closing * after the spaces):


| improve this answer | |
  • Nice! Unfortunately, I can't make it work in my real use case (much more complicated, involving LaTeX source code: printed thanks to listings, processed and resulting PDF included, \newenvironment involved, etc.). I'll try to see what's going on. – Denis Bitouzé Mar 13 '18 at 15:29
  • @Denis: Also make sure that @ isn't used for anything else, as it tends to be in LaTeX code. :-) – ShreevatsaR Mar 13 '18 at 15:51
  • That's what I'm fighting against: almost all the characters I'm trying are used by at least one package I'm loading. – Denis Bitouzé Mar 13 '18 at 16:03
  • 1
    @DenisBitouzé Another option is, instead of making a character active, use a short macro, like \? to delimit the comment. You can use the same macro to close it out, via \long\def\?#1\?{} – Steven B. Segletes Mar 13 '18 at 16:26
  • 1
    @DenisBitouzé I added some examples. Also, note that you probably want to define this after you've loaded the packages you want. Once all packages are loaded, the re-definition of @ (or whatever character) should only affect input that comes later in the same file, and not what has been defined earlier. (And Steven's suggested option is also a good one, without messing with catcodes. In fact the closing character can be anything even if it has a different catcode, e.g. \def\?#1${} to start with \? and end with $.) – ShreevatsaR Mar 13 '18 at 17:05

If luatex is a possibility you can make the substitution on the text stream before TeX tokenizes the input, so before you need to worry about catcodes

enter image description here

function at_star_comment (s)
return string.gsub(s,'@[^*]*\@percentchar*','')
luatexbase.add_to_callback("process_input_buffer", at_star_comment, "comment between @ and *")

foo @bar *baz

even mismatched braces \fbox{zz@  lose this brace} * this gets boxed} 

| improve this answer | |
  • I'd like to stay away from luatex as long as possible since my real document (based on beamer class) takes quite a long time to compile with pdflatex and that's significantly worse with luatex :) – Denis Bitouzé Mar 14 '18 at 10:19
  • 1
    @DenisBitouzé you could of course do the equivalent filter of the input buffer with pdflatex if instead of processing the source file you process the output of sed -e -s/@[^\*]*\*/g' file.tex – David Carlisle Mar 14 '18 at 11:19
  • Indeed but I'd like to stay away from external tools as well. I'm very demanding, am I not? :) – Denis Bitouzé Mar 14 '18 at 11:26
  • @DenisBitouzé there is the other answer (discarding the text as a macro argument) but like any macro argument, that is hard to make work if you want read the text verbatim and skip over mis-matched braces as in my example (or % etc) – David Carlisle Mar 14 '18 at 11:32

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.