xin/configs/emacs.org

15 KiB

Emacs Configuration

Literate emacs configuration

I can never rembember what various configs do. Jumping on this literate emacs config to see if it helps!

Start the emacs server

Starting as a server lets me connect externally to do things like change themes, save buffers via cron and other such dumbary!

(load "server")
(unless (server-running-p) (server-start))

Interface and Behavior

Interface

Global font

  (set-frame-font "Go Mono 11")

Use 80 columns, this helps keep things readable when windows are split

(setq whitespace-style '(trailing lines space-before-tab)
      whitespace-line-column 80)
(setq-default fill-column 80)

I know I am in emacs, don't need to see the startup screen.

(setq inhibit-startup-screen t)
Use UTF8 where ever possible
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
Change various UI bits
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)
(column-number-mode +1)
(global-font-lock-mode 1)
direnv
  (use-package direnv
    :config
    (direnv-mode))

Behavior

Switch various defaults to be more comfortable for myself.

  (fset 'yes-or-no-p 'y-or-n-p)
  (show-paren-mode t)

  (setq desktop-dirname             "~/.emacs.d/"
        desktop-base-file-name      "emacs.desktop"
        desktop-base-lock-name      "lock"
        desktop-path                (list desktop-dirname)
        desktop-save                t
        desktop-files-not-to-save   "^$" ;reload tramp paths
        desktop-load-locked-desktop nil
        desktop-auto-save-timeout   30)
  (desktop-save-mode 1)

  (setq backup-directory-alist '(("." . "~/.emacs-saves")))
  (setq auto-mode-alist
        (append
         (list
          '("\\.gpg$" . sensitive-minor-mode)
          )
         auto-mode-alist))
  (setq auth-sources
        '((:source "~/.netrc")))

Use spelling and auto-fill when we are in text mode.

(add-hook 'text-mode-hook (lambda ()
			    (auto-fill-mode 1)
			    (turn-on-flyspell)))

Unset custom-file

The customization file mostly just causes churn in the SCM so we disable it here.

(setq custom-file (make-temp-file ""))

Packages

parchment-theme

This is a nice theme that resembles acme in plan9. Minimal.

(use-package parchment-theme
  :config (load-theme 'parchment t))

keychain-environment

I make heavy use of ssh-agent this lets emacs pickup / use the existing agents I have running.

(use-package keychain-environment
  ;;:pin "melpa"
  :init
  (keychain-refresh-environment))

ivy

ivy is fantastic. It gives me nice visual search for buffers, code.. etc. Combined with smex for sorting (shows last used things first) and counsel (extends ivy into various areas like the help stuff).

  (use-package counsel)
  (setq smex-save-file (expand-file-name "~/.emacs.d/smex.save"))
  (use-package smex)
  (use-package ivy
    :hook (after-init . ivy-mode)
    :bind
    ("C-s"     . swiper)
    ("M-x"     . counsel-M-x)
    ("C-x C-f" . counsel-find-file)
    ("C-x b"   . ivy-switch-buffer))

magit

Magit is a awesome. Not sure what else to say about it. :P

(use-package magit
  :bind ("C-c m" . magit-status)
  :init
  (setq magit-completing-read-function 'ivy-completing-read))

flycheck

flycheck does automatic syntax checking for most things

(use-package flycheck
  :init (global-flycheck-mode))
  • [2020-05-29 Fri] Unfortunately it clobbers the "C-c !" prefix, so we need to add this to get it back:
(define-key flycheck-mode-map (kbd "C-c !") 'org-time-stamp-inactive)

lsp

Use eglot for lsp stuff. It's built in and shows a bit more information for auto-completion stuff.

  (use-package eglot)
  (define-key eglot-mode-map (kbd "C-c r") 'eglot-rename)

company and friends

company allows for auto-completion of various things. It can interface with lsp-mode to complete things like Go.

(use-package company
  :config
  (setq company-tooltip-limit 20
	company-minimum-prefix-length 1
	company-idle-delay .3
	company-echo-delay 0)
  :hook (prog-mode . company-mode))

gitgutter

This gives me a nice in-ui way to see modifications and what not.

(use-package git-gutter
  :hook
  (after-init . global-git-gutter-mode))

shell

I don't often use the shell from emacs, but when I do these bits make it easier for me to treat it like a regular shell.

  ;; Kill terminal buffers on exit so I din't have to kill the buffer after I exit.
  (defadvice term-handle-exit
      (after term-kill-buffer-on-exit activate)
    (kill-buffer))

sr-speedbar

Speedbar is almost perfect.. If it only ran in the current frame!! :D

Enter sr-speedbar
  (use-package sr-speedbar)

Speedbar options

  (setq
   speedbar-show-unknown-files t
   sr-speedbar-right-side nil)

  (global-set-key (kbd "C-x C-n") 'sr-speedbar-toggle)

Language Configurations

Shell

  (use-package shfmt)
  (add-hook 'sh-mode-hook 'shfmt-on-save-mode)

Typescript

  (use-package typescript-mode)

Nix

  (use-package nix-mode
    :mode "\\.nix\\'")

Elm

  (use-package elm-mode)

Haskell

  (use-package haskell-mode)

Go

go-add-tags

This lets one select a struct or similar and auto add the `json:"NAME"` bits.

  (use-package go-add-tags)

go-mode

This allows for things like gofmt and auto adding / removing of imports.

  (use-package go-mode
    :bind
    ("C-c t" . go-add-tags))
  (defun lsp-go-install-save-hooks ()
    (add-hook 'before-save-hook #'lsp-format-buffer t t)
    (add-hook 'before-save-hook #'lsp-organize-imports t t))
  (add-hook 'go-mode-hook #'lsp-go-install-save-hooks)

go-eldoc

This extends eldoc to be able to speak Go - quite handy for quickly looking up what things do.

(use-package go-eldoc
  :hook
  (go-mode . go-eldoc-setup))

org-mode

Oh org-mode. It's the reason I started using emacs.. and it's the reason I can't quit!

Config

  (org-babel-do-load-languages
   'org-babel-load-languages
   '((plantuml . t)
     (dot      . t)
     (latex    . t)))

Publish bits

I publish some of my notes on suah.dev/p. Also some recipes.

  (setq my-org-publish-alist
        '(("notes" :components ("org-notes" "notes-static" "notes-rss"))
          ("deftly" :components ("deftly-blog" "deftly-static"))
          ("ohmyksh" :components ("ohmy-web" "ohmy-static"))
          ("org-notes"
           :auto-preamble t
           :auto-sitemap t
           :headline-levels 4
           :publishing-directory "/ssh:suah.dev:/var/www/suah.dev/p/"
           :publishing-function org-html-publish-to-html
           :recursive t
           :section-numbers nil
           :html-head "<link rel=\"stylesheet\" href=\"https://suah.dev/p/css/stylesheet.css\" type=\"text/css\" />"
           :html-link-home "http://suah.dev/p/"
           :html-link-up "../"
           :style-include-default nil
           :sitemap-filename "index.org"
           :sitemap-title "Notes"
           :with-title t
           :author-info nil
           :creator-info nil
           :base-directory "~/org/notes")
          ("deftly-blog"
           :auto-preamble t
           :auto-sitemap t
           :headline-levels 1
           :publishing-directory "/ssh:suah.dev:/var/www/deftly.net/new/"
           :publishing-function org-html-publish-to-html
           :recursive t
           :section-numbers nil
           :html-head "<link rel=\"stylesheet\" href=\"https://deftly.net/new/css/stylesheet.css\" type=\"text/css\" />"
           :html-link-home "http://deftly.net/new"
           :html-link-up "../"
           :style-include-default nil
           :sitemap-title "Deftly.net"
           :with-title t
           :author-info t
           :creator-info nil
           :base-directory "~/org/deftly")
          ("ohmy-web"
           :auto-preamble t
           :auto-sitemap nil
           :headline-levels 2
           :publishing-directory "/ssh:suah.dev:/var/www/deftly.net/ohmyksh/"
           :publishing-function org-html-publish-to-html
           :recursive t
           :section-numbers nil
           :html-head "<link rel=\"stylesheet\" href=\"https://deftly.net/ohmyksh/css/stylesheet.css\" type=\"text/css\" />"
           :html-link-home "http://deftly.net/ohmyksh"
           :html-link-up "../"
           :style-include-default nil
           :with-title t
           :author-info t
           :creator-info nil
           :base-directory "~/src/ohmyksh")
          ("notes-static"
           :base-directory "~/org/notes"
           :publishing-directory "/ssh:suah.dev:/var/www/suah.dev/p/"
           :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|svg"
           :recursive t
           :publishing-function org-publish-attachment)
          ("deftly-static"
           :base-directory "~/org/deftly"
           :publishing-directory "/ssh:suah.dev:/var/www/deftly.net/new/"
           :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg"
           :recursive t
           :publishing-function org-publish-attachment)
          ("ohmy-static"
           :base-directory "~/src/ohmyksh"
           :publishing-directory "/ssh:suah.dev:/var/www/deftly.net/ohmyksh/"
           :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg"
           :recursive t
           :publishing-function org-publish-attachment)
          ("notes-rss"
           :publishing-directory "/ssh:suah.dev:/var/www/suah.dev/p/"
           :publishing-function org-rss-publish-to-rss
           :recursive t
           :rss-extension "xml"
           :section-numbers nil
           :exclude ".*"
           :include ("index.org")
           :table-of-contents nil
           :base-directory "~/org/notes")
          ("mammoth"
           :publishing-directory "/ssh:suah.dev:/var/www/mammothcircus.com/"
           :publishing-function org-html-publish-to-html
           :author-info nil
           :creator-info nil
           :section-numbers nil
           :recursive t
           :base-directory "~/org/mammoth")
          ("recipes"
           :auto-preamble t
           :auto-sitemap t
           :headline-levels 4
           :publishing-directory "/ssh:suah.dev:/var/www/suah.dev/recipes/"
           :publishing-function org-html-publish-to-html
           :recursive t
           :section-numbers nil
           :html-head "<link rel=\"stylesheet\" href=\"https://suah.dev/p/css/stylesheet.css\" type=\"text/css\" />"
           :html-link-home "http://suah.dev/recipes/"
           :html-link-up "../"
           :style-include-default nil
           :sitemap-filename "index.org"
           :sitemap-title "Recipes"
           :with-title t
           :author-info nil
           :creator-info nil
           :base-directory "~/org/recipes")
          ))

Capture templates

(setq my-org-capture-templates
      `(("t" "TODO"
	 entry (file+headline "~/org/todo.org" "TODOs")
	 ,(concat
	   "* TODO %?\n"
	   ":PROPERTIES:\n"
	   ":LOGGING: TODO(!) WAIT(!) DONE(!) CANCELED(!)\n"
	   ":END:\n") :prepend t)
	("f" "TODO with File"
	 entry (file+headline "~/org/todo.org" "TODOs")
	 ,(concat
	   "* TODO %?\n"
	   ":PROPERTIES:\n"
	   ":LOGGING: TODO(!) WAIT(!) DONE(!) CANCELED(!)\n"
	   ":END:\n"
	   "%i\n  %a") :prepend t)
	("b" "Bug"
	 entry (file+olp+datetree "~/org/bugs.org" "Bugs")
	 "* BUG %?\nEntered on %U\n  :PROPERTIES:\n  :FILE: %a\n  :END:\n" :prepend t)
	("p" "Protocol"
	 entry (file+headline "~/org/links.org" "Links")
	 "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?")
	("L" "Protocol Link" entry (file+headline "~/org/links.org" "Links")
	 "* %? %:link\n%:description\n")
	("j" "Journal"
	 entry (file+olp+datetree "~/org/journal.org")
	 "* %?\nEntered on %U\n  %i\n")))

org

  (use-package org
    :hook
    (org-mode . (lambda ()
                  (turn-on-flyspell)
                  (auto-revert-mode)
                  (auto-fill-mode 1)))
    :bind
    ("C-c c" . org-capture)
    ("C-c p" . org-publish)
    ("C-c l" . org-store-link)
    ("C-c a" . org-agenda)
    ("C-c b" . org-iswitchb)
    :config
    (load-library "find-lisp")
    (setq org-directory "~/org"
          org-agenda-files (find-lisp-find-files "~/org" "\.org$")
          org-startup-indented t
          org-log-done 'time
          org-export-with-sub-superscripts nil
          org-html-inline-images t
          org-log-into-drawer t
          org-src-tab-acts-natively t
          org-agenda-skip-scheduled-if-deadline-is-shown t
          org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)")
                              (sequence "REPORT(r)" "BUG(b)" "KNOWNCAUSE(k)" "|" "FIXED(f)")
                              (sequence "|" "CANCELED(c)")))
    (setq org-publish-project-alist my-org-publish-alist)
    (setq org-capture-templates my-org-capture-templates))
  (use-package org-contrib)

Extra bits

(use-package org-journal
  :defer t
  :config
  (setq org-journal-dir "~/org/journal/"
	org-journal-file-format "%Y/%m-%d"
	org-journal-date-format "%A, %d %B %Y"))

Add in some org-mode helpers:

  • org-habit lets me keep track of TODOs and other things.
  • org-checklist lets me reset checklists for reoccurring tasks.

    • This requires one to pkg_add a2ps.
    • RESET_CHECK_BOXES property to be set to t on a task headline. (properties can be set via C-c C-x d
(require 'org-habit)
(require 'org-checklist)

Custom agenda commands for various things.

  • Daily habits shows how well I am keeping track of daily things.
(setq org-agenda-custom-commands
      '(("h" "Daily habits"
	 ((agenda ""))
	 ((org-agenda-show-log t)
	  (org-agenda-ndays 7)
	  (org-agenda-log-mode-items '(state))))))