21

I've recently been asked whether the command to remove navigation bars in a Beamer presentation is the longest built-in LaTeX command:

\beamertemplatenavigationsymbolsempty

I've done some research but couldn't find anything that comes close to its 36 characters. Neither could I find any discussion of this completely fun trivial fact (although it might be useful to know for some procedural generation applications), so this seems like the right place to start one. The rules are: only the number of characters between the slash \ symbol and any option symbols ([ or {) count, and only commands that are built into the TeX core or commonly used packages and that do not depend on user data (such as those generated by \csname).

10
  • 3
    Welcome to TeX.SX! What is built-in for you? Many commonly used packages define macros on the fly with user data (by csnaming) which may get very long very easily.
    – TeXnician
    Dec 11 '20 at 11:01
  • 4
    An option rather than a command, but I use \documentclass[egregdoesnotlikesansseriftitles]{scrartcl} regularly.
    – Ingmar
    Dec 11 '20 at 11:01
  • @TeXnician Thanks! Yes, I realize that the question might not be fully precise yet, due to my lack of TeX knowledge. I wouldn't count anything that would require input from the user (like `\newcommand´), or that would have different names for different users, maybe depending on some options that they chose. Is that sufficiently precise?
    – Chris_77
    Dec 11 '20 at 11:08
  • 1
    I guess you'll have to ask @egreg … ? ETA: Actually, I think it might have started here: tex.stackexchange.com/questions/289853/…
    – Ingmar
    Dec 11 '20 at 12:01
  • 1
    @muzimuzhiZ You should write an answer :)
    – TeXnician
    Dec 11 '20 at 13:29
33

We can (sort of) find out.

Any LaTeX “command”—in TeX terminology, the escape character (usually backslash) followed by a control sequence—is put into the TeX program's internal hash table when it is defined. Using LuaTeX, we can look up this hash table directly, with tex.hashtokens.

\documentclass{article}
\usepackage{luacode}
\begin{document}
\begin{luacode}
function string.startswith(s, p) return string.sub(s, 1, string.len(p)) == p end
function string.contains(s, substring) return s:find(substring) ~= nil end

hashed = {}
count = 0
for i,v in pairs (tex.hashtokens()) do
   count = count + 1
   table.insert(hashed, v)
end
table.sort(hashed, function(a,b) return #a < #b end)
for i, v in ipairs(hashed) do
   if not (
      v:startswith('<')
      or v:contains(' ')
      or v:startswith('_')
   ) then
      print(#v, v)
   end
end   
print(string.format('There are %d entries in the hash table.', count))
\end{luacode}
\end{document}

When compiled with LuaTeX (need to invoke it with the environment variable hash_extra set to 0, because of a surprising behaviour/bug in LuaTeX), this prints many lines of output, ending with:

37  peek_charcode_remove_ignore_spaces:NT
37  peek_charcode_remove_ignore_spaces:NF
37  box_autosize_to_wd_and_ht_plus_dp:cnn
37  box_autosize_to_wd_and_ht_plus_dp:Nnn
37  c__text_mathchardef_group_begin_token
37  peek_catcode_remove_ignore_spaces:NTF
37  tex_scriptscriptbaselineshiftfactor:D
38  box_gautosize_to_wd_and_ht_plus_dp:cnn
38  use_none_delimit_by_q_recursion_stop:w
38  box_gautosize_to_wd_and_ht_plus_dp:Nnn
38  peek_charcode_remove_ignore_spaces:NTF
There are 13555 entries in the hash table.

Each of these would be invoked in LaTeX typically with a backslash (the escape character, that indicates to TeX that what follows is a control sequence to be looked up in the hash table), e.g. the last one as \peek_charcode_remove_ignore_spaces:NTF; we don't count the backslash in the character counts above. This is consistent with the question's example of counting \beamertemplatenavigationsymbolsempty as 36 rather than 37 characters.

The output above excluded some entries of the hash table:

  • The absolute longest entries in the hash table are strings like

    <-5.5>"[lmroman5-regular]:+tlig;"<5.5-6.5>"[lmroman6-regular]:+tlig;"<6.5-7.5>"[lmroman7-regular]:+tlig;"<7.5-8.5>"[lmroman8-regular]:+tlig;"<8.5-9.5>"[lmroman9-regular]:+tlig;"<9.5-11>"[lmroman10-regular]:+tlig;"<11-15>"[lmroman12-regular]:+tlig;"<15->"[lmroman17-regular]:+tlig;"
    

    which are some kind of internal font names. So let's exclude everything starting with a <.

  • The next longest is the 70-character entry @err@ (ending with 65 spaces); not sure what this is. But let's exclude entries containing spaces.

  • The next longest are entries like __text_change_case_letterlike_titleonly:nnN (length 43). Maybe the leading underscore indicates they're “internal” and not intended to be used by end users? Let's exclude those.

That leaves what you see above. The LuaTeX documentation mentions a caveat about tex.hashtokens:

note that this also reports control sequences that may be unreachable at this moment due to local redefinitions: it is strictly a dump of the hash table.

But there's a bigger caveat, which is the main problem with this question. Namely, a missing definition of “built-in LaTeX command”. One could make a precise definition as “commands built into LaTeX itself”, but that's clearly not what's intended by the question, as it includes the example \beamertemplatenavigationsymbolsempty from Beamer, and also mentions “built into the TeX core or commonly used packages”. (Beamer is a package that is not part of LaTeX itself; it's just a (widely used) package that someone happens to have written, which works with LaTeX and is distributed with TeX distributions like TeX Live / MiKTeX.)

For example, if we add \usepackage{tikz} near the top of the above file, we get different output:

44  pgfmath@operation@\pgfmath@bgroup@precedence
44  pgfmath@operation@\pgfmath@egroup@precedence
44  pgf@arrows@direct@name@end@{latex}[reversed]
44  pgfqkeysactivatesinglefamilyandfilteroptions
45  pgfkeys@ifexecutehandler@handlefullorexisting
45  pgf@plot@closedcurve@after@initial@presupport
45  pgfmathprintnumber@fixed@styleDEFAULT@DEC@SEP
45  pgfincludeexternalgraphics@read@dpth@line@EOI
45  pgfmathprintnumber@thousand@sep@in@fractional
46  pgfmathroundto@impl@ADD@ONE@ITERATE@gobble@dot
46  ifpgfmathround@impl@PREPERIOD@is@negative@zero
46  pgf@arrows@direct@name@end@{stealth}[reversed]
47  ifpgfmathprintnumber@thousand@sep@in@fractional
47  pgfmathprintnumber@RELATIVE@choice@roundtofixed
48  pgfmathroundto@impl@discard@suffix@zeros@ITERATE
48  pgfmathround@impl@PREPERIOD@is@negative@zerotrue
49  pgfmathprintnumber@fixed@styleDEFAULT@impl@period
49  pgfmathprintnumber@thousand@sep@in@fractionaltrue
49  pgfmathround@impl@PREPERIOD@is@negative@zerofalse
50  pgfmathprintnumber@fixed@styleDEFAULT@DEC@SEP@MARK
50  pgfmath@token@group@\pgfmath@bgroup\pgfmath@egroup
50  pgfmathprintnumber@thousand@sep@in@fractionalfalse
50  pgfincludeexternalgraphics@read@dpth@line@getfirst
50  pgfmathprintnumber@fixed@styleDEFAULT@THOUSAND@SEP
51  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod
52  pgfmathprintnumber@thousand@sep@in@fractional@finish
52  pgfmathprintnumber@RELATIVE@choice@roundtofixed@warn
53  pgfmathprintnumber@thousand@sep@in@fractional@finish@
56  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT
60  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printall
61  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printall@
61  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printsign
67  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@counteverythird
71  pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printtrailingdigits
There are 24340 entries in the hash table.

Many of the above are names internally generated by the package using \csname. You may want to exclude commands containing @ as they can be input only after \makeatletter, and are probably internal by convention. Still:

39  pgfmathfloatroundmayneedrenormalizetrue
39  pgfkeysactivatefamiliesandfilteroptions
40  pgfmathfloatroundmayneedrenormalizefalse
40  pgfmathfloatparsenumberpendingperiodtrue
40  pgfqkeysactivatefamiliesandfilteroptions
41  pgfmathfloatparsenumberpendingperiodfalse
43  pgfkeysactivatesinglefamilyandfilteroptions
44  pgfqkeysactivatesinglefamilyandfilteroptions

Loading further macros (adding further packages, or \usetikzlibrary etc) will change the output and somewhere there may exist a package that defines longer commands. For example, still excluding ones with @, with pgfmanual (suggested by user muzimuzhi Z in the comments):

38  box_gautosize_to_wd_and_ht_plus_dp:Nnn
38  ifpgfmathfloatparsenumberpendingperiod
38  use_none_delimit_by_q_recursion_stop:w
38  pgfmanualprettyprinternumcollectedargs
38  box_gautosize_to_wd_and_ht_plus_dp:cnn
38  peek_charcode_remove_ignore_spaces:NTF
39  pgfkeysactivatefamiliesandfilteroptions
39  ifpgfmanualprettyprinterfoundterminator
39  pgfmathfloatroundmayneedrenormalizetrue
40  pgfqkeysactivatefamiliesandfilteroptions
40  pgfmathfloatparsenumberpendingperiodtrue
40  pgfmathfloatroundmayneedrenormalizefalse
41  pgfmathfloatparsenumberpendingperiodfalse
41  pgfmanualprettyprinterhandlecollectedargs
41  pgfmanualprettyprinterfoundterminatortrue
42  pgfmanualprettyprinterfoundterminatorfalse
43  pgfkeysactivatesinglefamilyandfilteroptions
44  pgfqkeysactivatesinglefamilyandfilteroptions
45  ifpgfmanualprettyprinterarghasunmatchedbraces
45  pgfmanualprettyprinterhandlecollectedargsVtwo
47  pgfmanualprettyprinterarghasunmatchedbracestrue
48  pgfmanualprettyprinterarghasunmatchedbracesfalse

And as a sanity check, with \documentclass{beamer} instead, we do get the question's beamertemplatenavigationsymbolsempty and a few longer ones as well (this time I also removed expressions containing - or underscore or backslash, to keep this output smaller):

36  pgfmathprintnumberskipzeroperiodtrue
36  insertsubsectionnavigationhorizontal
36  beamertemplatenavigationsymbolsframe
36  beamertemplatenavigationsymbolsempty
36  pgfmathpointintersectionoflineandarc
36  beamertemplatesidebarverticalshading
36  pgfpagescurrentpagewillbelogicalpage
36  beamertemplatetransparentcoveredhigh
36  pgfrememberpicturepositiononpagetrue
36  MakeUppercaseUnsupportedInPdfStrings
36  beamertemplatenumberedballsectiontoc
36  MakeLowercaseUnsupportedInPdfStrings
37  useleftsidebarverticalshadingtemplate
37  pgfapproximatenonlineartransformation
37  pgfkeysaddhandleonlyexistingexception
37  pgfhorizontaltransformationadjustment
37  insertbackfindforwardnavigationsymbol
37  beamertemplatesphereminiframeinverted
37  ifpgfmathfloatroundmayneedrenormalize
37  beamertemplatecircleminiframeinverted
37  pgfmathprintnumberskipzeroperiodfalse
37  pgfrememberpicturepositiononpagefalse
38  beamertemplatenumberedcirclesectiontoc
38  beamertemplatesidebarhorizontalshading
38  ifpgfmathfloatparsenumberpendingperiod
38  beamertemplatetransparentcoveredmedium
38  userightsidebarverticalshadingtemplate
38  beamertemplatenumberedsquaresectiontoc
39  beamertemplatenavigationsymbolsvertical
39  pgfkeysactivatefamiliesandfilteroptions
39  useleftsidebarhorizontalshadingtemplate
39  beamertemplatetransparentcoveredhighest
39  beamertemplatetransparentcovereddynamic
39  pgfmathfloatroundmayneedrenormalizetrue
40  pgfqkeysactivatefamiliesandfilteroptions
40  pgfmathfloatroundmayneedrenormalizefalse
40  pgfmathfloatparsenumberpendingperiodtrue
40  userightsidebarhorizontalshadingtemplate
40  beamertemplaterightsidebarlogonavigation
41  pgfmathfloatparsenumberpendingperiodfalse
41  beamertemplatenavigationsymbolshorizontal
43  pgfkeysactivatesinglefamilyandfilteroptions
44  pgfqkeysactivatesinglefamilyandfilteroptions
45  beamertemplatetransparentcovereddynamicmedium
5
  • 2
    Hmm, there's obviously a bug somewhere, because with \documentclass{beamer} the above code (iterating over tex.hashtokens) doesn't seem to find beamertemplatenavigationsymbolsempty even though \beamertemplatenavigationsymbolsempty is defined. How can this be? (It does find beamertemplatenavigationsymbolsvertical and beamertemplatenavigationsymbolshorizontal which are both longer…) Dec 11 '20 at 14:28
  • Amazing work! I'll accept the answer as is, but it would of course be great if we could still figure out whether anythings' missing, based on the above comment.
    – Chris_77
    Dec 11 '20 at 15:05
  • Cheers! I don't have enough reputation yet to upvote it, hope we'll find the answer :)
    – Chris_77
    Dec 11 '20 at 16:34
  • 1
    @Chris_77 I got an answer at the other question; there were indeed a few things missing and I've updated the answer to account for them. So all should be fine now. Dec 11 '20 at 18:04
  • Amazing!! I like how the ones from Beamer still come out on so high :D
    – Chris_77
    Dec 12 '20 at 9:25
12

This is actually very hard to answer. The LaTeX kernel (very frequently used package ;)) loads expl3. It has commands like \use_none_delimit_by_q_recursion_stop:w (39 chars).

