I've repeatedly read that Lua can do some cool under-the-hood things to TeX. One thing that comes to mind: I have a rather forgetful coworker who always used a hyphen instead of en-dash between two numbers, ie: 0-60 instead of 0--60. I thought this would be a cool challenge (and selfishly good for my learning) to ask the following:

Could a Lua-based macro (or two) to enable/disable changing a - to -- if it is between two numbers?


1 Answer 1


I think there are two ways to interpret your request.

  • You could be looking for a LaTeX macro that takes an argument and converts - to -- if (and only if) - falls between two digits, as in 0-60. In the code below, this LaTeX macro is called \DashToEn. The macro, in turn, calls a Lua function called dash2en to do the actual work.

  • You could be looking for a preprocessor-type solution, which is supposed to act on (parts of) the input stream before TeX starts its usual work and converts all instances of [digit]-[digit] to [digit]--[digit]. In the code below, this approach is enabled and disabled via LaTeX macros called \EndashOn and \EndashOff, respectively. \EndashOn assigns a Lua function called makeEn to the LuaTeX process_input_buffer callback; conversely, \EndashOff removes this Lua function from the callback.

  • Observe that the dash2en and makeEn functions differ only in the way they "return" the result of the string.gsub operation: dash2en passes the result to the tex.sprint function, whereas makeEn just places the result back into the input stream. (Recall that TeX's usual processing -- "eyes", "mouth", etc. -- isn't active yet when the process_input_buffer callback is doing its job.

  • Finally, observe that the string A-Z is not converted to A--Z by \DashToEn or if \EndashOn has been invoked. This is, of course, exactly as it should be according to the OP's specifications.

enter image description here

\usepackage{luacode} % for 'luacode' environment

%% Lua-side code
function dash2en ( s )
  s = s:gsub ( "(%d)%-(%d)" , "%1--%2" )
  tex.sprint ( s )
function makeEn ( s )
  s = s:gsub ( "(%d)%-(%d)" , "%1--%2" ) 
  return s

%% LaTeX-side code
\newcommand\EndashOn{\directlua{luatexbase.add_to_callback (
   "process_input_buffer" , makeEn, "makeEn" )}}
\newcommand\EndashOff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer" , "makeEn" )}}

0-60 55-65 99-101 A-Z

\DashToEn{0-60 55-65 99-101 A-Z}

0-60 55-65 99-101 A-Z

0-60 55-65 99-101 A-Z

  • 1
    Very cool..didn't realize how easy it can be. cheers Sep 22, 2021 at 0:41
  • 1
    There are a few situations where an en-dash between two digits is wrong: (a) in a url or doi; (b) in an ISBN or ISSN; (c) in an ISO-formatted date (2021-09-21); (d) in a "sectioned" page number -- although this is usually something like "A-1" or "II-1", the first element is sometimes just an ordinary Arabic digit. So use with care. Sep 22, 2021 at 1:08
  • @barbarabeeton - I whole-heartedly agree with the "use with care" caveat. Speaking for myself, I interpreted the OP's write-up as looking for a proof-of-concept solution and not as something that would be put into action in an unsupervised manner.
    – Mico
    Sep 22, 2021 at 1:22
  • Definitely--this is why asked for the ability to turn it off when needed. You are correct @Mico, this is more out of interest. Sep 22, 2021 at 1:25
  • Still one caveat: a DOI and page numbers can very often occur in the same biblio entry, so more structure will be needed there than is usually provided by BibTeX formatting. (Not sure about biblatex. All I know is that I often shoot myself in the foot forgetting such details.) Sep 22, 2021 at 1:31

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.