#+PROPERTY: header-args :results silent * 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. #+BEGIN_SRC emacs-lisp (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) #+END_SRC *** =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. #+BEGIN_SRC emacs-lisp (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) #+END_SRC ** Basic Configuration Ensure that emacs doesn't add a custom file which will add configuration that isn't in described this file. #+BEGIN_SRC emacs-lisp (setq custom-file "/dev/null") #+END_SRC Configure some startup parameters. #+BEGIN_SRC emacs-lisp (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 (scroll-bar-mode 0) ;; disable scroll bars #+END_SRC *** 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. #+BEGIN_SRC emacs-lisp (setq delete-active-region t) #+END_SRC **** ChomeOS On ChromeOS, M-DEL is mapped to , so remap fix up. #+BEGIN_SRC emacs-lisp ;; TODO: Figure out how to make this conditional on ChromeOS (global-set-key (kbd "") 'backward-kill-word)' #+END_SRC *** Backups Enable automatic file saves to a location that won't clutter source directories. #+BEGIN_SRC emacs-lisp (savehist-mode t) (setq backup-directory-alist '(("." . "~/.emacs_backups"))) #+END_SRC *** 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. #+BEGIN_SRC emacs-lisp (use-package minions :init (minions-mode t)) #+END_SRC *** Theme Monokai theme is my theme of choice. #+BEGIN_SRC emacs-lisp (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) #+END_SRC *** Navigation Don't use the arrow keys, try to stay on the home row. #+BEGIN_SRC emacs-lisp (mapc 'global-unset-key '([left] [right] [up] [down] [C-down] [C-up] [C-right] [C-left])) #+END_SRC Use zoom-window to enable full-screening a single window, briefly. #+BEGIN_SRC emacs-lisp (use-package zoom-window :bind* ("C-c z z" . zoom-window-zoom)) #+END_SRC =ace-window= makes it easy to jump between windows. I usually have 3+, so this is nice. #+BEGIN_SRC emacs-lisp (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)) #+END_SRC =smooth-scrolling= makes emacs scroll nicely and keeps the buffer in a sane place when the point moves. bottom of the window. #+BEGIN_SRC emacs-lisp (use-package smooth-scrolling :config (smooth-scrolling-mode t)) #+END_SRC *** Replacement I use replace-string enough to deserve it's own binding. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-c r") 'replace-string) #+END_SRC ** 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. #+BEGIN_SRC emacs-lisp (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)))) #+END_SRC *** org-journal On the other hand, I do use org-journal for notetaking and searching through my notes. #+BEGIN_SRC emacs-lisp (use-package org-journal :bind (("C-c o j c" . org-journal-new-entry) ("C-c o j s" . org-journal-search-forever))) #+END_SRC ** Development Tools *** General Emacs When doing compilation, always jump to the first error to reduce development cycle times. #+BEGIN_SRC emacs-lisp (setq compilation-auto-jump-to-first-error t) #+END_SRC *** 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. #+BEGIN_SRC emacs-lisp (use-package dired-tree) #+END_SRC =dired= is great, but too detailed by default. Disable #+BEGIN_SRC emacs-lisp (use-package dired :hook ((dired . dired-hide-details-mode) (dired . (lambda (toggle-truncate-lines t)))) :bind ("" . dired-subtree-toggle)) #+END_SRC *** Git (=magit=) Install magit, the emacs porcelain for git. #+BEGIN_SRC emacs-lisp (use-package magit :custom (magit-bury-buffer-function 'magit-mode-quit-window)) (use-package with-editor) #+END_SRC *** Terminals (=multi-Term=) Multi-term is useful for having multiple terminal buffers. #+BEGIN_SRC emacs-lisp (use-package multi-term :custom (term-bind-key-alist '(("C-" . term-send-backward-kill-word) ("C-" . term-send-forward-kill-word) ("C-" . term-send-backward-word) ("C-" . term-send-forward-word) ("C-c C-j" . term-line-mode) ("C-c C-k" . term-char-mode) ("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)))) #+END_SRC *** File/command completion (=helm=) Install helm, a completion framework, and install its functions over some of the usual emacs keybinds. #+BEGIN_SRC emacs-lisp (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)) #+END_SRC =helm-gtags= works nicely for finding tags/references. Though it has confused me many times, =helm-gtags= does not depend on =ggtags=. #+BEGIN_SRC emacs-lisp (use-package helm-gtags) #+END_SRC =helm-mt= is integrates =multi-term= with helm. It works nicely to label and search multiple sesions. #+BEGIN_SRC emacs-lisp (use-package helm-mt :bind (("C-c t" . helm-mt))) #+END_SRC =Helm-projectile= integrates helm with projectile, which makes it very easy to search for files in a given project. #+BEGIN_SRC emacs-lisp (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)) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package helm-purpose :bind (("C-c b" . helm-purpose-switch-buffer-with-purpose))) #+END_SRC *** Code completion (=company=) Company is great for doing completion. It probably deserves more configuration than I'm giving it. #+BEGIN_SRC emacs-lisp (use-package company :init (global-company-mode)) #+END_SRC *** Projects (=projectile=) Install projectile for managing buffers within projects. #+BEGIN_SRC emacs-lisp (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)) #+END_SRC *** Licenses (=lice=) =lice= makes it easy to drop the MIT license into all of my code. #+BEGIN_SRC emacs-lisp (use-package lice :custom (lice:copyright-holder "Max Regan") (lice:default-license "mit" "MIT is my default license")) #+END_SRC Use the builtin =hs-minor-mode= to hide the initial comment in code files- usually its a big license notice. #+BEGIN_SRC emacs-lisp (add-hook 'prog-mode-hook #'hs-minor-mode) (add-hook 'hs-minor-mode-hook 'hs-hide-initial-comment-block) #+END_SRC *** Whitespace (=ws-butler=) Use =ws-butler= to automatically clean up any trailing whitespace I leave behind. Other lines are left untouched. #+BEGIN_SRC emacs-lisp (use-package ws-butler :config (ws-butler-global-mode t)) #+END_SRC *** Python (=elpy=) #+BEGIN_SRC emacs-lisp (setq python-shell-interpreter "python3") #+END_SRC #+BEGIN_SRC emacs-lisp (use-package elpy :init (elpy-enable)) #+END_SRC *** C/C++ TBD *** Other languages Add major modes for other languages/filetypes that I work with on occasion. #+BEGIN_SRC emacs-lisp (use-package yaml-mode) (use-package markdown-mode) #+END_SRC * Uncategorized C-mode configurations. Set tab width to 4, since that's what I'm used to. #+BEGIN_SRC emacs-lisp (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) #+END_SRC #+BEGIN_SRC emacs-lisp (setq-default c-basic-offset 4 tab-width 4 indent-tabs-mode nil) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package highlight-doxygen :init (highlight-doxygen-global-mode)) #+END_SRC Add the ability to toggle a buffer as dedicated to its window, to prevent other buffers from popping into that window. This comes from [[https://emacs.stackexchange.com/questions/2189][StackOverflow]]. #+BEGIN_SRC emacs-lisp (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)' #+END_SRC #+BEGIN_SRC emacs-lisp (add-to-list 'auto-mode-alist '("\\.ino\\'" . c++-mode)) (add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode)) #+END_SRC