I’ve been using Emacs extensively since the summer of 2013, and along the way I’ve become accustomed to many different tweaks for it.
This configuration uses the use-package package from John Wiegley, which is a fantastic way to manage package configurations.
If you see any keybindings that seem weird to you, it’s probably because I type with the Dvorak keyboard layout, so things’ll probably seem strange on other keyboard layouts. I may assign a keybinding just because it’s more on convenient on Dvorak. Though for the most part, I try to follow Emacs and assign bindings by mnemonics, would should make sense for any layout.
On macOS, homebrew is an easy way to install emacs.
Here’s what the parameters means.
--with-cocoa
- installs emacs with the macOS GUI version
--with-imagemagick
- installs emacs with imagemagick support for image processing
--with-gnutls
- installs emacs with GnuTLS for encrypted SSL and TLS connections
brew install emacs --with-cocoa --with-imagemagick --with-gnutls
(setq user-full-name "Daniel Mai"
user-mail-address "[email protected]")
Set up the customize file to its own separate file, instead of saving customize settings in init.el.
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file)
(defun switch-theme (theme)
"Disables any currently active themes and loads THEME."
;; This interactive call is taken from `load-theme'
(interactive
(list
(intern (completing-read "Load custom theme: "
(mapc 'symbol-name
(custom-available-themes))))))
(let ((enabled-themes custom-enabled-themes))
(mapc #'disable-theme custom-enabled-themes)
(load-theme theme t)))
(defun disable-active-themes ()
"Disables any currently active themes listed in `custom-enabled-themes'."
(interactive)
(mapc #'disable-theme custom-enabled-themes))
(bind-key "s-<f12>" 'switch-theme)
(bind-key "s-<f11>" 'disable-active-themes)
(use-package doom-themes
:ensure t
:config
(customize-set-variable 'doom-molokai-brighter-comments t)
(switch-theme 'doom-molokai))
The cyberpunk theme is dark and colorful. However, I don’t like the boxes around the mode line.
(use-package cyberpunk-theme
:if (window-system)
:ensure t
:init
(progn
(load-theme 'cyberpunk t)
(set-face-attribute `mode-line nil
:box nil)
(set-face-attribute `mode-line-inactive nil
:box nil)))
I tend to switch themes more often than normal. For example, switching
to a lighter theme (such as the default) or to a different theme
depending on the time of day or my mood. Normally, switching themes is
a multi-step process with disable-theme
and load-theme
. The
switch-theme
function will do that in one swoop. I just choose which
theme I want to go to.
Here’s some configuration for bbatsov’s solarized themes.
(use-package solarized-theme
:ensure t
:init
(setq solarized-use-variable-pitch nil)
:config
(switch-theme 'solarized-dark))
(use-package monokai-theme
:if (window-system)
:ensure t
:init
(setq monokai-use-variable-pitch nil)
(switch-theme 'monokai))
(use-package waher-theme
if (window-system)
:ensure t
:init
(load-theme 'waher))
Fira Code is a nice monospaced font.
To install it on macOS, you can use Homebrew with Homebrew Cask.
# You may need to run these two lines if you haven't set up Homebrew
# Cask and its fonts formula.
brew install caskroom/cask/brew-cask
brew tap caskroom/fonts
brew cask install font-fira-code
To install it on Ubuntu, install the package fonts-firacode
.
sudo apt-get install fonts-firacode
And here’s how we tell Emacs to use the font we want to use.
(add-to-list 'default-frame-alist
(cond
((string-equal system-type "darwin") '(font . "Fira Code-14"))
((string-equal system-type "gnu/linux") '(font . "Fira Code-12"))))
Note: To view all fonts that are available to use, run the following:
(font-family-list)
Display emojis. Source of system-specific fonts is in the README for the emacs-ac-emoji package.
(let ((font (if (= emacs-major-version 25)
"Symbola"
(cond ((string-equal system-type "darwin") "Apple Color Emoji")
((string-equal system-type "gnu/linux") "Symbola")))))
(set-fontset-font t 'unicode font nil 'prepend))
Let’s start with some sane defaults, shall we?
Sources for this section include Magnars Sveen and Sacha Chua.
;; These functions are useful. Activate them.
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)
;; Answering just 'y' or 'n' will do
(defalias 'yes-or-no-p 'y-or-n-p)
;; Keep all backup and auto-save files in one directory
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))
;; UTF-8 please
(setq locale-coding-system 'utf-8) ; pretty
(set-terminal-coding-system 'utf-8) ; pretty
(set-keyboard-coding-system 'utf-8) ; pretty
(set-selection-coding-system 'utf-8) ; please
(prefer-coding-system 'utf-8) ; with sugar on top
;; Turn off the blinking cursor
(blink-cursor-mode -1)
(setq-default indent-tabs-mode nil)
(setq-default indicate-empty-lines t)
;; Don't count two spaces after a period as the end of a sentence.
;; Just one space is needed.
(setq sentence-end-double-space nil)
;; delete the region when typing, just like as we expect nowadays.
(delete-selection-mode t)
(show-paren-mode t)
(column-number-mode t)
(global-visual-line-mode)
(diminish 'visual-line-mode)
(setq uniquify-buffer-name-style 'forward)
;; -i gets alias definitions from .bash_profile
(setq shell-command-switch "-ic")
;; Don't beep at me
(setq visible-bell nil)
(setq ring-bell-function (lambda () nil))
The following function for occur-dwim
is taken from Oleh Krehel from
his blog post at (or emacs. It takes the current region or the symbol
at point as the default value for occur.
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(thing-at-point 'symbol))
regexp-history)
(call-interactively 'occur))
(bind-key "M-s o" 'occur-dwim)
Here we make page-break characters look pretty, instead of appearing
as ^L
in Emacs. Here’s an informative article called “Using
Page-Breaks in GNU Emacs” by Eric J. M. Ritz.
(use-package page-break-lines
:ensure t)
There are configurations to make when running Emacs on macOS (hence the “darwin” system-type check).
(when (string-equal system-type "darwin")
;; Non-native fullscreen
(setq ns-use-native-fullscreen nil)
;; delete files by moving them to the trash
(setq delete-by-moving-to-trash t)
(setq trash-directory "~/.Trash")
;; Don't make new frames when opening a new file with Emacs
(setq ns-pop-up-frames nil)
;; set the Fn key as the hyper key
(setq ns-function-modifier 'hyper)
;; Use Command-` to switch between Emacs windows (not frames)
(bind-key "s-`" 'other-window)
;; Use Command-Shift-` to switch Emacs frames in reverse
(bind-key "s-~" (lambda() () (interactive) (other-window -1)))
;; Because of the keybindings above, set one for `other-frame'
(bind-key "s-1" 'other-frame)
;; Fullscreen!
(setq ns-use-native-fullscreen nil) ; Not Lion style
(bind-key "<s-return>" 'toggle-frame-fullscreen)
;; buffer switching
(bind-key "s-{" 'previous-buffer)
(bind-key "s-}" 'next-buffer)
;; Compiling
(bind-key "H-c" 'compile)
(bind-key "H-r" 'recompile)
(bind-key "H-s" (defun save-and-recompile () (interactive) (save-buffer) (recompile)))
;; disable the key that minimizes emacs to the dock because I don't
;; minimize my windows
;; (global-unset-key (kbd "C-z"))
;; Not going to use these commands
(put 'ns-print-buffer 'disabled t)
(put 'suspend-frame 'disabled t))
exec-path-from-shell
makes the command-line path with Emacs’s shell
match the same one on macOS.
(use-package exec-path-from-shell
:ensure t
:init
(exec-path-from-shell-initialize))
(defun open-dir-in-finder ()
"Open a new Finder window to the path of the current buffer"
(interactive)
(start-process "mai-open-dir-process" nil "open" "."))
(defun open-dir-in-iterm ()
"Open the current directory of the buffer in iTerm."
(interactive)
(let* ((iterm-app-path "/Applications/iTerm.app")
(iterm-brew-path "/opt/homebrew-cask/Caskroom/iterm2/1.0.0/iTerm.app")
(iterm-path (if (file-directory-p iterm-app-path)
iterm-app-path
iterm-brew-path)))
(start-process "mai-open-dir-process" nil "open" "-a" iterm-path ".")))
(defun open-dir-in-studio ()
"Open the current directory in Android Studio."
(interactive)
(start-process "mai-open-dir-process" nil "studio" "."))
(bind-key "C-c o f" 'open-dir-in-finder)
(bind-key "C-c o t" 'open-dir-in-iterm)
(bind-key "C-c o a" 'open-dir-in-studio)
http://stuff-things.net/2015/10/05/emacs-visible-bell-work-around-on-os-x-el-capitan/
(when (string-equal system-type "darwin")
(let* ((cmd "sw_vers -productVersion")
(macos-version (string-to-number
(cadr (split-string
(shell-command-to-string cmd)
"\\."))))
(elcapitan-version 11))
(when (>= macos-version elcapitan-version)
(setq visible-bell nil)
(setq ring-bell-function 'ignore)
;; El Capitan full screen animation is quick and delightful (enough to start using it).
(setq ns-use-native-fullscreen t))))
(when (string-equal system-type "darwin")
(add-to-list 'default-frame-alist
'(ns-transparent-titlebar . t))
(add-to-list 'default-frame-alist
'(ns-appearance . dark))) ;; light or dark
ibuffer is the improved version of list-buffers.
;; make ibuffer the default buffer lister.
(defalias 'list-buffers 'ibuffer)
source: http://ergoemacs.org/emacs/emacs_buffer_management.html
(add-hook 'dired-mode-hook 'auto-revert-mode)
;; Also auto refresh dired, but be quiet about it
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)
source: Magnars Sveen
(use-package recentf
:config
(recentf-mode t)
(setq recentf-max-saved-items 500))
Truly the way to live life in plain text. I mainly use it to take notes and save executable source blocks. I’m also starting to make use of its agenda, timestamping, and capturing features.
It goes without saying that I also use it to manage my Emacs config.
Although Org mode ships with Emacs, the latest version can be installed externally. The configuration here follows the Org mode ELPA installation instructions.
(use-package org
:ensure org-plus-contrib)
On Org mode version 9 I wasn’t able to execute source blocks out of the box. Others have ran into the same issue too. The solution is to remove the .elc files from the package directory:
rm ${ORG_DIR}/*.elc
Set up some global key bindings that integrate with Org Mode features.
(bind-key "C-c l" 'org-store-link)
(bind-key "C-c c" 'org-capture)
(bind-key "C-c a" 'org-agenda)
Learned about this delq
and mapcar
trick from Sacha Chua’s config.
(setq org-agenda-files
(delq nil
(mapcar (lambda (x) (and (file-exists-p x) x))
'("~/Dropbox/Agenda"))))
(bind-key "C-c c" 'org-capture)
(setq org-default-notes-file "~/Dropbox/Notes/notes.org")
(setq org-capture-bookmark nil)
Speed commands are a nice and quick way to perform certain actions while at the beginning of a heading. It’s not activated by default.
See the doc for speed keys by checking out the documentation for speed keys in Org mode.
(setq org-use-speed-commands t)
(setq org-image-actual-width 550)
(setq org-highlight-latex-and-related '(latex script entities))
The default value is -77, which is weird for smaller width windows. I’d rather have the tags align horizontally with the header. 45 is a good column number to do that.
(setq org-tags-column 45)
(use-package ob-restclient
:ensure t)
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(C . t)
(calc . t)
(latex . t)
(java . t)
(ruby . t)
(lisp . t)
(scheme . t)
(shell . t)
(sqlite . t)
(js . t)
(restclient . t)
(ledger . t)))
(defun my-org-confirm-babel-evaluate (lang body)
"Do not confirm evaluation for these languages."
(not (or (string= lang "C")
(string= lang "java")
(string= lang "python")
(string= lang "emacs-lisp")
(string= lang "sqlite"))))
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
I like to have source blocks properly syntax highlighted and with the editing popup window staying within the same window so all the windows don’t jump around. Also, having the top and bottom trailing lines in the block is a waste of space, so we can remove them.
I noticed that fontification doesn’t work with markdown mode when the
block is indented after editing it in the org src buffer—the leading
#s for headers don’t get fontified properly because they appear as Org
comments. Setting org-src-preserve-indentation
makes things
consistent as it doesn’t pad source blocks with leading spaces.
(setq org-src-fontify-natively t
org-src-window-setup 'current-window
org-src-strip-leading-and-trailing-blank-lines t
org-src-preserve-indentation t
org-src-tab-acts-natively t)
Source block templates
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("sh" . "src sh"))
(add-to-list 'org-structure-template-alist '("md" . "src markdown"))
(add-to-list 'org-structure-template-alist '("gq" . "src graphql"))
Pandoc converts between a huge number of different file formats.
(use-package ox-pandoc
:no-require t
:defer 10
:ensure t)
I’ve had issues with getting BiBTeX to work correctly with the LaTeX exporter for PDF exporting. By changing the command to `latexmk` references appear in the PDF output like they should. Source: http://tex.stackexchange.com/a/161619.
(setq org-latex-pdf-process (list "latexmk -pdf %f"))
(use-package tramp)
Using macOS Spotlight within Emacs by modifying the locate
function.
I usually use ~helm-locate~, which does live updates the spotlight search list as you type a query.
;; mdfind is the command line interface to Spotlight
(setq locate-command "mdfind")
Convenient keybindings to resize windows.
(bind-key "s-C-<left>" 'shrink-window-horizontally)
(bind-key "s-C-<right>" 'enlarge-window-horizontally)
(bind-key "s-C-<down>" 'shrink-window)
(bind-key "s-C-<up>" 'enlarge-window)
Whenever I split windows, I usually do so and also switch to the other window as well, so might as well rebind the splitting key bindings to do just that to reduce the repetition.
(defun vsplit-other-window ()
"Splits the window vertically and switches to that window."
(interactive)
(split-window-vertically)
(other-window 1 nil))
(defun hsplit-other-window ()
"Splits the window horizontally and switches to that window."
(interactive)
(split-window-horizontally)
(other-window 1 nil))
(bind-key "C-x 2" 'vsplit-other-window)
(bind-key "C-x 3" 'hsplit-other-window)
Winner mode allows you to undo/redo changes to window changes in Emacs and allows you.
(use-package winner
:config
(winner-mode t)
:bind (("C-c <left>" . winner-undo)
("C-c <right>" . winner-redo)))
(use-package transpose-frame
:ensure t
:bind ("C-c t" . transpose-frame))
(use-package ido
:disabled t
:init
(setq ido-enable-flex-matching t)
(setq ido-everywhere t)
(ido-mode t)
(use-package ido-vertical-mode
:ensure t
:defer t
:init (ido-vertical-mode 1)
(setq ido-vertical-define-keys 'C-n-and-C-p-only)))
(use-package whitespace
:bind ("<f10>" . whitespace-mode))
(bind-key "C-c u" #'revert-buffer)
(use-package hippie-exp
:bind (("C-c /" . hippie-expand)))
(use-package auth-source
:config
(customize-set-variable 'auth-sources
'((:source "~/.authinfo.gpg"))))
These are the packages that are not built into Emacs.
(use-package ag
:commands ag
:ensure t)
ace-window is a package that uses the same idea from ace-jump-mode for buffer navigation, but applies it to windows. The default keys are 1-9, but it’s faster to access the keys on the home row, so that’s what I have them set to (with respect to Dvorak, of course).
(use-package ace-window
:ensure t
:config
(setq aw-keys '(?a ?o ?e ?u ?h ?t ?n ?s))
(ace-window-display-mode)
:bind ("s-o" . ace-window))
This package displays function signatures in the mode line.
(use-package c-eldoc
:commands c-turn-on-eldoc-mode
:ensure t
:init (add-hook 'c-mode-hook #'c-turn-on-eldoc-mode))
(use-package clojure-mode
:defer t
:ensure t)
(use-package cider
:ensure t)
Integration with Dash, the API documentation browser on macOS. The
binding s-D
is the same as Cmd-Shift-D, the same binding that dash
uses in Android Studio (trying to keep things consistent with the
tools I use).
(use-package dash-at-point
:if (string-equal system-type "darwin")
:ensure t
:bind (("s-D" . dash-at-point)
("C-c e" . dash-at-point-with-docset)))
(use-package docker
:ensure t
:bind (("C-c d c" . docker-containers)
("C-c d i" . docker-images)
("C-c d v" . docker-volumes)))
(use-package dockerfile-mode
:ensure t)
(use-package kubernetes
:ensure t
:commands (kubernetes-overview))
(use-package helm
:disabled t
:ensure t
:diminish helm-mode
:bind (("C-c h" . helm-command-prefix)
("C-x b" . helm-mini)
("C-`" . helm-resume)
("M-x" . helm-M-x)
("C-x C-f" . helm-find-files)
("C-x C-r" . helm-recentf))
:init
(require 'helm-config)
:config
(setq helm-locate-command "mdfind -interpret -name %s %s"
helm-ff-newfile-prompt-p nil
helm-M-x-fuzzy-match t)
(helm-mode))
(use-package helm-projectile
:ensure t
:after helm-mode
:commands helm-projectile
:bind ("C-c p h" . helm-projectile))
(use-package helm-ag
:ensure t
:after helm-mode)
(use-package helm-swoop
:ensure t
:after helm-mode
:bind ("H-w" . helm-swoop))
(use-package ivy
:ensure t
:diminish (ivy-mode . "")
:bind
(:map ivy-mode-map
("C-'" . ivy-avy))
:config
(ivy-mode 1)
;; add ‘recentf-mode’ and bookmarks to ‘ivy-switch-buffer’.
(setq ivy-use-virtual-buffers t)
;; number of result lines to display
(setq ivy-height 10)
;; Show candidate index and total count
(setq ivy-count-format "(%d/%d) ")
;; no regexp by default
(setq ivy-initial-inputs-alist nil)
;; configure regexp engine.
(setq ivy-re-builders-alist
;; allow input not in order
'((t . ivy--regex-ignore-order))))
(use-package avy
:ensure t
:bind ("C-S-s" . avy-goto-char))
(use-package counsel
:ensure t
:bind (("M-x" . counsel-M-x)
("C-x C-r" . counsel-recentf)
("C-c h i" . counsel-imenu)
("C-h v" . counsel-describe-variable)
("C-h f" . counsel-describe-function)))
(use-package counsel-projectile
:ensure t
:config
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(counsel-projectile-mode)
(setq counsel-projectile-switch-project-action 'dired))
(use-package swiper
:ensure t
:bind (("C-c s" . swiper)))
A great interface for git projects. It’s much more pleasant to use than the git interface on the command line. Use an easy keybinding to access magit.
(use-package magit
:ensure t
:defer t
:bind (("C-c g" . magit-status)
("C-c G" . magit-dispatch)
("C-c m l" . magit-log-buffer-file)
("C-c m b" . magit-blame))
:config
(setq magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
(setq magit-diff-refine-hunk t))
The following code makes magit-status run alone in the frame, and then restores the old window configuration when you quit out of magit.
No more juggling windows after commiting. It’s magit bliss.
;; full screen magit-status
(defadvice magit-status (around magit-fullscreen activate)
(window-configuration-to-register :magit-fullscreen)
ad-do-it
(delete-other-windows))
(defun magit-quit-session ()
"Restores the previous window configuration and kills the magit buffer"
(interactive)
(kill-buffer)
(jump-to-register :magit-fullscreen))
Magit extension to interact with GitHub/GitLab.
(use-package forge
:ensure t
:after magit)
Editing input boxes from Chrome with Emacs. Pretty useful to keep all
significant text-writing on the web within emacs. I typically use this
with posts on Discourse, which has a post editor that overrides normal
Emacs key bindings with other functions. As such, markdown-mode
is
used.
(use-package edit-server
:ensure t
:config
(edit-server-start)
(setq edit-server-default-major-mode 'markdown-mode)
(setq edit-server-new-frame nil))
(use-package elfeed
:ensure t
:defer t)
(use-package expand-region
:ensure t
:bind ("C-@" . er/expand-region))
Still need to set up hooks so that flycheck automatically runs in python mode, etc. js2-mode is already really good for the syntax checks, so I probably don’t need the jshint checks with flycheck for it.
(use-package flycheck
:ensure t
:defer 10
:config (setq flycheck-html-tidy-executable "tidy5"))
Install the HTML5/CSS/JavaScript linters.
brew tap homebrew/dupes
brew install tidy
npm install -g jshint
npm install -g csslint
(use-package git-link
:ensure t)
Create a .dot
buffer in dot-mode and then quickly preview the rendered dot
diagram with C-c C-p
.
(use-package graphviz-dot-mode
:ensure t)
Macrostep allows you to see what Elisp macros expand to. Learned about it from the package highlight talk for use-package.
(use-package macrostep
:ensure t
:bind ("H-`" . macrostep-expand))
Install cmark or your Markdown processor of choice and set it as markdown-command
before using the live previewer commands.
(use-package markdown-mode
:ensure t
:mode (("\\.markdown\\'" . markdown-mode)
("\\.md\\'" . markdown-mode))
:config
(setq markdown-command "cmark"))
We’ll also need to (require 'multiple-cusors)
because of an autoload issue.
(use-package multiple-cursors
:ensure t
:bind (("C-S-c C-S-c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-!" . mc/mark-next-symbol-like-this)))
(use-package mustache-mode
:ensure t)
(use-package pinentry
:ensure t
:if (string-equal system-type "gnu/linux")
:config
(pinentry-start))
Project navigation and management library for Emacs.
(use-package projectile
:ensure t
:diminish projectile-mode
:commands (projectile-mode projectile-switch-project)
:bind (("C-c p p" . projectile-switch-project)
("C-c p s s" . projectile-ag)
("C-c p s r" . projectile-ripgrep))
:config
(setq projectile-keymap-prefix (kbd "C-c p"))
(projectile-global-mode t)
(setq projectile-enable-caching t)
(setq projectile-switch-project-action 'projectile-dired))
Integrates with IPython.
(use-package python-mode
:defer t
:ensure t)
Starting to use Racket now, mainly for programming paradigms class, though I’m looking forward to some “REPL-driven development” whenever I get the chance.
(use-package racket-mode
:ensure t
:commands racket-mode
:config
(setq racket-smart-open-bracket-enable t))
(use-package geiser
:ensure t
:defer t
:config
(setq geiser-default-implementation '(racket)))
See Emacs Rocks! Episode 15 to learn how restclient can help out with
testing APIs from within Emacs. The HTTP calls you make in the buffer
aren’t constrainted within Emacs; there’s the
restclient-copy-curl-command
to get the equivalent curl
call
string to keep things portable.
(use-package restclient
:ensure t
:mode ("\\.restclient\\'" . restclient-mode))
Quickly jumps between other symbols found at point in Emacs.
http://www.masteringemacs.org/article/smart-scan-jump-symbols-buffer
(use-package smartscan
:ensure t
:config (global-smartscan-mode 1)
:bind (("s-n" . smartscan-symbol-go-forward)
("s-p" . smartscan-symbol-go-backward)))
Smex integrates ido with M-x
. I used to use this before moving on to
helm.
(use-package smex
:if (not (featurep 'helm-mode))
:disabled t
:ensure t
:bind ("M-x" . smex))
This makes it so C-n
-ing and C-p
-ing won’t make the buffer jump
around so much.
(use-package smooth-scrolling
:ensure t
:config
(smooth-scrolling-mode))
(use-package web-mode
:ensure t)
Yeah, snippets! I start with snippets from Andrea Crotti’s collection and have also modified them and added my own.
It takes a few seconds to load and I don’t need them immediately when Emacs starts up, so we can defer loading yasnippet until there’s some idle time.
Setting yas-indent-line
to 'fixed
fixes Python indentation
behavior when typing a templated snippet.
(use-package yasnippet
:ensure t
:diminish yas-minor-mode
:config
(setq yas-snippet-dirs (concat user-emacs-directory "snippets"))
(setq yas-indent-line 'fixed)
(yas-global-mode))
According to their website, “Emmet — the essential toolkit for web-developers.”
(use-package emmet-mode
:ensure t
:commands emmet-mode
:config
(add-hook 'html-mode-hook 'emmet-mode)
(add-hook 'css-mode-hookg 'emmet-mode))
zoom-frm
is a nice package that allows you to resize the text of
entire Emacs frames (this includes text in the buffer, mode line, and
minibuffer). The zoom-in/out
command acts similar to the
text-scale-adjust
command—you can chain zooming in, out, or
resetting to the default size once the command has been initially
called.
Changing the frame-zoom-font-difference
essentially enables a
“presentation mode” when calling toggle-zoom-frame
.
(use-package frame-fns
:load-path "site-lisp/frame-fns"
:no-require t)
(use-package frame-cmds
:load-path "site-lisp/frame-cmds"
:no-require t)
(use-package zoom-frm
:load-path "site-lisp/zoom-frm"
:bind (("C-M-=" . zoom-in/out)
("H-z" . toggle-zoom-frame)
("s-<f1>" . toggle-zoom-frame))
:config
(setq frame-zoom-font-difference 10))
Convenient package to create *scratch*
buffers that are based on the
current buffer’s major mode. This is more convienent than manually
creating a buffer to do some scratch work or reusing the initial
*scratch*
buffer.
(use-package scratch
:ensure t
:commands scratch)
(use-package shell-pop
:ensure t
:bind ("M-<f12>" . shell-pop))
The Superior Lisp Interaction Mode for Emacs. First, Install SBCL with brew.
brew install sbcl
(use-package slime
:ensure t
:defer 10
:init
(setq inferior-lisp-program "/usr/local/bin/sbcl")
(add-to-list 'slime-contribs 'slime-fancy))
(use-package quickrun
:defer 10
:ensure t
:bind ("C-c r" . quickrun))
I found out about this mode by looking through simple.el. I use it to see raw org-mode files without going to a different mode like text-mode, which is what I had done in order to see invisible text (with org hyperlinks). The entire buffer contents will be visible while still being in org mode.
(use-package visible-mode
:bind (("H-v" . visible-mode)
("s-<f2>" . visible-mode)))
(use-package undo-tree
:ensure t)
Collection of Ridiculously Useful eXtensions
(use-package crux
:ensure t
:bind (("C-c o o" . crux-open-with)
("C-c o u" . crux-view-url)))
(use-package graphql-mode
:mode (("\\.q\\'" . graphql-mode))
:ensure t)
(use-package json-mode
:ensure t
:config
(customize-set-variable 'json-mode-hook
#'(lambda ()
(setq tab-width 2))))
(use-package terminal-here
:ensure t
:if (string-equal system-type "gnu/linux")
:bind (("C-c o t" . terminal-here-launch)
("C-c o p" . terminal-here-project-launch)))
(use-package yaml-mode
:ensure t)
Auto completion.
(use-package company
:ensure t
:config
(setq company-tooltip-limit 20)
(setq company-idle-delay .15)
(setq company-echo-delay 0)
(setq company-begin-commands '(self-insert-command))
(define-key company-active-map (kbd "C-n") #'company-select-next)
(define-key company-active-map (kbd "C-p") #'company-select-previous))
First, install all of the Go tools.
go get -u golang.org/x/tools/...
This includes tools like, godef
, goimports
, and guru
which are used in this config.
(use-package go-mode
:ensure t
:config
(bind-key "C-." #'godef-jump go-mode-map)
(bind-key "C-x 4 C-." #'godef-jump-other-window go-mode-map)
(bind-key "C-c C-r" #'go-remove-unused-imports)
(add-hook 'before-save-hook #'gofmt-before-save)
(setq gofmt-command "goimports")
(customize-set-variable 'go-mode-hook
#'(lambda ()
(setq tab-width 4)
(setq display-line-numbers 'relative))))
Use go-eldoc
to see things like function signatures in the modeline
.
(use-package go-eldoc
:ensure t
:config
(go-eldoc-setup))
go-guru
is great for source code analysis. The most common thing I use it for is
go-guru-referrers
, which finds all references to a particular thing across the workspace.
(use-package go-guru
:ensure t
:config
;; Search entire workspace
(customize-set-variable 'go-guru-scope "...")
(add-hook 'go-mode-hook #'go-guru-hl-identifier-mode))
To set up autocompletion with Go, first get gocode
: https://github.com/nsf/gocode.
go get -u github.com/nsf/gocode
(use-package company-go
:ensure t
:config
(add-hook 'go-mode-hook (lambda ()
(set (make-local-variable 'company-backends)
'(company-go))
(company-mode))))
(use-package gotest
:ensure t
:bind (:map go-mode-map
("C-c C-t p" . go-test-current-project)
("C-c C-t f" . go-test-current-file)
("C-c C-t ." . go-test-current-test)
("C-c r" . go-run))
:config
(setq go-test-verbose t))
(use-package jade-mode
:ensure t
:config
(add-hook 'jade-mode-hook
#'(lambda ()
(setq tab-width 2)
(setq indent-tabs-mode t))))
(use-package nginx-mode
:ensure t
:config
(setq nginx-indent-level 2))
Install ~keychain~ first, which will manage the SSH agent on Linux systems. This is useful when using SSH keys with passwords, such as with SSH git access or SSHing into other machines. The following must be run already before starting Emacs.
eval "$(keychain --eval --agents ssh id_rsa)"
(use-package keychain-environment
:if (string-equal system-type "gnu/linux")
:ensure t
:config
(keychain-refresh-environment))
Load some computer-specific settings, such as the name and email address. The way the settings are loaded is based off of Magnar Sveen’s config.
In my case, the computers I use usually use the same username (my
name, go figure), so instead of basing the specific settings from the
username, I use the hostname. The system-name
is a built-in function
which returns the host name of the machine you are running on, as a string.
(defvar mai/user-settings-dir nil
"The directory with user-specific Emacs settings for this
user.")
;; Settings for currently logged in user
(setq mai/user-settings-dir
(concat user-emacs-directory "users/" (system-name)))
(add-to-list 'load-path mai/user-settings-dir)
;; Load settings specific for the current user
(when (file-exists-p mai/user-settings-dir)
(mapc 'load (directory-files mai/user-settings-dir nil "^[^#].*el$")))
(load "~/.finda/integrations/emacs/finda.el" t)
I don’t like the default way that Emacs handles indentation. For instance,
int main(int argc, char *argv[])
{
/* What's with the brace alignment? */
if (check)
{
}
return 0;
}
switch (number)
{
case 1:
doStuff();
break;
case 2:
doStuff();
break;
default:
break;
}
Luckily, I can modify the way Emacs formats code with this configuration.
(defun my-c-mode-hook ()
(setq c-basic-offset 4)
(c-set-offset 'substatement-open 0) ; Curly braces alignment
(c-set-offset 'case-label 4)) ; Switch case statements alignment
(add-hook 'c-mode-hook 'my-c-mode-hook)
(add-hook 'java-mode-hook 'my-c-mode-hook)
Some packages aren’t in ELPA, so they’re stored in the site-lisp directory and loaded here.
As in the titlecase package instructions, the titlecase command needs to be in the $PATH for this to work.
(use-package titlecase
:load-path "~/.emacs.d/site-lisp")
When displaying the time with display-time-mode
, I don’t care about
the load average.
(setq display-time-default-load-average nil)
See the documentation for battery-mode-line-format
for the format
characters.
(setq battery-mode-line-format "[%b%p%% %t]")
Convenience bindings to use doc-view with the arrow keys.
(use-package doc-view
:commands doc-view-mode
:config
(define-key doc-view-mode-map (kbd "<right>") 'doc-view-next-page)
(define-key doc-view-mode-map (kbd "<left>") 'doc-view-previous-page))
(setq mouse-wheel-scroll-amount (quote (0.01)))
(use-package server
:config
(server-start))
(use-package dired
:config
(customize-set-variable 'dired-listing-switches
"-avl"))
(use-package typescript-mode
:ensure t)
(global-hl-line-mode 1)