I don't actually know whether there are longer macro names but many packages do something like

\csname module@property@#1\endcsname`

and therefore generate macro names often based on user data (e.g. keys in key-value interfaces etc.). Are these built-in? Probably yes, because they are implicitly defined in commonly used packages.

So while I think that thorough investigation will yield very long macro names, without a clear definition of built into in a language of TeX's kind this question does not have a definitive answer.

4
  • Great answer, thanks! If we count the colon character and anything following it, then `use_none_delimit_by_q_recursion_stop:w´ by my count has 38 chars, not 40, but it still beats the previous example. I wouldn't count anything that depended on user data, so I edited the question - does it give a sufficiently clear definition of what's built-in now?
    – Chris_77
    Dec 11 '20 at 11:22
  • @Chris_77 For expl3 commands :w is part of the command. Otherwise you did not identify the command, so excluding it does not make sense. The definition is now better but I can't improve my answer based on that :D
    – TeXnician
    Dec 11 '20 at 12:12
  • @TeXnician Note that use_none_delimit_by_q_recursion_stop:w has 38 characters (counting like the OP, where beamertemplatenavigationsymbolsempty has 36 characters). If you include the backslash, you still get only 39 characters, not 40. Maybe you included a trailing newline as well, to get 40? Dec 11 '20 at 12:28
  • @ShreevatsaR Thanks. I would love to blame wc but I should have known better :D
    – TeXnician
    Dec 11 '20 at 12:38

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.