emacs-config/config.org

22 KiB
Raw Blame History

Doom Emacs Configuration

Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do. — Donald Knuth

Make this file run (slightly) faster with lexical binding.

;;; config.el -*- lexical-binding: t; -*-

Rudimentary configuration

Personal Information

It's useful to have some basic personal information

(setq user-full-name "tecosaur"
      user-mail-address "tecosaur@gmail.com")

Apparently this is used by GPG, and all sorts of other things.

Better defaults

Simple settings

Browsing the web and seeing angrybacon/dotemacs and comparing with the values shown by SPC h v and selecting what I thought looks good, I've ended up adding the following:

(setq-default
 delete-by-moving-to-trash t                      ; Delete files to trash
 tab-width 4                                      ; Set width for tabs
 uniquify-buffer-name-style 'forward              ; Uniquify buffer names
 window-combination-resize t                      ; take new window space from all other windows (not just current)
 x-stretch-cursor t)                              ; Stretch cursor to the glyph width

(setq undo-limit 80000000)                         ; Raise undo-limit to 80Mb

(delete-selection-mode 1)                         ; Replace selection when inserting text
(display-time-mode 1)                             ; Enable time in the mode-line
(global-subword-mode 1)                           ; Iterate through CamelCase words

Fullscreen

I also like the idea of fullscreen-ing when opened by emacs or the .desktop file.

