Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
791 lines (626 sloc) 18.7 KB

Lexical binding

;; -*- lexical-binding: t -*-

Packages

Use-package setup

(unless (package-installed-p 'use-package)
  (package-install 'use-package))

try

(use-package try
  :ensure t)

pretty-symbols

(use-package pretty-symbols
  :ensure t
  :config
  (global-prettify-symbols-mode))

(defun add-pretty-symbols-list (symbols)
  "Add a list of prettified symbol-pairs to the buffer-local prettify-symbols-alist"
  (setq-local prettify-symbols-alist (append prettify-symbols-alist
                                             symbols)))

(defun add-pretty-symbols-hook (mode-hook symbols)
  "Add a list of prettified symbol-pairs to a given mode."
  (add-hook mode-hook `(lambda ()
                        (add-pretty-symbols-list (quote ,symbols)))))

(defvar double-struck-letters
  '(("|A|" . ?𝔸)
    ("|B|" . ?𝔹)
    ("|C|" . ?ℂ)
    ("|D|" . ?𝔻)
    ("|E|" . ?𝔼)
    ("|F|" . ?𝔽)
    ("|G|" . ?𝔾)
    ("|H|" . ?ℍ)
    ("|I|" . ?𝕀)
    ("|J|" . ?𝕁)
    ("|K|" . ?𝕂)
    ("|L|" . ?𝕃)
    ("|M|" . ?𝕄)
    ("|N|" . ?ℕ)
    ("|O|" . ?𝕆)
    ("|P|" . ?ℙ)
    ("|Q|" . ?ℚ)
    ("|R|" . ?ℝ)
    ("|S|" . ?𝕊)
    ("|T|" . ?𝕋)
    ("|U|" . ?𝕌)
    ("|V|" . ?𝕍)
    ("|W|" . ?𝕎)
    ("|X|" . ?𝕏)
    ("|Y|" . ?𝕐)
    ("|Z|" . ?ℤ)
    ("|gamma|" . ?ℽ)
    ("|Gamma|" . ?ℾ)
    ("|pi|" . ?ℼ)
    ("|Pi|" . ?ℿ)))

(defvar arrows
  '(("->" . ?→)
    ("-->" . ?⟶)
    ("<-" . ?←)
    ("<--" . ?⟵)
    ("<->" . ?↔)
    ("<-->" . ?⟷)
    ("=>" . ?⇒)
    ("==>" . ?⟹)
    ("<==" . ?⟸)
    ("<=>" . ?⇔)
    ("<==>" . ?⟺)
    ("|->" . ?↦)
    ("|-->" . ?⟼)
    ("<-|" . ?↤)
    ("<--|" . ?⟻)
    ("|=>" . ?⤇)
    ("|==>" . ?⟾)
    ("<=|" . ?⤆)
    ("<==|" . ?⟽)
    ("~>" . ?⇝)
    ("<~" . ?⇜)
    (">->" . ?↣)
    ("<-<" . ?↢)
    ("->>" . ?↠)
    ("<<-" . ?↞)
    (">->>" . ?⤖)
    ("<<-<" . ?⬻)
    ("<|-" . ?⇽)
    ("-|>" . ?⇾)
    ("<|-|>" . ?⇿)
    ("<-/-" . ?↚)
    ("-/->" . ?↛)
    ("<-|-" . ?⇷)
    ("-|->" . ?⇸)
    ("<-|->" . ?⇹)
    ("<-||-" . ?⇺)
    ("-||->" . ?⇻)
    ("<-||->" . ?⇼)
    ("-o->" . ?⇴)
    ("<-o-" . ?⬰)))

(defvar mathematical-symbols
  '(("forall" . ?∀)
    ("exists" . ?∃)
    ("not" . )
    ("&&" . ?∧)
    ("||" . ?∨)
    ("==" . ?≡)
    ("/=" . ?≠)
    ("!=" . ?≠)
    ("<=" . ?≤)
    (">=" . ?≥)
    ("/<" . ?≮)
    ("/>" . ?≯)
    ("++" . ?⧺)
    ("+++" . ?⧻)
    ("|||" . ?⫴)
    ("empty" . ?∅)
    ("elem" . ?∈)
    ("notElem" . ?∉)
    ("member" . ?∈)
    ("notMember" . ?∉)
    ("union" . ?∪)
    ("intersection" . ?∩)
    ("subsetOf" . ?⊆)
    ("properSubsetOf" . ?⊂)
    ("<<" . ?≪)
    (">>" . ?≫)
    ("<<<" . ?⋘)
    (">>>" . ?⋙)
    ("<|" . ?⊲)
    ("|>" . ?⊳)
    ("><" . ?⋈)
    (":=" . ?≔)
    ("=:" . ?≕)
    ("<+>" . ?⊕)
    ("<*>" . ?⊛)))

(defvar greek-letters
  '(("alpha" . )
    ("beta" . )
    ("gamma" . )
    ("delta" . )
    ("epsilon" . )
    ("zeta" . )
    ("eta" . )
    ("theta" . )
    ("iota" . )
    ("kappa" . )
    ("lambda" . )
    ("mu" . )
    ("nu" . )
    ("xi" . )
    ("omicron" . ?ο)
    ("pi" . )
    ("rho" . )
    ("sigma_final" . )
    ("sigma" . )
    ("tau" . )
    ("upsilon" . )
    ("phi" . )
    ("chi" . )
    ("psi" . )
    ("omega" . )))

which-key

(use-package which-key
  :ensure t
  :config
  (which-key-mode))

web-mode

(use-package web-mode
  :ensure t
  :mode (("\\.html?\\'" . web-mode)
         ("\\.php?\\'"  . web-mode)
         ("\\.js?\\'"   . web-mode)
         ("\\.css?\\'"  . web-mode)))

magit

(use-package magit
  :ensure t
  :config
  (defun my-magit-status ()
    (interactive)
    (if (string= (buffer-name) "jetbrains-idea-ce")
        (magit-status-internal "~/data/programming/Terasology/")
      (magit-status-internal default-directory)))
  :bind
  (("C-c g" . my-magit-status)))

evil

(use-package evil
  :ensure t
  :config
  ;; Make Evil's point behave more like Emacs'
  (setq evil-want-change-word-to-end nil)
  (setq evil-move-cursor-back nil)
  (evil-mode))

evil-surround

(use-package evil-surround
  :ensure t
  :config
  (global-evil-surround-mode))

evil-cleverparens

(defun global-evil-cleverparens-mode ()
  "Custom wrapper to enable evil-cleverparens-mode globally."
  (interactive)
  (add-hook 'evil-local-mode-hook #'evil-cleverparens-mode))

(use-package evil-cleverparens
  :ensure t
  :config
  (global-evil-cleverparens-mode))

exwm

(use-package exwm
  :ensure t
  :config
  (require 'exwm)
  (require 'exwm-config)

  ;; Set the initial workspace number.
  (setq exwm-workspace-number 0)
  ;; Make class name the buffer name
  (add-hook 'exwm-update-class-hook
            (lambda ()
              (exwm-workspace-rename-buffer exwm-class-name)))

  ;; Don't use evil-mode in exwm buffers
  (add-to-list 'evil-emacs-state-modes 'exwm-mode)

  ;; 's-w': Switch workspace
  (exwm-input-set-key (kbd "s-w") #'exwm-workspace-switch)
  ;; 's-N': Switch to certain workspace
  (dotimes (i 10)
    (exwm-input-set-key (kbd (format "s-%d" i))
                        `(lambda ()
                           (interactive)
                           (exwm-workspace-switch-create ,i))))
  ;; 's-r': Launch application
  (exwm-input-set-key (kbd "s-r")
                      (lambda (command)
                        (interactive (list (read-shell-command "$ ")))
                        (start-process-shell-command command nil command)))

  ;; Better window management
  (exwm-input-set-key (kbd "s-h") 'windmove-left)
  (exwm-input-set-key (kbd "s-j") 'windmove-down)
  (exwm-input-set-key (kbd "s-k") 'windmove-up)
  (exwm-input-set-key (kbd "s-l") 'windmove-right)

  (exwm-input-set-key (kbd "s-s") 'split-window-right)
  (exwm-input-set-key (kbd "s-v") 'split-window-vertically)

  (advice-add 'split-window-right :after 'windmove-right)
  (advice-add 'split-window-vertically :after 'windmove-down)

  (exwm-input-set-key (kbd "s-d") 'delete-window)
  (exwm-input-set-key (kbd "s-q") '(lambda ()
                                     (interactive)
                                     (kill-buffer (current-buffer))))

  ;; Save my hands
  (exwm-input-set-key (kbd "s-f") 'find-file)
  (exwm-input-set-key (kbd "s-b") 'ido-switch-buffer)

  (exwm-input-set-key (kbd "s-w") 'save-buffer)

  ;; Swap between qwerty and Dvorak with the same keyboard key
  (exwm-input-set-key (kbd "s-;") '(lambda ()
                                     (interactive)
                                     (start-process-shell-command "aoeu" nil "aoeu")
                                     (message "Qwerty")))
  (exwm-input-set-key (kbd "s-z") '(lambda ()
                                     (interactive)
                                     (start-process-shell-command "asdf" nil "asdf")
                                     (message "Dvorak")))

  ;; Line-editing shortcuts
  (exwm-input-set-simulation-keys
   '(([?\C-b] . left)
     ([?\C-f] . right)
     ([?\M-f] . C-right)
     ([?\M-b] . C-left)
     ([?\C-y] . S-insert)
     ([?\C-p] . up)
     ([?\C-n] . down)
     ([?\C-a] . home)
     ([?\C-e] . end)
     ([?\M-v] . prior)
     ([?\C-v] . next)
     ([?\C-d] . delete)
     ([?\C-k] . (S-end delete))))
  ;; Configure Ido
  (exwm-config-ido)
  ;; Other configurations
  (exwm-config-misc)

  ;; Allow switching buffers between workspaces
  (setq exwm-workspace-show-all-buffers t)
  (setq exwm-layout-show-all-buffers t)

  (call-process-shell-command "~/data/scripts/startup.sh"))

smex

(use-package smex
  :ensure t
  :bind
  (("M-x" . smex)))

zenburn-theme

(use-package zenburn-theme
  :ensure t
  :config
  (load-theme 'zenburn t))

;; Lots of improvements from https://gist.github.com/belak/ca1c9ae75e53324ee16e2e5289a9c4bc
;; TODO: add moree, and check out other configs, starter packs, etc.
;; TODO: maybe configure fonts?
;; TODO: properly setup evil-mode bindings

ido

ido

(use-package ido
  :ensure t
  :config
  (ido-mode 1)
  (ido-everywhere t)
  (setq ido-enable-flex-matching t)
  (setq ido-create-new-buffer 'always))

ido-ubiquitous

(use-package ido-ubiquitous
  :ensure t
  :config
  (ido-ubiquitous-mode))

ido-vertical-mode

(use-package ido-vertical-mode
  :ensure t
  :config
  (setq ido-vertical-define-keys 'C-n-C-p-up-down-left-right
        ido-vertical-show-count t)
  (ido-vertical-mode 1))

flx-ido

(use-package flx-ido
  :ensure t
  :config
  (flx-ido-mode 1))

org

(use-package org
  :ensure t
  :config
  (setq org-refile-use-outline-path 'file)
  (setq org-src-fontify-natively t)
  (setq org-src-tab-acts-natively t)
  (setq org-agenda-span 21)
  (setq org-directory "~/data/org")
  (setq org-agenda-files '("~/data/org/inbox.org"
                           "~/data/org/waiting.org"
                           "~/data/org/calendar.org"
                           "~/data/org/actions.org"
                           "~/data/org/projects.org"
                           "~/data/org/someday.org"
                           "~/data/org/review.org"
                           "~/data/org/reference.org"))
  (setq org-refile-targets '((org-agenda-files :maxlevel . 2)
                             ("~/data/org/archive/archive-projects.org" :level . 1)
                             ("~/data/org/archive/archive-actions.org" :level . 1)))
  (setf org-blank-before-new-entry '((heading . nil) (plain-list-item . nil)))
  (setq org-capture-templates
        '(("i" "Capture to inbox"
           entry (file "~/data/org/inbox.org") "* %?")
          ("f" "Capture to inbox with a link to the current file"
           entry (file "~/data/org/inbox.org") "* %?\n  %a")))
  (setq org-default-notes-file (concat org-directory "/inbox.org"))
  (defun find-org-directory () (interactive) (find-file org-directory))
  (defun my-org-capture () (interactive) (org-capture nil "i"))
  (defun my-org-time-stamp ()
    "Add a timestamp to an org-mode heading.
Put the timestamp on a newline, like org-schedule."
    (interactive)
    (let ((inhibit-quit t))
      (save-excursion
        (evil-open-below 1)
        (unless (with-local-quit (org-time-stamp nil))
          (call-interactively 'evil-delete-whole-line)))
      (evil-normal-state)))

  (add-pretty-symbols-hook 'org-mode-hook double-struck-letters)
  (add-pretty-symbols-hook 'org-mode-hook mathematical-symbols)
  (add-pretty-symbols-hook 'org-mode-hook arrows)
  (add-pretty-symbols-hook 'org-mode-hook greek-letters)

  :bind
  (("C-c c" . my-org-capture)
   ("C-c a" . org-agenda)
   ("C-c o" . find-org-directory)
   ("C-c d" . my-org-time-stamp)))

auto-complete

(use-package auto-complete
  :ensure t
  :config
  (ac-config-default)
  (global-auto-complete-mode))

eclim

(use-package eclim
  :ensure t
  :config
  (setq eclim-executable "/home/mitch/programs/eclipse-neon/eclim")
  (add-hook 'java-mode-hook 'eclim-mode)
  ;; Fixes a problem with multi-project eclim projects adding the project name twice
  (defun my-eclim-fix-relative-path (path)
    (replace-regexp-in-string "^.*src/" "src/" path))
  (advice-add 'eclim--project-current-file :filter-return #'my-eclim-fix-relative-path))

ace-jump-mode

(use-package ace-jump-mode
  :ensure t
  :config
  ;; Only search in the current frame
  ;; Might need to be adjusted if I want multi-monitor jumping
  ;; Currently exwm frames are always marked as visible, so 'visible won't work
  ;; (mapcar 'frame-visible-p (frame-list)) => (t t t t t t t)
  (setq ace-jump-mode-scope 'frame)
  :init
  (evil-define-key '(normal motion) global-map "s" 'evil-ace-jump-word-mode)
  :bind
  (("C-l" . ace-jump-word-mode)))

relative line numbers

If I’m using the experimental line-numbers build, use the line-number features from that build. Otherwise, use linum-relative.

(if (boundp 'display-line-numbers)
    (setq-default display-line-numbers 'relative)
  (use-package linum-relative
    :ensure t
    :config
    (setq linum-relative-current-symbol "")
    (setq linum-relative-format "%3s ")
    (linum-relative-global-mode)))

rainbow-delimiters

(use-package rainbow-delimiters
  :ensure t
  :config
  (rainbow-delimiters-mode 1))

paredit

(use-package paredit
  :ensure t
  :config
  (add-hook 'evil-cleverparens-mode-hook #'enable-paredit-mode))

gnus

(use-package gnus
  :ensure t
  :config
  (org-babel-load-file (concat user-emacs-directory "gnus.el.org")))

gpg

(setq epa-pinentry-mode 'loopback)
(pinentry-start)

haskell

(use-package haskell-mode
  :ensure t
  :config
  (add-pretty-symbols-hook 'haskell-mode-hook '(("::" . ?∷))))

Custom loads

(add-to-list 'load-path (concat user-emacs-directory "sources/exlb"))
(add-to-list 'load-path (concat user-emacs-directory "sources/exwm"))

General settings

UI

(blink-cursor-mode -1)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(setq inhibit-startup-message t)
(display-time)

Consistent prompts

(fset 'yes-or-no-p 'y-or-n-p)

Don’t ask about creating new buffer

(setq confirm-nonexistent-file-or-buffer nil)

Use the primary clipboard for emacs

(setq select-enable-primary t)
(setq-default indent-tabs-mode nil)

Make tab try to autocomplete

(setq tab-always-indent 'complete)

Scroll by one line at a time

;; But on big jumps, re-center ponit
(setq scroll-conservatively 5)

Put all backup files into ~/tmp/backups

(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq backup-by-copying t)

Show the matching paren

(show-paren-mode 1)
(setq show-paren-delay 0)

Help at point

(setq help-at-pt-display-when-idle t)
(setq help-at-pt-timer-delay 0)
(help-at-pt-set-timer)

Set the font

(set-face-attribute 'default nil :height 135 :weight 'normal)
(setq-default line-spacing 4)

Automatically revert files if their contents changes on disk

Todo: make Emacs ask whether to revert modified buffer when it is modified on disk

(global-auto-revert-mode 1)

Show trailing whitespace

Todo: make trailing whitespace only show when you have left Evil insert state

(setq-default show-trailing-whitespace t)

Minibuffer

;; Allow to read from minibuffer while in minibuffer.
(setq enable-recursive-minibuffers t)

;; Show the minibuffer depth (when larger than 1)
(minibuffer-depth-indicate-mode 1)

Server start

(server-start)

Custom functions

eval-current-sexp

(defun eval-current-sexp (arg)
  "Evaluate the current sexp (or the last sexp, if immediately following a )"
  (interactive "P")
  (save-excursion
    (unless (looking-at ")")
      (backward-char))
    (paredit-forward-up)
    (eval-last-sexp arg)))
(define-key global-map (kbd "C-c e") 'eval-current-sexp)

rename-file-and-buffer

(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME.
Taken from Steve Yegge's config (https://sites.google.com/site/steveyegge2/my-dot-emacs-file)."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (cond ((not filename)
           (message "Buffer '%s' is not visiting a file!" name))
          ((get-buffer new-name)
           (message "A buffer named '%s' already exists!" new-name))
          (t
           (rename-file filename new-name 1)
           (rename-buffer new-name)
           (set-visited-file-name new-name)
           (set-buffer-modified-p nil)))))

move-buffer-file

(defun move-buffer-file (dir)
  "Moves both current buffer and file it's visiting to DIR.
Taken from Steve Yegge's config (https://sites.google.com/site/steveyegge2/my-dot-emacs-file)."
  (interactive "DNew directory: ")
  (let* ((name (buffer-name))
         (filename (buffer-file-name))
         (dir
          (if (string-match dir "\\(?:/\\|\\\\)$")
              (substring dir 0 -1) dir))
         (newname (concat dir "/" name)))
    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (copy-file filename newname 1)
      (delete-file filename)
      (set-visited-file-name newname)
      (set-buffer-modified-p nil))))

auto-sharp-quote

(defun auto-sharp-quote ()
  "Insert #' unless in a string or comment.
  From http://endlessparentheses.com/get-in-the-habit-of-using-sharp-quote.html"
  (interactive)
  (call-interactively #'self-insert-command)
  (let ((ppss (syntax-ppss)))
    (unless (or (elt ppss 3))
      (elt ppss 4)
      (eq (char-after) ?')
      (insert "'"))))

(evil-define-key 'normal-state 'emacs-lisp-mode-map "#" #'auto-sharp-quote)
(define-key emacs-lisp-mode-map "#" #'auto-sharp-quote)