LaTeX Input for Impatient Scholars

Ever since Gilles Castel documented his method for taking math notes in real-time in Vim, I’ve noticed Emacs users asking if it’s possible to replicate this level of speed and convenience typing \(\LaTeX\) in Emacs1. Well, it’s Emacs. Of course all of this–and more–is possible. I write LaTeX all day, and I’m about as fast as when writing equations on paper. Sometimes a smidge faster. In this write-up I explain how, but first here’s what I mean:

Math input for the impatient:

(Direct link)

Matrices in a hurry:

(Direct link)

A typical statement:

(Direct link)

TL;DR: Just give me the code

The rest of this article outlines the components involved in LaTeX editing in Emacs and breaks down the features that are used to speed up text input specifically. The objective is to enable Emacs to let you type LaTeX, including math, as fast as you can type regular text or write math on paper. Fast enough to take live notes, at least.

You can use the TOC (to the right or below) to gain an overview of the tools involved. The demos might be helpful too.

The configuration code is available as a single file here. It will install three Emacs packages: AucTeX, CDLaTeX and YaSnippet. It does not install any YaS snippets. The snippets I use are here, but I recommend writing ones that suit your needs instead.

One of the features included in this code, used to rapidly input LaTeX tables or arrays, is available as a separate package here: Lazytab.

The state of LaTeX editing in Emacs

This is my rough understanding of LaTeX editing in Emacs:

Click to embiggen. Also every block is a link to the corresponding package.

At the core is the TeX document structure: the document tree, text and floats, the document class and style, cross-references and citations, other metadata and doc versions2. Surrounding it are the islands of concern when using a text editor to create this document: text input and text editing, document navigation, appearance, linting and compilation. The spokes leading into these islands are Emacs packages, libraries or library features that enable or hasten these tasks.

I’m not qualified to comment on most aspects of this map. Ask an Emacs user who’s written a book or two. This article is intended to be a collection of tips to speed up LaTeX editing to the point where you can take live notes, not a comprehensive guide to editing LaTeX in Emacs. Thus we’re mostly looking at the Text Input block, with quick dips into the Appearance and Text Editing sections. If you’re interested in the full picture I recommend starting with the AucTeX manual (C-h i m auctex in Emacs). It’s quite readable, and if you have the rare gene that lets you tolerate manuals, quite pleasant too!

On account of my ignorance, there are atleast a couple of big omissions in this chart. These are worth mentioning:

  • Digestif: The Language Server for LaTeX in combination with Eglot or LSP should handle many of these tasks: cross-references, citations, linting, autocompletion etc.
  • Xenops: Xenops is a full suite of tools built on top of the venerable AucTeX that collects the above features into a single package that you can install and use with no configuration. It also adds literate programming support.

If you want faster or more convenient ways to do the other tasks, check out the links in the chart above.

In a future post in this series I plan to cover the Text Editing block, which is different from Input in that it deals primarily with manipulating existing document structure without adding significantly to it. We will end up using a different set of tools from the ones I cover below.

The basic ingredients

Of this bunch, we only need a few ingredients (plus Emacs itself). We build the text input environment we need in three stages of laziness:

  • AucTeX, which is the foundation for LaTeX (and ConText) editing in Emacs. It provides commands and minor-modes for all the aspects of document creation above. It provides all the ingredients we need. You could live with just AucTeX and be completely satisfied with your speed of text input and convenience of editing, as I was for many years.

  • CDLaTeX, which is a collection of commands and convenience features mostly intended to reduce how much you need to type. This is one of Emacs’ best kept secrets, and the secret sauce in our recipe.

  • YaSnippet, which is a package for Emacs to insert text snippets, i.e. templates with placeholder fields that you can fill in. Of course, we bend it into doing a lot more. This overlaps in functionality with CDLaTeX in an inconvenient way, but them’s the breaks.

    Let’s get this out of the way now: A google search for faster LaTeX input in Emacs usually leads people straight to Yasnippet and the more contemporary auto-activating-snippets packages. While I make some use of Yasnippet in the demos above (and below), I think heavy use of expanding snippets is the wrong approach to speed up your LaTeX editing. More on this in a bit.

