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
    Commented Mar 13, 2018 at 15:10
  • @Manuel Indeed. I'll edit my question. Commented Mar 13, 2018 at 15:21
  • luatex a possibility? Commented Mar 13, 2018 at 23:13

2 Answers 2


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):


  • 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. Commented Mar 13, 2018 at 15:29
  • @Denis: Also make sure that @ isn't used for anything else, as it tends to be in LaTeX code. :-) Commented Mar 13, 2018 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. Commented Mar 13, 2018 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\?{} Commented Mar 13, 2018 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 $.) Commented Mar 13, 2018 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} 

  • 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 :) Commented Mar 14, 2018 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 Commented Mar 14, 2018 at 11:19
  • Indeed but I'd like to stay away from external tools as well. I'm very demanding, am I not? :) Commented Mar 14, 2018 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) Commented Mar 14, 2018 at 11:32

You must log in to answer this question.

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