(if (eq initial-window-system 'x)                 ; if started by emacs command or desktop file
    (toggle-frame-maximized)
  (toggle-frame-fullscreen))

Auto-customisations

By default changes made via a customisation interface are added to init.el. I prefer the idea of using a separate file for this. We just need to change a setting, and load it if it exists.

(setq-default custom-file (expand-file-name ".custom.el" default-directory))
(when (file-exists-p custom-file)
  (load custom-file))

Doom configuration

Visual Settings

Font Face

'Fira Code' is nice, and 'Overpass' makes for a nice sans companion. We just need to fiddle with the font sizes a tad so that they visually match.

(setq doom-font (font-spec :family "Fira Code" :size 20)
      doom-big-font (font-spec :family "Fira Code" :size 36)
      doom-variable-pitch-font (font-spec :family "Overpass" :size 22))
Theme

doom-one is nice and all, but I find the vibrant variant nicer.

(setq doom-theme 'doom-vibrant)

However, by default red text is used in the modeline, so let's make that orange so I don't feel like something's gone wrong when editing files.

(custom-set-faces!
  '(doom-modeline-buffer-modified :foreground "orange"))
Miscellaneous

Relative line numbers are fantastic for knowing how far away line numbers are, then ESC 12 <UP> gets you exactly where you think.

(setq display-line-numbers-type 'relative)

Some helper macros

There are a few handy macros added by doom, namely

  • load! for loading external .el files relative to this one
  • use-package for configuring packages
  • add-load-path! for adding directories to the load-path where emacs looks when you load packages with require or use-package
  • map for binding new keys

To find more,

Other things

Editor interaction

Mouse buttons
(defun add-mouse-back-button-to-Info-mode ()
  "Add some browser styled nav keys for `Info-mode'."
  (local-set-key (kbd "<mouse-8>") 'Info-history-back)
  (local-set-key (kbd "<mouse-9>") 'Info-history-forward))

(add-hook 'Info-mode-hook 'add-mouse-back-button-to-Info-mode)

Package loading

This file shouldn't be byte compiled.

;; -*- no-byte-compile: t; -*-

Loading instructions

This is where you install packages, by declaring them with the package! macro, then running doom refresh on the command line. You'll need to restart Emacs for your changes to take effect! Or at least, run M-x doom/reload.

WARNING: Don't disable core packages listed in ~/.emacs.d/core/packages.el. Doom requires these, and disabling them may have terrible side effects.

Packages in MELPA/ELPA/emacsmirror

To install some-package from MELPA, ELPA or emacsmirror:

(package! some-package)

Packages from git repositories

To install a package directly from a particular repo, you'll need to specify a :recipe. You'll find documentation on what :recipe accepts here:

(package! another-package
  :recipe (:host github :repo "username/repo"))

If the package you are trying to install does not contain a PACKAGENAME.el file, or is located in a subdirectory of the repo, you'll need to specify :files in the :recipe:

(package! this-package
  :recipe (:host github :repo "username/repo"
           :files ("some-file.el" "src/lisp/*.el")))

Disabling built-in backages

If you'd like to disable a package included with Doom, for whatever reason, you can do so here with the :disable property:

(package! builtin-package :disable t)

You can override the recipe of a built in package without having to specify all the properties for :recipe. These will inherit the rest of its recipe from Doom or MELPA/ELPA/Emacsmirror:

(package! builtin-package :recipe (:nonrecursive t))
(package! builtin-package-2 :recipe (:repo "myfork/package"))

Specify a :branch to install a package from a particular branch or tag. This is required for some packages whose default branch isn't 'master' (which our package manager can't deal with; see raxod502/straight.el#279)

(package! builtin-package :recipe (:branch "develop"))

Packages

Auto-complete

(package! company-tabnine ; tab9 autocomplete
  :recipe (:host github :repo "TommyX12/company-tabnine"
           :files ("company-tabnine.el" "fetch-binaries.sh")))

Prettification

prettify-mode is nice and all, but adding substitutions is a little verbose. This helps with that.

(package! prettify-utils ; simplify messing with prettify-mode
  :recipe (:host github :repo "Ilazki/prettify-utils.el"))

Org Mode

Org tables aren't the prettiest thing to look at. This package is supposed to redraw them in the buffer with box-drawing characters. Sounds like an improvement to me! Just need to get it working…

(package! org-pretty-table-mode
  :recipe (:host github :repo "Fuco1/org-pretty-table"))

Because of the lovely variety in markdown implementations there isn't actually such a thing a standard table spec … or standard anything really. Because org-md is a goody-two-shoes, it just uses HTML for all these non-standardised elements (a lot of them). So ox-gfm is handy for exporting markdown with all the features that GitHub has. Initialised in /tec/emacs-config/src/commit/201774cac98e722356561649c8e01ebce5b560b8/Exporting%20to%20GFM.

(package! ox-gfm)

Pandoc is also a very handy export tool. org-pandoc also exists, but this seems to be better maintained.

(package! ox-pandoc)

Package configuration

Centaur Tabs

We want to make the tabs a nice, comfy size (36), with icons. The modifier marker is nice, but the particular default Unicode one causes a lag spike, so let's just switch to an o, which still looks decent but doesn't cause any issues. A 'active-bar' is nice, so let's have one of those. If we have it under needs us to turn on x-underline-at-decent though. For some reason this didn't seem to work inside the (after! ... ) block ¯\_(ツ)_/¯. Then let's change the font to a sans serif, but the default one doesn't fit too well somehow, so let's switch to 'P22 Underground Book'; it looks much nicer.

(after! centaur-tabs
  (setq centaur-tabs-height 36
        centaur-tabs-set-icons t
        centaur-tabs-modified-marker "o"
        centaur-tabs-set-bar 'above)
        centaur-tabs-gray-out-icons 'buffer
  (centaur-tabs-change-fonts "P22 Underground Book" 160))
;; (setq x-underline-at-descent-line t)

Company

It's nice to have completions almost all the time, in my opinion. Key strokes are just waiting to be saved!

(after! company
  (setq company-idle-delay 0.2
        company-minimum-prefix-length 2)
  (setq company-show-numbers t))

Now, the improvements from precident are mostly from remembering history, so let's improve that memory.

(setq-default history-length 1000)
(setq-default prescient-history-length 1000)

Plain Text

ispell is nice, let's have it in text, markdown, and GFM.

(set-company-backend! '(text-mode
                        markdown-mode
                        gfm-mode)
  '(:seperate company-ispell
              company-files
              company-yasnippet))

The SCOWL word list I got for VSCode is better than the default (I think), so let's use that.

(setq company-ispell-dictionary (file-truename "~/.config/Code/User/Custom cSpell Dictionaries/SCOWL-workdlist-au-uk-60.txt"))

Oh, and by the way, if company-ispell-dictionary is nil, then ispell-complete-word-dict is used instead.

ESS

company-dabbrev-code is nice. Let's have it.

(set-company-backend! 'ess-r-mode '(company-R-args company-R-objects company-dabbrev-code :separate))

Emacs Anywhere configuration

It's nice to recognise GitHub (so we can use GFM)

(defun github-conversation-p (window-title)
(or (string-match-p "Pull Request" window-title)
    (string-match-p "Issue" window-title)
    ))

When the window opens, we generally want text so let's use a nice sans serif font, a position the window below and to the left. Oh, and don't forget about checking for GFM, otherwise let's just use markdown.

(defun ea-popup-handler (app-name window-title x y w h)
(set-frame-size (selected-frame) 80 12)
; font
(interactive)
(setq buffer-face-mode-face '(:family "P22 Underground Book" :height 160))
(buffer-face-mode)
; position
(let* ((mousepos (split-string (shell-command-to-string "xdotool getmouselocation | sed -E \"s/ screen:0 window:[^ ]*|x:|y://g\"")))
        (mouse-x (- (string-to-number (nth 0 mousepos)) 100))
        (mouse-y (- (string-to-number (nth 1 mousepos)) 50)))
    (set-frame-position (selected-frame) mouse-x mouse-y))
; set major mode
(cond
    ((github-conversation-p window-title) (gfm-mode))
    (t (markdown-mode)) ; default major mode
    )
; start in insert
(evil-insert-state)
)
(add-hook 'ea-popup-hook 'ea-popup-handler)

Language configuration

Org Mode

Basic config

We want to set the org directory, I tend to keep everything in ~/Desktop/TEC anyway, so…

(setq org-directory "~/Desktop/TEC/Organisation")

It's also nice to have properties be inherited

(setq org-use-property-inheritance t)

Visuals

In editor

Mixed pitch is great. As is +org-pretty-mode, let's use them.

(use-package mixed-pitch
  :hook (org-mode . mixed-pitch-mode))
(add-hook 'org-mode-hook '+org-pretty-mode)

Earlier I loaded the org-pretty-table package, let's enable it everywhere!

(setq global-org-pretty-table-mode t)

Unfortunately it doesn't seem to do anything ATM 😞.

It's also nice to change the character used for collapsed items (by default ), I think is better for indicating 'collapsed section'. and add an extra org-bullet to the default list of four. I've also added some fun alternatives, just commented out.

(setq org-ellipsis " ▾ "
      org-bullets-bullet-list '("◉" "○" "✸" "✿" "✤")
      ;; org-bullets-bullet-list '("" "Ⅱ" "Ⅲ" "Ⅳ" "" "Ⅵ" "Ⅶ" "Ⅷ" "Ⅸ" "")
      )

It's also nice to make use of the unicode characters for check boxes, and other commands.

(after! org
  (appendq! +pretty-code-symbols
            '(:checkbox   "☐"
              :pending    "◼"
              :checkedbox "☑"
              :results "🠶"
              :property "☸"
              :title "𝙏"
              :author "𝘼"
              :begin_quote ""
              :end_quote ""
              :em_dash "—"))
  (set-pretty-symbols! 'org-mode
    :merge t
    :checkbox   "[ ]"
    :pending    "[-]"
    :checkedbox "[X]"
    :results "#+RESULTS:"
    :property "#+PROPERTY:"
    :title "#+TITLE:"
    :author "#+AUTHOR:"
    :begin_quote "#+BEGIN_QUOTE"
    :end_quote "#+END_QUOTE"
    :em_dash "---")
)
(plist-put +pretty-code-symbols :name "⁍") ; or  could be good?
Exporting to HTML

There is a fantastic exporter config (fniessen/org-html-themes) which we can setup to be used with all our org files. Since most of the syntax highlighting colours from our /tec/emacs-config/src/commit/201774cac98e722356561649c8e01ebce5b560b8/Theme gets used, we benefit from customising the code block style.

We also want to make the background and foreground colours of the <pre> blocks match out theme (they don't by default), so I scraped some code from emacs.stackexchange.

(defun my-org-inline-css-hook (exporter)
  "Insert custom inline css to automatically set the
   background of code to whatever theme I'm using's background"
  (when (eq exporter 'html)
      (setq
       org-html-head-extra
       (concat
        org-html-head-extra
        (format "
<style type=\"text/css\">
   :root {
      --theme-bg: %s;
      --theme-bg-alt: %s;
      --theme-base0: %s;
      --theme-base1: %s;
      --theme-base2: %s;
      --theme-base3: %s;
      --theme-base4: %s;
      --theme-base5: %s;
      --theme-base6: %s;
      --theme-base7: %s;
      --theme-base8: %s;
      --theme-fg: %s;
      --theme-fg-alt: %s;
      --theme-grey: %s;
      --theme-red: %s;
      --theme-orange: %s;
      --theme-green: %s;
      --theme-teal: %s;
      --theme-yellow: %s;
      --theme-blue: %s;
      --theme-dark-blue: %s;
      --theme-magenta: %s;
      --theme-violet: %s;
      --theme-cyan: %s;
      --theme-dark-cyan: %s;
   }
</style>"
       (doom-color 'bg)
       (doom-color 'bg-alt)
       (doom-color 'base0)
       (doom-color 'base1)
       (doom-color 'base2)
       (doom-color 'base3)
       (doom-color 'base4)
       (doom-color 'base5)
       (doom-color 'base6)
       (doom-color 'base7)
       (doom-color 'base8)
       (doom-color 'fg)
       (doom-color 'fg-alt)
       (doom-color 'grey)
       (doom-color 'red)
       (doom-color 'orange)
       (doom-color 'green)
       (doom-color 'teal)
       (doom-color 'yellow)
       (doom-color 'blue)
       (doom-color 'dark-blue)
       (doom-color 'magenta)
       (doom-color 'violet)
       (doom-color 'cyan)
       (doom-color 'dark-cyan))
        "
<<orgHtmlStyle>>
"
        ))))

(add-hook 'org-export-before-processing-hook 'my-org-inline-css-hook)

Since we have verbatim and code, let's use verbatim for key strokes.

(setq org-html-text-markup-alist
      '((bold . "<b>%s</b>")
        (code . "<code>%s</code>")
        (italic . "<i>%s</i>")
        (strike-through . "<del>%s</del>")
        (underline . "<span class=\"underline\">%s</span>")
        (verbatim . "<kbd>%s</kbd>")))

We also want to use HTML checkboxes, however we want to get a bit fancier than default

(after! org
(appendq! org-html-checkbox-types '((html-span .
	  ((on . "<span class='checkbox'></span>")
	  (off . "<span class='checkbox'></span>")
	  (trans . "<span class='checkbox'></span>")))))
(setq org-html-checkbox-type 'html-span))
  • I'm yet to do this
  • Work in progress
  • This is done
Exporting to LaTeX
(with-eval-after-load 'ox-latex
  (add-to-list 'org-latex-classes
               '("fancy-article"
               "\\documentclass{scrartcl}\n\\usepackage[default,sfdefault]{lato}"
               ("\\section{%s}" . "\\section*{%s}")
               ("\\subsection{%s}" . "\\subsection*{%s}")
               ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
               ("\\paragraph{%s}" . "\\paragraph*{%s}")
               ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
  (setq org-latex-default-class "fancy-article")

   (add-to-list 'org-latex-packages-alist '("" "minted"))
   (setq org-latex-listings 'minted)
   (setq org-latex-hyperref-template "\\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k},\n pdfsubject={%d},\n pdfcreator={%c}, \n pdflang={%L}, colorlinks=true}\n\\urlstyle{same}\n")
   (setq org-latex-pdf-process
         '("latexmk -shell-escape -interaction=nonstopmode -f -pdf -output-directory=%o %f")))
Exporting to GFM

We just need to load ox-gfm for org-mode documents

(eval-after-load "org"
  '(require 'ox-gfm nil t))