The remaining packages in the Text input block above mostly overlap in function with the above:

  • tempo, skeleton and abbrev all offer some flavor of template insertion or expansion. YaSnippet and CDLaTeX handle this and do a lot more besides.
  • capfs, or the completion-at-point functionality is provided by AucTeX, but we will seldom need it because of how we enter text. If you need it to complete a keyword for whatever reason, you can call completion-at-point or use one of many packages that act as frontends for it, such as company-mode or corfu.
  • auto-activating-snippets and its add-on LaTeX-auto-activating-snippets: This is a cleaner and faster implementation of the specific functionality that we use YaSnippet for. If I was to start over I would probably use these, so do check them out.
  • LaTeX-math-mode, part of AucTeX. This is a method to insert mathematical symbols efficiently. CDLaTeX does it better though.

So we begin with AucTeX, then add CDLaTeX and pile on YaSnippet at the end. With each addition we gain a boost in the speed of LaTeX input, but also introduce a little more jank and make the tower teeter a bit. I’ve been using the former two for decades and added YaS a few years ago, and I think I’ve worked most bugs out of the system by now. Still, caveat emptor.

All set? OK, let’s go.

A note for org-mode users

Org-mode has very good support for LaTeX input out of the box, so you can use the tips in this article with minimal modifications. When necessary, I add org-mode specific details below.

Step 1: AucTeX

AucTeX does most of the work of creating a full fledged LaTeX editing environment, leaving us with the task of adding time-saving convenience features.

AucTeX is generally responsible for providing completions when typing. The most general, always available options for text input are:

  • Insert an arbitrary environment with LaTeX-environment (C-c C-e),
  • or a macro with TeX-insert-macro (C-c C-m), which it will do so after prompting you for arguments.
  • Insert a section header with LaTeX-section (C-c C-s).

Further below I describe much faster ways to do this, however, so treat this as a fallback option that’s always available.

A couple of AucTeX’s convenience features I use that do not pertain to text input:


I turn on outline-minor-mode in TeX buffers so I can fold sections, jump across section headings and so on. If you use Emacs 28 or higher this enables the outline-cycle command that you can use to cycle section visibility with a single key like in Org-mode. I bind it to TAB like in Org-mode3.

TAB’ometer count: 2 (outline-cycle and LaTeX-indent-line)

Here are a couple of useful appearance-related AucTeX features that inject a bit of WYSIWYG into the document:

Pretty symbols (M-x prettify-symbols-mode)

prettify-symbols-mode in LaTeX buffers will replace math symbols with more readable unicode equivalents. This makes parsing equations much easier:

This is for display only, the underlying text does not change. You can still search for the text in these symbols, for instance.

There’s nothing to set up, AucTeX defines these replacements for you. Just turn on prettify-symbols-mode:

Turning on prettify-symbols
(add-hook 'LaTeX-mode-hook 'prettify-symbols-mode)
Pretty symbols in org-mode

Org has its own version of prettify-symbols-mode. Use M-x org-toggle-pretty-entities instead. It’s bound to C-c C-x \ by default.

In-buffer previews (M-x preview-buffer)

What’s better than replacing individual symbols with unicode characters? Replacing entire equations and figures with compiled previews:

Moving the cursor over the equation will temporarily remove the image overlay and allow you to edit the environment:

(Direct link)

You can preview the environment at point, active region, section or the entire buffer, they’re all bound under the preview map (C-c C-p). A common practice is to auto-preview math environments whenever you move out of one, and many packages provide this feature. Over the decades I’ve found this more jarring than convenient. I prefer to edit freely (with the pretty symbols turned on) and call preview-section when I’m done.

