View raw

Smart Documents

Table of Contents

# -*- mode: org; -*-

#+OPTIONS: html-style:nil #+MACRO: SD /Smart Document/ #+MACRO: SDs /Smart Documents/

# LaTeX setup #+SETUPFILE: /.emacs.d/resources/templates/documents/gnu-default.setup # Title page #+INCLUDE: /.emacs.d/resources/templates/documents/title-default.org #+LATEX_HEADER_EXTRA: \newfontfamily\garamond{EB Garamond} #+LATEX_HEADER_EXTRA: \newfontfamily\publicsans{Public Sans}

#+LATEX: \begin{abstract} The idea of {{{SDs}}} came to me as I was reflecting on how to improve the document creation process in my workplace. The GNU Emacs editor had captured my imagination, and I wanted to create an accessible and highly productive text editor to benefit my organization. In this paper, I'll lay out my vision for the /Smart Document/, a file containing both text destined to the reader, and code describing how to update, validate, and present this text; then, I'll weave my personal GNU Emacs customizations with a tutorial. This paper is a {{{SD}}} itself! #+LATEX: \end{abstract}

COMMENT All TODOs

TODO Harmonize ~compagnon~ themes

TODO Soft-coded paths

TODO Normalize `sd-path-' names

sd-paths alist?

TODO Project vision/values/core objectives

TODO <apps> button as master {{{sd}}} entry point

TODO Turn ~left-fringe~ into ~org-agenda~ buffer drawer

WAITING Display ~*Messages*~ buffer on startup

TODO Integrate site publishing recipes

TODO ~transient-*-file~ paths

Put them somewhere it makes sense.

Introduction

The following sections were laid out very deliberately. When we start Emacs, the source code blocks contained in this document are evaluated sequentially---our editing environment is constructed in real time as we execute the blocks in order. For instance, we only begin loading packages once we ensured use-package is working properly.[fn::For more information on the detailed steps Emacs takes upon starting, refer to https://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html.]

Customizing Emacs goes far, far beyond rewriting sections of this document---feel free to experiment and discover. Here are three commands that will help you understand all the symbols in this file, if you are browsing this paper within Emacs itself:

~C-h f~
describe function
~C-h v~
describe variable
~C-h k~
describe key

You can press f1 at any time to access Emacs built-in help.

TODO User details

One advantage of working with {{{SDs}}} is that they can automatically be populated with our details in the header, footer, or other appropriate element.

#+NAME: user-details-get

  (setq user-full-name "Marius Peter")

  (defun my/user-details-get ()
    "Get user details."
    (interactive)
    (setq user-full-name (read-string "Enter full user name:"))
    (setq user-mail-address (read-string "Enter user e-mail address:"))
    (message "Successfully captured user details."))

#+NAME: user-details

  (defun my/tokenize-user-details ()
    "Tokenize user details."

    (cons 'user-full-name user-full-name))

  (unless (file-exists-p (concat user-emacs-directory
                                 "meta/user-details"))
    (setq user-details '(user-full-name
                         user-mail-address))
    (append-to-file "Foobar\n" nil "~/.emacs.d/meta/foobar"))

File system paths

In this subsection, we tell Emacs about relevant paths to resources.

On my MS Windows machine, I add the path to Portable Git.[fn::Download from https://git-scm.com/download/win]

  (when (string-equal system-type "windows-nt")
    (add-to-list 'exec-path "C:/Users/marius.peter/PortableGit/bin/"))

Early setup

TODO The first file to load

:PROPERTIES: :sd-unpack-path: init.el :END:

The contents of this Section was automatically moved to ~/.emacs.d/init.el. Use `sd-pack-section' to copy the contents back into this section.

This is the very first user-editable file loaded by Emacs.[fn::This feature became available in version 27.1.] In it, we disable GUI elements that would otherwise be loaded and displayed once Emacs is ready to accept user input.

It can be found here: file:early-init.el

The second file to load

:PROPERTIES: :sd-unpack-path: early-init.el :END:

#+BEGIN_QUOTE Traditionally, file ~/.emacs is used as the init file, although Emacs also looks at the following locations:

From the GNU website[fn::https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html] #+END_QUOTE

This file can be found here: file:init.el

If no file is found, Emacs then loads in its purely vanilla state.

Server start

Emacs can run as a server, spawning client windows as needed. This reduces start-up times, and enables access to all buffers from all frames.

  (server-start)

Profiling---start

We start the profiler now , and will interrupt it in Section Profiling---stop. We will then present profiling report in Section Profiling---report.

#+NAME: profiler-start

  (profiler-start)

Usual paths to files & directories

This section defines the paths that structure the overall {{{SD}}} logic.

File
A collection of information recognized by a computer---to us, a normal file appears as programs (source code or /executables/) or data (an image, a video, a document...). It is usually stored in a computer's memory or on a storage device (hard drive, USB drive...)
Path
A description of a file's location from the user's perspective. A path is program searches for a file or executable program.
Directory
Synonymous with /folder/. From the computer's---and Emacs'---perspective, a file which contains other files. These files may themselves be directories.

Meta files---files about files

In this section, we'll be tidying up the .emacs.d/ directory---by default, many Emacs packages create files useful for themselves in our user-emacs-directory. This leads to undesirable clutter. Certain packages create files that log recently visited files (Recently visited files); log location of known projects (Projects' bookmarks); log location in recently visited files (Location in previously visited file) The commonality between all these files is that they tend to reference... other files. Thus, I decided to refer to them as meta files.

A meta files should follow the following best practices:

Be located at [[help:sd-path-meta][sd-path-meta]]
This ensures a tidy user-emacs-directory.
Be explicit
Meta filenames should not begin with a period: they would be hidden by default on GNU/Linux systems. Novices must see all files by default.
  (defcustom sd-path-meta
    (concat user-emacs-directory "meta/")
    "Directory containing files about files.")

Recently visited files

  (setq recentf-save-file
        (concat sd-path-meta "recentf"))

File bookmarks

  (setq bookmark-default-file
        (concat sd-path-meta "bookmarks"))

Projects' bookmarks

  (setq projectile-known-projects-file
        (concat sd-path-meta "projectile-bookmarks.eld"))

Org id locations

#+begin_quote We track IDs through files, so that links work globally. The file defined at org-id-locations-file maintains a hash table for IDs and writes this table to disk when exiting Emacs. Because of this, it works best if you use a single Emacs process, not many.

Paraphrased from the Emacs help interface. #+end_quote

  (setq org-id-locations-file
        (concat sd-path-meta "org-id-locations"))
  ;; The leading period is removed because no files are hidden in the
  ;; metafiles' directory.

Location in previously visited file

  (setq save-place-file
        (concat sd-path-meta "places"))

Auto save file lists

  (setq auto-save-list-file-prefix
        (concat sd-path-meta "auto-save-list/.saves-"))

Resources

