UP  |  HOME

Emacs

Table of Contents

I mostly use emacs for working with a few orgmode things. It's in evil mode.

Color theme

Darkokai - A darker Monokai theme

Unpackaged stuff

hl-fill-column
Highlights the fill column to maintain max line width

ELPA packages

For manual install from elpa run M-x package-refresh-contents then M-x package-install. Enter the package name at the prompt. M-x list-packages might be useful for finding particular ones.

Manually pulled

names
dependency of hl-fill-column

Packaged in Debian

evil
Vim layer
org
for notes, documentation
s
string manipulation
f
file API
slime
a maybe better Lisp REPL
fill-column-indicator
for toggle-able fill column indicator (thin vertical line)

Configuration

Listing 1: ~/.config/emacs/init.el
(add-to-list 'load-path (expand-file-name "elisp" user-emacs-directory))
(customize-save-variable
  'custom-file (expand-file-name "elisp/custom.el" user-emacs-directory))
(load-file custom-file)
(if noninteractive (package-initialize)) ;; allow elpa packages in batch mode
(load-library "org-settings")
(load-library "evil-settings")
(load-library "slime-settings")
(load-library "hl-fill-column")

(make-directory "~/.local/share/emacs/backups/" t)
(setq auto-save-file-name-transforms '((".*" "~/.local/share/emacs/backups/" t)))
(setq backup-directory-alist `(("." . "~/.local/share/emacs/backups")))
(setq lock-file-name-transforms '(("\\`/.*/\\([^/]+\\)\\'" "~/.local/share/emacs/backups/\\1" t)))

(global-display-line-numbers-mode)
(setq show-paren-mode-delay 0)
(show-paren-mode 1)

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq c-basic-offset 4)
(setq js-indent-level 2)
(setq css-indent-offset 2)

(setq ring-bell-function 'ignore)
(setq-default inhibit-startup-screen t)
(setq inhibit-splash-screen t)
(setq inhibit-startup-message t)

(column-number-mode)
(setq-default sentence-end-double-space nil)
(setq-default show-trailing-whitespace t)
(setq-default indicate-empty-lines t)
(setq-default indicate-buffer-boundaries 'left)
(setq-default fill-column 80)
(setq-default scroll-margin 5)
(setq-default scroll-conservatively 1)
(setq-default scroll-up-aggressively 0)
(setq-default scroll-down-aggressively 0)
(setq mouse-wheel-progressive-speed nil)

(require 'whitespace)
;; mappings are KIND CHAR VECTOR (of replacement chars)
(setq whitespace-display-mappings
           '((space-mark   ?\    [?\␣]     [?_])               ; space
             (space-mark   ?\xA0 [?\⍽]     [?_])               ; hard space
             (newline-mark ?\n   [?\␤ ?\n] [?↵ ?\n] [?$ ?\n])  ; end-of-line
             (tab-mark     ?\t   [?\‣ ?\t] [?» ?\t] [?\\ ?\t]) ; tab
             ))
(global-set-key [f2] 'whitespace-mode)

(require 'fill-column-indicator)
(global-set-key [f6] 'fci-mode)

;; relies on hl-fill-column.el which needs names.el package installed
(global-hl-fill-column-mode)

(add-to-list 'custom-theme-load-path "~/.config/emacs/themes")
(when (display-graphic-p)
  (tool-bar-mode -1)
  (load-theme 'darkokai t)
  (set-face-attribute 'default nil :font "Fira Code Medium-8"))

(defun xterm-title-update ()
    (interactive)
    (when
      (not window-system)
      (send-string-to-terminal
        (concat "\033]1; " (buffer-name) " - emacs@" (system-name) "\007"))
      (if buffer-file-name
        (send-string-to-terminal
          (concat "\033]2; " (buffer-file-name)
                  " - emacs@" (system-name) "\007"))
        (send-string-to-terminal
          (concat "\033]2; " (buffer-name)
                  " - emacs@" (system-name) "\007")))))

(add-hook 'post-command-hook 'xterm-title-update)

(setq frame-title-format
      (list '(buffer-file-name "%f" "%b")
            '(:eval (format " - emacs@%s" (system-name)))))
Listing 2: ~/.config/emacs/elisp/evil-settings.el
(require 'evil)
(evil-mode 1)

;; Give dired a vim-like alias
(require 'dired-x)
(defalias 'explore 'dired-jump)
(defalias 'Explore 'dired-jump)

(evil-ex-define-cmd "[W]rite" "write")

(define-key evil-normal-state-map (kbd "RET") 'evil-forward-paragraph)
(define-key evil-normal-state-map (kbd "DEL") 'evil-backward-paragraph)
(define-key evil-visual-state-map (kbd "RET") 'evil-forward-paragraph)
(define-key evil-visual-state-map (kbd "DEL") 'evil-backward-paragraph)

;; Enable tab for org visibility cycling despite being in evil mode
(evil-define-key 'normal org-mode-map (kbd "<tab>") #'org-cycle)

;; K inserts newline and places cursor after current line
;; (split line at cursor)
(define-key evil-normal-state-map
            "K" (lambda () (interactive)
                  (evil-insert 1)
                  (evil-ret-gen 1 nil)
                  (evil-force-normal-state)
                  (evil-next-line-1-first-non-blank 1)
                  (indent-according-to-mode)
                  (let (line-move-visual) (evil-line-move (- 1)))
                  (evil-move-end-of-line 1)))
Listing 3: ~/.config/emacs/elisp/org-settings.el
(when (require 'org nil t)
    (require 'server)
    (or (server-running-p)
        (server-start))

    (require 'org-protocol)

    (define-key global-map "\C-cl" 'org-store-link)
    (define-key global-map "\C-ca" 'org-agenda)
    (setq org-log-done t)
    (setq org-export-allow-bind-keywords t)

    ;; Custom entities
    (add-to-list 'org-entities-user
                 '("vdots" "\\vdots{}" t "&#x22ee" "..." "..." "⁞"))

    ;; Allow binds (used in sitemap to disable some filters)
    (setq org-export-allow-bind-keywords t)

    ;; Code evaluation
    ;; Use CAPTION for the keyword because then source blocks with a NAME
    ;; become code blocks with a caption
    (setq org-babel-results-keyword "CAPTION")
    (setq org-babel-python-command "python3")
    (defun my-org-confirm-babel-evaluate (lang body)
      (not (or
             (string= lang "R")
             (string= lang "emacs-lisp")
             (string= lang "elisp")
             (string= lang "shell")
             (string= lang "dot")
             (string= lang "ditaa")
             (string= lang "latex")
             (string= lang "python")
             )))
    (setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate)
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((emacs-lisp . t)
       (C . t)
       (R . t)
       (dot . t)
       (ditaa . t)
       (shell . t)
       (latex . t)
       (python . t)))
    ;; Require curly braces for sub/super-scripts
    (setq org-export-with-sub-superscripts '{})
    (setq org-use-sub-superscripts '^:{})
    ;; Keep my indentation, otherwise we get indentation dependent on language
    (setq org-src-preserve-indentation t)

    (setq org-hide-leading-stars t)
    ;; show link markup
    (setq org-link-descriptive nil)

    ;; Don't center images.
    ;; Was causing issues by throwing \begin{center}s in my tables
    (setq org-latex-images-centered nil)
    ;; Don't upsize small images
    (setq org-latex-image-default-width "")

    (setq org-html-preamble t)
    (setq org-html-postamble nil)

    (ignore-errors (require 'org-roam))
    (require 'ob-shell)

    ;; reset truncate lines since org-mode is opinionated
    (add-hook 'org-mode-hook 
              (lambda () (setq truncate-lines nil)))

    ;; Enable habits
    (setq org-modules '(org-habit
                         ))
    (setq org-habit-show-habits-only-for-today nil)

    ;; Agenda/Calendar stuff
    (setq org-agenda-start-on-weekday nil)
    (setq org-agenda-format-date "%a [%b %d]")

    ;; disable some categories of holidays for agenda/calendar
    (setq holiday-bahai-holidays nil)
    (setq holiday-hebrew-holidays nil)
    (setq holiday-islamic-holidays nil)
    )

(defun file-if-file-exists (file)
  (if (file-exists-p file) file nil))

(setq org-agenda-files (remq nil (list (file-if-file-exists "/path/to/agenda.org")
                                       (file-if-file-exists "/path/to/agenda.org"))))