I use both appearance enhancements in the demos in this write-up.

Optional: Changing the preview image size

One thing you may want is change the size of the preview images as displayed. Replace the number here with whatever works best for you:

(add-hook 'LaTeX-mode-hook
          (defun preview-larger-previews ()
            (setq preview-scale-function
                  (lambda () (* 1.25
                           (funcall (preview-scale-from-face)))))))
In-buffer previews in Org-mode

Org has its own version of in-buffer LaTeX previews too. Instead of preview-region, you would do M-x org-latex-preview. (Bound to C-c C-x C-l)

The rest of AucTeX

AucTeX is comprehensive: For example, TeX-fold-mode adds another way to hide some of the visual noise when looking at a document, while allowing you to step into the noisy bits seamlessly:

(Direct link)

TeX-error- and TeX-command- deal with compilation and debugging, TeX-view with viewing output PDFs, TeX-master with multi-file documents, TeX-documentation with help and so on. These are beyond the scope of this article.

Step 2: CDLaTeX

CDLaTeX provides a collection of convenience functions that speed up editing LaTeX documents.

This is an understatement. A more accurate assessment would be that after a couple of days of practice, CDLaTeX lets you type in and navigate LaTeX chunks like a motorcyclist weaving through traffic.

Technically AucTeX already does most of this, but in a stodgy 90s sort of way. Do you want to type C-c C-o C-o after filling in every math environment? Me neither.

CDLaTeX in org-mode

Instead of installing CDLaTeX you’d turn on org-cdlatex-mode. You don’t even need to install CDLaTeX, it’s already on your system! Org-cdlatex-mode is part of Org.

This is not a coincidence. CDLaTeX was written by Carsten Dominik (hence the CD), who was also the primary author of Org-mode.

The TABinator

CDLaTeX’s best trick is its heavy overloading of the TAB key. Pressing TAB jumps you to the next “point of interest”, placing your cursor at convenient spots for text input. This is much simpler to watch than to explain. Here I navigate through a chunk of my document with a hundred presses of the TAB key and nothing else:

(Direct link)

The heuristic it uses for where TAB should jump to next is generally pretty good, and handles delimiters and LaTeX macros adroitly:

(Direct link)

In this example, it jumps from outside the \left( to before the integral, then to the integrand, then the variable of integration, and finally past the \right). As the manual helpfully summarizes:

When in doubt, press TAB.

TAB’ometer count: 3 (Jumping around with cdlatex-tab)

Entering symbols

Typing in the grave key (`) and a letter inserts symbols into the buffer, automatically adding inline math dollars if necessary:

(Direct link)

The keys are chosen to be mnemonic:

  • ` and a-z (A-Z) insert greek letters (uppercase), so `a gives \alpha, `L gives \Lambda etc
  • ` plus keys to insert arrows:
    key grave ` + key two graves ` ` + key
    > or < \(\rightarrow\) or \(\leftarrow\) \(\longrightarrow\) or \(\longleftarrow\)
    ] or [ \(\Rightarrow\) or \(\Leftarrow\) \(\Longrightarrow\) or \(\Longleftarrow\)
    ^ or _ \(\uparrow\) or \(\downarrow\)
    = \(\Leftrightarrow\) \(\Longleftrightarrow\)

There are mappings for symbols for other operations, such as on sets etc. But you don’t need to remember any of this: a menu with hints pops up if you wait for a second. There are actually three layers of symbols, with less common ones accessed via repeated presses of the grave key: ` `<key> and ` ` `<key>:

(Direct link)

I found myself typing the first layer of symbols (single `) automatically after a couple of days of using CDLaTeX, and usually waiting for the hints to pop up for the less common symbols in the double ` ` and triple grave menu.

You can change or add to this list of symbols by customizing cdlatex-math-symbol-alist. Lastly, if you need to type in a literal grave key in your document you can prefix it with C-q.

