Files
configs/.emacs.d/init.org

11 KiB

Overview

This is my personal emacs configuration, which enables my workflow. Highlights include:

  • helm for completion
  • projectile for project interaction
  • magit for an emacs-based git porcelain
  • org-mode for note organization and capture

Package Manager Bootstrapping

Setting Repositories

First, use package to set up additional repos, which will be leveraged later.

  (require 'package)
  (setq package-enable-at-startup nil)
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
  (add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/"))
  (package-initialize)

use-package

Setup use-package and configure it to always install missing packages. This means that emacs will be slow to boot, as it reaches out to the network to pull down updated versions. I tend to run emacs as a daemon, so this doesn't happen too often.

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

  (eval-when-compile
    (require 'use-package))
  (setq use-package-always-ensure t)

Basic Configuration

Ensure that emacs doesn't add a custom file which will add configuration that isn't in described this file.

  (setq custom-file "/dev/null")

Configure some startup parameters.

  (line-number-mode t) ;; enable line numbers
  (column-number-mode t) ;; enable column numbers
  (setq inhibit-splash-screen t) ;; disable the splash screen on boot
  (menu-bar-mode 0) ;; disable the menu bar
  (tool-bar-mode 0) ;; disable the tool bar
  (if (window-system)
      (scroll-bar-mode nil)) ;; disable scroll bars

Deleting

By default, if you a region selected and hit "backspace" it does not actually delete the region, which is weird to me. This changes that behavior.

  (setq delete-active-region t)
ChomeOS

On ChromeOS, M-DEL is mapped to <deletechar>, so remap fix up.

  ;; TODO: Figure out how to make this conditional on ChromeOS
  (global-set-key (kbd "<deletechar>") 'backward-kill-word)'

Backups

Enable automatic file saves to a location that won't clutter source directories.

  (savehist-mode t)
  (setq backup-directory-alist '(("." . "~/.emacs_backups")))

Minions Mode (Hide minor modes)

The modeline can get cluttered with lots of minor modes. Use minions-mode to diminish all of the minor modes, and leave room for more important context like major mode, line number, and git branch.

(use-package minions
  :init (minions-mode t))

Theme

Monokai theme is my theme of choice.

  (use-package monokai-theme)
  ;; This is busted when the font isn't installed (i.e. on MacOS)
  ;; (set-frame-font "Ubuntu Mono-12" nil t)

Navigation

Don't use the arrow keys, try to stay on the home row.

  (mapc 'global-unset-key '([left] [right] [up] [down] [C-down] [C-up] [C-right] [C-left]))

Use zoom-window to enable full-screening a single window, briefly.

  (use-package zoom-window
    :bind* ("C-c z z" . zoom-window-zoom))

ace-window makes it easy to jump between windows. I usually have 3+, so this is nice.

  (use-package ace-window
    :bind ("C-x o" . ace-window)
    :custom
      (aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
      (aw-scope 'frame))

smooth-scrolling makes emacs scroll nicely and keeps the buffer in a sane place when the point moves. bottom of the window.

  (use-package smooth-scrolling
    :config (smooth-scrolling-mode t))

Replacement

I use replace-string enough to deserve it's own binding.

  (global-set-key (kbd "C-c r") 'replace-string)

Org-mode

Org-mode is great. As a format, it's fine- but it's emacs integration is powerful

Enable org-capture, which is intended for jotting down quick notes. I don't use it enough, so I haven't fleshed out useful templates yet.

  (use-package org
    :bind (("C-c o c" . org-capture)
	   ("C-c o l" . org-store-link))
    :custom (initial-major-mode 'org-mode)
    (org-src-tab-acts-natively t)
    (org-confirm-babel-evaluate nil)
    (org-capture-templates
     '(("b" "Bookmark" entry
	(file+headline "~/notes/bookmarks.org" "Unsorted")
	"* %T %^{Title}\n\n Source: %u, %c\n\n %i")))
    :init (org-babel-do-load-languages 'org-babel-load-languages
				       '((shell . t)
					 (ruby . t)
					 (python . t)
					 (C . t))))

org-journal

On the other hand, I do use org-journal for notetaking and searching through my notes.

  (use-package org-journal
    :bind (("C-c o j c" . org-journal-new-entry)
           ("C-c o j s" . org-journal-search-forever)))

Development Tools

General Emacs

When doing compilation, always jump to the first error to reduce development cycle times.

  (setq compilation-auto-jump-to-first-error t)

Dired

dired-tree allows expanding directories in dired buffers. This is nice for pinning a dired buffer to the side to use as a file browser.

  (use-package dired-tree)

dired is great, but too detailed by default. Disable

  (use-package dired
    :hook ((dired . dired-hide-details-mode)
           (dired . (lambda (toggle-truncate-lines t))))
    :bind ("<TAB>" . dired-subtree-toggle))

Git (magit)

Install magit, the emacs porcelain for git.

    (use-package magit
      :custom (magit-bury-buffer-function 'magit-mode-quit-window))

    (use-package with-editor
      :init (add-hook 'shell-mode-hook  'with-editor-export-editor)
      (add-hook 'term-exec-hook   'with-editor-export-editor)
      (add-hook 'eshell-mode-hook 'with-editor-export-editor))

Terminals (multi-Term)

Multi-term is useful for having multiple terminal buffers.

  (use-package multi-term
    :custom
    (term-bind-key-alist
     '(("C-<backspace>" . term-send-backward-kill-word)
       ("C-<delete>" . term-send-forward-kill-word)
       ("C-<left>" . term-send-backward-word)
       ("C-<right>" . term-send-forward-word)
       ("C-c C-j" . term-line-mode)
       ("C-c C-k" . term-char-mode)
       ("C-c C-c" . term-interrupt-subjob)
       ("C-r" . term-send-reverse-search-history)
       ("C-v" . scroll-up)
       ("C-y" . term-paste)
       ("C-z" . term-stop-subjob)
       ("C-p" . term-send-prior)
       ("C-n" . term-send-next)
       ("M-p" . scroll-up-line)
       ("M-n" . scroll-down-line)
       ("M-DEL" . term-send-backward-kill-word)
       ("M-d" . term-send-forward-kill-word)
       ("M-r" . isearch-backward)
       ("M-s" . term-send-forward-kill-word))))

File/command completion (helm)

Install helm, a completion framework, and install its functions over some of the usual emacs keybinds.

  (use-package helm
    :config (helm-mode)
    :bind (("M-x" . helm-M-x)
           ("C-x b" . helm-mini)
           ("C-x C-b" . helm-buffers-list)
           ("M-y" . helm-show-kill-ring))
    :custom (helm-split-window-inside-p t))

helm-gtags works nicely for finding tags/references. Though it has confused me many times, helm-gtags does not depend on ggtags.

    (use-package helm-gtags)

helm-mt is integrates multi-term with helm. It works nicely to label and search multiple sesions.

    (use-package helm-mt
      :bind (("C-c t" . helm-mt)))

Helm-projectile integrates helm with projectile, which makes it very easy to search for files in a given project.

    (use-package helm-projectile
      :bind (("C-c p f" . helm-projectile))
      :init (add-to-list 'helm-mini-default-sources 'helm-projectile-sources-list)
      (helm-projectile-on))
  (use-package helm-purpose
      :bind (("C-c b" . helm-purpose-switch-buffer-with-purpose)))

Code completion (company)

Company is great for doing completion. It probably deserves more configuration than I'm giving it.

  (use-package company
    :init (global-company-mode))

Projects (projectile)

Install projectile for managing buffers within projects.

    (use-package projectile
      :config (projectile-mode)
      :bind (("C-c p c" . projectile-compile-project)
             ("C-c p t" . projectile-test-project))
      :custom (projectil-completion-system 'helm))

Licenses (lice)

lice makes it easy to drop the MIT license into all of my code.

  (use-package lice
    :custom (lice:copyright-holder "Max Regan")
    (lice:default-license "mit" "MIT is my default license"))

TODO: Fix this. It seems like this breaks syntax highlighting.

Use the builtin hs-minor-mode to hide the initial comment in code files- usually its a big license notice.

;; (add-hook 'prog-mode-hook #'hs-minor-mode)
;; (add-hook 'hs-minor-mode-hook 'hs-hide-initial-comment-block)

Whitespace (ws-butler)

Use ws-butler to automatically clean up any trailing whitespace I leave behind. Other lines are left untouched.

  (use-package ws-butler
    :config (ws-butler-global-mode t))

Python (elpy)

(setq python-shell-interpreter "python3")
(use-package elpy
  :init (elpy-enable))

C/C++

TBD

Other languages

Add major modes for other languages/filetypes that I work with on occasion.

  (use-package yaml-mode)
  (use-package markdown-mode)

Uncategorized

C-mode configurations. Set tab width to 4, since that's what I'm used to.

  (defun my-c-common-hook()
    (setq c-hungry-delete-key t)
    (setq adaptive-wrap-extra-indent c-basic-offset)
    (adaptive-wrap-prefix-mode t)
    (toggle-word-wrap t))

  (add-hook 'c-mode-common-hook 'my-c-common-hook)
    (setq-default c-basic-offset 4
                  tab-width 4
                  indent-tabs-mode nil)
  (use-package highlight-doxygen
    :init (highlight-doxygen-global-mode))

Add the ability to toggle a buffer as dedicated to its window, to prevent other buffers from popping into that window. This comes from StackOverflow.

  (defun toggle-window-dedicated ()
    "Control whether or not Emacs is allowed to display another
  buffer in current window."
    (interactive)
    (message
     (if (let (window (get-buffer-window (current-buffer)))
           (set-window-dedicated-p window (not (window-dedicated-p window))))
         "%s is dedicated to the window."
       "%s is released from the window.")
     (current-buffer)))

  (global-set-key (kbd "C-c d") 'toggle-window-dedicated)'
   (add-to-list 'auto-mode-alist '("\\.ino\\'" . c++-mode))
   (add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))