Emacs Initialisation
2024-02-24
Emacs is a highly extensible text-oriented user interface, with capabilities extending far beyond what most other text editors offer. This blog post is a complete Emacs literate configuration file and can be used to initialise the program with my preferences. I have also drawn some Emacs Lisp code from another stand-alone export script. These two sources have their own repositories:
Emacs additionally provides an interpreter for Emacs Lisp, the functional programming language in which much of its codebase is written. Emacs is extensible via code written in this language, examples of which are given here.
Initialisation
So that this file can be rendered nicely on GitHub or here on my
website, it is called README.org
, Org being a
markup language (you are currently reading a version of this file that
has been transformed to Markdown, edited and then transformed to HTML).
Emacs will not expect its configuration to be found in such file; it is
the contents of init.el
that are loaded by Emacs on
startup. There are two ways the contents of a literate configuration
document could be extracted to a plain text file:
- Load the file in Emacs and export the contents of the source blocks to a clean file.
- Extract the contents of the source block via an Emacs Lisp script or
even the
init.el
file itself.
The second of these options is preferable as a new installation can
be bootstrapped without an existing Emacs environment. A minimal
init.el
capable of loading a literate configuration might
look like:
(setq custom-file (locate-user-emacs-file "custom_vars.el"))
(load custom-file 'noerror 'nomessage)
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
(require 'org)
(org-babel-load-file
(expand-file-name "README.org"
user-emacs-directory))
Unfortunately, this approach requires that Org is loaded before the contents of the custom configuration. This means that package repository initialisation must take place first to ensure that a single Org version is used, not loaded partially once and then again in the literate configuration. In some cases, users have been able to export the contents of a literate configuration using only primitive Emacs Lisp functions, however I was understandably hesitant to work out the required regular expressions. Here is a screenshot of the finished configuration displaying an Org buffer:

Configuration Options
The remainder of the initialisation can be performed from the literate file itself. The first step is calling some functions to disable some unhelpful GUI components.
(menu-bar-mode -1) (tool-bar-mode -1)
(scroll-bar-mode -1)
(fringe-mode '(0 . 0))
(global-auto-revert-mode 1)
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
(global-set-key (kbd "M-u") 'universal-argument)
Followed by setting the values of some variables.
(setq-default indent-tabs-mode nil)
(setq-default c-basic-offset 4)
(setq inhibit-startup-echo-area-message "alex"
inhibit-startup-message t
initial-scratch-message "; Hello!"
tab-width 4
use-dialog-box nil
scroll-conservatively 1000
backup-inhibited t
auto-save-default nil
global-auto-revert-non-file-buffers t
x-select-enable-clipboard nil
user-full-name "Alexander Neville")
The default font is given an absolute height of 100
. The
height of other fonts is specified relative to the height of the default
font. In this case, :height 1.0
can be omitted.
(set-face-attribute 'default nil :family "VictorMono Nerd Font" :height 110)
(set-face-attribute 'variable-pitch nil :family "Noto Sans")
(set-face-attribute 'fixed-pitch nil :family "VictorMono Nerd Font")
Themes
The modus themes are very feature-rich and roll a lot of initialisation into one package.
(use-package modus-themes
:config
(setq modus-themes-mode-line '(accented)
modus-themes-region '(accented bg-only)
modus-themes-completions '(opinionated)
modus-themes-bold-constructs t
modus-themes-italic-constructs t
modus-themes-paren-match '(bold underline)
modus-themes-syntax '(faint)
modus-themes-subtle-line-numbers t
modus-themes-org-blocks nil
modus-themes-common-palette-overrides modus-themes-preset-overrides-faint
modus-themes-common-palette-overrides
'((fg-heading-1 blue)
(fg-heading-2 cyan)
(fg-heading-3 green)
)
)
(load-theme 'modus-operandi t)
)
The set of doom emacs themes is also quite nice. I only ever load one of modus or doom.
(use-package doom-themes
:ensure t
:config
(setq doom-themes-enable-bold t
doom-themes-enable-italic t)
(doom-themes-org-config)
(load-theme 'doom-one t))
The all-the-icons
package is required by doom modeline
and some other packages.
(use-package all-the-icons
:ensure t)
Optionally include the doom modeline.
(use-package doom-modeline
:ensure t
:hook (after-init . doom-modeline-mode)
:config
(setq doom-modeline-height 50)
(setq doom-modeline-bar-width 0))
Base16 is another good theme project for Emacs and other applications. This package can be loaded in place of one of the other theme packages.
(use-package base16-theme
:ensure t
:demand
:init
(setq base16-theme-distinct-fringe-background nil)
(setq base16-theme-highlight-mode-line 'contrast)
(setq base16-theme-256-color-source 'colors)
:config
(load-theme 'base16-gruvbox-material-dark-hard t)
; Set the cursor color based on the evil state
(defvar myconfig/base16-colors base16-gruvbox-material-dark-hard-theme-colors)
(setq evil-emacs-state-cursor `(,(plist-get myconfig/base16-colors :base0D) box)
evil-insert-state-cursor `(,(plist-get myconfig/base16-colors :base0D) bar)
evil-motion-state-cursor `(,(plist-get myconfig/base16-colors :base0E) box)
evil-normal-state-cursor `(,(plist-get myconfig/base16-colors :base0B) box)
evil-replace-state-cursor `(,(plist-get myconfig/base16-colors :base08) bar)
evil-visual-state-cursor `(,(plist-get myconfig/base16-colors :base09) box)))
The same is true of autothemer.
(use-package autothemer
:ensure t
:config
(load-theme 'notebook-light t))
Navigation & Bindings
Improve the default M-x
behaviour with fuzzy
finding. Ivy also includes swiper, which is a
great way to search a file that the buffer is visiting.
(use-package ivy
:diminish
:bind (("C-s" . swiper)
:map ivy-minibuffer-map
("TAB" . ivy-alt-done)
("C-l" . ivy-alt-done)
("C-j" . ivy-next-line)
("C-k" . ivy-previous-line)
:map ivy-switch-buffer-map
("C-k" . ivy-previous-line)
("C-l" . ivy-done)
("C-d" . ivy-switch-buffer-kill)
:map ivy-reverse-i-search-map
("C-k" . ivy-previous-line)
("C-d" . ivy-reverse-i-search-kill))
:config
(setq ivy-initial-inputs-alist nil)
(ivy-mode 1))
(use-package ivy-rich
:init
(ivy-rich-mode 1))
(use-package counsel
:bind (("M-x" . counsel-M-x)
("C-x b" . counsel-ibuffer)
("C-x C-f" . counsel-find-file)
:map minibuffer-local-map
("C-r" . 'counsel-minibuffer-history)))
A reasonably self-explanatory package to provide a nice splash screen and display an encouraging message.
(use-package dashboard
:ensure t
:config
(setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))
dashboard-banner-logo-title "GNU Emacs"
dashboard-center-content t
dashboard-items '((recents . 5)
(projects . 5)
)
dashboard-set-heading-icons t
dashboard-set-file-icons t
dashboard-footer-messages '("Do something useful!")
dashboard-footer-icon (all-the-icons-octicon "dashboard"
:height 1.1
:v-adjust -0.05
:face 'font-lock-keyword-face)
dashboard-set-init-info t
)
(dashboard-setup-startup-hook))
I use Vi/Vim keys in Emacs. It would probably be too difficult to use Emacs keys and Vi keys in different applications simultaneously. I also use the Vi keys in tmux, zsh and my window manager, so Emacs would be the exception.
(use-package evil
:init
(setq evil-want-integration t
evil-want-keybinding nil
evil-want-C-u-scroll t
evil-want-C-i-jump nil
evil-respect-visual-line-mode t
evil-insert-state-cursor nil)
:config
(evil-mode 1)
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
(define-key evil-insert-state-map
(kbd "C-h") 'evil-delete-backward-char-and-join)
(define-key evil-normal-state-map (kbd "<return>") nil)
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(evil-global-set-key 'motion "0" 'evil-beginning-of-visual-line)
(evil-global-set-key 'motion "$" 'evil-end-of-visual-line)
(evil-global-set-key 'motion "^" 'evil-first-non-blank-of-visual-line)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal))
(with-eval-after-load 'evil-maps
(define-key evil-motion-state-map (kbd "RET") nil))
(use-package evil-collection
:after evil
:config
(evil-collection-init))
The Which-key package will show you a list of keybindings prefixed by the current combination after a short delay. This restores some of the discoverability lost by disabling the UI.
(use-package general
:config
(general-evil-setup t)
(general-create-definer myconfig/leader-keys
:prefix "SPC"
:global-prefix "C-c"))
(myconfig/leader-keys 'normal 'override
"bb" 'counsel-switch-buffer
"ff" 'counsel-find-file
"ss" 'swiper
"d" 'dired
"y" 'clipboard-kill-ring-save
"e" 'eval-buffer
"x" 'counsel-M-x
"i" 'ibuffer
"c" 'evil-delete-buffer
"t" 'counsel-load-theme
"le" '(lambda () (interactive) (find-file "~/.config/emacs/README.org"))
"or" 'org-mode-restart
"op" 'org-latex-preview
"otl" 'org-toggle-link-display
"oti" 'org-toggle-inline-images
"otb" 'org-toggle-blocks
"obt" 'org-toggle-blocks
"oby" 'org-copy-src-block
"obY" 'org-clipboard-copy-src-block
"pp" 'projectile-switch-project
)
(use-package which-key
:init (which-key-mode)
:diminish which-key-mode
:config
(setq which-key-idle-delay 0.01))
Define some interactive functions for those bindings.
(defun org-copy-src-block ()
(interactive)
(org-edit-src-code)
(beginning-of-buffer)
(mark-end-of-buffer)
(kill-ring-save (point) (mark))
(org-edit-src-abort)
(message "Copied to register!"))
(defun org-clipboard-copy-src-block ()
(interactive)
(org-edit-src-code)
(beginning-of-buffer)
(mark-end-of-buffer)
(clipboard-kill-ring-save (point) (mark))
(org-edit-src-abort)
(message "Copied to clipboard!"))
(defvar org-blocks-hidden nil)
(defun org-toggle-blocks ()
(interactive)
(if org-blocks-hidden
(org-show-block-all)
(org-hide-block-all))
(setq-local org-blocks-hidden (not org-blocks-hidden)))
Programming
This is a very quick programming setup as I won’t be using Emacs for programming very often, preferring Neovim. Enable line highlighting and line numbers.
(setq display-line-numbers-type 'relative)
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
(add-hook 'prog-mode-hook #'hl-line-mode)
Optional tree-sitter support.
(use-package tree-sitter
:config
(global-tree-sitter-mode))
(use-package tree-sitter-langs)
Company is a completion front-end.
(use-package company
:config
(setq company-minimum-prefix-length 1
company-idle-delay 0
company-tooltip-limit 6
company-tempo-expand t
company-backends '((company-capf company-dabbrev-code company-files company-yasnippet)))
)
(defun my-company-org-mode-hook ()
(setq-local company-backends
'((company-capf company-yasnippet company-dabbrev company-ispell company-tempo :separate)
)))
(setq ispell-alternate-dictionary "/home/alex/.config/emacs/completion-words.txt")
(with-eval-after-load 'company
(define-key company-active-map (kbd "TAB") nil))
(add-hook 'org-mode-hook #'my-company-org-mode-hook)
(add-hook 'org-mode-hook #'company-mode)
(add-hook 'text-mode-hook #'company-mode)
(add-hook 'prog-mode-hook #'company-mode)
(use-package company-box
:hook (company-mode . company-box-mode))
Language server support via lsp-mode
.
(use-package lsp-mode
:init
(setq lsp-keymap-prefix "C-c l")
:commands lsp)
(use-package smartparens
:config
(require 'smartparens-config)
(add-hook 'prog-mode-hook #'smartparens-mode))
I haven’t relied on snippets too heavily in the past, but I am gradually getting used to the idea. As it is so easy to set up in Emacs, I will include some snippets.
(use-package yasnippet
:config
(setq yas-snippet-dirs '("~/.config/emacs/snippets"))
(add-hook 'prog-mode-hook #'yas-minor-mode)
(add-hook 'prog-mode-hook #'yas-minor-mode))
(define-key yas-minor-mode-map (kbd "<tab>") nil)
(define-key yas-minor-mode-map (kbd "TAB") nil)
(define-key yas-minor-mode-map (kbd "C-c y") #'yas-expand)
(yas-global-mode 1))
(use-package yasnippet-snippets)
Projectile is a package for managing projects.
(use-package projectile
:config
(projectile-mode)
(setq projectile-project-search-path '("~/vcon/")
projectile-auto-discover t
projectile-switch-project-action #'projectile-dired)
)
Org Mode
Org and the Org major mode are greats tool for authoring. Another strength of Org mode is its handling of source blocks, with which you can write code notebooks and do literate programming. This document acts as a literate configuration file for Emacs, for example.
Define a function to evaluate when Org mode is loaded, this is easier
than many (add-hook 'org-mode-hook ...)
expressions.
(defun org-mode-setup ()
(org-indent-mode t)
(visual-line-mode nil)
(setq org-hide-emphasis-markers t
org-pretty-entities t
org-return-follows-link t
org-list-allow-alphabetical t
org-hide-leading-stars nil
org-catch-invisible-edits 'smart
org-use-sub-superscripts '{}
org-export-with-sub-superscripts '{}
org-src-preserve-indentation nil
org-edit-src-content-indentation 2
org-format-latex-options (plist-put org-format-latex-options :scale 3.0)
org-src-fontify-natively t
org-image-actual-width (list 600)
org-ellipsis " ..."
org-link-frame-setup
'((vm . vm-visit-folder-other-frame)
(vm-imap . vm-visit-imap-folder-other-frame)
(gnus . org-gnus-no-new-news)
(file . find-file)
(wl . wl-other-frame))
))
Call the setup function when Org mode is loaded.
(require 'org-indent)
(require 'org-src)
(setq
org-startup-folded nil
org-startup-with-latex-preview nil
org-startup-with-inline-images nil)
(add-hook 'org-mode-hook 'org-mode-setup)
Structure templates make inserting source blocks much easier.
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("txt" . "src text"))
Org babel is used for literate programming, including handling this very file.
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)))
(setq org-confirm-babel-evaluate nil)
To use varaible-pitch-mode
, some faces need to be set to
mono-space, such as code blocks and tables.
(set-face-attribute 'org-block-begin-line nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-block-end-line nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-block nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit 'fixed-pitch)
(set-face-attribute 'org-indent nil :inherit '(org-hide fixed-pitch))
(set-face-attribute 'org-document-info-keyword nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
The mixed-pitch package does many of the same things.
(use-package mixed-pitch
:hook
(org-mode . mixed-pitch-mode))
Change the height of the face used to display Org mode headings and the document title.
(defun org-heading-face-setup ()
(dolist (face '((org-level-1 . 1.5)
(org-level-2 . 1.4)
(org-level-3 . 1.3)
(org-level-4 . 1.2)
(org-level-5 . 1.1)
(org-level-6 . 1.1)
(org-level-7 . 1.1)
(org-level-8 . 1.1)))
(set-face-attribute (car face) nil :family
(face-attribute 'default :family)
:weight 'bold :height (cdr face)))
)
(add-hook 'org-mode-hook 'org-heading-face-setup)
(defun org-title-face-setup ()
(set-face-attribute 'org-document-title nil :family (face-attribute 'default :family) :weight 'bold :height 1.6)
)
(add-hook 'org-mode-hook 'org-title-face-setup)
Replace bullet points (lines with leading dashes) with Unicode characters.
(font-lock-add-keywords 'org-mode
'(("^ *\\([-]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
Ensure LaTeX blocks are highlighted, but keep the default text background.
(setq org-highlight-latex-and-related '(latex native entities))
(add-to-list 'org-src-block-faces '("latex" (:inherit default :extend t)))
I am now experimenting with some additional org features, besides
those used for authoring. I am modifying the sequence(s) of
TODO
keywords and adding a prefix letter to each, for easy
navigation. Creating and changing the state of a TODO
item
records a timestamp and switching to the cancelled state additionally
requires a comment. This information is placed inside a drawer.
(setq org-todo-keywords
'((sequence "TODO(t!)" "ACTIVE(a!)" "|" "DONE(d!)" "CANCELED(c@)")
(sequence "QUESTION(q!)" "|" "SOLVED(s@)"))
org-log-into-drawer t)
Optionally use a package like org-modern to style the buffer. I am not using it currently.
(use-package org-modern
:hook (org-mode . org-modern-mode))
Most of the time I choose to hide a few org syntax elements. The org-bullets package replaces the asterisks before each heading with Unicode symbols. org-appear shows emphasis markers when the cursor hovers over emphasised text.
(use-package org-bullets
:after org
:hook (org-mode . org-bullets-mode)
:custom
(org-bullets-bullet-list '("●" "○" "●" "○" "●" "○" "●")))
(use-package org-appear
:hook (org-mode . org-appear-mode)
:config
(setq org-appear-autoemphasis t
org-appear-autolinks t)
(run-at-time nil nil #'org-appear--set-elements))
For writing text, visual-line-mode
is enabled. The
visual-fill-column package can set the point at which text
wraps and centre text in the buffer, which is very helpful.
(use-package visual-fill-column
:config
(setq-default visual-fill-column-center-text t)
(setq-default visual-fill-column-width 100))
(add-hook 'visual-line-mode-hook #'visual-fill-column-mode)
(advice-add 'text-scale-adjust :after #'visual-fill-column-adjust)
A couple of packages to help with editing LaTeX in Org mode. Some snippets have also been loaded.
(use-package cdlatex
:config
(setq cdlatex-simplify-sub-super-scripts nil)
(add-hook 'org-mode-hook #'turn-on-org-cdlatex))
(use-package org-fragtog
:config
(add-hook 'org-mode-hook 'org-fragtog-mode))
Spell checking is an essential feature for writing text. Ispell ignores words in my private dictionary and code inside source blocks. Flycheck highlights possible errors in the buffer.
(setq
ispell-program-name "aspell"
ispell-dictionary "en_GB-ise"
ispell-local-dictionary "en_GB-ise"
ispell-personal-dictionary "~/.config/emacs/british-ise.pws"
)
(defun my_config/org-ispell ()
"Configure `ispell-skip-region-alist' for `org-mode'."
(make-local-variable 'ispell-skip-region-alist)
(add-to-list 'ispell-skip-region-alist '(org-property-drawer-re))
(add-to-list 'ispell-skip-region-alist '("~" "~"))
(add-to-list 'ispell-skip-region-alist '("=" "="))
(add-to-list 'ispell-skip-region-alist '("^#\\+BEGIN_SRC" . "^#\\+END_SRC"))
(add-to-list 'ispell-skip-region-alist '("^#\\+begin_src" . "^#\\+end_src")))
(add-hook 'org-mode-hook #'my_config/org-ispell)
(dolist (hook '(org-mode-hook))
(add-hook hook (lambda () (flyspell-mode 1))))
(add-hook 'flyspell-mode-hook 'flyspell-buffer)
Org Export & Publish
Emacs org-mode has its own export and publishing system which is highly configurable and useful for exporting many documents at once. The relevant sections of the Org Manual:
Very simply, the export function can be used to convert a single org document to some other format and the publish utility can convert many files to some format by using an exporter.
Setup
Require the exporters for HTML and LaTeX.
(require 'ox-html)
(require 'ox-latex)
(require 'ox-publish)
Set some default variables for both exporters.
(setq
user-full-name "Alexander Neville"
org-export-with-archived-trees nil
org-export-exclude-tags nil
org-export-default-language nil
org-export-preserve-breaks nil
org-export-with-section-numbers nil
org-export-select-tags nil
org-export-with-author nil
org-export-with-broken-links t
org-export-with-clocks nil
org-export-with-creator nil
org-export-with-date nil
org-export-with-drawers nil
org-export-with-email nil
org-export-with-emphasize t
org-export-with-fixed-width nil
org-export-with-footnotes nil
org-export-with-latex t
org-export-with-planning nil
org-export-with-priority nil
org-export-with-properties nil
org-export-with-special-strings nil
org-export-with-sub-superscripts '{}
org-export-with-tables t
org-export-with-tags nil
org-export-with-tasks nil
org-export-with-timestamps nil
org-export-with-title nil
org-export-with-toc nil
org-export-with-todo-keywords nil
)
In Org mode, it is possible to nest sections deeply, but in HTML and
LaTeX the number of available heading levels is limited. In HTML, the
tags h1, ..., h6
are available, with h1
being
used for the document title, leaving a maximum of 5 levels. In the
default LaTeX article class, subsubsection
is the
lowest heading level above paragraph, which is 3 useful levels of
nesting. The class should be changed to book or report if greater
heading depth is required.
5. part <- report/book
4. chapter
3. section <- article
2. subsection
1. subsubsection
Set the maximum headline export level to 3, for the reasons given above. This can be changed on a file-by-file basis.
(setq org-export-headline-levels 3)
LaTeX Exporter
LaTeX is a uniquely powerful typesetting system, though in many cases I would rather focus on the content of my writing than worry about LaTeX syntax. The more intuitive Org syntax with the ability to embed latex fragments where required is a much better system.
Org must be configured to export documents to latex properly. Firstly, the values of a number of variables must be considered when exporting to LaTeX.
org-latex-default-packages-alist
: minimal preamble, best to leave unchanged.org-latex-packages-alist
: empty by default, add preamble common to all Org documents.org-latex-classes
: a list of ways to convert an Org-structured document to LaTeX.
The list org-latex-classes
is very important. New
classes can be added with a class-name, header-string
and sectioning-structure (see the variable’s help for more
detailed information). In the header string you can write a preamble,
optionally including the contents of org-*-packages-alist
.
So as to avoid repeating LaTeX fragments, a custom preamble can be
broken into sections and bind to variables.
(setq
chapter-redef
"
\\patchcmd{\\chapter}{\\thispagestyle{plain}}{\\thispagestyle{fancy}}{}{}
\\makeatletter
\\def\\@makechapterhead#1{
\\vspace*{50\\p@}
{\\parindent \\z@ \\raggedright \\normalfont
\\ifnum \\c@secnumdepth >\\m@ne
\\huge\\bfseries \\@chapapp\\space \\thechapter
\\Huge\\bfseries \\thechapter.\\space%
\\par\\nobreak
\\vskip 20\\p@
\\fi
\\interlinepenalty\\@M
\\Huge \\bfseries #1\\par\\nobreak
\\vskip 40\\p@
}}
\\makeatother\n"
report-fancyheader-def
"
\\usepackage{fancyhdr}
\\pagestyle{fancy}
\\renewcommand{\\sectionmark}[1]{\\markright{\\thesection~- ~#1}}
\\renewcommand{\\chaptermark}[1]{\\markboth{\\chaptername~\\thechapter. \\textit{#1}}{}}
\\fancyhf{}
\\rfoot{page \\textbf{\\thepage}}
\\lfoot{\\nouppercase{\\leftmark}}
\\renewcommand{\\headrulewidth}{0pt}
\\renewcommand{\\footrulewidth}{0.4pt}\n"
article-fancyheader-def
"
\\usepackage{fancyhdr}
\\pagestyle{fancy}
\\fancyhf{}
\\rfoot{page \\textbf{\\thepage}}
\\lfoot{\\nouppercase{\\leftmark}}
\\renewcommand{\\headrulewidth}{0pt}
\\renewcommand{\\footrulewidth}{0.4pt}\n"
common-head
"
\\usepackage{svg}
\\svgsetup{inkscapelatex=false}
\\usepackage{blindtext}
\\usepackage{tcolorbox}
\\usepackage{etoolbox}
\\hypersetup{hidelinks}
\\usemintedstyle{bw}
\\setminted{autogobble=true, breaklines=true, breakbytokenanywhere=true, fontsize=\\small, xleftmargin=1cm, xrightmargin=1cm}
\\usepackage[indent=0.5cm]{parskip}
\\usepackage[a4paper, includefoot, margin=2.54cm]{geometry}\n"
default-head-setup
"
\\usepackage[utf8]{inputenc}
\\usepackage{libertine}
\\usepackage{libertinust1math}
\\usepackage[T1]{fontenc}
\\usepackage{graphicx}
\\usepackage{longtable}
\\usepackage{wrapfig}
\\usepackage{rotating}
\\usepackage[normalem]{ulem}
\\usepackage{amsmath}
\\usepackage{amssymb}
\\usepackage{capt-of}
\\usepackage{hyperref}
\\usepackage{minted}\n"
)
Create each class as a list containing cons cells which represent the
headline levels of the latex document. Build the header-string
by concatenating latex snippets together and add to the list. Finally,
add each user-defined class to org-latex-classes
.
(setq long-report '(("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
short-report '(("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
custom-article '(("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))
(setq report-common-header-string (concat "\\documentclass{report}\n[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n" default-head-setup chapter-redef common-head report-fancyheader-def "[EXTRA]"))
(add-to-list 'short-report report-common-header-string)
(add-to-list 'long-report report-common-header-string)
(add-to-list 'custom-article (concat "\\documentclass{article}\n[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n" default-head-setup common-head article-fancyheader-def "[EXTRA]"))
(add-to-list 'short-report "short-report")
(add-to-list 'long-report "long-report")
(add-to-list 'custom-article "custom-article")
(with-eval-after-load 'ox-latex
(add-to-list 'org-latex-classes long-report)
(add-to-list 'org-latex-classes short-report)
(add-to-list 'org-latex-classes custom-article))
The following export options can be set in each Org document:
latex_class
: looked up inorg-latex-classes
to find the header to use.latex_class_options
: document class options, could be rolled into the class header.latex_header
&latex_header_extra
: lines to be added to the header string for this file.
Use minted for exporting code blocks and set the preferred compiler.
The compiler can be changed with the Org option
latex_compiler
.
(setq org-latex-listings 'minted
org-latex-default-class "custom-article"
org-export-in-background t
org-latex-compiler "pdflatex"
org-latex-pdf-process '("latexmk -f -pdf -%latex -shell-escape -interaction=nonstopmode -output-directory=%o %f"))
HTML Exporter
Set the value of some variables.
(setq org-html-doctype "html5"
org-html-self-link-headlines t
org-html-metadata-timestamp-format "%H:%M:%S %d/%m/%Y"
org-html-creator-string "<a href=\"https://www.gnu.org/software/emacs/\">Emacs</a> 28.2 + <a href=\"https://orgmode.org\">Org mode</a> 9.5.5"
org-html-head-include-default-style nil
org-html-head-include-scripts nil
)
This is a default MathJax configuration block. Its results are not used as I overwrite the MathJax template in the block below.
(setq org-html-mathjax-options
'((path "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML")
(scale "100")
(align "center")
(font "STIX-Web")
(linebreaks "false")
(autonumber "AMS")
(indent "0em")
(multlinewidth "85%")
(tagindent ".8em")
(tagside "right")))
Overwrite the template for inserting MathJax configuration to point to my own copy of the scripts.
(setq org-html-mathjax-template
"
<script>
MathJax = {
tex: { inlineMath: [['$', '$'], ['\\(', '\\)']] },
svg: { fontCache: 'global' }
};
</script>
<script type=\"text/javascript\" id=\"MathJax-script\" async
src=\"https://cdn.afneville.com/mathjax/tex-svg.js\">
</script>")
Additional lines for the head of each exported document. These lines are given as an example.
(setq org-html-head-extra
"<link href=\"/res/style.css\" rel=\"stylesheet\" />
<script src=\"/res/script.js\" defer></script>")
The preamble and postamble are inserted at the beginning and end of the generated document respectively.
(setq org-html-preamble
"<header>
<!-- ... -->
</header>")
(setq org-html-postamble
"<footer>
<!-- ... -->
</footer>")
Publishing
The publishing feature of Org uses the configured exporters to convert batches of files, according to some conditions.
(setq main_html
'("main_html"
:recursive nil
:base-directory "./src"
:publishing-directory "./out"
:base-extension "org"
:publishing-function org-html-publish-to-html
:with-title nil
:with-toc nil
:headline-levels 5
)
)
(setq main_res
'("main_res"
:recursive t
:base-directory "./src/res"
:publishing-directory "./out/res"
:base-extension "pdf\\|jpg\\|gif\\|png\\|svg\\|css\\|js"
:publishing-function org-publish-attachment)
With initialisation complete, each of the publishing functions is executed.
(setq org-publish-project-alist (append (list main_html) (list main_res)))
(org-publish-all t)
See Also
- GnuPG Usage
- Object Orientation in C
- Functional Programming
- Haskell Programming
- Emacs Initialisation
- Working with Java Packages
- Asynchronous & Concurrent Programming
Or return to the index.