Note: There is also TeX-math-mode, provided by AucTeX that does something very similar.

Symbol entry in Org-mode

org-cdlatex inserts symbols in org-mode without the math delimiters. This is because it’s less visually distracting this way and Org’s LaTeX export backend automatically adds the delimiters.

Math and Text modifiers

You can add modifiers to typed in text with the single quote ('). This includes things like hats, dots, tildes and graves and over/underlines on symbols, as well as font style changes in both math and text modes:

(Direct link)

As before, typing in a quote ' and waiting pops up a window with hints. (There are many more modifiers available here, I use only a few.)

This works the other way too. You can start with the modifier and type in the symbol or text after:

(Direct link)

You can change or add to this list by customizing cdlatex-math-modify-alist. To type in a literal quote you can use ''.

The live help feature of CDLaTeX used to be a revelation ten years ago. These days which-key and other packages have brought this to all of Emacs.

Environments and Math templates

CDLaTeX defines a collections of templates that expand into environments with TAB. You can then TAB your way across text fields in that expansion. In text mode, for example, you can type in equ<tab> to generate an equation environment or sn<tab> for a section, fg<tab> for a figure and inc<tab> for an \includegraphics macro. env<tab> or beg<tab> will insert any environment with prompting. Here are a few examples:

(Direct link)

(Note that I used TAB to both insert the template templates and navigate the document here.)

There are similar shortcuts for common delimiters and macros inside math environments. For example, it modifies caret (^) and underscore (_) to insert ^{} and _{}, and gracefully handles the braces. Here are more examples:

(Direct link)

You can, of course, add your own. I added a few environments to enter AMSMath style matrices by customizing cdlatex-command-alist. (Demo of matrix/array input below.)

This is familiar, expected stuff: these appear to be snippets like those provided by other packages. But there’s one crucial difference. The text fields in a template/snippet inserter like YaSnippet lose their special meaning once the insertion is complete. CDLaTeX’s TAB does not use special markers in the template, but a heuristic method to jump forward instead. So you can revisit these fields (and intermediate ones) in the same order at any time. See Snippets snap easy.

TAB’ometer count: 4 (Expand CDLaTeX templates with cdlatex-tab)

We could stop here, and things would be Good.

With fast symbol, modifier and environment insertion AucTeX and CDLaTeX together offer a stable and speedy LaTeX input and editing experience. The complete customizability of these features usually puts them well ahead of an online suite (like Overleaf) or LaTeX IDE (like TeXStudio) for most editing tasks4.

You can skip to the section on Putting it into practice now if this covers what you need.

But our laziness and impatience knows no bounds. Hitting TAB every other second is too much work, as is typing arcane modifiers like '^ or '}. That Shift key can really tire out the pinkies, especially if you type LaTeX all day. So it’s time for…

Step 3: Yasnippet & automatic snippets

We use Yasnippet primarily for auto-expansion of snippets. Auto-expansion implies that there’s no need to hit TAB. This is useful when trying to take notes and keep up with a speaker, for instance. In my experience this can get quite annoying if you’re not expecting it, so I use it for only a select few cases5.

If AucTeX and CDLaTeX are the soup, think of YaSnippet as the garnish added at the end for some extra flavor.

To make YaSnippet expand snippets automatically, we’re going to bend it into shape.

