Files
configs/.emacs.d/init.org
2019-02-19 17:22:40 +00:00

11 KiB

  (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)

Setup use-package and configure it to always install missing packages.

  (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)

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)
  (column-number-mode t)
  (setq inhibit-splash-screen t)
  (menu-bar-mode 0)
  (tool-bar-mode 0)
  (scroll-bar-mode 0)
  (savehist-mode t)

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)'

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.

(use-package winner
  :init
  (winner-mode))

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.

  (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))

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)
    (use-package org-journal
      :bind (("C-c C-j" . org-journal-new-entry)))
  (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"))))

Install magit, and explicitly call out with-editor as well, even though its a requirement for magit.

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

  (use-package with-editor)

Multi-term is useful for having multiple terminal buffers.

  (use-package multi-term
	:config
	(add-hook 'term-mode-hook
			  (lambda ()
				(dolist
					(bind
					 '(("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-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)))))

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))
    :init (setq helm-split-window-inside-p t))

Install projectile for managing buffers within projects.

    (use-package projectile
      :config (projectile-mode))

Install ggtags. It requires that the "gtags" executable be in the users PATH, and is installable on Ubuntu as "global".

  (use-package ggtags)

Use helm completions for projectile, multi-term, and projectile.

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

Add helm-swoop for searching across multiple buffers.

  (use-package helm-swoop)
  (use-package helm-purpose
      :bind (("C-c b" . helm-purpose-switch-buffer-with-purpose)))

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))

Scroll buffers so that the cursor doesn't get too close to the top or bottom of the window.

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

Monokai theme is my theme of choice.

  (use-package monokai-theme)

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))
  (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))

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)
    (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)
  (defconst my-cc-style
    '("linux"
      (c-offsets-alist . ((innamespace . [0])))))

  (c-add-style "my-cc-style" my-cc-style)
  (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)'

Because ChomeOS maps M-backspace to delete.

  (global-set-key (kbd "<deletechar>") 'backward-kill-word)

Configure desktop-save mode to restore lost state on emacs exit.

  (desktop-save-mode 1)
  (add-to-list 'desktop-modes-not-to-save 'dired-mode)
  (add-to-list 'desktop-modes-not-to-save 'term-mode)

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

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

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.

  (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)
  ;; 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))))))
  (use-package clang-format
    :commands clang-format clang-format-buffer clang-format-region)
   (add-to-list 'auto-mode-alist '("\\.ino\\'" . c++-mode))
   (add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
  (use-package yaml-mode)
  (use-package markdown-mode)
  (use-package adaptive-wrap)

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.
  (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))