Terror Emacs is a simple and functional configuration of GNU Emacs aimed at academic use, mainly for the creation of technical articles, presentations, notes, literary programming and reproducibility. It allows working with multiple formats (TeX, org, markdown
) and exporting to many others (odt, pdf, html, epub
and probably any format useful to humans using the power of pandoc
).
Terror Emacs is not intended as a feature-rich distribution, but as a simple working environment for plain text. However, it can serve as a base for more complex configurations if you have a bit of Emacs Lisp skills. In case you need more functionality, or a straightforward IDE, it is highly recommended to check out the following distributions:
Many ideas have been taken from the System Crafters EFS:
Git
GNU Emacs
(27.1+)JetBrains Mono
PDF Tools
The following tools are optional and serve to open files from dired
. They can be replaced by any other of preference by changing them in the corresponding section at the end of this config file.
sxiv
(image viewer)mpv
(media player)If any previous Emacs configuration exists, remove or move it:
$ mv .emacs.d/ old-emacs-d
Clone and rename this repo at =~/=:
$ git clone https://notabug.org/dlmayhem/terror-emacs.git .emacs.d
Run Emacs et voilà !
Once all the required packages have been installed, all that remains is to run the following command within Emacs:
M-x all-the-icons-install-fonts
We configure the lexical-binding
.
;;; init.el -*- lexical-binding: t; -*-
And we will use the GPLv3 license or higher.
;;-----------------------------------------------------------------------;; ;; TERROR EMACS ;; ;; A simple Emacs setup for the terror of academic life ;; ;; ;; ;; This program is free software: you can redistribute it and/or modify ;; ;; it under the terms of the GNU General Public License as published by ;; ;; the Free Software Foundation, either version 3 of the License, or ;; ;; any later version. ;; ;; ;; ;; This program is distributed in the hope that it will be useful, ;; ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; ;; GNU General Public License for more details. ;; ;; ;; ;; You should have received a copy of the GNU General Public License ;; ;; along with this program. If not, see . ;; ;;-----------------------------------------------------------------------;;
The behaviour of the garbage collector is momentarily changed to improve start-up time.
(setq gc-cons-threshold (* 50 1000 1000))
Optionally, we add our personal data (they don't have to be real).
(setq user-full-name "DELM" user-mail-address "dlmayhem@riseup.net")
In this section we will configure the general appearance and behaviour of our editor. Here, for example, you can activate or deactivate toolbars, line numbers, font type and size, etc.
(menu-bar-mode -1) (scroll-bar-mode -1) (tool-bar-mode -1) (tooltip-mode -1) (set-fringe-mode 4) (global-visual-line-mode 1) (global-auto-revert-mode 1) (if (window-system) (global-hl-line-mode 1)) (set-face-font 'default "JetBrainsMono 12") (set-face-font 'variable-pitch "JetBrainsMono 12") (fset 'yes-or-no-p 'y-or-n-p) (delete-selection-mode 1) (column-number-mode) (set-frame-parameter (selected-frame) 'internal-border-width 20) (dolist (mode '(c-mode-hook emacs-lisp-mode-hook sh-mode-hook shell-mode-hook python-mode-hook LaTeX-mode-hook)) (add-hook mode (lambda () (display-line-numbers-mode t)))) (setq-default cursor-in-non-selected-windows nil frame-title-format '("%f [%m]")) (setq default-fill-column 100 make-backup-files nil inhibit-startup-message t use-dialog-box nil vc-follow-symlinks t tramp-default-method "ssh" custom-file "~/.emacs.d/custom.el" global-auto-revert-non-file-buffers t large-file-warning-threshold nil) (load custom-file)
These are the sources from which the packages required for Terror Emacs will be automatically downloaded, as well as those that you may want to add in the future. Also, we add use-package, which helps us to keep a clean, efficient, tidy and easy to read configuration file.
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/") ("nongnu" . "https://elpa.nongnu.org/nongnu/") ("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)
Next, we set up a minimalist ecosystem consisting of a vertical completion UI (vertico), marginal notes with useful information (marginalia), a practical context menu (embark), fuzzy searches (orderless) and an autocompletion system (corfu).
(use-package vertico :ensure t :init (vertico-mode))
(use-package vertico-directory :after vertico :ensure nil :bind (:map vertico-map ("RET" . vertico-directory-enter) ("DEL" . vertico-directory-delete-char) ("M-DEL" . vertico-directory-delete-word)) :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
(use-package savehist :init (savehist-mode))
(use-package marginalia :after vertico :ensure t :init (marginalia-mode) :custom (marginalia-align 'right))
(use-package embark :ensure t :bind (("C-." . embark-act) ("C-;" . embark-dwim) ("C-h B" . embark-bindings)) :init (setq prefix-help-command #'embark-prefix-help-command) :config (add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none)))))
(use-package orderless :ensure t :after vertico :custom (completion-styles '(orderless)))
(use-package corfu :custom (corfu-auto t) (corfu-separator ?\s) :init (global-corfu-mode))
(use-package corfu-terminal :config (unless (display-graphic-p) (corfu-terminal-mode +1)))
We will use some Doom Emacs tools on the visual side: doom-themes is a very polished collection of colour schemes to suit all tastes; solaire-mode assigns slightly different background colours to different buffers depending on their content, which helps to maintain focus; doom-modeline is a clean and elegant mode line, showing only the most relevant information.
(use-package doom-themes :if window-system :init (load-theme 'doom-wilmersdorf t))
(use-package solaire-mode :config (add-to-list 'solaire-mode-themes-to-face-swap 'doom-wilmersdorf) (setq solaire-mode-auto-swap-bg t) (solaire-global-mode +1))
(use-package doom-modeline :init (doom-modeline-mode 1) :custom (doom-modeline-height 15))
Some elegant icons.
(use-package all-the-icons :if (display-graphic-p))
There are times when we can't remember the gigantic number of key combinations in our editor. That's when we rely to which-key, which shows us all the shortcuts available in the context in which we invoke it.
(use-package which-key :defer 0 :config (which-key-mode) (setq which-key-idle-delay 0.3))
Everything we need to work with git
is just a couple of keystrokes away: magit needs no further introduction.
(use-package magit :bind ("C-x g" . magit-status))
The following packages help us when using parentheses (if you work with any Lisp you will understand). smartparens automatically completes the pair of parentheses, quotation marks and other symbols that usually go together; rainbow-delimiters shows each pair of parentheses with a distinctive colour, and paren highlights the corresponding pair when we place the cursor over a beginning or ending.
(use-package smartparens :hook (prog-mode . smartparens-mode))
(use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode))
(use-package paren :config (show-paren-mode 1))
The rainbow-mode shows the hexadecimal codes with their respective associated colour, very useful for working with web content and configuration files.
(use-package rainbow-mode :defer t :hook (org-mode emacs-lisp-mode web-mode c-mode))
The following tools are useful when working on creating web content. simple-httpd is a web server in Emacs, and htmlize allows code snippets to be exported to html while retaining syntax highlighting and other features.
(use-package simple-httpd :ensure t)
(use-package htmlize :ensure t)
The writeroom-mode mode is very useful when writing long text or code, as it removes all distractions by putting Emacs in full screen mode and centring the text.
(use-package writeroom-mode :bind ("C-c d" . writeroom-mode) :config (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust))
To create templates we will use YASnippet. You can add your own in the directory you specify. A few are included in Terror Emacs, but you can install Andrea Crotti's amazing collection from MELPA.
(use-package yasnippet :config (setq yas-snippet-dirs '("~/.emacs.d/templates/yasnippet")) (yas-global-mode 1))
Finally, lorem-ipsum allows us to insert random text in Latin, useful for showing examples in presentations or similar stuff.
(use-package lorem-ipsum)
This is a basic configuration of PDF Tools, a powerful PDF reader.
(use-package pdf-tools :defer t :custom (pdf-view-midnight-colors '("#c6c6c6" . "#1f2024")))
(pdf-loader-install)
(use-package pdf-view-restore :after pdf-tools :config (add-hook 'pdf-view-mode-hook 'pdf-view-restore-mode))
To read e-books in epub
format we will use nov.el.
(use-package nov :defer t :mode ("\\.epub\\'" . nov-mode))
The citar package uses the ecosystem mentioned at the beginning of this section to provide a simple way to insert bibliographic references that works perfectly well in LaTeX, org, markdown, etc.
(use-package citar :bind (("C-c b" . citar-insert-citation) :map minibuffer-local-map ("M-b" . citar-insert-preset)) :custom (citar-bibliography '("~/Documentos/refs.bib")))
(use-package citar-embark :after citar embark :no-require :config (citar-embark-mode))
With Ebib we can easily manage our =.bib= files.
(use-package ebib :defer t :config (require 'ebib-biblio) (define-key ebib-index-mode-map (kbd "B") #'ebib-biblio-import-doi) (define-key biblio-selection-mode-map (kbd "e") #'ebib-biblio-selection-import))
As a news reader we use elfeed. We can add sources directly in the elfeed.org
file placed in the main directory. Terror Emacs includes some sample sources, but you can of course remove them.
(use-package elfeed :no-require t :bind ("C-x w" . elfeed))
(use-package elfeed-org :ensure t :after elfeed :config (elfeed-org) (setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed.org")))
In addition, we will use the very useful arXiv-mode, which will allow us to search and download papers from arXiv very easily.
(use-package arxiv-mode :ensure t :bind ("C-x x" . arxiv-search) :config (setq arxiv-default-download-folder "~/Documentos/"))
The ultimate Emacs feature. This is where the magic happens. Let's start with the basic configuration.
(use-package org :commands (org-capture org-agenda) :bind (("C-c l" . org-store-link) ("C-c a" . org-agenda) ("C-c c" . org-capture)) :hook (org-mode . smartparens-mode) :config (setq org-agenda-files '("~/.agenda.org") org-ellipsis " ▾" org-footnote-auto-adjust t org-fontify-quote-and-verse-blocks t org-log-done 'time org-capture-bookmark nil org-html-validation-link nil org-startup-indented t org-startup-folded nil org-format-latex-options (plist-put org-format-latex-options :scale 3.0))
Some templates for org-agenda
.
(setq org-capture-templates '(("b" "Birthday" entry (file+headline "~/.agenda.org" "Birthdays") "** BIRTHDAY %^{Name}\n%^t") ("d" "Deadline" entry (file+headline "~/.agenda.org" "Deadlines") "** TODO %^{Name}\nDEADLINE %^t\n") ("e" "Event") ("ec" "Concert" entry (file+headline "~/.agenda.org" "Events") "** CONCERT %^{Band}\n- SCHEDULED %^t\n- Location :: %^{Place/link}") ("ef" "Congress" entry (file+headline "~/.agenda.org" "Events") "** CONGRESS %^{Name}\n- SCHEDULED %^t\n- Location :: %^{Place/link}") ("em" "Meeting" entry (file+headline "~/.agenda.org" "Events") "** MEETING %^{Meeting}\n- SCHEDULED %^t\n- Location :: %^{Place/link}") ("ep" "Party" entry (file+headline "~/.agenda.org" "Events") "** PARTY %^{Name}\n- SCHEDULED %^t\n- Location :: %^{Place/link}") ("et" "Talk" entry (file+headline "~/.agenda.org" "Events") "** TALK %^{Talk's name}\n- Author :: %^{Name}\n- SCHEDULED %^t\n- Location :: %^{Place/link}") ("l" "Loaned" entry (file+headline "~/.agenda.org" "Loans") "** LOANED %^{Object|BOOK|MUSIC|OTHER}\n- Title :: %^{Title}\n- To whom :: %^{Name}\n- Date :: %t") ("t" "To-Do" entry (file+headline "~/.agenda.org" "To-Do") "** TODO %^{To do}\n%?")))
(setq org-todo-keywords '((sequence "TODO(t)" "RETURNED(r)" "CANCELLED(c)" "DONE(d)")))
Now we specify the languages we will use with org-babel
. The list of available languages can be found here.
(org-babel-do-load-languages 'org-babel-load-languages '((C . t) (java . t) (python . t) (shell . t) (latex . t) (latex-as-png . t))) (add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images) (setq org-confirm-babel-evaluate nil))
We use org-contrib
for some useful export options, like the tag :ignore:
.
(use-package org-contrib :after org :config (require 'ox-extra) (ox-extras-activate '(latex-header-blocks ignore-headlines)))
A default configuration for Org-roam, a wonderful knowledge management system based on the Zettelkasten method.
(defun org-roam-node-insert-immediate (arg &rest args) (interactive "P") (let ((args (cons arg args)) (org-roam-capture-templates (list (append (car org-roam-capture-templates) '(:immediate-finish t))))) (apply #'org-roam-node-insert args)))
(use-package org-roam :ensure t :init (setq org-roam-v2-ack t) :custom (org-roam-directory (file-truename "~/Proyectos/org/roam")) (org-roam-capture-templates '(("a" "Author" plain (file "~/.emacs.d/templates/roam/author.org") :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("b" "Bibliography" plain (file "~/.emacs.d/templates/roam/biblio.org") :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("c" "Concept" plain (file "~/.emacs.d/templates/roam/concept.org") :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("f" "Field" plain (file "~/.emacs.d/templates/roam/field.org") :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("q" "Quote" plain (file "~/.emacs.d/templates/roam/quote.org") :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t))) :bind (("C-c n l" . org-roam-buffer-toggle) ("C-c n f" . org-roam-node-find) ("C-c n i" . org-roam-node-insert) ("C-c n I" . org-roam-node-insert-immediate) ("C-c n g" . org-roam-ui-mode) ("C-c n c" . org-roam-capture) ("C-c n j" . org-roam-dailies-capture-today)) :config (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))) (org-roam-setup) (require 'org-roam-protocol))
The ox-twbs package allows us to export an org
file to a clean and elegant html=; [[https://github.com/alhassy/ob-latex-as-png][ob-latex-as-png]] speaks for itself: it exports the =TeX
code of an org
file to a png
image.
(use-package ox-twbs :after org)
(use-package ob-latex-as-png :after org)
The following packages are aesthetic, and we will use them to make our presentations look cleaner and neater.
(use-package org-bullets :no-require t :custom (org-bullets-bullet-list '("◉" "●" "○" "●" "○" "●")))
(use-package hide-lines)
(use-package hide-mode-line :defer t)
And for presentations we will use Org Tree Slide.
(defun terror/slide-setup () (global-hl-line-mode -1) (setq org-hide-emphasis-markers t) (org-bullets-mode 1) (setq text-scale-mode-amount 3) (text-scale-mode 1) (set-frame-parameter (selected-frame) 'internal-border-width 75) (org-display-inline-images) (toggle-frame-fullscreen) (hide-mode-line-mode 1) (hide-lines-matching "#\\+begin") (hide-lines-matching "#\\+end"))
(defun terror/slide-end () (global-hl-line-mode 1) (setq org-hide-emphasis-markers nil) (org-bullets-mode -1) (text-scale-mode -1) (set-frame-parameter (selected-frame) 'internal-border-width 20) (toggle-frame-fullscreen) (hide-mode-line-mode -1) (hide-lines-show-all))
(use-package org-tree-slide :after org :bind ("C-c p" . org-tree-slide-mode) :hook ((org-tree-slide-play . terror/slide-setup) (org-tree-slide-stop . terror/slide-end)) :config (setq org-tree-slide-slide-in-effect nil org-image-actual-width nil org-tree-slide-header t org-tree-slide-breadcrumbs " > " org-tree-slide-activate-message "Let's begin..." org-tree-slide-deactivate-message "The end :)"))
This LaTeX setup is quite simple thanks to AUCTeX. However, we need an installation of some LaTeX version on our machine. This can be done using your favourite package manager. In the case of Debian GNU/Linux, for example: # apt install texlive-full
(use-package latex :ensure auctex :defer t :init (server-force-delete) :custom (TeX-source-correlate-mode t) (TeX-source-correlate-start-server t) :config (setq TeX-view-program-selection '((output-pdf "PDF Tools"))) (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer))
I don't have much to say. I don't use it, but a basic configuration is provided anyway.
(use-package markdown-mode :ensure t :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)))
GNU LilyPond is an excellent plain-text system for music notation, allowing us to create sheet music or tablature, from simple to very complex.
(use-package lilypond-mode :defer t :load-path "var/lisp/lilypond-mode" :config (setq auto-mode-alist (cons '("\\.ly$" . LilyPond-mode) auto-mode-alist)) (add-hook 'LilyPond-mode-hook (lambda () (turn-on-font-lock))) (setq LilyPond-command-alist '(("LilyPond" "lilypond %s" "%s" "%l" "View") ("2PS" "lilypond -f ps %s" "%s" "%p" "ViewPS") ("Book" "lilypond-book %x" "%x" "%l" "LaTeX") ("LaTeX" "latex '\\nonstopmode\\input %l'" "%l" "%d" "ViewDVI") ("View" "open %f") ("ViewPDF" "open %f") ("ViewPS" "gv --watch %p") ("Midi" "") ("MidiAll" ""))))
Finally, we configure the powerful directory editor, dired
. With it, we can browse and modify directories, visit and manipulate files, etc. With dired-open we can also open files with an external application by specifying the extension and the program to use.
(use-package dired :ensure nil :defer 1 :config (setq dired-recursive-copies 'always dired-listing-switches "--group-directories-first -alh"))
(use-package dired-hide-dotfiles :after dired :hook (dired-mode . dired-hide-dotfiles-mode) :config (define-key dired-mode-map "." #'dired-hide-dotfiles-mode))
(use-package dired-open :after dired :config (setq dired-open-extensions '(("mp3" . "mpv") ("mp4" . "mpv") ("mkv" . "mpv") ("png" . "sxiv") ("gif" . "sxiv") ("jpg" . "sxiv") ("jpeg" . "sxiv"))))
The final lines show us at Emacs startup how long it takes to start (for Vim users who live in a hurry it seems to be important)...
(add-hook 'emacs-startup-hook (lambda () (message "Emacs ready in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time))) gcs-done)))
...and returns garbage collection to normal.
(setq gc-cons-threshold (* 2 1000 1000))
We have reached the end of the Terror Emacs configuration.
;;; Happy hacking! ;;;