Auto-expansion with YaSnippet
;; Function that tries to autoexpand YaSnippets
;; The double quoting is NOT a typo!
(defun my/yas-try-expanding-auto-snippets ()
  (when (bound-and-true-p 'yas-minor-mode)
      (let ((yas-buffer-local-condition ''(require-snippet-condition . auto)))

;; Try after every insertion
(add-hook 'post-self-insert-hook #'my/yas-try-expanding-auto-snippets)

Elisp note: Adding this check to post-self-insert-hook might seem crazy, but it does not cause any slowdown that I’ve noticed. Check out the auto-activating-snippets package or abbrev-mode (Emacs built-in) for a different approach if this bothers you.

The next step is to declare a snippet as auto-expanding. To do this you add the # condition: line to snippet definitions. For example, this is the snippet for auto-expanding left and right curly braces:

# key: set
# name: set
# condition: (and (texmathp) 'auto)
# group: math
# --
\\left\\{ $0 \\right\\}

See the YaSnippet docs for more details on writing snippets.

Reusing LaTeX YaSnippets in org-mode

To use your LaTeX Yasnippets in Org, you can copy them to the org section of your snippets directory, or better yet, add a file named .yas-parents in the org snippets folder with the contents


This makes all the latex-mode snippets available in Org as well.

My snippets are here, but these are tailored to the kind of math I use (mostly Calculus and Linear Algebra). I straight up stole most of these from Gilles Castel. There are many snippets here for historical reasons. I only use a few.

Consider the auto-expanding examples below as examples to inspire you to write ones more suited to your needs.

Create math environments

mk and dm create inline and equation environments. There’s nothing special about these shortcuts, they’re easier to type than $, $$ or \[ \] and not words by themselves. (YaSnippet expands only at word boundaries, so Words like “admin” or “gymkhana” will not trigger these snippets.)

Here’s a demo (where I also use the CDLaTeX symbols, math modifiers and templates from above):

(Direct link)

Faster math modifiers

Replace cdlatex’s '^\hat{} with just typing “hat” after a symbol. This way I can type how I read or hear math: a hat gives me \(\hat{a}\), and so on:

(Direct link)

I make a few more such automatic translations:

I type Becomes Mnemonic
x sr \(x²\) x squared
x cb \(x³\) x cubed
x td \(x^{\{\}}\) x to the
x conj \(x^{\star} \) x conjugate
x adj \(x^{\dagger} \) x adjoint

Where x is any symbol or s-expression (i.e. delimited expression). Check Putting it into practice to see these in action.

Note that this behavior involves editing the buffer prior to the point, and is not possible with Emacs’ built-in abbrev library. In most other cases abbrev-mode can suffice for auto-expansion.

Suppressing Yasnippet warnings

YaSnippet complains if we use a snippet to edit the buffer directly, as we do with the above examples of wrapping symbols in \hat{}, etc. This is probably bad practice, but I haven’t had an issue yet. I suppress these warnings with

(with-eval-after-load 'warnings
  (cl-pushnew '(yasnippet backquote-change) warning-suppress-types
              :test 'equal))

Faster \frac

Make // set up a \frac expression:

(Direct link)

Useful simple replacements

These are simple but useful auto-replacements for my purposes:

I type Becomes Which is
neq, leq or geq \(\ne \), \(\le \) or \(\ge \) \ne, \le or \ge
~~ \(\sim \) \sim
-> and => \( \to \) and \( \implies \) \to and \implies
inn \(\in \) \in
set \(\{ \} \) \{ \}
cc or cceq \(\subset \) or \(\subseteq \) \subset or \subseteq
EE or nEE \(\exists \) or \(\nexists \) \exists or \nexists
VV \(\forall \) \forall
xx \(\times \) \times
ox \(\otimes \) \otimes
o+ \(\oplus \) \oplus
... \(\dots \) \dots
;. \(\vdots \) \vdots
;/ \(\ddots \) \ddots
,, or ;; \( \& \) or \\ field sep or linebreak

And so on. This functionality overlaps somewhat with cdlatex’s symbol entry (`) command, and you could add these there instead. The point of these is not so much to save time as it is to preserve the flow of my thoughts when writing. I type them as I sound them out in my head (thus leq instead of \le, x adj instead of x^{\dag}) and they’re automatically changed to the correct symbols. You can catch many of these replacements in the demos at the start of this write-up.

Optional: conventional snippets with multiple placeholders

You can also add some more conventional snippets in the mix. I use these quite often for derivatives and definite integrals, for instance:

(Direct link)

In principle these can just be added to the cdlatex-command-alist instead (which is much simpler to set up), but the above are relics of more experimental times that I’ve not bothered to change.

It’s also tempting to set up snippets for typing in arrays, matrices or vectors, whose syntax has a lot of structure. However there is a better way, see table, matrix or array entry.

TAB’ometer count: 5 (Expand a conventional YaSnippet with yas-expand.)

Snippets snap easy

Template or snippet based insertion is a very limited form of interaction with the document, both in time and space. The placeholder fields retain their special navigation and insertion behavior only until the snippet “exits”, and this behavior is not available anywhere else in the document.

Snippets are rigid and monolithic, in that you have to bake in all the variables (such as field locations, mirrors or transformations) in the definition, and can’t modify it on the fly. They’re also brittle: things often break if you deviate from the expected behavior of TAB → insert text → TAB → insert text. For example, when you move the cursor away to copy something from another part of the document to a snippet field. They’re modal in a bad way: you can exit the snippet mode but there’s no resuming their state without starting over.

What we would like instead is snippet-like navigation between fields, including field transformations, but at any time, anywhere in the document, and without the notion of a snippet being “active”. CDlatex’s TAB goes some way towards this ideal, but its regex based jump heuristic is quite limited compared to what’s possible.

I can imagine a better system through some combination of Vim/ evil-mode style text-objects, a semantically aware tree-sitter based LaTeX parser and a further improved CDLaTeX style DWIM command set that’s integrated into AucTeX. That’s without bringing AI helpers into the picture. Maybe something like this already exists or is in the works for $MODERN_EDITOR.

But there’s no need to let perfect be the enemy of good enough. A little bit of YaS to plaster over the gaps goes a long way.

Putting it into practice

Environment, floats and math input

The goal is to write LaTeX (and especially math) in a way that mirrors our stream of thought, where our eyes, fingers and the cursor all glide over the clutter of the markup. The above described process isn’t quite there yet, but it’s close. In summary,

  • Turn on prettify-symbols-mode to enhance readability.
  • Enter symbols with grave (`) and modify text or macros with the quote (').
  • Use TAB to jump forward to the next “point of interest” when typing.
  • Insert environment and float templates with CDLaTeX’s commands or YaS snippets. env <tab> for an arbitrary environment (with completion).
  • Use YaS’ auto-expanding snippets (or abbrev-mode abbrevs) to type without breaking the flow. Generally useful, but especially handy for math operators.
  • Preview your work with preview- commands. preview-at-point is quite handy.
  • When everything else fails, use the slower but fully document aware AucTeX commands: LaTeX-environment (C-c C-e) and TeX-insert-macro (C-c C-m).

Here I type in a simple equation using many of the features we discussed above:

(Direct link)

Play by play
  1. Start an equation env with dm (YaS)
  2. Expand an integral snippet with intl <tab> (cdlatex, but you could define a YaS for this)
  3. Tab my way through the integration limits, use ` 8 to enter \(∞\) as the upper limit (CDLaTeX symbol)
  4. Obtain \(e^{\{\}}\) by auto-expansion of e td (YaS)
  5. Obtain \(- x^2 \) as the exponent from -x sr (YaS)
  6. Obtain \mathrm{d} from following d with 'r (CDLaTeX math modifier)
  7. Type in π on the right hand side as `p (CDLaTeX symbol)
  8. Obtain \(\pi^{\{\}}\) by auto-expansion of \pi td (YaS)
  9. Get \(\frac{1}{2} \) as the exponent of \(\pi \) using the auto-expansion of 1 // 2 (YaS)
  10. Call preview-at-point to preview the equation using a keybinding.

Table, matrix or array entry

In my Batteries Included series I briefly mentioned orgtbl-mode, a built-in feature of Emacs that brings org-mode style table editing to all buffers. This is a powerful and often underutilized ability that we will use to write LaTeX.

Org-mode tables are very capable. Folks go as far as maintaining spreadsheets in them, but for our purposes what matters is that you can navigate and edit the table structurally. You can move between cells with TAB, move columns or cells around, delete or add new ones, transpose the table etc. Using this to input matrices or arrays in a free-form way feels very natural. The speed-up is a bonus. Here I’ve rigged my CDLaTeX snippets for typing in matrices to automatically start orgtbl-mode. When I’m done I can press C-c C-c and the table is converted to a LaTeX array:

(Direct link)

Here is the idea applied to a full matrix equation:

(Direct link)

And here it is applied to a text table. I start by expanding the tbl template in cdlatex, which I’ve set to start an org-mode table. I press C-c C-c when I’m done to generate the LaTeX tabular environment:

I moved the code for this out of my configuration into a standalone package, although it requires CDLaTeX to be installed. You can find LazyTab here. Turning a LaTeX array or matrix back into an org-table is not yet implemented.

TAB’ometer count: 6 (Next field in an org table with org-table-next-field.)

Cross-references and citations

There are many tools for Emacs to help you insert citations and cross-references without hassle, but these are mostly out of the scope of this write-up. You can check the chart above.

However, one aspect that’s relevant here is the method of invoking these features. Instead of binding these command to keys (like the commonly used C-c ] and C-c )), you can invoke these commands using a snippet. To not break the flow, I use CDLaTeX to expand the words ref and cite into calls to my reference and citation handlers:

(Direct link)

Math input using Calc

It wouldn’t be one of my rambling Emacs pieces if I didn’t mention the Emacs Calculator. What can Calc do for you here? Quite a bit, it turns out.

Calc has a built in parser for handling LaTeX math. While it’s pretty basic, it can convert simple objects and equations from their “programming language” representation to LaTeX. The former is usually much simpler to input when using a keyboard. Here I call a helper function that invokes calc on a matrix and an equation:

(Direct link)

An additional advantage is that Calc can do some math for you in the process. Here I invert the above matrix in the process of displaying it as a LaTeX array.

(Direct link)

Also shown: Some Taylor expansion and integration.

LaTeX math forms using Calc
(defun latex-math-from-calc ()
  "Evaluate `calc' on the contents of line at point."
  (cond ((region-active-p)
         (let* ((beg (region-beginning))
                (end (region-end))
                (string (buffer-substring-no-properties beg end)))
           (kill-region beg end)
           (insert (calc-eval `(,string calc-language latex
                                        calc-prefer-frac t
                                        calc-angle-mode rad)))))
        (t (let ((l (thing-at-point 'line)))
             (end-of-line 1) (kill-line 0)
             (insert (calc-eval `(,l
                                  calc-language latex
                                  calc-prefer-frac t
                                  calc-angle-mode rad)))))))

(define-key LaTeX-mode-map (kbd "C-S-e") 'latex-math-from-calc)
(define-key org-mode-map (kbd "C-S-e") 'latex-math-from-calc)

Invoking other parsers

Calc is an amazing piece of software, but unfortunately it falls somewhere in between a programmable calculator and a full CAS or numerical computation suite: constantly surprising in its abilities but too limited to use full time. Its built-in LaTeX syntax parser is quite rigid and in non-interactive use the built-in functions have non-standard, hard to remember names. Transpose is trn, for instance.

While I haven’t set it up, it’s also possible to convert programming style formulas into LaTeX strings using a similar interface as the above Calc command, but with more fully featured external program instead. Parsers to do this are available as part of Mathematica, Python (with Sympy) and Julia (with Latexify.jl), for example. Xenops includes support for this.

Keeping tabs on TAB

You may have noticed the TAB'ometer climbing as we progressively overload the key with more context-sensitive functions. The simple approach is to assign different keys to outline-cycle, cdlatex-tab, yas-expand etc, but I don’t want to stop to think what key to press next when typing LaTeX. So I configure the TAB key to do everything, in this order:

  1. At an outline heading, like a section? Cycle the outline like in Org.
  2. Looking at text that CDLaTeX can expand? Expand it.
  3. At the end of a Yasnippet field? Jump to the next field.
  4. In a Yasnippet field? Try a CDLaTeX TAB jump. If that takes us out of the field, go to the end of the field instead.
  5. At the end of text in an org-table cell? Jump to the next cell like in a regular table.
  6. In a table cell? Try a CDLaTeX TAB jump. If that takes us out of the cell, go to the end of the cell instead.

This reads like a blueprint for a Rube Goldberg machine, but in practice it does exactly what you expect at any location. The code for this is included in the gist, but there may be still be edge cases that need filing before it works in every context.

Some concluding thoughts

This collection of tips is just what I’ve scrabbled together over the years, not an authoritative or exhaustive exploration of this area. I think of it as a 90% solution: the remaining 10% is jank that someone needs to jump into and scrub out of the system. This rabbit hole goes very deep if you dive in headfirst, so I’m quite content to hang out here for now.

I’ve been asked what the point is of speeding up LaTeX input - after all, the bottleneck with writing is usually your speed of thought, not typing. Leaving aside the issue of transcribing handwritten notes to the screen, I’ve found that this bottleneck theory isn’t true. Instead, normally there’s a thinking phase followed by a busywork phase where you translate your thought into LaTeX. When you can type math fast enough that this busywork phase disappears (or as fast as someone can teach with a blackboard), new possibilities open up. Recording self-taught lessons in technical subjects into your hyperlinked, indexed and/or searchable digital archive becomes automatic, as you don’t have to set aside time to do it. Written communication becomes easier, as dashing off a fully formatted, easy to parse technical email or message is no extra effort. The write → review → rewrite cycle when publishing material is much faster, and you can go through more iterations and feedback. It’s one of those situations where quantity has an emergent quality.

  1. Henceforth just LaTeX, because sheesh. ↩︎

  2. Not included in the chart: literate programs in or as the document. This is covered essentially by PythonTeX in LaTeX files and by org-babel in org-mode. ↩︎

  3. If you’re on Emacs 27.2 or lower there are the Outshine and Bicycle packages for one-key Org-style cycling. ↩︎

  4. Of course, this presumes that the user is comfortable with Emacs. And the alternatives are well ahead of AucTeX in other aspects, like collaboration. ↩︎

  5. You could also go the other way, eschew cdlatex and auto-expand all your snippets with YaS. But snippet packages have a fundamental problem, see Snippets snap easy. ↩︎

Add a comment, or comment via email

Tianshu Wang
You may also have a look at laas and evil-tex if use evil. BTW, how do you draw beautiful illustration

@Tianshu Wang

Indeed, both laas and evil-tex (and many other relevant packages) are already part of the chart. I mention auto-activating-snippets and several other alternatives in the text as well. Evil-tex is not directly relevant as this write-up is specifically about rapid text input, not editing existing document structure.

The illustrations were created in Inkscape.


All the boxes in your writing (may be image boxes) showing following error. I have observed this in your previous post also.

Secure Connection Failed

An error occurred during a connection to PR_CONNECT_RESET_ERROR

Thanks for the post! What software did you use to make the diagrams? Found the color scheme for different node types and the hyperlinks neat!

@murali: I’m aware, Streamable fails to load or is blocked by some ISPs or orgs. I’m looking into alternatives. If you open this page in a text-oriented browser like Lynx or w3m there are direct links to the videos.

@gtpedrosa: The illustrations were created in Inkscape.


Thanks for the wonderful post! I have added the code to suppress the warnings of backquote change.

(with-eval-after-load 'warnings
  (cl-pushnew '(yasnippet backquote-change) warning-suppress-types
              :test 'equal))

However, I still get the warnings.. I am running on doom emacs. Do you know what could be the issue?