Skip to content

threeve/emacs.d

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

General Config

(setq inhibit-default-init t
      load-prefer-newer t
      make-backup-files nil)

Use Package

Install use-package to make package management and configuration nicer.

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

(eval-when-compile
  (require 'use-package))
(require 'diminish)
(require 'bind-key)

Custom

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file 'noerror)

Mac keys

Different distributions of Emacs on macOS have different ideas about what the Command and Option keys should do, so be explicit here to make the consistent.

(setq mac-option-modifier 'none
      mac-command-modifier 'super
      mac-right-command-modifier 'meta)

(global-set-key (kbd "s-a") #'mark-whole-buffer)
(global-set-key (kbd "s-k") #'kill-this-buffer)
(global-set-key (kbd "s-l") #'goto-line)
(global-set-key (kbd "s-q") #'save-buffers-kill-terminal)
(global-set-key (kbd "s-s") #'save-buffer)
(global-set-key (kbd "s-w") #'delete-frame)

Add some text scaling bindings similar to other macOS apps.

(defun jafo-text-scale-reset ()
  "Reset text scaling to base size."
  (interactive)
  (text-scale-set 0))

(global-set-key (kbd "s-+") #'text-scale-increase)
(global-set-key (kbd "s-=") #'text-scale-increase)
(global-set-key (kbd "s--") #'text-scale-decrease)
(global-set-key (kbd "s-0") #'jafo-text-scale-reset)

Exec Path

(use-package exec-path-from-shell
  :ensure t
  :config (exec-path-from-shell-initialize))

Help

Which key provides visual guidance on incomplete key chords which aids in discovery.

(use-package which-key
  :ensure t
  :demand t
  :diminish ""
  :bind ("C-h C-k" . which-key-show-top-level)
  :config
  (setq which-key-idle-delay 0.2
        which-key-add-column-padding 0)
  (which-key-declare-prefixes
   "<SPC> g" '("scm" . "Magit, git, scm commands")
   "<SPC> p" '("projectile" . "Projectile commands")
   "<SPC> d" '("deft" . "notes: deft, etc")
   "<SPC> o" '("org" . "org mode")
   "<SPC> u" "package"
   "<SPC> n" "narrow"
   ;; "<SPC> i" "idomenu"
   )
  (which-key-mode t))

Discover My Major displays keybindings for the current major mode.

(use-package discover-my-major
  :ensure t
  :bind ("C-h C-m" . discover-my-major)
  :config
  (with-eval-after-load 'evil
    (evil-set-initial-state 'makey-key-mode 'motion)))

Misc

(use-package recentf)
(use-package no-littering
  :ensure t
  :config
  (with-eval-after-load 'recentf
    (add-to-list 'recentf-exclude no-littering-var-directory)
    (add-to-list 'recentf-exclude no-littering-etc-directory))
  (setq auto-save-file-name-transforms
        `((".*" ,(no-littering-expand-var-file-name "auto-save/") t))))

UI

Theme

(use-package nord-theme
  :ensure t
  :config
  (load-theme 'nord t)
  (with-eval-after-load 'ivy
    (set-face-attribute 'ivy-current-match nil :underline '(:color "#88c0d0" :style line) :foreground nil :background nil)
    (set-face-attribute 'ivy-minibuffer-match-face-1 nil :foreground nil :weight 'normal :background nil)
    (set-face-attribute 'ivy-minibuffer-match-face-2 nil :foreground "#88c0d0" :weight 'bold :background nil)
    (set-face-attribute 'ivy-minibuffer-match-face-3 nil :foreground "#88c0d0" :weight 'bold :background nil)
    (set-face-attribute 'ivy-minibuffer-match-face-4 nil :foreground "#88c0d0" :weight 'bold :background nil))
  )

(use-package apropospriate-theme
  :ensure t
  :disabled t
  :config (load-theme 'apropospriate-dark t))

Fonts

Adobe’s “Source” family of fonts are quite nice, and Hasklig is a derivative of Source Code Pro that adds many programming ligatures. Use of the ligatures requires using the railwaycat emacs port with mac-auto-operator-composition-mode enabled.

On macOS these fonts can be installed with Homebrew Cask.

(prefer-coding-system 'utf-8-unix)

(set-face-attribute 'default nil
                    :family "Hasklig"
                    :height 120
                    :weight 'normal)

(set-face-attribute 'variable-pitch nil
                    :family "Source Sans Pro"
                    :height 120
                    :weight 'normal)

Additionally configure some icon fonts that add various programming related glyphs to the private use area:

;; FontAwesome private use area, e.g. Rebel logo: 
;; https://fortawesome.github.io/Font-Awesome/
(set-fontset-font t '(#xf000 . #xf3ff)
                  (font-spec :family "FontAwesome")
                  nil 'prepend)

;; devicons private use area, e.g. React logo: 
;; http://vorillaz.github.io/devicons/#/main
(set-fontset-font t '(#xe600 . #xe6ff)
                  (font-spec :family "icomoon")
                  nil 'prepend)

Enable font ligatures when running the “Railwaycat” version of emacs that actually supports them.

(when (fboundp #'mac-auto-operator-composition-mode)
  (mac-auto-operator-composition-mode))

Chrome

(setq
 indicate-empty-lines t
 inhibit-startup-screen t
 initial-scratch-message nil
 ring-bell-function 'ignore
 scroll-conservatively 10000
 scroll-preserve-screen-position t
 use-dialog-box nil
 )

(setq-default
 cursor-in-non-selected-windows nil
 )

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

(global-hl-line-mode t)
(global-visual-line-mode 0)
(line-number-mode 0)
(scroll-bar-mode 0)
(show-paren-mode t)
(tool-bar-mode 0)

Indent Guide

Indent Guide draws a vertical line indicator to show the indentation level of the current block. This is useful in programming modes, less so in text modes. It also can require some tweaking to get the face to look right with your theme.

(use-package indent-guide
  :ensure t
  :diminish ""
  :config
  (setq indent-guide-char "")
  (add-hook 'prog-mode-hook #'indent-guide-mode))

Evil

Evil mode is an impressively complete Vim emulation layer for emacs. With evil mode, emacs can act as a better vim than vim itself due to having a much more flexible platform upon which to build an editor ecosystem.

(use-package evil
  :ensure t
  :demand t
  :bind (:map evil-motion-state-map
              ("j" . evil-next-visual-line)
              ("k" . evil-previous-visual-line)
              ("C-j" . evil-scroll-down)
              ("C-k" . evil-scroll-up)
         :map evil-normal-state-map
              ("[ q" . previous-error)
              ("] q" . next-error))
  :init
  (setq evil-mode-line-format '(before . mode-line-front-space)
        evil-want-C-w-in-emacs-state t
        evil-want-Y-yank-to-eol t
        evil-visual-state-cursor 'hollow)
  :config
  (add-hook 'git-commit-mode-hook #'evil-insert-state)
  (evil-mode t))

(use-package evil-commentary
  :ensure t
  :after evil
  :diminish ""
  :config (evil-commentary-mode))

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

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

(use-package evil-lion
  :ensure t
  :after evil
  :config
  (setq evil-lion-left-align-key (kbd "g /"))
  (setq evil-lion-right-align-key (kbd "g \\"))
  (evil-lion-mode))

(use-package evil-org
  :ensure t
  :after org
  :config
  (add-hook 'org-mode-hook 'evil-org-mode)
  (add-hook 'evil-org-mode-hook
            (lambda ()
              (evil-org-set-key-theme))))

Org mode

Package + contrib

Use an up-to-date version of Org mode from the Org package archive, and include the optional contributed features and packages.

(use-package org
  :ensure org-plus-contrib
  :pin org
  :demand t
  :mode ("\\.org$" . org-mode)
  :bind (:map evil-normal-state-map
              ("<SPC> o a" . org-agenda)
              ("<SPC> o b" . org-ido-switchb)
              ("<SPC> o c" . org-capture)
              ("<SPC> o l" . org-store-link)
         :map evil-motion-state-map
              ("[ [" . org-previous-visible-heading)
              ("] ]" . org-next-visible-heading))
  :init
  (setq
        org-completion-use-ido t
        org-deadline-warning-days 3
        org-default-notes-file "~/Resilio/org/gtd.org"
        org-directory "~/Resilio/org/"
        org-ellipsis ""
        org-enforce-todo-dependencies t
        org-export-with-toc nil
        org-hide-leading-stars t
        org-imenu-depth 4
        org-log-done 'time
        org-log-into-drawer t
        org-log-redeadline 'time
        org-log-reschedule 'time
        org-outline-path-complete-in-steps nil
        org-refile-allow-creating-parent-nodes 'confirm
        org-refile-targets '((nil :maxlevel . 9)
                             (org-agenda-files :maxlevel . 9))
        org-refile-use-outline-path t
        org-return-follows-link t
        org-src-fontify-natively t
        org-src-tab-acts-natively t
        org-src-window-setup 'current-window
        org-startup-indented t)
  (set-face-attribute 'org-level-1 nil :height 1.6 :weight 'semi-bold)
  (set-face-attribute 'org-level-2 nil :height 0.875 :weight 'semi-bold)
  (set-face-attribute 'org-level-3 nil :height 0.75)
  (set-face-attribute 'org-level-4 nil :height 0.6875)
  (set-face-attribute 'org-level-5 nil :height 0.625)
  (set-face-attribute 'org-level-6 nil :height 0.625)
  (set-face-attribute 'org-level-7 nil :height 0.625)
  (set-face-attribute 'org-level-8 nil :height 0.625)
  ;; (set-face-attribute 'org-block nil :foreground nil) ; org 9... seems a bug in apropospriate
  :config
  (use-package org-checklist)
  (use-package org-mime))

Agenda

(use-package org-agenda
  :init
  (setq org-agenda-files '("~/Resilio/org/")
        org-agenda-repeating-timestamp-show-all t
        org-agenda-restore-windows-after-quit t
        org-agenda-skip-deadline-if-done t
        org-agenda-skip-scheduled-if-done t
        org-agenda-start-on-weekday nil)
  :config
  (org-add-agenda-custom-command
   '("d" "Deadlines and scheduled work" alltodo ""
     ((org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline))
      (org-agenda-prefix-format '((todo . " %i %-22(org-entry-get nil \"DEADLINE\") %-12:c %s")))
      (org-agenda-sorting-strategy '(deadline-up)))))
  )

Version Control

Magit

Magit is the best interface for git, period.

(use-package magit
  :ensure t
  :bind (:map evil-normal-state-map
              ("<SPC> g b" . magit-blame)
              ("<SPC> g c" . magit-clone)
              ("<SPC> g d" . magit-diff-buffer-file-popup)
              ("<SPC> g l" . magit-log-buffer-file)
              ("<SPC> g s" . magit-status)
              )
  :config
  (use-package evil-magit :ensure t)
  (magit-define-popup-switch 'magit-log-popup
                             ?m "Omit merge commits" "--no-merges")
  (setq magit-completing-read-function #'magit-ido-completing-read))

Git Time Machine

Time travel through git revisions.

(use-package git-timemachine
  :ensure t
  :bind (:map evil-normal-state-map
              ("<SPC> g t" . git-timemachine))
  :config
  ;; see https://bitbucket.org/lyro/evil/issue/511/let-certain-minor-modes-key-bindings
  (evil-make-overriding-map git-timemachine-mode-map 'normal)
  (add-hook 'git-timemachine-mode-hook #'evil-normalize-keymaps))

Ediff

Instruct ediff to not open a separate frame for the diff controls.

(setq ediff-window-setup-function #'ediff-setup-windows-plain)

diffhl

Diffhl will indicated changed hunks in the fringe.

(use-package diff-hl
  :ensure t
  :config (global-diff-hl-mode))

gist

(use-package gist
  :ensure t
  :commands (gist-list gist-region-or-buffer gist-region-or-buffer-private)
  :init
  (setq gist-command-map
        (let ((map (make-sparse-keymap)))
          (define-key map (kbd "l") #'gist-list)
          (define-key map (kbd "c") #'gist-region-or-buffer)
          (define-key map (kbd "C") #'gist-region-or-buffer-private)
          map))
  (fset 'gist-command-map gist-command-map)
  (with-eval-after-load 'evil
    (define-key evil-normal-state-map (kbd "<SPC> g g") 'gist-command-map)))

Browse at Remote

Support browsing to files on github/gitlab/etc.

(use-package browse-at-remote
  :ensure t
  :bind (:map evil-normal-state-map
              ("<SPC> g h" . browse-at-remote)))

Completion

Ido

Ido is a completion system included with Emacs.

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

Ido-ubiquitous adds ido to many places that use completing-read like Magit and Projectile.

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

Use flx-ido to get fuzzy matching.

(use-package flx-ido
  :ensure t
  ;; disabled because S...L...O...W...
  :disabled t
  :after ido
  :config (flx-ido-mode t))

By default Ido shows completion candidates inline, but ido-vertical-mode turns that into a vertical list.

(use-package ido-vertical-mode
  :ensure t
  :after ido
  :init
  (setq ido-vertical-indicator "─►")
  :config
  (defun jafo/ido-setup-hook ()
    (define-key ido-completion-map (kbd "C-j") #'ido-next-match)
    (define-key ido-completion-map (kbd "C-k") #'ido-prev-match))
  (add-hook 'ido-setup-hook #'jafo/ido-setup-hook)
  (setq ido-vertical-define-keys 'C-n-and-C-p-only)
  (ido-vertical-mode t))

Smex integrates completion into M-x.

(use-package smex
  :ensure t
  :disabled t
  :bind (("M-x" . smex)
         ("M-X" . smex-major-mode-commands)))

Integrating ido with imenu makes for easier imenu navigation.

(use-package idomenu
  :ensure t
  :disabled t
  :after ido
  :bind (:map evil-normal-state-map
              ("<SPC> i" . idomenu)))

Ivy

(use-package ivy
  :ensure t
  :diminish ivy-mode
  :bind (:map ivy-minibuffer-map
              ("C-j" . ivy-next-line)
              ("C-k" . ivy-previous-line))
  :init
  (setq ivy-count-format ""
        ivy-format-function #'ivy-format-function-arrow
        ivy-use-virtual-buffers t
        ivy-re-builders-alist '((t . ivy--regex-fuzzy)))
  :config
  (ivy-mode t)
  (with-eval-after-load 'magit
    (setq magit-completing-read-function 'ivy-completing-read))
  (with-eval-after-load 'projectile
    (setq projectile-completion-system 'ivy)))

(use-package swiper
  :ensure t)

(use-package ivy-hydra
  :ensure t)

(use-package counsel
  :ensure t
  :bind (("M-x" . counsel-M-x)
         ("C-x C-f" . counsel-find-file)
         ("C-h f" . counsel-describe-function)
         ("C-h v" . counsel-describe-variable)
         :map evil-normal-state-map
         ("<SPC> i" . counsel-imenu)))

(use-package counsel-projectile
  :ensure t
  :after projectile
  :bind (:map projectile-command-map
              ("/" . counsel-projectile-rg))
  :config (counsel-projectile-on))

Company

Company provides in-buffer completion for various text and programming modes via pluggable backends.

(use-package company
  :ensure t
  :diminish ""
  :config
  (define-key company-active-map (kbd "C-n") #'company-select-next)
  (define-key company-active-map (kbd "C-j") #'company-select-next)
  (define-key company-active-map (kbd "C-p") #'company-select-previous)
  (define-key company-active-map (kbd "C-k") #'company-select-previous)
  (setq company-idle-delay 0.2
        company-dabbrev-downcase nil    ; pretty sure company has a bug in the default
        company-require-match nil
        company-selection-wrap-around t
        company-tooltip-align-annotations t)
  (global-company-mode t))

Company quickhelp can show inline documentation for company completion candidates.

(use-package company-quickhelp
  :ensure t
  :after company
  :config (company-quickhelp-mode t))

Yasnippet

(use-package yasnippet
  :ensure t
  :diminish yas-minor-mode
  :config
  (setq yas-prompt-functions '(yas-completing-prompt))
  (yas-global-mode t))

Project and File Management

Projectile

Projectile adds project management and navigation.

(use-package projectile
  :ensure t
  :init
  (setq projectile-mode-line '(:eval (format " P⟨%s" (projectile-project-name))))
  :config
  (with-eval-after-load 'evil
    (define-key evil-normal-state-map (kbd "<SPC> p") 'projectile-command-map))
  (projectile-global-mode))

Add ripgrep support to projectile.

(use-package projectile-ripgrep
  :ensure t
  :after projectile
  :bind (:map projectile-command-map
              ("s r" . projectile-ripgrep)))

macOS trash

Delete files by moving them to the macOS trash folder.

(use-package osx-trash
  :ensure t
  :config (osx-trash-setup))

dired

Configure and extend the built-in file manager, dired.

(use-package dired
  :after evil
  :bind (:map evil-motion-state-map
              ("-" . dired-jump))
  :init
  (setq dired-recursive-copies 'always
        dired-recursive-deletes 'top)
  :config
  (evil-define-key 'normal dired-mode-map "-" 'dired-up-directory))

Doing additional configuration when gnu ls is available.

(when (executable-find "gls")
  (setq insert-directory-program "gls"
        dired-listing-switches "-lFAGh1v"
        dired-use-ls-dired t))

Writing and Editing

Text Settings

(auto-save-mode 0)
(global-auto-revert-mode t)             ; automatically read changed files

(setq-default indent-tabs-mode nil)     ; use spaces by default
(setq require-final-newline t           ; always end files with a newline
      sentence-end-double-space nil)

(add-hook 'text-mode-hook #'turn-on-auto-fill)

Spell Checking

Enable flyspell to do spellchecking automatically.

(use-package flyspell
  :diminish ""
  :config
  (add-hook 'text-mode-hook 'flyspell-mode)
  (add-hook 'prog-mode-hook 'flyspell-prog-mode))

EditorConfig

This allows Emacs to read EditorConfig settings if the exist.

(use-package editorconfig
  :ensure t
  :diminish ""
  :config (editorconfig-mode t))

Markdown

(use-package markdown-mode
  :ensure t
  :mode (("\\.md$" . markdown-mode)
         ("\\.markdown$" . markdown-mode))
  :config
  ;; embiggen headers 
  (set-face-attribute 'markdown-header-face-1 nil :height 1.6)
  (set-face-attribute 'markdown-header-face-2 nil :height 1.4)
  (set-face-attribute 'markdown-header-face-3 nil :height 1.2)
  (set-face-attribute 'markdown-header-face-4 nil :height 1.1))

(use-package evil-markdown
  :load-path "~/.emacs.d/vendor/evil-markdown")

Pandoc

(use-package pandoc-mode
  :ensure t
  :commands pandoc-mode
  :init (add-hook 'markdown-mode-hook #'pandoc-mode))

Programming

General

Bug Reference Mode

Use .dir-locals.el to set bug-reference-bug-regexp as needed.

(add-hook 'text-mode-hook #'bug-reference-mode)
(add-hook 'prog-mode-hook #'bug-reference-prog-mode)

Compilation

(setq compilation-always-kill t
      compilation-ask-about-save nil
      compilation-read-command nil
      compilation-scroll-output 'always)

(require 'ansi-color)
(defun jafo/colorize-compilation-buffer ()
  (let ((inhibit-read-only t))
    (ansi-color-apply-on-region compilation-filter-start (point))))
(add-hook 'compilation-filter-hook #'jafo/colorize-compilation-buffer)

(with-eval-after-load 'compile
  (add-to-list 'compilation-error-regexp-alist 'xcpretty)
  (add-to-list 'compilation-error-regexp-alist-alist
               '(xcpretty
                 "^\\(?:\\(\u26a0\ufe0f\\|\\[!\\]\\)\\|\\(?:\u274c\\|\\[x\\]\\)\\)\\s-+\\([^:]+?\\):\\([0-9]+\\):\\([0-9]+\\): .*"
                 2 3 4 nil 2)))

Rest Client

Rest client allows http debugging in emacs.

(use-package restclient
  :ensure t
  :mode (("\\.http$" . restclient-mode)))

Add autocompletion for http headers.

(use-package company-restclient
  :ensure t
  :after restclient
  :config
  (with-eval-after-load 'company
    (add-to-list 'company-backends #'company-restclient)))

Flycheck

Flycheck provides real time syntax checking. It supports many syntax checkers and linters out of the box and is highly extensible. While not strictly a programming-specific tool (it supports text checking and markdown linters, etc) it is included under the programming heading since it is primarily used to detect syntax errors in source code.

(use-package flycheck
  :ensure t
  :init
  (setq flycheck-mode-line-prefix "")
  :config
  (setq flycheck-display-errors-delay 0.5
        flycheck-display-errors-function #'flycheck-display-error-messages-unless-error-list)
  (add-hook 'after-init-hook #'global-flycheck-mode))

Use flycheck-package for linting emacs packages.

(use-package flycheck-package
  :ensure t
  :after flycheck
  :config (flycheck-package-setup))

c / c++ / objc

base settings

(add-hook 'c-mode-common-hook
          (lambda ()
            (c-set-offset 'innamespace 0)
            (setq c-basic-offset 4)))

;; treat .mm files as objc. alas there is no objc++-mode
(add-to-list 'auto-mode-alist '("\\.mm\\'" . objc-mode))

;; try to detect objc headers automatically
(add-to-list 'magic-mode-alist
             `(,(lambda ()
                  (and (string= (file-name-extension buffer-file-name) "h")
                       (re-search-forward "@\\(?:\\<interface\\>\\|\\<protocol\\>\\)" magic-mode-regexp-match-limit t)))
               . objc-mode))

clang-format

Requires that clang-format be installed via brew or other method.

(use-package clang-format
  :ensure t
  :commands (clang-format-region clang-format-buffer)
  :init
  (evil-define-key 'visual c-mode-base-map (kbd "g =") #'clang-format-region)
  (evil-define-key 'normal c-mode-base-map (kbd "g =") #'clang-format-buffer))

cmake

(use-package cmake-mode
  :ensure t)

rtags

RTags is an indexer based on clang that provides autocompletion and symbol navigation for c/c++/objc. The package is installed via homebrew, so refer to its elisp directory under /usr/local/share instead of requesting installation from MELPA.

Using RTags necessitates the creation of a compile_commands.json file for each project. For Xcode projects the best way to do this is to install xcpretty and filter the output of xcodebuild through it.

(use-package rtags
  :ensure t
  :config
  (use-package flycheck-rtags
    :ensure t)
  (setq rtags-autostart-diagnostics t
        rtags-completions-enabled t)
  (rtags-enable-standard-keybindings)
  (rtags-diagnostics)
  (with-eval-after-load 'company
    (push 'company-rtags company-backends)))

Djinni

(use-package djinni-mode
  :load-path "~/Source/djinni-mode"
  :config
  (with-eval-after-load 'flycheck
    (flycheck-define-checker djinni
      "A simple syntax checker for djinni IDL files.
Requires the `djinni` executable to be in the executable path."
      :command ("djinni"
                "--skip-generation" "true"
                "--idl" source-original)
      :error-patterns
      ((error line-start (file-name) " (" line "." column "): " (message) line-end))
      :modes (djinni-mode))
    (add-to-list 'flycheck-checkers 'djinni 'append)))

Haskell

  (use-package haskell-mode
    :ensure t
    :pin melpa-stable)

** Rust


  (use-package rust-mode
    :ensure t
    :config
    (setq rust-format-on-save t)
    (use-package racer
      :ensure t)
    (use-package company-racer
      :ensure t)
    (use-package flycheck-rust
      :ensure t
      :after flycheck))

About

an emacs config

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published