Writing Assignments with Org-mode (in Doom Emacs)

Introduction

This post will be a brief tour on writing (work/university) assignments in org-mode, with the goal of producing a nicely typesetted PDF document without having to use much LaTeX.

Everything mentioned will also apply to Emacs in general, but Doom Emacs comes with all the features I mention.

Prerequisites

Basic knowledge of org-mode, LaTeX (if math required), and Emacs.

(Very) Quick Org-Mode Primer

Org-mode is a plain-text hierarchical markup language.

* This is a (top-level) heading.
  This is text that falls under the main heading.
  * This is a sub heading. *This is bold text that falls under the sub heading.*

This would be syntax-highlighted in Doom Emacs.

Comments are supported (unlike Markdown AFAIK):

# This is a comment. This will not be compiled.
* This is a heading
  # This is also a comment. They must be on their own line.
  This is text that falls under the main heading.

More here, if you are totally new to org-mode.

Org-mode Options

You can (optionally) add options to the top of your org document, to customize the output.

# Self-explanatory, will generate your name when compiled.
#+AUTHOR: Chris

# This one removes the default Table of Contents, to save space:
#+OPTIONS: toc:nil

# The default LaTeX class is article,
#+LATEX_CLASS: report

# Options to modify the class. E.g. font size.
#+LATEX_CLASS_OPTIONS: [11pt,breaklines=true]

# Other LaTeX code that you'd need in the preamble, notably, using packages.
#+LATEX_HEADER: \usepackage[margin=2cm]{geometry}
#+LATEX_HEADER: \usepackage{setspace}
# Options don't need to be in capital letters
#+latex_header: \setstretch{0.90}

Above, I set the font size to 11pt, the margin to 2cm, and the space between lines to be 90% of what it normally would be.

Source Code Embedding

The bad news is that (by default at least), your created PDF will not get syntax highlighting; the good news is that you will (in the editor), and even language-specific indentation!

# the general syntax is #+begin_src [language]
#+BEGIN_SRC python
def fib(n):
    a = 0
    b = 1
    for _ in range(n-1):
        a, b = b, a+b
    return b if n > 0 else 0
#+END_SRC
# #+end_src marks the end of the code block

See here for the languages that are supported. Org itself is supported, so I'm currently two (three?) layers deep as I write this in org-mode (i.e. python source in org source in org source). I think Douglas Hofstadter would appreciate this level of recursion.

The above code would look something like this in your editor:

def fib(n):
    a = 0
    b = 1
    for _ in range(n-1):
        a, b = b, a+b
    return b if n > 0 else 0

However as mentioned before, after compiling, you will lose the syntax highlighting (but not the indentation).

By the way, code-blocks are executable, so you might even be able to use org-mode as an alternative to Jupyter Notebooks. Try it by pressing enter with the cursor in the source region.

Math

Inline math is pretty straightforward:

This is a graph: $G = (V,E)$

Just enclose LaTeX in two dollar signs.

Equations may be troublesome. While you could simply type any LaTeX source into your org document, often after compiling, the equation is too long to fit in (the width of) the page.

The solution wasn't anything special to org-mode; instead of using '\begin{equation}', use '\begin{gather*}':

\begin{gather*}
    \text{This is a nice equation.}\\
    e^{i \cdot \pi} + 1 = 0
\end{gather*}

This should properly create line-breaks when used with '\\'.

Now, you can run `M-x org-latex-preview` or C-c C-x C-l on Doom Emacs, to create a preview in the editor, instead of compiling everytime.

UML Diagrams

You need plantUML. Head over to your private init.el (on Doom Emacs) and uncomment the line with 'plantuml'. Then save, exit and `doom sync` on the terminal to install, and now you're ready.

PlantUML is considered source code like any other:

#+BEGIN_SRC plantuml
Bob->Alice : hello
#+END_SRC

Remember what I said about code blocks? You can execute this code in the editor to generate a diagram/preview without having to compile! This creates a temporary image that's rendered in your buffer. Press enter on the image to minimize it.

Now we'll change the image size. First, your buffer would look like this:

#+BEGIN_SRC plantuml
Bob->Alice : hello
#+END_SRC

#+RESULTS:
[[file:/tmp/babel-2F1Rb7/plantuml-kHD2c1.png]]

You can add an attribute/option like so:

#+BEGIN_SRC plantuml
Bob->Alice : hello
#+END_SRC

# Both of them are optional:
#+ATTR_LATEX: :width 150px :height 150px
#+RESULTS:
[[file:/tmp/babel-2F1Rb7/plantuml-kHD2c1.png]]

Now, after compiling or re-executing the code, the size should be as specified.

Compiling

Finally, you can execute the function 'M-x org-export-dispatch', or press 'SPC m e' to run the exporter/dispatcher. You can choose any output type you like, but 'Export to LaTeX' supports all the features described wheras others may not.

Alternatives

If you want a quicker option to get a PDF from some text, perhaps try a markdown to LaTeX converter, such as pandoc). Although I believe you would still need to compile it yourself.