All third-party resources are saved at the following location.

  (defcustom sd-path-resources
    (concat user-emacs-directory "resources/")
    "Directory containing the third-party resources.
  Resources may be any data that is not auto-generated during Emacs
  startup.")

Packages

  (setq package-user-dir
        (concat sd-path-resources "elpa/"))

Themes

  (setq custom-theme-directory
        (concat sd-path-resources "themes/"))

Snippets

This path, specifically, is required to be in list form.

  (setq yas-snippet-dirs
        (list (concat sd-path-resources "snippets/")))

Templates

  (setq sd-path-templates
        (concat sd-path-resources "templates/"))

Emojis

  (setq emojify-emojis-dir
        (concat sd-path-resources "emojis/"))

Custom file

Load settings created automatically by GNU Emacs Custom. (For example, any clickable option/toggle is saved here.) Useful for fooling around with M-x customize-group <package>.

#+NAME: custom-file-location

  (setq custom-file (concat sd-path-resources "custom.el"))
  (load custom-file)

Backups

Backups are very important!

  (setq backup-directory-alist
        `((".*" . "~/.cache/emacs/"))
        auto-save-file-name-transforms
        `((".*" ,"~/.cache/emacs/" t))
        backup-by-copying t    ; Don't delink hardlinks
        version-control t      ; Use version numbers on backups
        delete-old-versions t  ; Automatically delete excess backups
        kept-new-versions 20   ; how many of the newest versions to keep
        kept-old-versions 5)   ; and how many of the old

Undo history

We save undo history in a designated directory, so as not to pollute our ~/.emacs.d/ file hierarchy.

  (setq undo-tree-history-directory-alist '(("." . "~/.cache/emacs/")))

Initial and default frames

We set the dimensions of the initial frame:

  (add-to-list 'initial-frame-alist '(width  . 80))
  (add-to-list 'initial-frame-alist '(height . 24))

We also set the dimensions of subsequent frames:

  (add-to-list 'default-frame-alist '(width  . 80))
  (add-to-list 'default-frame-alist '(height . 24))

Transparency.

: (set-frame-parameter (selected-frame) 'alpha '(<active> . <inactive>)) : (set-frame-parameter (selected-frame) 'alpha <both>)

  (set-frame-parameter (selected-frame) 'alpha '(95 . 95))
  (add-to-list 'default-frame-alist '(alpha . (95 . 95)))

Secrets

The code contained in the secrets.org file is loaded by Emacs, but not rendered in this PDF for the sake of privacy. It contains individually identifying information such as names and e-mail addresses, which are used to populate Org templates (Section ~org-mode~). You need to create this secrets.org file, as it is ignored by git by default.

  (let ((secrets (concat user-emacs-directory "secrets.org")))
    (when (file-exists-p secrets) (org-babel-load-file secrets)))

Keyboard shortcuts

What follows are the most useful keybindings, as well as the keybindings to the functions we defined ourselves. It doesn't matter if we haven't defined the functions themselves yet; Emacs will accept a keybinding for any symbol and does not check if the symbol's function definition exists, until the keybinding is pressed.

CUA mode

The bindings in the following sections strive to further enhance CUA mode.[fn::Common User Access. This is a term coined by IBM which has influenced user navigation cues on all modern desktop OSes. From IBM's CUA, we get the Ctrl-c, Ctrl-v, and other keyboard shortcuts.]

  (cua-mode)

Files

COMMENT Save a file

# This is made redundant by C-x C-s.

  (global-set-key (kbd "C-s") 'save-buffer)

COMMENT Open a file

# This is made redundant by C-x C-f.

  (global-set-key (kbd "C-c o") 'find-file)

COMMENT List open files

# This is made redundant by C-x b.

  (global-set-key (kbd "C-c b") 'ivy-switch-buffer)

Open this very file

(Function defined in Section This very file)

  (global-set-key (kbd "C-c c") 'sd-find-literate-config)

Open the Org diary

  (global-set-key (kbd "C-c d") 'sd-find-org-diary)

Capture Org content

  (global-set-key (kbd "C-c k") 'org-capture)

Open a recently visited file

  (global-set-key (kbd "C-r") 'counsel-recentf)

Locate a file

  (global-set-key (kbd "C-c l") 'counsel-locate)

Open the agenda

  (global-set-key (kbd "C-c a") 'org-agenda)

Open the diary

# SSH headache with lws VPS

  (global-set-key [f9]
                  '(lambda ()
                     "Load `org-agenda-diary-file'."
                     (interactive)
                     (find-file org-agenda-diary-file)))

Open Org mode document properties

  (global-set-key [f8] 'sd-document-properties)

Windows

COMMENT Close window and quit

# When considering key chord usage frequency, Emacs default # keybindings make more sense every passing day.

The following bindings lead to more natural window & frame exit behaviors.

#+NAME: close-window-or-previous-buffer

  (global-set-key (kbd "C-w") 'sd-delete-window-or-previous-buffer)

Frame

Make new frame

  (global-set-key (kbd "C-c n") 'make-frame)

Make only frame

  (global-set-key (kbd "C-`") 'delete-other-windows)

Delete frame or kill Emacs

#+NAME: delete-frame-or-kill-emacs

  (global-set-key (kbd "C-q") 'sd-delete-frame-or-kill-emacs)

Remap =C-z= when using a graphical interface

By default, C-z suspends the editor. This is extremely handy when the editor is started with the -nw option (no window, i.e. launched in a terminal), because it returns control to the terminal command line without quitting Emacs---it simply places the Emacs process in the background. The user may then use the Linux job management tools to return inside the Emacs process.

However, when using a graphical display, we have no need for suspending the frame, so we remap C-z to the much more sensible undo behaviour.

  (when (display-graphic-p)
    (global-set-key (kbd "C-z") 'undo))

Text display

Zoom

The typical binding on both GNU/Linux and MS Windows is adequate here: C-= to zoom in, C-- to zoom out.

It seems that starting with Emacs 27.1, Control + mousewheel works.

  (global-set-key (kbd "C--") 'text-scale-decrease)
  (global-set-key (kbd "C-=") 'text-scale-increase)
  (global-set-key (kbd "C-+") 'text-scale-increase)

TODO COMMENT Navigation

# [2021-09-13 Mon] # # Kinda don't like this... This is some more text. And then some. # And then some.

Alt (Meta) is the privileged key for motion in a buffer. It is followed by an optional numerical argument, and a movement command. You may navigate in a buffer by keeping Alt pressed, optionally inputting a number from the keypad or number row, then pressing any of the following movement keys: j, k, h, and l. You will move in that direction in the amount of the numerical argument.

#+NAME: keybinding-navigation #+CAPTION[Navigation keybindings]: Navigation keybindings. #+ATTR_LATEX: :booktabs t | | *Backwards* | *Forwards* | |-----------+-------------+------------| | Character | M-h | M-l | | Line | M-k | M-j | | Word | M-f | M-b | | Paragraph | M-a | M-e |

We prevent Org mode from overriding preferred navigation keys.

  (add-hook 'org-mode
            '(lambda ()
               (local-unset-key (kbd "M-j"))
               (local-unset-key (kbd "M-k"))
               (local-unset-key (kbd "M-l"))
               (local-unset-key (kbd "M-h"))))

Move down one line

  (global-set-key (kbd "M-j") 'next-line)

Move up one line

  (global-set-key (kbd "M-k") 'previous-line)

Move left one character

  (local-unset-key (kbd "M-h"))
  (global-set-key (kbd "M-h") 'left-char)

Move right one character

  (global-set-key (kbd "M-l") 'right-char)

Accessing customization

Customize a variable

  (global-set-key (kbd "C-c v") 'customize-variable)

Customize a face

  (global-set-key (kbd "C-c f") 'customize-face)

One-click workflows

A major advantage of Emacs is the following: arbitrarily complicated workflows can be described by a series of functions assigned to a single keybinding. This means we can build automations to a pretty absurd level.

Export to PDF

PDF is probably the most prevalent file format for sharing static documents.

Document

  (global-set-key (kbd "C-c p") 'sd-quick-export)

TODO Presentation


Clean up buffer

Clean up buffer in every mode.

  (global-set-key [f12] 'sd-beautify-buffer)

Smart compilation

  (global-set-key (kbd "C-c m") 'sd-smart-compile)

Packages

Packages are collections of .el files providing added functionality to Emacs.

Meta

How do we bootstrap packages? First, let's figure out:

  1. Where we get our packages from
  2. How we upgrade packages
  3. How we ensure our required packages are installed

Package archives

List of package archives.

#+NAME: package-archives

  (require 'package)
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
  (add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)
  (package-initialize)

TODO Convenient package update

One-function rollup of upgradeable package tagging, download and lazy install.


~use-package~

We ensure use-package is installed, as well as all packages described in this configuration file.

  (unless (package-installed-p 'use-package)
    (package-refresh-contents)
    (package-install 'use-package)
    (eval-when-compile (require 'use-package)))
  (setq use-package-always-ensure t)
  (require 'use-package)
  (require 'bind-key)

COMMENT ~evil-mode~

Forgive me, for I have sinned.

This is the 2^{nd} most significant customization after org-mode. Enabling evil-mode completely changes editing keys.[fn::For more information on vi keybindings, visit https://hea-www.harvard.edu/~fine/Tech/vi.html.]

  (use-package evil)
  (setq evil-toggle-key "C-c d")
  (evil-mode 1)

Spelling, completion, and snippets

The following customizations open the doors to vastly increased typing speed and accuracy.

Syntax checking

We require a package to highlight syntax errors and warnings. The flycheck package ensures we are aware of all our code's syntactical shortcomings.

#+NAME: flycheck

  (use-package flycheck)
  (global-flycheck-mode)

Spelling

#+NAME: flyspell

  (use-package flyspell)
  (add-hook 'text-mode-hook 'flyspell-mode)

Completion

  (use-package company)
  (add-hook 'after-init-hook 'global-company-mode)

Insert template from keyword

Thanks to yasnippet, we can type certain keywords, then press TAB, to automatically insert a predefined text snippet. We can then navigate through the snippet by using <tab> (next field) and <backtab> (previous field).[fn::<backtab> is synonymous with pressing shift-tab.]

For instance: typing src then pressing TAB will expand the keyword to the following text:

: #+BEGIN_SRC emacs-lisp :tangle yes : : #+END_SRC

We notice that emacs-lisp is highlighted---this is the first modifiable field. Many clever programming tricks can be performed with yasnippet to save us a ton of time with boilerplate text!

#+NAME: yasnippet

  (use-package yasnippet)
  (yas-global-mode 1)

Delete all consecutive whitespaces

#+NAME: hungry-delete

  (use-package hungry-delete
    :config (progn
              (global-hungry-delete-mode)
              (add-to-list
               'hungry-delete-except-modes ;; Otherwise minibuffer paths can't be backspaced.
               'minibuffer-mode)))

Utilities

Versioning of files

Wonderful Git porcelain for Emacs. Enables the administration of a Git repository in a pain-free way.

  (use-package magit
    :bind ("C-c g" . magit-status))

This enables us to better manage our .git projects.

  (use-package projectile
    :bind ("C-c p" . 'projectile-command-map)
    :init (projectile-mode 1)
    (setq projectile-completion-system 'ivy))

Display keyboard shortcuts on screen

  (use-package which-key
    :init (which-key-mode))

Jump to symbol's definition

dumb-jump is a reliable symbol definition finder. It uses different matching algorithms and heuristics to provide a very educated guess on the location of a symbol's definition.

  (use-package dumb-jump)
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)

Graphical representation of file history

  (use-package undo-tree)
  (global-undo-tree-mode)

Auto-completion framework

  (use-package ivy
    :config (setq ivy-use-virtual-buffers t
                  ivy-count-format "%d/%d "
                  enable-recursive-minibuffers t))
  (ivy-mode t)

Smartly suggesting interactive search matches

And he will be called Wonderful *Counselor*, Mighty God, Everlasting Father, Prince of Peace.

  (use-package counsel
    :bind ("M-x" . counsel-M-x)
    :config (counsel-mode t))

Searching for items in current buffer

  (use-package swiper
    :bind (("C-c f" . swiper)))

COMMENT Web browsing

Thanks Xah![fn::http://ergoemacs.org/emacs/emacs_set_default_browser.html]

We use a browser depending on the url.

  (setq browse-url-browser-function
        '(("wikipedia\\.org" . browse-url-firefox)
          ("github\\.com" . browse-url-chromium)
          ("thefreedictionary\\.com" . eww-browse-url)
          ("." . browse-url-default-browser)))

IRC

Emacs ships with an IRC client called erc.

  (use-package erc
    :custom
    (erc-autojoin-channels-alist '(("freenode.net"
                                    "#linux"
                                    "#archlinux"
                                    "#emacs"
                                    "#bitcoin"
                                    "#latex"
                                    "#org-mode"
                                    "#python")))
    (erc-autojoin-timing 'ident) ; Autojoin after NickServ identification.
    (erc-fill-function 'erc-fill-static)
    (erc-fill-static-center 16)
    ;; (erc-hide-list '("JOIN" "PART" "QUIT"))
    (erc-lurker-hide-list '("JOIN" "PART" "QUIT"))
    (erc-lurker-threshold-time (* 3600 4)) ; Four hours
    (erc-prompt-for-nickserv-password nil)
    (erc-server-reconnect-attempts 5)
    (erc-server-reconnect-timeout 3)
    :config
    (add-to-list 'erc-modules 'spelling)
    (erc-services-mode 1)
    (erc-update-modules))

TODO Telegram

Yeah, a Telegram client exists for Emacs.

  (use-package telega
    :load-path "~/telega.el/telega.el"
    :commands (telega)
    :defer t)

COMMENT Drawings

  +-----------+    +-----------------+
  | c06F      |    | c06F            |
  | Create a  |    | Open the source |
  | source    |--->| block and       |
  | block for |    | start drawing!  |
  | ditaa     |    |                 |
  +-----------+    +-----------------+

#+RESULTS: file:resources/images/ditaa.png

TODO UML diagrams

# Implement automatically downloading this kind of executable!

  ;; (require 'plantuml-mode)
  (use-package plantuml-mode)

  (setq plantuml-default-exec-mode 'jar
        plantuml-jar-path (concat sd-path-resources
                                  "executables/plantuml.jar")
        org-plantuml-jar-path (concat sd-path-resources
                                      "executables/plantuml.jar"))
  @startuml doob.png
  !theme cerulean-outline
  title Example diagram with Plantuml

  package "Package 1" as pkg1 {
          node node1
          node node2
  }
  package "Package 2" as pkg2 {
          component "Component 1" as comp1
          component "Component 2" as comp2
          interface "Interface" as int
  }

  pkg1 .. pkg2

  comp1 --> int
  comp2 --> int
  @enduml

#+ATTR_LATEX: :width 0.8\textwidth #+RESULTS: file:resources/images/uml.png

Coding languages

TODO Emacs Lisp

Python

Python is included by default on most Linux distributions.

  (use-package py-yapf)
  (add-hook 'python-mode-hook 'py-yapf-enable-on-save)

OCaml

  (use-package tuareg)
  (use-package merlin)
  (add-hook 'tuareg-mode-hook #'merlin-mode)
  (use-package utop)

Haskell

  (use-package haskell-mode)

Smalltalk

  (use-package smalltalk-mode)

Lua

# If I have to deal with luaotfload one more time, I swear...

  (use-package lua-mode)

Web languages

Encompasses HTML, CSS, Javascript, Jinja(2), as well as many other web-related markup languages.

  (use-package web-mode)
  (use-package nginx-mode)
  ;; (use-package js-mode)

File formats

These aren't tied to a particular language per se.

=csv= and Excel

  (use-package csv-mode)

COMMENT Interacting with PDFs

# Doesn't work on Guix...

Org mode shines particularly when exporting to PDF---Org files can reliably be shared and exported to PDF.

  (use-package pdf-tools)
  (unless (string-equal system-type "windows-nt")
    (pdf-tools-install))

Accounting

Ledger is a creation of John Wiegley's. It enables double-entry accounting in a simple plaintext format, and reliable verification of account balances through time.[fn::For more information, visit https://www.ledger-cli.org/.]

  (use-package ledger-mode
    :bind
    ("C-c r" . ledger-report)
    ("C-c C" . ledger-mode-clean-buffer))

These reports can be generated within Emacs. It is quite useful to pipe their output to an automated ``smart document''.

  (setq ledger-reports
        '(("bal" "%(binary) -f %(ledger-file) bal")
          ("bal-USD" "%(binary) -f %(ledger-file) bal --exchange USD")
          ("reg" "%(binary) -f %(ledger-file) reg")
          ("net-worth" "%(binary) -f %(ledger-file) bal ^Assets ^Liabilities --exchange USD")
          ("net-income" "%(binary) -f %(ledger-file) bal ^Income ^Expenses --exchange USD --depth 2 --invert")
          ("payee" "%(binary) -f %(ledger-file) reg @%(payee)")
          ("account" "%(binary) -f %(ledger-file) reg %(account)")
          ("budget" "%(binary) -f %(ledger-file) budget --exchange USD")))

Plotting & charting

  (use-package gnuplot)

Cosmetics

Start page

We replace the standard welcome screen with our own.


Better parentheses

  (use-package rainbow-delimiters
    :config (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
  (show-paren-mode 1)

Highlight /color/ keywords in that color

This highlights hexadecimal numbers which look like colors, in that same color.

  (use-package rainbow-mode
    :init
    (add-hook 'prog-mode-hook 'rainbow-mode))

Minor modes in mode line

We hide minor modes in the mode line.

  (use-package rich-minority)
  (rich-minority-mode 1)
  (setf rm-whitelist "projectile")

Emojis

Emojis are a symbol of modernity, and their tasteful use enables communicating with people from around the world---we're all for that! B-) \smiley

  (when (string-equal system-type "gnu/linux")
    (use-package emojify
      :hook (after-init . global-emojify-mode)))

~org-mode~

Org mode is so significant that this section of the paper deserves its own introduction.

Introduction

Phew, after all this initialization, I can finally introduce Org mode! I am so *excited*.

Org mode replaces a word processor, a presentation creator, and a spreadsheet editor. The spreadsheet ability captures more than 80% use cases wherein one wishes to include a table in a text document destined for physical publication. (It is clear that Excel spreadsheets are /not/ destined for physical publication---simply attempt to print an Excel spreadsheet with the default settings.) In my opinion, Org mode matches all /useful/ features of the Microsoft Office suite 1-to-1.

What follows are customizations designed to make Org mode behave more like Microsoft Word. The end goal is, once again, to draw as many new users to Emacs as possible!

Check out how much information Org mode keeps concerning the most recent header:

#+NAME: org-meta-info

  (save-excursion
    (org-previous-visible-heading 1)
    (org-entry-properties))

(This block was evaluated on Microsoft Windows.)

#+RESULTS[cf982044956d8f3ec89e7a9da80976b1b19db423]: org-meta-info : (("CATEGORY" . "smart-documents") : ("BLOCKED" . "") : ("FILE" . "c:/Users/blend/AppData/Roaming/.emacs.d/smart-documents.org") : ("PRIORITY" . "A") : ("ITEM" . "Introduction"))

Basic customization

Base folder

Org base directory is in user home on GNU/Linux, or in AppData in MS Windows.

#+NAME: org-directory

  (setq org-directory (concat user-emacs-directory "~/org"))

Prevent/warn on invisible edits

  (setq org-catch-invisible-edits t)

Org cosmetics

First, we ensure the display of markup symbols for *bold*, /italic/, _underlined_ and +strikethrough+ text, and ensure our document appears indented upon loading.[fn::It /appears/ indented, but the underlying plaintext file does not contain tab characters!]

We then set values for many other Org-related cosmetic symbols.

  (setq org-hide-emphasis-markers nil
        org-startup-indented t
        org-src-preserve-indentation nil
        org-edit-src-content-indentation 2)

Pretty LaTeX symbols

We display LaTeX entities as UTF8 symbols \rArr this is a slick idea to further make Emacs look like the exported PDF. Using symbols in tables is discouraged?

  (setq org-pretty-entities t)

Dynamic numbering of headlines

We enable the dynamic numbering of headlines in an Org buffer. We also set the numbering face to org-special-keyword, which specifies a :background white attribute. This is necessary because otherwise, the background of the numbering may be overridden by the TODO face attribute :background coral.

  (add-hook 'org-mode-hook 'org-num-mode)
  (setq org-num-face 'org-special-keyword
        org-num-skip-commented t
        org-num-skip-unnumbered t)

By default, we hide Org document properties such as #+TITLE, #+AUTHOR, and #+DATE, because those keywords are defined when the document template is populated. We can nevertheless always access those properties and edit them manually, with a simple keyboard shortcut (cf. Section Open Org mode document properties).

TODO Document properties

  (defun org-property-value (property)
    "Return the value of a given Org document property."
    (interactive)
    (save-excursion
      (goto-char (point-min))
      (re-search-forward
       (concat
        "^[[:space:]]*#\\+"
        property
        ":[[:space:]]*\\(.*?\\)[[:space:]]*$")
       nil t)
      (nth 3 (car (cdr (org-element-at-point))))))
  (defun sd-document-properties ()
    "Open separate buffer to edit Org mode properties."
    (interactive)
    (let ((title (car (org-property-value "TITLE")))
          (date (org-property-value "DATE")))
      (with-output-to-temp-buffer "Smart Document Properties"
        (print title)
        (print date))))
  (add-hook 'org-src-mode-hook
            '(lambda ()
               "Disable flycheck for `emacs-lisp-mode'."
               (setq-local flycheck-disabled-checkers
                           '(emacs-lisp-checkdoc))))

Timestamps

# This is a terrible idea :-( but leaving the option to the # reader. Long live ISO-8601! # https://orgmode.org/manual/Custom-time-format.html

More literary timestamps can be exported to LaTeX using the following custom format:

  (setq org-time-stamp-custom-formats
        '("%d %b. %Y (%a)" . "%d %b. %Y (%a), at %H:%M"))

COMMENT Sequence of TODOs

  (setq org-todo-keywords
        '((sequence "TODO"		; Vanilla sequence
                    "|"
                    "DONE")
          (sequence "APPLY"		; Job applications
                    "FOLLOW UP"
                    "|"
                    "REJECTED"
                    "STOP"
                    "OFFER")
          (sequence "STUCK"		; Project mgmt
                    "WAITING"
                    "|"
                    "N/A"
                    "COMPLETED")))


  (setq org-todo-keyword-faces
        '(("STUCK" . (:height 1.6 :background "red" :foreground "white" :weight bold))
          ("WAITING" . (:height 1.6 :background "yellow"))
          ("N/A" . (:height 1.6 :background "LightSteelBlue3" :foreground "white"))
          ("COMPLETED" . (:height 1.6 :background "green" :foreground "white"))))

Agenda

The agenda displays a chronological list of headings across all agenda files for which the heading or body contain a matching org-time-stamp.[fn::An org-time-stamp can be inserted with C-c . (period)]

COMMENT Open agenda in separate frame

# Meh

We open the agenda in a separate frame.

  (setq org-agenda-window-setup 'other-frame)

Diary file

The diary file can be included in all agenda views.

  (setq org-agenda-diary-file "~/org/PERSONAL/diary/diary.org")

List of agenda files

If the agenda file does not already exist, create it at the expected location.

  (unless (file-exists-p (concat sd-path-meta "org-agenda-files"))
    (with-temp-buffer
      (write-file (concat sd-path-meta "org-agenda-files"))))

The list of agenda files is saved at the following location.

  (setq org-agenda-files (concat sd-path-meta "org-agenda-files"))

Org Capture

  (setq org-default-notes-file (concat sd-path-resources "org/default-notes.org"))

Programming a {{{SD}}}

The following languages can be used inside SRC blocks, in view of being executed by the Org Babel backend upon document export.

  (org-babel-do-load-languages
   'org-babel-load-languages
   '((shell . t)
     (python . t)
     (ditaa . t)
     (plantuml . t)
     (emacs-lisp . t)
     (awk . t)
     ;; (ledger . t) ;; Deprecated in Emacs 28.1?
     (lua . t)
     (latex . t)
     (C . t)
     (gnuplot . t)
     (ocaml . t)))

Exporting {{{SDs}}}

LaTeX export

We'll be compiling our documents with LuaTeX. This will afford us some future-proofing, since it was designated as the successor to pdfTeX by the latter's creators.

First, we define the command executed when an Org file is exported to LaTeX. We'll use latexmk, the Perl script which automagically runs binaries related to LaTeX in the correct order and the right amount of times.

Options and why we need them:

~-shell-excape~
required by minted to color source blocks
~-pdflatex=lualatex~
we use lualatex to generate our PDF
~-interaction=nonstopmode~
go as far as possible without prompting user for input
  (setq org-latex-pdf-process
        '("latexmk -f -pdf -%latex \
-interaction=nonstopmode -output-directory=%o %f -shell-escape"))

Exporting timestamps

We customize the format for org time stamps to make them appear monospaced in our exported LaTeX documents. This makes it easy to distinguish time stamps from body text, and make them align nicely in definition lists, which I prefer when logging events:

[2021-10-03 Sun]
Did something
[2021-10-04 Mon]
Did something else
[2021-10-05 Tue]
Did yet another thing
  (setq org-latex-active-timestamp-format
        "\\texttt{%s}")
  (setq org-latex-inactive-timestamp-format
        "\\texttt{%s}")

LaTeX packages

The following packages are loaded for every time we export to LaTeX.

  (setq org-latex-packages-alist
        '(("AUTO" "babel" t
           ("pdflatex"))
          ("AUTO" "polyglossia" t ; Babel replacement for LuaLaTeX
           ("xelatex" "lualatex"))
          ("" "fontspec" t ; Fonts for LuaLaTeX
           ("lualatex"))
          ("" "booktabs" t ; Publication quality tables
           ("pdflatex" "lualatex"))
          ("" "wasysym" t ; Emojis and other symbols
           ("pdflatex" "lualatex"))
          ("" "lettrine" t
           ("pdflatex" "lualatex"))
          ("table,svgnames" "xcolor" t ; svgnames opens up ~150 new color keywords
           ("pdflatex" "lualatex"))
          ("skip=0.5\\baselineskip" "caption" t ; Increase space between floats and captions
           ("pdflatex" "lualatex"))))

COMMENT Colored source blocks in PDF export

# Too distracting. Focus on fonts.

Little bonus for GNU/Linux users: syntax highlighting for source code blocks in LaTeX exports.

  (when (string-equal system-type "gnu/linux")
    (add-to-list 'org-latex-packages-alist '("AUTO" "minted" t
                                             ("pdflatex" "lualatex")))
    (setq org-latex-listings 'minted)
    (setq org-latex-minted-options '(("style" "friendly")
                                     ("breaklines" "true")
                                     ("breakanywhere" "true"))))

Cleaning directory after export

Now, we set the files to be deleted when a LaTeX \rightarrow PDF compilation occurs. We only care about two files, in the end: the Org mode file for edition, and the PDF for distribution.

  (setq org-latex-logfiles-extensions
        '("aux" "bcf" "blg" "fdb_latexmk"
          "fls" "figlist" "idx" "log" "nav"
          "out" "ptc" "run.xml" "snm" "toc" "vrb" "xdv"
          "tex" "lot" "lof"))

Chronological diary entries

By default, Org agenda inserts diary entries as the first under the selected date. It is preferable to insert entries in the order that they were recorded, i.e. chronologically.

  (setq org-agenda-insert-diary-strategy 'date-tree-last)

Extra LaTeX class

These /letter/ classes (LaTeX templates) complete the other default LaTeX classes. The lettre class is not always included by default in our LaTeX distribution; it can be installed from the CTAN.

  (require 'ox-publish)

  (add-to-list 'org-latex-classes
               '("lettre"
                 "\\documentclass[10pt]{lettre}"
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection*{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection*{%s}" . "\\subsubsection*{%s}")))

  (add-to-list 'org-latex-classes
               '("letter"
                 "\\documentclass[11pt]{letter}"
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection*{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection*{%s}" . "\\subsubsection*{%s}")))

  (add-to-list 'org-latex-classes
               '("book-blendoit"
                 "\\documentclass[11pt]{book}"
                 ("\\chapter{%s}" . "\\chapter*{%s}")
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection*{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection*{%s}" . "\\subsubsection*{%s}")))

COMMENT Table of contents

# Commented out on <2021-09-21 Tue>.

By default, body text can immediately follow the table of contents. It is however cleaner to separate table of contents with the rest of the work.

  (setq org-latex-toc-command "\\tableofcontents\\clearpage")

AUCTEX

  (use-package tex
    :defer t
    :ensure auctex
    :ensure auctex-latexmk)
  (auctex-latexmk-setup)

Groff export

  (require 'ox-groff)

This is a mind-bending capacity of Org mode: we can assign arbitrary functions to be executed when a user follows an Org link. Org links appear as hyperlinks both in buffers and PDF exports---e.g. the following link to this very section, Section Org links---but their in-buffer behavior can be arbitrarily assigned.

  (org-add-link-type
   "tag" 'endless/follow-tag-link)

  (defun endless/follow-tag-link (tag)
    "Display a list of TODO headlines with tag TAG.
  With prefix argument, also display headlines without a TODO keyword."
    (org-tags-view (null current-prefix-arg) tag))

  [[tag:work+phonenumber-boss][Optional Description]]

One-click workflows

In this section, we'll implement useful one-click workflows. It comes later than the keybinding definitions for two reasons:

  1. To a new user, keybindings are more relevant than the implementation of the bound function---it is more important to know how to drive a car than how a car works.
  2. If the following subsections share the same name as the keybinding subsection (Section Keyboard shortcuts), the links to that name will resolve to the earliest heading in the document, i.e. the keybinding subsection, and not the subsection describing the ``one-click workflow''.

Opening files

First off, we identify files that we'd like to jump to conveniently.

This very file

We begin by defining a function to open this very file.

  (defun sd-find-literate-config ()
    "Visit this very file."
    (interactive)
    (find-file sd-literate-config))

Org diary file

  (defun sd-find-org-diary()
    "Visit the `org-agenda-diary-file'."
    (interactive)
    (find-file org-agenda-diary-file))

TODO Export to PDF

This series of quick-export functions have one objective: harmonize the export of Emacs buffers to PDF. Org mode does this by design; we describe additional exports for other modes, most notably Nroff mode and Ledger mode.

From Org mode

This reimplements the most common Org mode export: Org \rightarrow LaTeX \rightarrow PDF. The binding is defined in Section Export to PDF.

  (defun sd-quick-export--org ()
    "Org mode async export to PDF and open.
       This basically reimplements `C-c C-e C-a l o'."
    (org-open-file (org-latex-export-to-pdf)))

From a Ledger report

  (defun sd-quick-export--ledger-report ()
    "Quick export for `ledger-mode' report buffers."
    (let ((old-buffer (current-buffer)))
      (with-output-to-temp-buffer "**SD Export**"
        (print "#+SETUPFILE: ~/.emacs.d/resources/templates/documents/default.org")
        (newline)
        (insert-buffer-substring old-buffer)
        (forward-line 10)
        (org-table-convert-region (point) (goto-char (point-max)))
        (setq more-lines-p t)
        (while more-lines-p
          (move-end-of-line 1)
          (newline)
          (setq more-lines-p (= 0 (forward-line 1))))
        (org-open-file (org-latex-export-to-pdf)))))

From Nroff mode

  (defun sd-quick-export--nroff (macros)
    "Export Nroff/Groff buffer to PDF, with specified macro set."
    (let* ((file-exported-name
            (concat (file-name-sans-extension buffer-file-name)
                    (format "-%s.pdf" macros)))
           (command-export
            (format "groff -%s -Tps %s | ps2pdf - > %s"
                    macros
                    (buffer-file-name)
                    file-exported-name)))
      (shell-command command-export)
      (org-open-file file-exported-name)))

Quick export

  (defun sd-quick-export ()
    "Quickly prettify and export current buffer to PDF."
    (interactive)
    (cond ((eq major-mode 'org-mode)
           (sd-quick-export--org))
          ((eq major-mode 'nroff-mode)
           (sd-quick-export--nroff
            (read-string "Macro set used (ms, me, mm...): ")))
          ((eq major-mode 'emacs-lisp-mode)
           (message "No quick-export implemented for emacs-lisp-mode yet."))
          ((eq major-mode 'ledger-report-mode)
           (sd-quick-export--ledger-report))
          (t (message (format "No sd-quick-export backend for %s." major-mode)))))

Operate on whole buffer

Fix indentation

  (defun sd-indent-buffer
      ()
    "Indent entire buffer."
    (interactive)
    (save-excursion
      (indent-region
       (point-min)
       (point-max)
       nil)))

Beautify

All types of buffers

  (defun sd-beautify-buffer
      ()
    "Clean up buffer in the most general sense.

  This means performing the following actions:
  1) indenting the buffer according to the major mode in force,
  2) deleting trailing whitespaces.

  As well as a couple other things."
    (interactive)
    (sd-indent-buffer)
    (delete-trailing-whitespace)
    (cond
     ((string-equal major-mode "org-mode")
      (sd-org-fix-headlines-spacing))
     ((string-equal major-mode "python-mode")
      (or
       (shell-command
        (concat "~/.local/bin/black " buffer-file-name))
       (message "Could not find black Python formatter.")))))

TODO COMMENT For Org mode, specifically

  (defun sd-org-fix-headlines-spacing ()
    "Insert the proper amount of newlines between Org headlines."
    (save-excursion
      (progn
        (goto-char (point-min))
        (flush-lines "^[[:space:]]*$")
        (while (re-search-forward "^*" nil t)
          (beginning-of-line)
          (newline 2)
          (next-line)
          (newline))))

Smart quitting

:PROPERTIES: :test: t :END:

Window

  (defun sd-delete-window-or-previous-buffer ()
    "Delete window; if sole window, previous buffer."
    (interactive)
    (if (> (length (window-list)) 1)
        (delete-window)
      (previous-buffer)))

Frame

  (defun sd-delete-frame-or-kill-emacs
      ()
    "Delete frame; if sole frame, kill Emacs."
    (interactive)
    (if
        (>
         (length
          (frame-list))
         1)
        (delete-frame)
      (save-buffers-kill-terminal)))

Programming

Smart compilation

  (defun sd-smart-compilation
      ()
    "recompile if `compile-command` was modified, or prompt
  for `compile-command`."
    (interactive)
    (if
        (eq
         (default-value 'compile-command)
         compile-command)
        (recompile)
      (compile)))

Editing preferences

These customizations enhance editor usability. They also encompass cosmetic changes not brought about a specific package.

Editor

Coding standards

This is just a better default. Don't @ me.

  (setq c-default-style "linux"
        c-basic-offset 4)

Recent files

The keybinding for opening a recently visited file is described in paragraph Open a recently visited file.

  (recentf-mode 1)
  (setq recentf-max-menu-items 100)
  (setq recentf-max-saved-items 100)
  (run-at-time nil (* 5 60) 'recentf-save-list)

Reload changed files silently

  (global-auto-revert-mode)

Frame

COMMENT Header & mode lines

# Top of the buffer is more intuitive for buffer info, bottom is more # intuitive for buffer action.

TODO Icons

:PROPERTIES: :sd-unpack-path: sd-icons.el :END:

We start by defining some icons we wish to include in our user interface. Emacs allows the usage of GIF images---this paves the way for UI elements which may be animated.

  (defcustom sd-icon-loading
    (create-image
     (concat user-emacs-directory "resources/images/icons/ellipsis.gif")
     'gif nil
     :scale 0.4)
    "The GIF representing \"loading\". Not animated by default."
    :type 'sexp
    :version "27.1"
    :group 'sd)

  (defun sd-icon-loading ()
    "Insert an animated blue ellipsis."
    (insert-image sd-icon-loading)
    (image-animate sd-icon-loading 0 t))

Header line

In Org mode, the document header line will be the title of the document we are working on currently. We start by defining keybindings for our header line buttons for navigating through open windows.

  (defvar sd-header-line-previous-buffer-keymap
    (let ((map (make-sparse-keymap)))
      (define-key map [header-line mouse-1] 'previous-buffer)
      map)
    "Keymap for what is displayed in the header line, with a single
    window.")

  (defvar sd-header-line-kill-buffer-keymap
    (let ((map (make-sparse-keymap)))
      (define-key map [header-line mouse-1] 'kill-buffer-and-window)
      map)
    "Keymap for closing current window.")

  (defvar sd-header-line-maximize-window-keymap
    (let ((map (make-sparse-keymap)))
      (define-key map [header-line mouse-1] 'delete-other-windows)
      map)
    "Keymap for maximizing the current window.")

  (defvar sd-header-line-minimize-window-keymap
    (let ((map (make-sparse-keymap)))
      (define-key map [header-line mouse-1] 'delete-window)
      map)
    "Keymap for minimizing the current window.")

Now, we describe the actual format of the header line.

  (use-package all-the-icons)

  (setq-default
   header-line-format
   '(:eval
     (list
      (if (eq (length (window-list)) 1)
          (propertize " ↤ "
                      'face 'org-meta-line
                      'mouse-face 'highlight
                      'keymap sd-header-line-previous-buffer-keymap
                      'help-echo "Return to previous window.")
        (list (propertize " ❌ "
                          'face 'org-meta-line
                          'mouse-face 'org-todo
                          'keymap sd-header-line-kill-buffer-keymap
                          'help-echo "Close this window.")
              (propertize " ⇱"
                          'face 'org-meta-line
                          'mouse-face 'highlight
                          'keymap sd-header-line-maximize-window-keymap
                          'help-echo "Maximize this window.")
              (propertize "⇲ "
                          'face 'org-meta-line
                          'mouse-face 'highlight
                          'keymap sd-header-line-minimize-window-keymap
                          'help-echo "Minimize this window.")))
      mode-line-buffer-identification)))

  (image-animate sd-icon-loading 0 t)

TODO Mode line

This interpretation of the ideal mode line is the result of carefully studying the default mode-line, as well as studying various customizations online.

  (defvar sd-mode-line-lock-buffer-keymap
    (let ((map (make-sparse-keymap)))
      (define-key map [mode-line mouse-1] 'read-only-mode)
      map)
    "Keymap for locking/unlocking the current buffer.")
  (setq-default
   mode-line-format
   (list
    mode-line-front-space
    '(:eval (if buffer-read-only
                (propertize "🔒"
                            'keymap sd-mode-line-lock-buffer-keymap
                            'help-echo "C-x C-q: unlock buffer.")
              (propertize "🔓"
                          'keymap sd-mode-line-lock-buffer-keymap
                          'help-echo "C-x C-q: lock buffer.")))
    '(:eval (if (buffer-modified-p)
                (propertize " 🖉 "
                            'help-echo "Buffer is modified.")
              (propertize " ✓ "
                          'help-echo "Buffer is saved.")))
    mode-line-modes " "
    mode-line-end-spaces))

Window

Buffer

Save cursor location

Save cursor location in visited buffer after closing it or Emacs.

  (save-place-mode 1)

Column filling

We leave the default fill-column unchanged, so as to minimally disrupt a user's existing documents. We automatically break lines longer than fill-column.

    (add-hook 'org-mode-hook
              'turn-on-auto-fill)

Text

COMMENT Beautiful symbols

# Honestly not that useful. In LaTeX, \newline is prettified into # oblivion...

We want the Emacs Lisp keyword lambda to be rendered as \lambda within the editor. This is mostly for a subjective ``cool'' factor.

  (global-prettify-symbols-mode 1)

Org mode sugar

Let's pimp out the appearance of our text in Org mode. First, we prettify checkbox lists when viewed on GNU/Linux systems.

  (when (string-equal system-type "gnu/linux")
    (add-hook 'org-mode-hook
              (lambda ()
                "Beautify Org symbols."
                (push '("[ ]" .  "○") ; Unchecked item
                      prettify-symbols-alist)
                (push '("[X]" . "◉" ) ; Checked item
                      prettify-symbols-alist)
                (push '("[-]" . "◎" ) ; Partially checked item
                      prettify-symbols-alist)
                (push '("-" . "⁃" ) ; Plain list dash
                      prettify-symbols-alist)
                (prettify-symbols-mode))))

Electric modes

Electricity is a very important technology. In Emacs jargon, ``electric'' modes tend to automate behaviors or present some elegant simplification to a workflow.[fn::More information can be found at https://www.emacswiki.org/emacs/Electricity.]

  (electric-pair-mode) ; Certain character pairs are automatically completed.
  (electric-indent-mode) ; Newlines are always intelligently indented.

Minibuffer

We replace the longer yes-or-no-p questions with more convenient y-or-n-p.

  (defalias 'yes-or-no-p 'y-or-n-p)

Disable minibuffer scroll bar.

  (set-window-scroll-bars (minibuffer-window) nil nil)

Themes

# This is just another comment.

Without a carefully designed theme, our editor would become unusable. Thus, we /describe/ two themes that were developed *purposefully* and iteratively.

  ;; (load-theme 'sd-compagnon-dark)
  ;; (load-theme 'molokai)
  ;; (load-theme 'wombat)
  ;; (load-theme 'sd-light)
  ;; (load-theme 'sd-dark)
  ;; (load-theme 'gotham)

My light and dark themes

A highly legible, unambiguous, and classic theme.

Colors

The default face is a black foreground on a white background, this matches MS Word. We are striving for a simple, intuitive color scheme.

Most of the affordance cues derived from color are identical in both light and dark themes (Table theme-color-1).

#+NAME: theme-color-1 #+CAPTION[Light and dark themes' colors]: Light and dark themes' colors. #+ATTR_LATEX: :booktabs t | Color | sd-light | sd-dark | |---------------------------------+---------------------------------+--------------------| | Black | default text | default background | | \_ Lighter shades | lesser headers | /n/a/ | | White | default background | default text | | \_ Darker shades | /n/a/ | lesser headers | | \color{Red} Red | negative | /same/ | | \color{Tomato} Tomato | timestamp `TODO' | /same/ | | \color{Green} Green | positive | /same/ | | \color{ForestGreen} ForestGreen | timestamp `DONE' | /same/ | | \color{Blue} Blue | interactive content; links | /same/ | | \color{SteelBlue} SteelBlue | anything Org mode; anchor color | /same/ | | \color{DeepSkyBlue} DeepSkyBlue | highlight | /same/ | | \color{DodgerBlue} DodgerBlue | isearch | /same/ | | \color{Purple} Purple | Code syntax highlighting | /same/ |

Red

Green

Blue

Purple

Purple is Emacs' main logo color. Since we use Emacs for coding a lot, code syntax highlighting to could be in the pink/purple shades. This is also a nod to Spacemacs' dark theme.2 hour

TODO Cursors

In order to imitate other modern text editors, we resort to a blinking bar cursor. We choose red, the most captivating color, because the cursor is arguably the region on our screen:

  1. most often looked at;
  2. most often searched when lost.

In files containing only fixed-pitch fonts (i.e. files containing only code), the cursor becomes a high-visibility box.

In files containing a mix of variable-pitch and fixed-pitch fonts, the cursor is a more MS Word-like bar.

  (setq-default cursor-type 'box)

TODO Fonts

Here are some fonts I discovered and enjoyed since I began learning Emacs.

Serif

Crimson Pro[fn::]
variable-pitch, default body text font - Inspired by Garamond
Linux Libertine[fn::]
variable-pitch, default body text font - Inspired by Garamond

Sans serif

Public Sans[fn::https://public-sans.digital.gov/]
variable-pitch, default body text font - Very modern yet neutral - Designed for the U.S. government - Exceptional color on screen
Jost[fn::https://indestructibletype.com/Jost.html]
org-document-title and org-level-1 - Ultra-modern - Tasteful amount of geometric inspiration
Open Sans[fn::https://www.opensans.com/]
variable-pitch - Ooh geometric Bauhaus influences, look at me - Tall leading height is harmonious
Liberation Sans[fn::https://en.wikipedia.org/wiki/Liberation_fonts]
+variable-pitch+ - Metrically compatible with /Arial/ (ugh) - Unoffensive, unambitious forms - Pretty angular letters, it's like you're trying to read squares

Monospace

Hack[fn::https://sourcefoundry.org/hack/]
default and fixed-pitch, default code font - Legible, modern monospace font - Strict, sharp, uncompromising
Hermit[fn::https://pcaro.es/p/hermit/]
org-block, anything Org/meta in general - Slightly wider than Hack - More opinionated shapes - Very legible parentheses, very useful for Emacs Lisp!
Courier Prime[fn::https://quoteunquoteapps.com/courierprime/index.php]
monospace in print

COMMENT Using proportional fonts when needed

We use variable-pitch-mode for appropriate modes.

  (add-hook 'org-mode-hook 'variable-pitch-mode)
  (add-hook 'info-mode-hook 'variable-pitch-mode)

TODO Default font size

Make default font size larger on displays of which the resolution is greater than 1920\times1080.

  (if (< screen-width 1920)
      (default-font)
    else)

TODO /Wealthy/ document theme

#+NAME: claude-garamont #+CAPTION[Claude Garamont, an icon of font design]: Claude Garamont, an icon of font design. World-renowned for his elegant typefaces, which inspired many generations of typographers. #+ATTR_LATEX: :width 0.4\textwidth ~/.emacs.d/resources/images/smart-documents/ClaudeGaramond.jpeg

#+LATEX: \garamond \lettrine{G}{ood} golly, nobody wishes for a /pedestrian/ theme! Let your entourage know that you're rocking an editor fit for a king with this finely crafted `wealthy' theme. Selecting it shall enable the following fancitudes:

  1. The default font shall be sublimed in the form of /EB Garamond/
  2. Bullets will be tastefully replaced with pointing fingers
  3. Heading stars will be replaced with Black Queen chess pieces

#+BEGIN_QUOTE \lettrine{C}{laude} Garamont (c. 1510--1561), known commonly as *Claude Garamond*, was a French type designer, publisher and punch-cutter based in Paris. Garamond worked as an engraver of punches, the masters used to stamp matrices, the moulds used to cast metal type. He worked in the tradition now called old-style serif design, which produced letters with a relatively organic structure resembling handwriting with a pen but with a slightly more structured and upright design. Considered one of the leading type designers of all time, he is recognised to this day for the elegance of his typefaces. Many old-style serif typefaces are collectively known as Garamond, named after the designer.

From https://en.wikipedia.org/wiki/Claude_Garamond #+END_QUOTE

#+LATEX: \publicsans

Symbol substitution

  (defun sd-wealthy ()
    "Beautify symbols for our wealthy theme."
    (push '("-" . "☞" ) prettify-symbols-alist) ; unnumbered bullets
    (push '("*" . "♛" ) prettify-symbols-alist) ; headings
    (prettify-symbols-mode))

TODO ~minimal~

Late setup

At this point, our editor is almost ready to run. Phew! All that's left to do is to interrupt our profiling activities, and smartly store the result of our profiling.

Profiling---stop

  (profiler-stop)

Profiling---report

  (profiler-report)

Conclusion

In this configuration file, we described a series of customization steps taken to make Emacs more palatable to modern word processors users.

COMMENT Local files variables

:PROPERTIES: :UNNUMBERED: t :END:

If the following variable is set to nil, org-babel will not ask to confirm the evaluation of source code blocks during export or tangling of this very file.