#+BEGIN_SRC emacs-lisp (require 'package) (setq package-enable-at-startup nil) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")) (package-initialize) #+END_SRC Setup use-package and configure it to always install missing packages. #+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 Automatically update packages one per week. #+BEGIN_SRC emacs-lisp (use-package auto-package-update :ensure t :config (setq auto-package-update-delete-old-versions t auto-package-update-interval 7) (auto-package-update-maybe)) #+END_SRC 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) (column-number-mode t) (setq inhibit-splash-screen t) (menu-bar-mode 0) (tool-bar-mode 0) (scroll-bar-mode 0) (savehist-mode t) #+END_SRC 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 Winner-mode keeps a history of window configurations. Handy when magit decides to blow away, or I hit the wrong key and blow away my windows. #+BEGIN_SRC emacs-lisp (use-package winner :init (winner-mode)) #+END_SRC Add Purpose for binding a "purpose" to a window, such as "terminal" or "edit", so only buffers with that purpose may end up in that window. This helps keep things organized without too much manual tweaking. You can also save and load window layouts and purposes. #+BEGIN_SRC emacs-lisp (use-package window-purpose :bind (("C-c p s" . purpose-set-window-purpose)) :init (purpose-mode t) ;(purpose-x-kill-setup) ;; This seems to cause slowness in helm (purpose-x-magit-multi-on)) #+END_SRC 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 #+BEGIN_SRC emacs-lisp (use-package org-journal :bind (("C-c C-j" . org-journal-new-entry))) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package org :bind (("C-c c" . org-capture) ("C-c l" . org-store-link)) :config (setq org-capture-templates '(("b" "Bookmark" entry (file+headline "~/notes/bookmarks.org" "Unsorted") "* %T %^{Title}\n\n Source: %u, %c\n\n %i")))) #+END_SRC Install magit, and explicitly call out with-editor as well, even though its a requirement for magit. #+BEGIN_SRC emacs-lisp (use-package magit :config (setq magit-bury-buffer-function 'magit-mode-quit-window)) (use-package with-editor) #+END_SRC Multi-term is useful for having multiple terminal buffers. #+BEGIN_SRC emacs-lisp (use-package multi-term :config (add-hook 'term-mode-hook (lambda () (dolist (bind '(("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))) (add-to-list 'term-bind-key-alist bind))))) #+END_SRC 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)) :init (setq helm-split-window-inside-p t)) #+END_SRC Install projectile for managing buffers within projects. #+BEGIN_SRC emacs-lisp (use-package projectile :config (projectile-mode)) #+END_SRC Install ggtags. It requires that the "gtags" executable be in the users PATH, and is installable on Ubuntu as "global". #+BEGIN_SRC emacs-lisp (use-package ggtags) #+END_SRC Use helm completions for projectile, multi-term, and projectile. #+BEGIN_SRC emacs-lisp (use-package helm-gtags) (use-package helm-mt :bind (("C-c t" . helm-mt))) (use-package helm-projectile) #+END_SRC Add helm-swoop for searching across multiple buffers. #+BEGIN_SRC emacs-lisp (use-package helm-swoop) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package helm-purpose :bind (("C-c b" . helm-purpose-switch-buffer-with-purpose))) #+END_SRC 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 Scroll buffers so that the cursor doesn't get too close to the top or bottom of the window. #+BEGIN_SRC emacs-lisp (use-package smooth-scrolling :config (smooth-scrolling-mode t)) #+END_SRC Monokai theme is my theme of choice. #+BEGIN_SRC emacs-lisp (use-package monokai-theme) #+END_SRC 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 #+BEGIN_SRC emacs-lisp (use-package ace-window :bind* ("C-x o" . ace-window) :init (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)) (setq aw-scope 'frame)) #+END_SRC 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) (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 (defconst my-cc-style '("linux" (c-offsets-alist . ((innamespace . [0]))))) (c-add-style "my-cc-style" my-cc-style) #+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 Because ChomeOS maps M-backspace to delete. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "") 'backward-kill-word) #+END_SRC Configure desktop-save mode to restore lost state on emacs exit. #+BEGIN_SRC emacs-lisp (desktop-save-mode 1) (add-to-list 'desktop-modes-not-to-save 'dired-mode) (add-to-list 'desktop-modes-not-to-save 'term-mode) #+END_SRC 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 Cycling forward or backward one buffer is handy when using slighty more buffers than windows, but helm buffers (and others) can really add a lot of unhelpful buffers. Instead, filter out "boring" buffers. Boring buffers can still be found via helm/ibuffer. #+BEGIN_SRC emacs-lisp (defun buffer-is-boring (buffer) (or (and (string-match-p "^\*" (buffer-name buffer))) (string-match-p "^magit" (buffer-name buffer)))) (defun buffer-iterate (iter-fun) (let ((bread-crumb (buffer-name))) (funcall iter-fun) (while (and (buffer-is-boring (current-buffer)) (not (equal bread-crumb (buffer-name)))) (funcall iter-fun)))) (defun my-next-buffer () (interactive) (buffer-iterate 'next-buffer)) (defun my-previous-buffer () (interactive) (buffer-iterate 'previous-buffer)) (global-set-key [remap next-buffer] 'my-next-buffer) (global-set-key [remap previous-buffer] 'my-previous-buffer) #+END_SRC #+BEGIN_SRC emacs-lisp ;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file (defun rename-file-and-buffer (new-name) "Renames both current buffer and file it's visiting to NEW-NAME." (interactive "sNew name: ") (let ((name (buffer-name)) (filename (buffer-file-name))) (if (not filename) (message "Buffer '%s' is not visiting a file!" name) (if (get-buffer new-name) (message "A buffer named '%s' already exists!" new-name) (progn (rename-file filename new-name 1) (rename-buffer new-name) (set-visited-file-name new-name) (set-buffer-modified-p nil)))))) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package clang-format :commands clang-format clang-format-buffer clang-format-region) #+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 #+BEGIN_SRC emacs-lisp (use-package yaml-mode) (use-package markdown-mode) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package adaptive-wrap) #+END_SRC Add cquery for completions. This requires. 1. The cquery is checked out into ~/software/cquery/ and built. 2. The project has a .cquery file at its root, which specifies all of the includes paths. #+BEGIN_SRC emacs-lisp (defun cquery//enable () (condition-case nil (lsp) (user-error nil))) (use-package cquery :commands lsp :after (:any c-mode c++-mode objc-mode) :config (setq cquery-executable "~/software/cquery/build/release/bin/cquery") (add-hook 'c-mode-hook #'cquery//enable) (add-hook 'c++-mode-hook #'cquery//enable) ;; Do not use projectile for root-matching, since we have multiple git projects that are compiled together (setq cquery-project-root-matchers '(cquery-project-roots-matcher "compile_commands.json" ".cquery" "build/compile_commands.json")) (push 'company-lsp company-backends) ) (use-package company :init (add-hook 'c-mode-hook company-mode) (add-hook 'c++-mode-hook company-mode) ) (use-package company-lsp :init (push 'company-lsp company-backends)) #+END_SRC