Org-mode

about | blog | config | notes | github

1. Your Life in Plain Text

org_mode_logo.png

Org-mode is a powerful plain text markup language for GNU/Emacs. You can use it for taking notes, generating to-do-lists, creating research papers, running code, you name it! Here is a simple example that I took from Nick Higham's blogpost. Made minor changes as org-mode has changed a small amount.

#+TITLE: Org Mode Syntax Cheat Sheet
#+OPTIONS: toc:nil
# Adapted from http://karl-voit.at/2017/09/23/orgmode-as-markup-only/

* Top Level Heading
** Second Level Heading
*** Third Level Heading

# A comment line.  This line will not be exported.

Paragraphs are separated by at least one empty line.

*bold* /italic/ _underlined_ +strikethrough+ =monospaced=

[[https://nickhigham.wordpress.com/][Link description]]

https://nickhigham.wordpress.com/ A link without a description.

A DOI (digital object identifier) link:
[[doi:10.1093/comnet/cnv016][Matching Exponential-Based and Resolvent-Based Centrality Measures]]

A horizontal line, fill-width across the page:
-----

- First item in a list.
- Second item.
  - Sub-item
    1. Numbered item.
    2. Another item.
- [ ] Item yet to be done.
- [X] Item that has been done.

LaTeX macros can be included: $x_2 = \alpha + \beta^2 - \gamma$.

**** TODO A todo item.
**** DONE A todo item that has been done.

#+BEGIN_QUOTE
This text will be indented on both the left margin and the right margin.
#+END_QUOTE

: Text to be displayed verbatim (as-is), without markup
: (*bold* does not change font), e.g., for source code.
: Line breaks are respected.

Some MATLAB source code:
#+BEGIN_SRC matlab
>> rand(1,3)
ans =
   5.5856e-01   7.5663e-01   9.9548e-01
#+END_SRC

Some arbitrary text to be typeset verbatim in monospace font:
#+BEGIN_SRC text
Apples, oranges,
cucumbers, tomatoes
#+END_SRC

# Table and spreadsheet.  The column headed "Ratio" is automatically
# calculated by hitting C-c C-c in Emacs on the #+TBLFM line.

|----------------+-----------+-----------+-------|
| Country        | Abstracts | Downloads | Ratio |
|----------------+-----------+-----------+-------|
| United States  |         7 |       497 |  71.0 |
| Unknown        |         4 |        83 |  20.8 |
| United Kingdom |         3 |        41 |  13.7 |
| Germany        |         3 |        29 |   9.7 |
| Netherlands    |         2 |        21 |  10.5 |
| Japan          |         1 |        18 |  18.0 |
|----------------+-----------+-----------+-------|
#+TBLFM: $4=$3/$2;%.1f

Include an image:
file:nickhighamwordpress.jpg

2. Useful Resources

3. Configuration

3.1. Basic Configuration

I should probably split this bloody mess up.

(use-package org
  :hook
  ;; (org-mode    . zamlz/org-mode-setup-simple)
  (org-mode    . zamlz/org-mode-setup-fancy)
  (before-save . zamlz/update-org-modified-property-hook)
  :bind (:map org-mode-map
              ("C-M-h" . org-previous-link)
              ("C-M-l" . org-next-link))
  :custom
  ;; Setup directories
  (org-directory "~/org/gtd/")
  (org-agenda-files (list org-directory))
  ;; Add some nice visuals changes
  (org-ellipsis " ▾")
  ;; (org-ellipsis " ")
  ;; This is so that the imenu displays all levels in ivy
  (org-imenu-depth 6)
  ;; dont use C-c C-o for opening links REEEEEEEEEEEE
  (org-return-follows-link t)
  ;; Some todo/logging changes
  (org-enforce-todo-dependencies t)
  (org-log-done 'time)
  (org-log-into-drawer t)
  (org-treat-S-cursor-todo-selection-as-state-change nil)
  ;; Setup org capture mode
  ;; Setup refiling
  (org-log-refile 'time)
  (org-refile-use-outline-path 'file)
  (org-outline-path-complete-in-steps nil)
  (org-refile-allow-creating-parent-nodes nil)
  ;; TODO: need to figure out how to setup project refile targets
  (org-refile-targets
   `((,(concat org-directory "/tasks.org") :maxlevel . 5)))
  ;; Setup archive location
  (org-archive-location (concat org-directory "/archive.org::"))
  ;; ensure that refiling saves buffers
  (advice-add 'org-refile :after 'org-save-all-org-buffers)
  ;; Inline Image improvements
  (org-startup-with-inline-images t)
  (org-image-actual-width 300)
  ;; Align org tags
  (org-tags-column (* -1 (- zamlz/default-screen-width 10)))
  (org-agenda-tags-column (* -1 zamlz/default-screen-width )))

3.2. Mode Startup Hooks

These are some hooks that we would like to run when org-mode is started. We have two variants here. One is a fancy version that configures different fonts depending on the style, while the second does not.

(defun zamlz/org-mode-setup-simple ()
  (org-indent-mode)
  (org-num-mode)
  (visual-line-mode +1)
  (setq fill-column 10000)
  (zamlz/org-level-face-setup-simple))
(defun zamlz/org-mode-setup-fancy ()
  (org-indent-mode)
  (visual-line-mode +1)
  (setq evil-auto-indent nil)
  (setq fill-column 10000)
  (variable-pitch-mode)
  (zamlz/org-level-face-setup-fancy)
  (zamlz/org-fixed-pitch-setup-fancy))

3.3. Better Font Faces Hook

We can configure org-mode font faces via a seperate function that we define. We need to add it as a hook afterwards however which is why this section appears before the basic configuration.

(defun zamlz/org-level-face-setup-fancy ()
  (interactive)
  ;; hide #+TITLE:
  (setq org-hidden-keywords '(title))
  (setq org-fontify-whole-heading-line t)
  (setq org-fontify-done-headline t)
  (setq org-fontify-quote-and-verse-blocks t)
  ;; set basic title font
  (set-face-attribute 'org-level-8 nil :weight 'normal :slant 'italic :inherit 'outline-8
                      :height 1.0)
  ;; Low levels are unimportant => no scaling
  (set-face-attribute 'org-level-7 nil :weight 'normal :slant 'italic :inherit 'outline-7
                      :height 1.1)
  (set-face-attribute 'org-level-6 nil :weight 'normal :slant 'italic :inherit 'outline-6
                      :height 1.2)
  (set-face-attribute 'org-level-5 nil :weight 'normal :slant 'italic :inherit 'outline-5
                      :height 1.3)
  (set-face-attribute 'org-level-4 nil :weight 'normal :slant 'italic :inherit 'outline-4
                      :height 1.4)
  (set-face-attribute 'org-level-3 nil :weight 'normal :slant 'italic :inherit 'outline-3
                      :height 1.5)
  (set-face-attribute 'org-level-2 nil :weight 'normal :slant 'italic :inherit 'outline-2
                      :height 1.6)
  (set-face-attribute 'org-level-1 nil :weight 'normal :slant 'italic :inherit 'outline-1
                      :height 1.7)
  ;; Only use the first 4 styles and do not cycle.
  (setq org-cycle-level-faces nil)
  (setq org-n-level-faces 8)
  ;; Document Title, (\huge)
  (set-face-attribute 'org-document-title nil
                      :slant 'normal
                      :weight 'normal
                      :height 2.5
                      :underline t
                      :foreground 'unspecified))

Here is an alternate that is simpler.

(defun zamlz/org-level-face-setup-simple ()
  (interactive)
  ;; Only use the first 4 styles and do not cycle.
  (setq org-cycle-level-faces t)
  (set-face-attribute 'org-document-title nil
                      :slant 'normal
                      :weight 'bold
                      :height 1.0
                      :underline t
                      :foreground 'unspecified)
  (set-face-attribute 'org-level-8 nil :inherit 'outline-8)
  (set-face-attribute 'org-level-7 nil :inherit 'outline-7)
  (set-face-attribute 'org-level-6 nil :inherit 'outline-6)
  (set-face-attribute 'org-level-5 nil :inherit 'outline-5)
  (set-face-attribute 'org-level-4 nil :inherit 'outline-4)
  (set-face-attribute 'org-level-3 nil :inherit 'outline-3)
  (set-face-attribute 'org-level-2 nil :inherit 'outline-2)
  (set-face-attribute 'org-level-1 nil :inherit 'outline-1))

Thanks to this blog post from Protesliaos, I was able to properly configure variable pitched fonts in these org-mode buffers.

(defun zamlz/org-fixed-pitch-setup-fancy ()
  (interactive)
  (dolist (face '(org-block
                  org-block-begin-line
                  org-code
                  org-drawer
                  org-ellipsis
                  org-special-keyword
                  org-property-value
                  org-document-info-keyword
                  org-meta-line
                  org-table
                  org-formula
                  font-lock-comment-face
                  org-date
                  org-sexp-date
                  org-verbatim))
    (set-face-attribute `,face nil :inherit 'fixed-pitch))
  (set-face-attribute 'org-block-begin-line nil :inherit 'org-block :slant 'italic)
  (set-face-attribute 'org-block-end-line nil :inherit 'org-block-begin-line :slant 'italic))

3.4. Center Org buffers

Center the org buffers and remove line numbers to reduce visual clutter.

(defun zamlz/org-mode-visual-fill ()
  (setq visual-fill-column-width zamlz/default-screen-width
        ;; visual-fill-column-extra-text-width (0 . 1000)
        visual-fill-column-center-text t)
  (visual-fill-column-mode 1))

 (use-package visual-fill-column
   :hook (org-mode . zamlz/org-mode-visual-fill))

3.5. General Keybindings

Just quick access to my most used org-mode functions via the General Leader Keybindings Definer.

(require 'init-general)
(zamlz/leader-keys
  "c" '(org-capture :which-key "org-capture")
  "a" '(org-agenda :which-key "org-agenda")
  "o"  '(:ignore t :which-key "Org Mode")
  "ol" '(org-store-link :which-key "org-store-link")
  "oi" '((lambda () (interactive)
           (org-tags-view t "INBOX")
           (message "Opened:  %s" (buffer-name)))
         :which-key "Inbox")
  "og" '((lambda () (interactive)
           (find-file (concat org-directory "/tasks.org"))
           (message "Opened:  %s" (buffer-name)))
         :which-key "GOTO tasks.org")
  "oj" '((lambda () (interactive)
           (find-file (concat org-directory "/journal.org"))
           (message "Opened:  %s" (buffer-name)))
         :which-key "GOTO journal.org"))

3.6. LaTeX Inline Preview

Pretty straightforward except that you need to have LaTeX installed and also dvipng as well. We'll add dvipng to this file's package set.

\begin{equation} R_{\mu \nu} - {1 \over 2}R \, g_{\mu \nu} + \Lambda g_{\mu \nu}= {8 \pi G \over c^4} T_{\mu \nu} \end{equation}
(setq org-startup-with-latex-preview t)
(setq org-highlight-latex-and-related '(native script entities))
(with-eval-after-load 'org
  (setq org-format-latex-options (plist-put org-format-latex-options
                                            :scale zamlz/org-latex-scale-factor))
  (setq org-preview-latex-image-directory  "/tmp/ltximg/")
  (add-to-list 'org-src-block-faces '("latex" (:inherit default :extend t))))

3.7. Last Modified Timestamp

The following allows any #+LAST_MODIFIED headers to be updated on file-save.

(defun zamlz/update-org-modified-property-hook ()
  "If an org file contains a '#+LAST_MODIFIED' property,
  update it to contain the current date/time"
  (when (eq major-mode 'org-mode)
    (interactive)
    (save-excursion
      (widen)
      (goto-char (point-min))
      (when (re-search-forward "^#\\+LAST_MODIFIED:" (point-max) t)
        (progn
          (delete-region (point) (save-excursion (move-end-of-line 1) (point)))
          (insert (format-time-string " [%Y-%m-%d %a %H:%M:%S]") ))))))

3.8. Custom Link Types

The variable org-link-abbrev-alist provides us a powerful way of defining our own link types to be used within org-mode. Let's define one for Google Maps below. Now to use it, we simply need to type [[gmap:UCSC, Santa Cruz][UCSC]] and we'll have a link open up to google maps!

(setq org-link-abbrev-alist
      '(("gmap" . "http://maps.google.com/maps?q=%s")))

3.9. Feature Provider

(provide 'init-org)

Created: 2021-11-13

Emacs 26.1 (Org mode 9.5)