emacs-config/config.org

35 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

Intro

Customising an editor can be very rewarding … until you have to leave it. For years I have been looking for ways to avoid this pain. Then I discovered vim-anywhere, and found that it had an emacs companion, emacs-anywhere. To me, this looked most attractive.

Separately, online I have seen the following statement enough times I think it's a catchphrase

Redditor1: I just discovered this thing, isn't it cool. Redditor2: Oh, there's an emacs mode for that.

I tried out the spacemacs distribution a bit, but it wasn't quite to my liking. Then I heard about doom emacs and thought I may as well give that a try. TLDR; it's great.

Now I've discovered the wonders of literate programming, and am becoming more settled by the day. This is my config.

Rudimentary configuration

Make this file run (slightly) faster with lexical binding (see this blog post for more info).

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

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
      evil-want-fine-undo t)                      ; By default while in insert all changes are one big blob. Be more granular

(delete-selection-mode 1)                         ; Replace selection when inserting text
(display-time-mode 1)                             ; Enable time in the mode-line
(display-battery-mode 1)                          ; On laptops it's nice to know how much power you have
(global-subword-mode 1)                           ; Iterate through CamelCase words

; This really simplifies prompt style issues with tramp
(eval-after-load 'tramp '(setenv "SHELL" "/bin/bash"))

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))

Windows

I find it rather handy to be asked which buffer I want to see after splitting the window. Let's make that happen. First, we'll enter the new window

(setq evil-vsplit-window-right t
      evil-split-window-below t)

Then, we'll pull up ivy

(defadvice! prompt-for-buffer (&rest _)
  :after '(evil-window-split evil-window-vsplit)
  (+ivy/switch-buffer))

Buffer defaults

I'd much rather have my new buffers in org-mode than fundamental-mode, hence

(setq-default major-mode 'org-mode)

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 22)
      doom-big-font (font-spec :family "Fira Code" :size 36)
      doom-variable-pitch-font (font-spec :family "Overpass" :size 24))
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)

I'd like some slightly nicer default buffer names

(setq doom-fallback-buffer-name "► Doom"
      +doom-dashboard-name "► Doom")

There's a bug with the modeline in insert mode for org documents (issue), so

;; (custom-set-faces! '(doom-modeline-evil-insert-state :weight bold :foreground "#339CDB"))

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
(map! :n [mouse-8] #'better-jumper-jump-backward
      :n [mouse-9] #'better-jumper-jump-forward)

Window title

I'd like to have just the buffer name, then if applicable the project folder

(setq frame-title-format
    '(""
      "%b"
      (:eval
       (let ((project-name (projectile-project-name)))
         (unless (string= "-" project-name)
           (format " ● %s" project-name))))))

Systemd daemon

For running a systemd service for a emacs server I have the following

[Unit]
Description=Emacs server daemon
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/

[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook nil) (kill emacs))"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure

[Install]
WantedBy=default.target

which is then enabled by

systemctl --user enable emacs.service

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 packages

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/bb2cca50c369d767ed5211a42cda0111a6f57c62/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)

NB: I found that org +pandoc exists, however after enabling it I couldn't find/ any org-pandoc-y commands with M-x, so I'm using this

Came across this and … it's cool

(package! org-graph-view :recipe (:host github :repo "alphapapa/org-graph-view"))

Window management

(package! rotate)

Fun

Sometimes one just wants a little fun. XKCD comics are fun.

(package! xkcd)

Every so often, you want everyone else to know that you're typing, or just to amuse oneself. Introducing: typewriter sounds!

(package! selectric-mode)

Hey, let's get the weather in here while we're at it.

(package! wttrin)

Why not flash words on the screen. Why not — hey, it could be fun.

(package! spray)

With all our fancy emacs themes, my terminal is missing out!

(package! theme-magic)

Other

Flyspell-lazy

To alleviate some issues with flyspell

(package! flyspell-lazy)
CalcTeX

This is a nice extension to calc

(package! calctex :recipe (:host github :repo "johnbcoughlin/calctex"
                                 :files ("*.el")))
Systemd

For editing systemd unit files

(package! systemd)
ESS

View dataframes better with

(package! ess-view)

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-close-button "×"
        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.1
        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 (org-mode)) ; default major mode
   )

  (evil-insert-state); start in insert
  'centaur-tabs-local-mode ; disable tab
  )
(add-hook 'ea-popup-hook 'ea-popup-handler)

Flyspell

