11 KiB
Overview
This is my personal emacs configuration, which enables my workflow. Highlights include:
helmfor completionprojectilefor project interactionmagitfor an emacs-basedgitporcelainorg-modefor 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)
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"))
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))