At one point, typing became noticably laggy, Profiling revealed flyspell-post-command-hook was responsible for 47% of CPU cycles by itself! So I'm going to make use of flyspell-lazy

(after! flyspell (require 'flyspell-lazy) (flyspell-lazy-mode 1))

Miscallanious

wttrin

Set the default city. It's initially Taipei but I find the ip-locating that's done perfectly acceptable, so let's make that happen.

(setq wttrin-default-cities '(""))

spray

Let's make this suit me slightly better.

(setq spray-wpm 500
      spray-height 700)

theme magic

Let's automaticly update terminals on theme change

(add-hook 'doom-load-theme-hook 'theme-magic-from-emacs)

calc

Radians are just better

(setq calc-angle-mode 'rad)

Language configuration

Org Mode

Behaviour

(setq org-directory "~/.org"                      ; let's put files here
      org-use-property-inheritance t              ; it's convenient to have properties inherited
      org-log-done 'time                          ; having the time a item is done sounds convininet
      org-list-allow-alphabetical t               ; have a. A. a) A) list bullets
      org-export-in-background t)                 ; run export processes in external emacs process

Let's also make creating an org buffer just that little bit easier.

(evil-define-command evil-buffer-org-new (count file)
  "Creates a new ORG buffer replacing the current window, optionally
   editing a certain FILE"
  :repeat nil
  (interactive "P<f>")
  (if file
      (evil-edit file)
    (let ((buffer (generate-new-buffer "*new org*")))
      (set-window-buffer nil buffer)
      (with-current-buffer buffer
        (org-mode)))))
(map! :leader
  (:prefix "b"
    :desc "New empty ORG buffer" "o" #'evil-buffer-org-new))

Visuals

In editor
Font Display

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

(add-hook! 'org-mode-hook #'+org-pretty-mode #'mixed-pitch-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 😞.

Symbols

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    "☸"
              :option      "⌥"
              :title       "𝙏"
              :author      "𝘼"
              :date        "𝘿"
              :begin_quote ""
              :end_quote   ""
              :em_dash     "—"))
  (set-pretty-symbols! 'org-mode
    :merge t
    :checkbox    "[ ]"
    :pending     "[-]"
    :checkedbox  "[X]"
    :results     "#+RESULTS:"
    :property    "#+PROPERTY:"
    :option      "#+OPTION:"
    :title       "#+TITLE:"
    :author      "#+AUTHOR:"
    :date        "#+DATE:"
    :begin_quote "#+BEGIN_QUOTE"
    :end_quote   "#+END_QUOTE"
    :em_dash     "---")
)
(plist-put +pretty-code-symbols :name "⁍") ; or  could be good?
LaTeX Fragments

It's nice to customise the look of LaTeX fragments so they fit better in the text. Let's start by adding a sans font. \(\sqrt{\beta^2+3}-\sum_{\phi=1}^\infty \frac{x^\phi-1}{\Gamma(a)}\)

(setq org-format-latex-header "\\documentclass{article}
\\usepackage[usenames]{color}
[PACKAGES]
[DEFAULT-PACKAGES]
\\pagestyle{empty}             % do not remove
% The settings below are copied from fullpage.sty
\\setlength{\\textwidth}{\\paperwidth}
\\addtolength{\\textwidth}{-3cm}
\\setlength{\\oddsidemargin}{1.5cm}
\\addtolength{\\oddsidemargin}{-2.54cm}
\\setlength{\\evensidemargin}{\\oddsidemargin}
\\setlength{\\textheight}{\\paperheight}
\\addtolength{\\textheight}{-\\headheight}
\\addtolength{\\textheight}{-\\headsep}
\\addtolength{\\textheight}{-\\footskip}
\\addtolength{\\textheight}{-3cm}
\\setlength{\\topmargin}{1.5cm}
\\addtolength{\\topmargin}{-2.54cm}
% my custom stuff
\\usepackage{arev}
\\usepackage{arevmath}")

On the rendering side, there are two .dvi-to-image convertors which I am interested in. dvipng and dvisvgm. For inline preview we care about speed. Using the above latex expression and benchmarking lead to the following results:

dvipng time dvisvgm time
0.09±0.002s 0.18±0.004s

So, let's use dvipng for previewing LaTeX fragments in-emacs, but dvisvgm for [[ Exporting to HTML][LaTeX Rendering]]. Unfortunately: it seems that svg sizing is annoying ATM, so let's not do this right now.

As well as having a sans font, there are a few other tweaks which can make them look better. Namely making the background transparent, and increasing the resolution.

(after! org
;; make background of fragments transparent
;; (let ((dvipng--plist (alist-get 'dvipng org-preview-latex-process-alist)))
;;   (plist-put dvipng--plist :use-xcolor t)
;;   (plist-put dvipng--plist :image-converter '("dvipng -D %D -bg 'transparent' -T tight -o %O %f")))
  (add-hook! 'doom-load-theme-hook
    (defun +org-refresh-latex-background ()
      (plist-put! org-format-latex-options
                  :background
                  (face-attribute (or (cadr (assq 'default face-remapping-alist))
                                      'default)
                                  :background nil t))))
)
Exporting to HTML
Custom CSS/JS

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/bb2cca50c369d767ed5211a42cda0111a6f57c62/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)
Make verbatim different to code

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>")))
Change checkbox type

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
LaTeX Rendering

On the maths side of things, I consider dvisvgm to be a rather compelling option. However this isn't sized very well at the moment.

;; (setq-default org-html-with-latex `dvisvgm)
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},\n colorlinks=true,\nlinkcolor=}\n\\urlstyle{same}\n")
   (setq org-latex-pdf-process
         '("latexmk -xelatex -shell-escape -interaction=nonstopmode -f -pdf -output-directory=%o %f")))
Exporting to Beamer

It's nice to use a different theme

(setq org-beamer-theme "[progressbar=foot]metropolis")

Then customise it a bit

And I think that it's natural to divide a presentation into sections, e.g. Introduction, Overview… so let's set bump up the headline level that becomes a frame from 1 to 2.

(setq org-beamer-frame-level 2)
Exporting to GFM

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

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

Babel

Doom lazy-loads babel languages, with is lovely.

We need to tell babel to use python3. Who uses python2 anymore anyway? And why doesn't python refer to the latest version!?

(setq org-babel-python-command "python3")

We also like autocompletion here

(defun tec-org-python ()
  (if (eq major-mode 'python-mode)
   (progn (anaconda-mode t)
          (company-mode t)))
  )
(add-hook 'org-src-mode-hook 'tec-org-python)

ESS

We don't want R evaluation to hang the editor, hence

(setq ess-eval-visibly 'nowait)

Syntax highlighting is nice, so let's turn all of that on

(setq ess-R-font-lock-keywords '((ess-R-fl-keyword:keywords . t)
 (ess-R-fl-keyword:constants . t)
 (ess-R-fl-keyword:modifiers . t)
 (ess-R-fl-keyword:fun-defs . t)
 (ess-R-fl-keyword:assign-ops . t)
 (ess-R-fl-keyword:%op% . t)
 (ess-fl-keyword:fun-calls . t)
 (ess-fl-keyword:numbers . t)
 (ess-fl-keyword:operators . t)
 (ess-fl-keyword:delimiters . t)
 (ess-fl-keyword:= . t)
 (ess-R-fl-keyword:F&T . t)))

R

Editor Visuals

(after! ess-r-mode
  (appendq! +pretty-code-symbols
            '(:assign "⟵"
              :multiply "×"))
  (set-pretty-symbols! 'ess-r-mode
    ;; Functional
    :def "function"
    ;; Types
    :null "NULL"
    :true "TRUE"
    :false "FALSE"
    :int "int"
    :floar "float"
    :bool "bool"
    ;; Flow
    :not "!"
    :and "&&" :or "||"
    :for "for"
    :in "%in%"
    :return "return"
    ;; Other
    :assign "<-"
    :multiply "%*%"))

hledger

ledger-mode is great and all, but hledger seems to be more actively maintained. For example, from 20182020, the most prolific contributor to ledger produced 31 commits. For hledger this statistic is 1800 commits. In addition, over the last decade, ledger seems to have lost steam, while hledger seems as actively developed as ever. From this basic comparison hledger looks to have a more promising outlook. It also has a few extra nicities that ledger doesn't, but is a little slower (hascell vs. c++). Since this uses the same format, and ledger-mode is well integrated into emacs, and produced by John Weigley — author of ledger and current Emacs maintainer — using this seems like a good idea. Thankfully we can, with a little modification.

(setq ledger-mode-should-check-version nil
      ledger-report-links-in-register nil
      ledger-binary-path "hledger")

Beancount

The beancount package online has been put into ./lisp, we just need to load and enable it for .beancount files.

(use-package! beancount
   :load-path "~/.config/doom/lisp"
   :mode ("\\.beancount\\'" . beancount-mode))