Lee's Emacs settings file
Table of Contents
- Configuration
- A note about keyboard shortcuts
- Packages that need to be installed
- Basics and settings used everywhere
- Programming language-specific configuration
- theme
- org-mode
- org-clock
- org-publishing
- org-reveal (ox-reveal)
- exec-path-from-shell
- vkill
- alert (notifications)
- ERC Configuration (IRC)
- Email (mu4e) Configuration
- Email (gnus) configuration
- ace-jump-mode
- ediff
- smooth-scrolling
- paredit
- smartparens
- golden-ratio
- flycheck
- ggtags
- expand-region
- with-editor
- magit
- projectile
- prodigy
- git-gutter
- git-annex
- diff-hl
- anzu
- easy-kill
- helm
- helm-ls-git
- helm-dash
- hydra
- yasnippet
- markdown-mode
- log4j-mode
- bookmark+
- editorconfig
- company-mode (auto-complete)
- smart-tab
- undo-tree
- popwin
- paren-face
- ido-mode
- multiple-cursors
- twittering-mode
- scpaste
- smex
- volatile-highlights
- color-identifiers-mode
- iedit
- eyebrowse
- origami
- hideshow
- abbrev
- vlf (view large files)
- eww
- visible-mark
- fill-column-indicator
- idle-highlight-mode
- Bindings
- Utility methods
- Fixing SSH agent settings
- Format JSON more beautifully
- Recompile startup elisp files
- Adding directories to $PATH
- Misc methods for cleaning up a buffer
- Browsing URLs
- Numbering rectangles
- Insert look of disapproval
- Browse Elasticsearch documentation
- Narrow-widen DWIM (do what I mean)
- Move by block of text
- File previews
- Replace smart quotes
- Change number of replicas for an index
- Finalizers
Configuration
This file is used by org-mode to load my personal emacs configuration file. The latest version of this file is always at https://github.com/dakrone/dakrone-dotfiles
This file was last exported: 2015-07-09 16:22
It can be loaded by putting the following in your .emacs.d/init.el:
;; Keep track of loading time (defconst emacs-start-time (current-time)) ;; initalize all ELPA packages (require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/")) (package-initialize) (setq package-enable-at-startup nil) (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loaded packages in %.3fs" elapsed)) ;; Dvorak nicety, regardless of loading settings (define-key key-translation-map "\C-t" "\C-x") ;; Load use-package, used for loading packages (require 'use-package) ;; keep customize settings in their own file (setq custom-file "~/.emacs.d/custom.el") (when (file-exists-p custom-file) (load custom-file)) (require 'org) (org-babel-load-file (expand-file-name "settings.org" user-emacs-directory)) ;; Message how long it took to load everything (minus packages) (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loading settings...done (%.3fs)" elapsed))
Or, you can manually tangle the file and use this alternative instead:
;; Keep track of loading time (defconst emacs-start-time (current-time)) ;; initalize all ELPA packages (require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/")) ;; for wanderlust (add-to-list 'package-archives '("e6h" . "http://www.e6h.org/packages/")) (package-initialize) (setq package-enable-at-startup nil) (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loaded packages in %.3fs" elapsed)) ;; Dvorak nicety, regardless of loading settings (define-key key-translation-map "\C-t" "\C-x") ;; Load use-package, used for loading packages (require 'use-package) ;; keep customize settings in their own file (setq custom-file "~/.emacs.d/custom.el") (when (file-exists-p custom-file) (load custom-file)) (load "~/.emacs.d/settings.el") ;; Message how long it took to load everything (minus packages) (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loading settings...done (%.3fs)" elapsed))
A note about keyboard shortcuts
There are a lot (like, a lot) of keyboard shortcuts in this configuration, and they aren't all collected in one place. So I thought I should collect the most common of them into a single place so anyone looking at this can get an idea of what I use the most. I borrowed the idea from a different configuration I saw, when I thought it was useful for seeing how people bound things.
This doesn't include stuff that I haven't really rebound, like C-x C-f
,
which just calls find-file
, though there may be a few sprinkled in there.
This list is in no way exhaustive.
Shortcut | What it does | Usage frequency |
---|---|---|
C-c a SPC |
open my custom agenda view | Every time I start emacs |
C-x m |
open eshell | Every time I start emacs |
C-x C-r |
helm-mini | Very |
C-x b |
helm-mini | Very |
C-x f |
helm-projectile | Very |
C-c b |
switch between org-mode buffers | Very |
M-g M-g |
open Magit | Very |
C-x C-i |
open helm's semantic imenu | Very |
C-c n |
cleanup buffer (reindent, clean whitespace) | Often |
C-x C-j |
open dired folder for current file | Often |
C-M-n |
scroll half a page down | Often |
C-M-p |
scroll half a page up | Often |
M-i |
open helm-swoop | Often |
<F11> |
prompt for recent headlines to clock into | Often |
<F12> |
clock out of current task | Often |
M-g . |
helm-grep, with C-u prefix, rgrep | Sometimes |
C-c p s |
switch projectile projecs | Sometimes |
C-h b |
see the current bindings (helm-descbinds) | Sometimes |
C-h a |
look through all emacs vars, functions, faces (helm-apropos) | Sometimes |
C-h t |
see the current time in different locations (helm-world-time) | Sometimes |
C-c c |
open capture template for capturing org agenda things | Sometimes |
C-x M-b |
open a list of my file/buffer bookmarks (helm-bookmarks) | Sometimes |
C-c d |
look up something in the Elasticsearch documentation | Sometimes |
C-c u |
search for the last URL and browse to it with system browser | Sometimes |
C-x 4 t |
transpose the current buffers | Rarely |
C-h e |
pop up the *Messages* buffer |
Rarely |
C-x RET |
open shell (zsh) | Rarely |
Packages that need to be installed
This is code that installs packages before any config is loaded, since a lot of things add hooks that don't work if packages aren't installed.
(defvar my/install-packages '( ;; package management use-package ;; themeing rainbow-mode leuven-theme dakrone-theme color-identifiers-mode moe-theme nyan-mode color-theme-sanityinc-tomorrow powerline volatile-highlights apropospriate-theme material-theme visible-mark ;; misc diminish gist scpaste async sx exec-path-from-shell bbdb ;; es-mode is run from a git checkout ;; IRC/ERC and social stuff erc-hl-nicks ercn alert twittering-mode ;; for auto-complete fuzzy popup company ;; editing utilities expand-region smex windresize ag undo-tree iedit ido-ubiquitous ido-vertical-mode yasnippet smart-tab anzu smartparens flx-ido projectile smooth-scrolling ace-jump-mode multiple-cursors easy-kill simple-call-tree simple-call-tree+ editorconfig ggtags bookmark+ fill-column-indicator golden-ratio wc-mode eyebrowse vlf origami ;; external process things prodigy vkill ;; logs log4j-mode logstash-conf ;; infrastructure stuff restclient company-restclient ;; highlighting idle-highlight-mode ;; LaTeX auctex ;; org-mode org htmlize gnuplot-mode gnuplot ox-reveal ox-gfm ;; buffer utils popwin dired+ ;; haskell haskell-mode ghc ghci-completion ;; config ssh-config-mode ;; flycheck flycheck flycheck-tip flycheck-haskell ;; clojure clojure-mode clojure-mode-extra-font-locking cider paredit paren-face ;; perl cperl-mode ;; python hy-mode jedi ;; ruby ruby-mode ruby-test-mode inf-ruby puppet-mode rbenv chruby ;; rust rust-mode ;; go go-mode ;; java malabar-mode groovy-mode javap-mode ;; javascript tern json-mode js2-mode ;; emacs-lisp elisp-slime-nav paredit ;; racket racket-mode ;; markup language markdown-mode markdown-mode+ yaml-mode zencoding-mode adoc-mode ;; helm helm helm-descbinds helm-ag helm-projectile helm-swoop helm-gtags helm-ls-git helm-flycheck helm-flyspell helm-dash ;; git magit git-gutter git-timemachine magit-gh-pulls with-editor git-annex diff-hl ;; eshell eshell-prompt-extras ;; gnus gnus-x-gm-raw ;; eww eww-lnum )) (defvar packages-refreshed? nil) (dolist (pack my/install-packages) (unless (package-installed-p pack) (unless packages-refreshed? (package-refresh-contents) (setq packages-refreshed? t)) (package-install pack))) ;; Load use-package, used for loading packages everywhere else (require 'use-package) ;; Set to t to debug package loading (setq use-package-verbose nil)
Basics and settings used everywhere
Mostly settings that don't fit in elsewhere, so they end up here. However, this does include settings that aren't part of packages and need to configure Emacs' built-in packages.
General settings
Turn on debugging, it will be turned off at the end. In case something happens during loading that breaks something, it's nice to have a debug information.
(setq debug-on-error t) (setq debug-on-quit t)
First, let's determine whether I'm going to be using a dark theme,
or a light theme. I set a var to either 'light
or 'dark
depending on whatever I'm in the mood for. This is used later on for the
modeline theme, as well as the general theme for things.
;;(defvar my/background 'light) (defvar my/background 'dark)
Now some personal information about me:
(setq user-full-name "Lee Hinman" user-mail-address "matthew.hinman@gmail.com")
Always, always, prefer UTF-8, anything else is insanity
(prefer-coding-system 'utf-8) (set-default-coding-systems 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (setq default-buffer-file-coding-system 'utf-8)
Turn on syntax highlighting for all buffers:
(global-font-lock-mode t)
We don't really need to garbage collect as frequently as Emacs would like to by default, so set the threshold up higher:
(setq gc-cons-threshold (* 100 1024 1024)) ;; 100 mb ;; Allow font-lock-mode to do background parsing (setq jit-lock-stealth-time 1 ;; jit-lock-stealth-load 200 jit-lock-chunk-size 1000 jit-lock-defer-time 0.05)
line-number-mode
displays the current line number in the mode line, however it
stops doing that in buffers when encountering at least one overly long line and
displays two question marks instead. This is pretty unhelpful, the only
workaround I've been able to find was to increase line-number-display-width to a
substantially higher value.
(setq line-number-display-limit-width 10000)
Make gnutls a bit safer
(setq gnutls-min-prime-bits 4096)
Fix some things for scrolling a bit better
(setq scroll-conservatively 10000 scroll-preserve-screen-position t)
Echo commands I haven't finished quicker than the default of 1 second:
(setq echo-keystrokes 0.4)
Don't warn me about large files unless they're at least 25mb:
(setq large-file-warning-threshold (* 25 1024 1024))
If you change buffer, or focus, disable the current buffer's mark:
(transient-mark-mode 1)
Don't indicate empty lines or the end of a buffer with visual marks (the lines are cleaned up automatically anyway)
(setq-default indicate-empty-lines nil) (setq-default indicate-buffer-boundaries nil)
Turn off all kinds of modes, I don't need the menu bar, or the tool bar:
(when (functionp 'menu-bar-mode) (menu-bar-mode -1)) (when (functionp 'set-scroll-bar-mode) (set-scroll-bar-mode 'nil)) (when (functionp 'mouse-wheel-mode) (mouse-wheel-mode -1)) (when (functionp 'tooltip-mode) (tooltip-mode -1)) (when (functionp 'tool-bar-mode) (tool-bar-mode -1)) (when (functionp 'blink-cursor-mode) (blink-cursor-mode -1))
Don't beep. Just don't. Also, don't show the startup message, I know Emacs is starting.
(setq ring-bell-function (lambda ())) (setq inhibit-startup-message t initial-major-mode 'fundamental-mode)
Why would you not want to know lines/columns in your mode-line?
(line-number-mode 1) (column-number-mode 1)
Ignore case when using completion for file names:
(setq read-file-name-completion-ignore-case t)
Nobody likes to have to type "yes" to questions, so change it to
just hitting the y
key to confirm:
(defalias 'yes-or-no-p 'y-or-n-p)
Confirm before killing emacs, but only on graphical sessions
(when (window-system) (setq confirm-kill-emacs 'yes-or-no-p))
It's much easier to move around lines based on how they are displayed, rather than the actual line. This helps a ton with long log file lines that may be wrapped:
(setq line-move-visual t)
Hide the mouse while typing:
(setq make-pointer-invisible t)
Set up the fill-column to 80 characters and set tab width to 2
(setq-default fill-column 80) (setq-default default-tab-width 2) (setq-default indent-tabs-mode nil)
Fix some weird color escape sequences
(setq system-uses-terminfo nil)
Resolve symlinks:
(setq-default find-file-visit-truename t)
Require a newline at the end of files:
(setq require-final-newline t)
Uniquify buffers, using angle brackets, so you get foo
and
foo<2>
:
(use-package uniquify :config (setq uniquify-buffer-name-style 'post-forward-angle-brackets))
Search (and search/replace) using regex by default, since that's usually what I want to do:
(global-set-key (kbd "C-s") 'isearch-forward-regexp) (global-set-key (kbd "C-r") 'isearch-backward-regexp) (global-set-key (kbd "M-%") 'query-replace-regexp)
Single space still ends a sentence:
(setq sentence-end-double-space nil)
Split windows a bit better (don't split horizontally, I have a widescreen :P)
(setq split-height-threshold nil) (setq split-width-threshold 180)
Make sure auto automatically rescan for imenu changes:
(set-default 'imenu-auto-rescan t)
Seed the random number generator:
(random t)
Switch to unified diffs by default:
(setq diff-switches "-u")
Turn on auto-fill mode in text buffers:
(add-hook 'text-mode-hook 'turn-on-auto-fill) (use-package diminish :init (progn (diminish 'auto-fill-function "")))
Set the internal calculator not to go to scientific form quite so quickly:
(setq calc-display-sci-low -5)
Bury the *scratch*
buffer, never kill it:
(defadvice kill-buffer (around kill-buffer-around-advice activate) (let ((buffer-to-kill (ad-get-arg 0))) (if (equal buffer-to-kill "*scratch*") (bury-buffer) ad-do-it)))
These are some settings for version control stuff.
Automatically revert file if it's changed on disk:
(global-auto-revert-mode 1) ;; be quiet about reverting files (setq auto-revert-verbose nil)
Start a server if not running, but a only for text-only:
(use-package server :config (progn (when (not (window-system)) (if (server-running-p server-name) nil (server-start)))))
GUI-specific thing:
(when (window-system) (setenv "EMACS_GUI" "t"))
Prettify all the symbols, if available (an Emacs 24.4 feature):
(when (boundp 'global-prettify-symbols-mode) (add-hook 'emacs-lisp-mode-hook (lambda () (push '("lambda" . ?λ) prettify-symbols-alist))) (add-hook 'clojure-mode-hook (lambda () (push '("fn" . ?ƒ) prettify-symbols-alist))) (global-prettify-symbols-mode +1))
Always prefer to load newer files, instead of giving precedence to the .elc files.
(setq load-prefer-newer t)
Turn on winner-mode, which allows me to use C-c LEFT
to undo window
configuration changes, if so desired.
(use-package winner :init (winner-mode 1))
Display the time and load on the modeline
(setq ;; don't display info about mail display-time-mail-function (lambda () nil) ;; update every 15 seconds instead of 60 seconds display-time-interval 15) (display-time-mode 1)
Quit as fast as possible with kill -USR1 <pid>
(defun my/quit-emacs-unconditionally () (interactive) (my-quit-emacs '(4))) (define-key special-event-map (kbd "<sigusr1>") #'my/quit-emacs-unconditionally)
OS-specific settings
These are settings that are applied depending on what OS I'm
currently running on. On gnu/linux systems, I bind C-M-w
to the
yank-to-x-clipboard method, which uses xsel
to yank text. On OSX, I use the
pbpaste
and pbcopy
methods to interact with the system clipboard.
For OSX, use brew install coreutils
to get gls
which has better support for
dired buffers.
(when (eq system-type 'gnu/linux) (setq dired-listing-switches "-lFaGh1v --group-directories-first") (defun yank-to-x-clipboard () (interactive) (if (region-active-p) (progn (shell-command-on-region (region-beginning) (region-end) "xsel -i -b") (message "Yanked region to clipboard!") (deactivate-mark)) (message "No region active; can't yank to clipboard!"))) (global-set-key (kbd "C-M-w") 'yank-to-x-clipboard) ;; suspend-frame isn't working on Linux? (global-unset-key (kbd "C-z")) (global-unset-key (kbd "C-x C-z"))) (when (eq system-type 'darwin) (setq ns-use-native-fullscreen nil) ;; brew install coreutils (if (executable-find "gls") (progn (setq insert-directory-program "gls") (setq dired-listing-switches "-lFaGh1v --group-directories-first")) (setq dired-listing-switches "-ahlF")) (defun copy-from-osx () "Handle copy/paste intelligently on osx." (let ((pbpaste (purecopy "/usr/bin/pbpaste"))) (if (and (eq system-type 'darwin) (file-exists-p pbpaste)) (let ((tramp-mode nil) (default-directory "~")) (shell-command-to-string pbpaste))))) (defun paste-to-osx (text &optional push) (let ((process-connection-type nil)) (let ((proc (start-process "pbcopy" "*Messages*" "/usr/bin/pbcopy"))) (process-send-string proc text) (process-send-eof proc)))) (setq interprogram-cut-function 'paste-to-osx interprogram-paste-function 'copy-from-osx) (defun move-file-to-trash (file) "Use `trash' to move FILE to the system trash. When using Homebrew, install it using \"brew install trash\"." (call-process (executable-find "trash") nil 0 nil file)) ;; Trackpad scrolling (global-set-key [wheel-up] 'previous-line) (global-set-key [wheel-down] 'next-line))
Sometimes I use the OSX emacs-mac
port:
https://github.com/railwaycat/emacs-mac-port , which has a whole other set of
issues, so this is special handling of it…
(when (eq window-system 'mac) (defun my/max-fullscreen () (interactive) (set-frame-parameter nil 'fullscreen 'fullboth)) ;; fullscreen (add-hook 'after-init-hook #'my/max-fullscreen) ;; use alt as hyper (setq mac-option-modifier 'meta) ;; use command as meta (setq mac-command-modifier 'hyper))
Windows
Hahahahaha, you must be joking.
Clipboard settings
Change the clipboard settings to better integrate into Linux:
(setq x-select-enable-clipboard t) ;; Treat clipboard input as UTF-8 string first; compound text next, etc. (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
Save whatever's in the current (system) clipboard before replacing it with the Emacs' text.
(setq save-interprogram-paste-before-kill t)
Temporary file settings
Settings for what to do with temporary files.
;; savehist (setq savehist-additional-variables ;; also save my search entries '(search-ring regexp-search-ring) savehist-file "~/.emacs.d/savehist") (savehist-mode t) (setq-default save-place t) ;; delete-auto-save-files (setq delete-auto-save-files t) (setq backup-directory-alist '(("." . "~/.emacs_backups"))) ;; delete old backups silently (setq delete-old-versions t)
Shell settings
Things for running shells inside of emacs
First, Emacs doesn't handle less
well, so use cat
instead for the shell
pager:
(setenv "PAGER" "cat")
(custom-set-variables '(comint-scroll-to-bottom-on-input t) ; always insert at the bottom '(comint-scroll-to-bottom-on-output nil) ; always add output at the bottom '(comint-scroll-show-maximum-output t) ; scroll to show max possible output ;; '(comint-completion-autolist t) ; show completion list when ambiguous '(comint-input-ignoredups t) ; no duplicates in command history '(comint-completion-addsuffix t) ; insert space/slash after file completion '(comint-prompt-read-only nil) ; if this is t, it breaks shell-command '(comint-get-old-input (lambda () "")) ; what to run when i press enter on a ; line above the current prompt ) (defun my/shell-kill-buffer-sentinel (process event) (when (memq (process-status process) '(exit signal)) (kill-buffer))) (defun my/kill-process-buffer-on-exit () (set-process-sentinel (get-buffer-process (current-buffer)) #'my/shell-kill-buffer-sentinel)) (dolist (hook '(ielm-mode-hook term-exec-hook comint-exec-hook)) (add-hook hook 'my/kill-process-buffer-on-exit)) (defun set-scroll-conservatively () "Add to shell-mode-hook to prevent jump-scrolling on newlines in shell buffers." (set (make-local-variable 'scroll-conservatively) 10)) (defadvice comint-previous-matching-input (around suppress-history-item-messages activate) "Suppress the annoying 'History item : NNN' messages from shell history isearch. If this isn't enough, try the same thing with comint-replace-by-expanded-history-before-point." (let ((old-message (symbol-function 'message))) (unwind-protect (progn (fset 'message 'ignore) ad-do-it) (fset 'message old-message)))) (add-hook 'shell-mode-hook 'set-scroll-conservatively) ;; truncate buffers continuously (add-hook 'comint-output-filter-functions 'comint-truncate-buffer) ;; interpret and use ansi color codes in shell output windows (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
Eshell settings
Eshell is great for one-off shell things, but I use ZSH too much for it to be a full replacement. Regardless, it needs some tweaks in order to be fully useful.
First, a function to be called when eshell-mode is entered
(defun my/setup-eshell () (interactive) ;; turn off semantic-mode in eshell buffers (semantic-mode -1) ;; turn off hl-line-mode (hl-line-mode -1) (define-key eshell-mode-map (kbd "M-l") 'helm-eshell-history))
Also, after eshell has loaded its options, let's load some other niceties like completion, prompt and term settings:
(use-package eshell :config (progn (defalias 'emacs 'find-file) (defalias 'ec 'find-file) (setenv "PAGER" "cat") (use-package esh-opt :config (progn (use-package em-cmpl) (use-package em-prompt) (use-package em-term) (setq eshell-cmpl-cycle-completions nil ;; auto truncate after 12k lines eshell-buffer-maximum-lines 12000 ;; history size eshell-history-size 350 ;; buffer shorthand -> echo foo > #'buffer eshell-buffer-shorthand t ;; my prompt is easy enough to see eshell-highlight-prompt nil ;; treat 'echo' like shell echo eshell-plain-echo-behavior t) ;; Visual commands (setq eshell-visual-commands '("vi" "screen" "top" "less" "more" "lynx" "ncftp" "pine" "tin" "trn" "elm" "vim" "nmtui" "alsamixer" "htop" "el" "elinks" )) (setq eshell-visual-subcommands '(("git" "log" "diff" "show"))) (defun my/truncate-eshell-buffers () "Truncates all eshell buffers" (interactive) (save-current-buffer (dolist (buffer (buffer-list t)) (set-buffer buffer) (when (eq major-mode 'eshell-mode) (eshell-truncate-buffer))))) ;; After being idle for 5 seconds, truncate all the eshell-buffers if ;; needed. If this needs to be canceled, you can run `(cancel-timer ;; my/eshell-truncate-timer)' (setq my/eshell-truncate-timer (run-with-idle-timer 5 t #'my/truncate-eshell-buffers)) (when (not (functionp 'eshell/rgrep)) (defun eshell/rgrep (&rest args) "Use Emacs grep facility instead of calling external grep." (eshell-grep "rgrep" args t))) (defun eshell/cds () "Change directory to the project's root." (eshell/cd (locate-dominating-file default-directory ".git"))) (defun eshell/l (&rest args) "Same as `ls -lh'" (apply #'eshell/ls "-lh" args)) (defun eshell/ll (&rest args) "Same as `ls -lh'" (apply #'eshell/ls "-lh" args)) (defun eshell/la (&rest args) "Same as `ls -alh'" (apply #'eshell/ls "-alh" args)) (defun eshell/clear () "Clear the eshell buffer" (interactive) (let ((eshell-buffer-maximum-lines 0)) (eshell-truncate-buffer))))) (add-hook 'eshell-mode-hook #'my/setup-eshell) ;; See eshell-prompt-function below (setq eshell-prompt-regexp "^[^#$\n]* [#$] ") ;; So the history vars are defined (require 'em-hist) (if (boundp 'eshell-save-history-on-exit) ;; Don't ask, just save (setq eshell-save-history-on-exit t)) (if (boundp 'eshell-ask-to-save-history) ;; For older(?) version (setq eshell-ask-to-save-history 'always)) ;; See: https://github.com/kaihaosw/eshell-prompt-extras (use-package eshell-prompt-extras :init (progn (setq eshell-highlight-prompt nil ;; epe-git-dirty-char "Ϟ" epe-git-dirty-char "*" eshell-prompt-function 'epe-theme-dakrone))) (defun eshell/magit () "Function to open magit-status for the current directory" (interactive) (magit-status default-directory) nil)))
I use a dedicated buffer for connection to my desktop, with a binding of C-x
d
, if the buffer doesn't exist it is created.
(defun my/create-or-switch-to-delta-buffer () "Switch to the *eshell delta* buffer, or create it" (interactive) (if (get-buffer "*eshell-delta*") (switch-to-buffer "*eshell-delta*") (let ((eshell-buffer-name "*eshell-delta*")) (eshell)))) (global-set-key (kbd "C-x d") 'my/create-or-switch-to-delta-buffer) (defun my/create-or-switch-to-eshell-1 () "Switch to the *eshell* buffer, or create it" (interactive) (if (get-buffer "*eshell*") (switch-to-buffer "*eshell*") (let ((eshell-buffer-name "*eshell*")) (eshell)))) (defun my/create-or-switch-to-eshell-2 () "Switch to the *eshell*<2> buffer, or create it" (interactive) (if (get-buffer "*eshell*<2>") (switch-to-buffer "*eshell*<2>") (let ((eshell-buffer-name "*eshell*<2>")) (eshell)))) (defun my/create-or-switch-to-eshell-3 () "Switch to the *eshell*<3> buffer, or create it" (interactive) (if (get-buffer "*eshell*<3>") (switch-to-buffer "*eshell*<3>") (let ((eshell-buffer-name "*eshell*<3>")) (eshell)))) (global-set-key (kbd "H-1") 'my/create-or-switch-to-eshell-1) (global-set-key (kbd "H-2") 'my/create-or-switch-to-eshell-2) (global-set-key (kbd "H-3") 'my/create-or-switch-to-eshell-3) (global-set-key (kbd "s-1") 'my/create-or-switch-to-eshell-1) (global-set-key (kbd "s-2") 'my/create-or-switch-to-eshell-2) (global-set-key (kbd "s-3") 'my/create-or-switch-to-eshell-3) (global-set-key (kbd "M-1") 'my/create-or-switch-to-eshell-1) (global-set-key (kbd "M-2") 'my/create-or-switch-to-eshell-2) (global-set-key (kbd "M-3") 'my/create-or-switch-to-eshell-3)
Tramp settings
I have really been getting into TRAMP lately, I use it with eshell all the time, and dired tramp buffers are great for file management.
(use-package tramp :defer t :config (progn (with-eval-after-load 'tramp-cache (setq tramp-persistency-file-name "~/.emacs.d/etc/tramp")) (setq tramp-default-user-alist '(("\\`su\\(do\\)?\\'" nil "root")) tramp-adb-program "/Users/hinmanm/android-sdk-macosx/platform-tools/adb" ;; use the settings in ~/.ssh/config instead of Tramp's tramp-use-ssh-controlmaster-options nil backup-enable-predicate (lambda (name) (and (normal-backup-enable-predicate name) (not (let ((method (file-remote-p name 'method))) (when (stringp method) (member method '("su" "sudo")))))))) (use-package tramp-sh :config (progn (add-to-list 'tramp-remote-path "/usr/local/sbin") (add-to-list 'tramp-remote-path "/opt/java/current/bin") (add-to-list 'tramp-remote-path "~/bin")))))
Spell check and flyspell settings
I use Hunspell and Aspell checking spelling, ignoring words under 3 characters
and running very quickly. My personal word dictionary is at
~/.flydict
.
First, set up some Hunspell things if applicable, falling back to Aspell if Hunspell isn't available:
;; Standard location of personal dictionary (setq ispell-personal-dictionary "~/.flydict") ;; Mostly taken from ;; http://blog.binchen.org/posts/what-s-the-best-spell-check-set-up-in-emacs.html ;; if (aspell installed) { use aspell } ;; else if (hunspell installed) { use hunspell } ;; whatever spell checker I use, I always use English dictionary (setq ispell-program-name (executable-find "aspell")) (setq ispell-extra-args (list "--sug-mode=fast" ;; ultra|fast|normal|bad-spellers "--lang=en_US" "--ignore=3")) ;; hunspell ;; (setq ispell-program-name "hunspell") ;; ;; just reset dictionary to the safe one "en_US" for hunspell. ;; ;; if we need use different dictionary, we specify it in command line arguments ;; (setq ispell-local-dictionary "en_US") ;; (setq ispell-local-dictionary-alist ;; '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil nil nil utf-8))) (add-to-list 'ispell-skip-region-alist '("[^\000-\377]+")) (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:")) (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC")) (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_EXAMPLE" . "#\\+END_EXAMPLE"))
In most non-programming modes, M-.
can be used to spellcheck the word
(otherwise it would jump to the definition)
(defun my/enable-flyspell-prog-mode () (interactive) (flyspell-prog-mode)) (use-package flyspell :defer t :diminish "" :init (add-hook 'prog-mode-hook #'my/enable-flyspell-prog-mode) :config (use-package helm-flyspell :init (define-key flyspell-mode-map (kbd "M-S") 'helm-flyspell-correct)))
View-mode and doc-view
Read-only viewing of files. Keybindings for paging through stuff in a less/vim manner.
Make sure you install mupdf
for the best quality PDFs on Linux and OSX. (brew
install mupdf
on osx)
(use-package view :defer t :bind (("C-M-n" . View-scroll-half-page-forward) ("C-M-p" . View-scroll-half-page-backward)) :config (progn ;; When in view-mode, the buffer is read-only: (setq view-read-only t) (defun View-goto-line-last (&optional line) "goto last line" (interactive "P") (goto-line (line-number-at-pos (point-max)))) ;; less like (define-key view-mode-map (kbd "N") 'View-search-last-regexp-backward) (define-key view-mode-map (kbd "?") 'View-search-regexp-backward?) (define-key view-mode-map (kbd "g") 'View-goto-line) (define-key view-mode-map (kbd "G") 'View-goto-line-last) ;; vi/w3m like (define-key view-mode-map (kbd "h") 'backward-char) (define-key view-mode-map (kbd "j") 'next-line) (define-key view-mode-map (kbd "k") 'previous-line) (define-key view-mode-map (kbd "l") 'forward-char))) (use-package doc-view :config (define-key doc-view-mode-map (kbd "j") #'doc-view-next-line-or-next-page) (define-key doc-view-mode-map (kbd "k") #'doc-view-previous-line-or-previous-page) ;; use 'q' to kill the buffer, not just hide it (define-key doc-view-mode-map (kbd "q") #'kill-this-buffer))
Dired
Dired is sweet, I require dired-x
also so I can hit C-x C-j
and go directly to a dired buffer.
Setting ls-lisp-dirs-first
means directories are always at the
top. Always copy and delete recursively. Also enable
hl-line-mode
in dired, since it's easier to see the cursor then.
To start, a helper to use "open
" to open files in dired-mode with M-o
(similar to Finder in OSX).
(defun my/dired-open () "Use the OSX `open' command to open a file with the correct editor" (interactive) (save-window-excursion (dired-do-async-shell-command "~/bin/open" current-prefix-arg (dired-get-marked-files t current-prefix-arg))))
And then some other things to setup when dired runs. C-x C-q
to edit
writable-dired mode is aawwweeeesssoooommee, it makes renames super easy.
(defun my/dired-mode-hook () (my/turn-on-hl-line-mode) (toggle-truncate-lines 1)) (use-package dired :bind ("C-x C-j" . dired-jump) :config (progn (use-package dired-x :init (setq-default dired-omit-files-p t) :config (add-to-list 'dired-omit-extensions ".DS_Store")) (customize-set-variable 'diredp-hide-details-initially-flag nil) (use-package dired+) (use-package dired-aux :init (use-package dired-async)) (put 'dired-find-alternate-file 'disabled nil) (setq ls-lisp-dirs-first t dired-recursive-copies 'always dired-recursive-deletes 'always dired-dwim-target t ;; -F marks links with @ dired-ls-F-marks-symlinks t delete-by-moving-to-trash t ;; Auto refresh dired global-auto-revert-non-file-buffers t wdired-allow-to-change-permissions t) (define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file) (define-key dired-mode-map (kbd "C-M-u") 'dired-up-directory) (define-key dired-mode-map (kbd "M-o") #'my/dired-open) (define-key dired-mode-map (kbd "C-x C-q") 'wdired-change-to-wdired-mode) (add-hook 'dired-mode-hook #'my/dired-mode-hook)))
emacsclient
Let's make sure to start up a server!
Disabled, I actually start up a background emacs --daemon
for this
saveplace
Navigates back to where you were editing a file next time you open it
(use-package saveplace :defer t :init (setq-default save-place t) (setq save-place-file (expand-file-name ".places" user-emacs-directory)))
recentf
Set up keeping track of recent files, up to 2000 of them.
If emacs has been idle for 10 minutes, clean up the recent files. Also save the list of recent files every 5 minutes.
This also only enables recentf-mode if idle, so that emacs starts up faster.
(use-package recentf :defer t :init (progn (setq recentf-max-saved-items 300 recentf-exclude '("/auto-install/" ".recentf" "/repos/" "/elpa/" "\\.mime-example" "\\.ido.last" "COMMIT_EDITMSG" ".gz" "~$" "/tmp/" "/ssh:" "/sudo:" "/scp:") recentf-auto-cleanup 600) (when (not noninteractive) (recentf-mode 1)) (defun recentf-save-list () "Save the recent list. Load the list from the file specified by `recentf-save-file', merge the changes of your current session, and save it back to the file." (interactive) (let ((instance-list (cl-copy-list recentf-list))) (recentf-load-list) (recentf-merge-with-default-list instance-list) (recentf-write-list-to-file))) (defun recentf-merge-with-default-list (other-list) "Add all items from `other-list' to `recentf-list'." (dolist (oitem other-list) ;; add-to-list already checks for equal'ity (add-to-list 'recentf-list oitem))) (defun recentf-write-list-to-file () "Write the recent files list to file. Uses `recentf-list' as the list and `recentf-save-file' as the file to write to." (condition-case error (with-temp-buffer (erase-buffer) (set-buffer-file-coding-system recentf-save-file-coding-system) (insert (format recentf-save-file-header (current-time-string))) (recentf-dump-variable 'recentf-list recentf-max-saved-items) (recentf-dump-variable 'recentf-filter-changer-current) (insert "\n \n;;; Local Variables:\n" (format ";;; coding: %s\n" recentf-save-file-coding-system) ";;; End:\n") (write-file (expand-file-name recentf-save-file)) (when recentf-save-file-modes (set-file-modes recentf-save-file recentf-save-file-modes)) nil) (error (warn "recentf mode: %s" (error-message-string error)))))))
whitespace-mode
I set the width to 140, because although it should be 80, I only want highlighting past 140 columns, otherwise Java is unreadable.
(setq whitespace-line-column 140)
Here are the things that whitespace-mode should highlight
(setq whitespace-style '(tabs newline space-mark tab-mark newline-mark face lines-tail))
Display pretty things for newlines and tabs (nothing for spaces)
(setq whitespace-display-mappings ;; all numbers are Unicode codepoint in decimal. e.g. (insert-char 182 1) ;; 32 SPACE, 183 MIDDLE DOT '((space-mark nil) ;; 10 LINE FEED ;;(newline-mark 10 [172 10]) (newline-mark nil) ;; 9 TAB, MIDDLE DOT (tab-mark 9 [183 9] [92 9])))
Disable it in certain modes where whitespace doesn't make sense.
(setq whitespace-global-modes '(not org-mode eshell-mode shell-mode web-mode log4j-mode "Web" dired-mode emacs-lisp-mode clojure-mode lisp-mode))
Always turn on whitespace mode
;; turn on whitespace mode globally (global-whitespace-mode 1) (diminish 'global-whitespace-mode "")
Indicate trailing empty lines in the GUI:
(set-default 'indicate-empty-lines t) (setq show-trailing-whitespace t)
Programming language-specific configuration
Configuration options for language-specific packages live here. I
generally only have configuration for languages I use, but the
"order of usage" usually goes clojure & shell > elisp > python >
ruby > java > everything else
.
CEDET (semantic-mode)
Basic semantic-mode things
First, use a development version of cedet if applicable, I download the latest
snapshot from http://www.randomsample.de/cedet-snapshots/ and extract it in
~/src/elisp. Don't forget to run make
in it!
And then things to set up semantic mode
(defun my/setup-semantic-mode () (interactive) (use-package semantic) (require 'semantic/ia) (require 'semantic/wisent) ;; Use a better (though slower) parser for java, if it exists ;; (autoload 'wisent-java-default-setup "semantic/wisent/java") (setq semantic-default-submodes '(global-semantic-idle-scheduler-mode global-semanticdb-minor-mode global-semantic-idle-summary-mode global-semantic-stickyfunc-mode)) (semantic-mode t) (local-set-key [(control return)] 'semantic-ia-complete-symbol) (local-set-key "\C-c>" 'semantic-complete-analyze-inline) (local-set-key "\C-c?" 'semantic-analyze-proto-impl-toggle)) (add-hook 'c-mode-hook #'my/setup-semantic-mode) (add-hook 'java-mode-hook #'my/setup-semantic-mode)
General prog-mode hooks
Remove some back-ends from vc-mode, no need to check all this ancient things:
(setq vc-handled-backends '(SVN Git))
In programming modes, make sure things like FIXME and TODO are highlighted so they stand out:
(defun my/add-watchwords () "Highlight FIXME, TODO, and NOCOMMIT in code" (font-lock-add-keywords nil '(("\\<\\(FIXME\\|TODO\\|NOCOMMIT\\)\\>" 1 '((:foreground "#d7a3ad") (:weight bold)) t)))) (defun my/turn-on-hl-line-mode () "Turn on hl-line-mode" (interactive) (hl-line-mode 1)) (add-hook 'prog-mode-hook #'my/add-watchwords) (add-hook 'prog-mode-hook #'my/turn-on-hl-line-mode) (add-hook 'org-mode-hook #'my/turn-on-hl-line-mode)
Clojure
Some helper functions for jumping between tests, I prefer test/foo.clj instead of foo_test.clj
;; custom test locations instead of foo_test.clj, use test/foo.clj (defun clojure-test-for-without-test (namespace) (interactive) (let* ((namespace (clojure-underscores-for-hyphens namespace)) (segments (split-string namespace "\\.")) (before (subseq segments 0 1)) (after (subseq segments 1)) (test-segments (append before (list "test") after))) (format "%stest/%s.clj" (locate-dominating-file buffer-file-name "src/") (mapconcat 'identity test-segments "/")))) (defun clojure-test-implementation-for-without-test (namespace) (interactive) (let* ((namespace (clojure-underscores-for-hyphens namespace)) (segments (split-string namespace "\\.")) (before (subseq segments 0 1)) (after (subseq segments 2)) (impl-segments (append before after))) (format "%s/src/%s.clj" (locate-dominating-file buffer-file-name "src/") (mapconcat 'identity impl-segments "/"))))
Other Clojure-specific settings:
(defun my/clojure-things-hook () "Set up clojure-y things" (eldoc-mode 1) (subword-mode t) ;; use my test layout fns ;; (setq clojure-test-for-fn 'my-clojure-test-for) ;; (setq clojure-test-implementation-for-fn 'my-clojure-test-implementation-for) ;; compile faster (setq font-lock-verbose nil) (global-set-key (kbd "C-c t") 'clojure-jump-between-tests-and-code) (paredit-mode 1)) (use-package clojure-mode :config (progn (add-hook 'clojure-mode-hook 'my/clojure-things-hook)))
Let's define a couple of helper functions for setting up the cider and ac-nrepl packages:
(defun my/setup-cider () (lambda () (setq cider-history-file "~/.nrepl-history" cider-hide-special-buffers t cider-repl-history-size 10000 cider-prefer-local-resources t cider-popup-stacktraces-in-repl t) (paredit-mode 1) (eldoc-mode 1)))
And then finally use them if cider and ac-nrepl packages are available:
(use-package cider :init (progn (add-hook 'cider-mode-hook 'my/setup-cider) (add-hook 'cider-repl-mode-hook 'my/setup-cider) (add-hook 'cider-mode-hook 'my/clojure-things-hook) (add-hook 'cider-repl-mode-hook 'my/clojure-things-hook)))
Shell
I write a LOT of shell-scripts, I turn off show-paren-mode (I have show-smartparen-mode anyway) and flycheck (I don't want to run it!) as well as not blinking the matching paren.
(add-hook 'sh-mode-hook (lambda () (show-paren-mode -1) (flycheck-mode -1) (setq blink-matching-paren nil))) (add-to-list 'auto-mode-alist '("\\.zsh$" . shell-script-mode))
Elisp
This contains the configuration for elisp programming
First, turn on eldoc everywhere it's useful:
(defun my/turn-on-paredit-and-eldoc () (interactive) (paredit-mode 1) (eldoc-mode 1)) (add-hook 'emacs-lisp-mode-hook #'my/turn-on-paredit-and-eldoc) (add-hook 'ielm-mode-hook #'my/turn-on-paredit-and-eldoc)
And some various eldoc settings:
(use-package eldoc :config (progn (use-package diminish :init (progn (diminish 'eldoc-mode ""))) (setq eldoc-idle-delay 0.3) (set-face-attribute 'eldoc-highlight-function-argument nil :underline t :foreground "green" :weight 'bold)))
Change the faces for elisp regex grouping:
(set-face-foreground 'font-lock-regexp-grouping-backslash "#ff1493") (set-face-foreground 'font-lock-regexp-grouping-construct "#ff8c00")
Define some niceties for popping up an ielm buffer:
(defun ielm-other-window () "Run ielm on other window" (interactive) (switch-to-buffer-other-window (get-buffer-create "*ielm*")) (call-interactively 'ielm)) (define-key emacs-lisp-mode-map (kbd "C-c C-z") 'ielm-other-window) (define-key lisp-interaction-mode-map (kbd "C-c C-z") 'ielm-other-window)
Turn on elisp-slime-nav if available, so M-.
works to jump to function
definitions:
(use-package elisp-slime-nav :init (add-hook 'emacs-lisp-mode-hook #'elisp-slime-nav-mode))
Borrowed from Steve Purcell's config. This pretty-prints the results.
(bind-key "M-:" 'pp-eval-expression) (defun sanityinc/eval-last-sexp-or-region (prefix) "Eval region from BEG to END if active, otherwise the last sexp." (interactive "P") (if (and (mark) (use-region-p)) (eval-region (min (point) (mark)) (max (point) (mark))) (pp-eval-last-sexp prefix))) (bind-key "C-x C-e" 'sanityinc/eval-last-sexp-or-region emacs-lisp-mode-map) (define-key lisp-mode-shared-map (kbd "RET") 'reindent-then-newline-and-indent)
Python
Some various python settings, including loading jedi if needed to set up keys, the custom hook only loads jedi when editing python files:
(use-package python :defer t :config (progn (define-key python-mode-map (kbd "C-c C-z") 'run-python) (define-key python-mode-map (kbd "<backtab>") 'python-back-indent) (defun my/setup-jedi () (interactive) (use-package jedi :config (progn (jedi:setup) (jedi:ac-setup) (setq jedi:setup-keys t) (setq jedi:complete-on-dot t) (define-key python-mode-map (kbd "C-c C-d") 'jedi:show-doc) (setq jedi:tooltip-method nil) (set-face-attribute 'jedi:highlight-function-argument nil :foreground "green") (define-key python-mode-map (kbd "C-c C-l") 'jedi:get-in-function-call)))) (add-hook 'python-mode-hook #'my/setup-jedi)))
Java
Java uses eclim and/or malabar to make life at least a little bit livable.
intellij-java-style
is a copy of our Intellij indentation rules for
Elasticsearch, which are a little weird in some cases, but needed in order to
work with the ES codebase.
(defun java-line-up-only-constructor-or-dont (thing) "If at a class constructor, line up with the paren, if not, use ++ indentation" (interactive) (save-excursion (beginning-of-line) (backward-up-list 1) (backward-word 2) ;; Now at either "new" or something else (let* ((sym (semantic-ctxt-current-symbol))) (if (eq '("new") sym) '++ (c-lineup-arglist-intro-after-paren thing))))) (defconst intellij-java-style '((c-basic-offset . 4) (c-comment-only-line-offset . (0 . 0)) ;; the following preserves Javadoc starter lines (c-offsets-alist . ((inline-open . 0) (topmost-intro-cont . +) (statement-block-intro . +) (knr-argdecl-intro . +) (substatement-open . +) (substatement-label . +) (case-label . +) (label . +) (statement-case-open . +) (statement-cont . ++) (arglist-intro . 0) ;; (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-cont-nonempty . ++) ;; (arglist-cont-nonempty . java-line-up-only-constructor-or-dont) (arglist-close . --) ;; (arglist-close . c-lineup-arglist) (inexpr-class . 0) (access-label . 0) (inher-intro . ++) (inher-cont . ++) ;; (brace-list-intro . ++) (brace-list-intro . +) (func-decl-cont . ++)))) "Elasticsearch's Intellij Java Programming Style") (c-add-style "intellij" intellij-java-style) (customize-set-variable 'c-default-style '((java-mode . "intellij") (awk-mode . "awk") (other . "gnu"))) (defun setup-java () (interactive) (define-key java-mode-map (kbd "M-,") 'pop-tag-mark) (c-set-style "intellij" t) (subword-mode 1) ;; Generic java stuff things (setq-local fci-rule-column 99) ;; remove the stupid company-eclim backend (when (boundp 'company-backends) (delete 'company-eclim company-backends))) (add-hook 'java-mode-hook 'setup-java)
malabar-mode
Malabar mode is for dealing with maven projects, such as Elasticsearch, where it is nice to be able to compile the code.
(defun my/malabar-java-hook () (use-package malabar-mode) (malabar-mode 1)) ;; (add-hook 'java-mode-hook #'my/malabar-java-hook)
Ruby
Using rbenv, set it up correctly when idle
(use-package rbenv :disabled t :init (global-rbenv-mode t))
Or, chruby, which is much simpler (no shims)
brew install chruby ruby-install ruby-install 2.1.3
(use-package chruby :defer t :init (chruby "ruby-2.1.3"))
Haskell
Use GHC for haskell mode, and turn on auto-complete and some doc/indent modes:
(use-package haskell-mode :defer t :init (progn (add-hook 'haskell-mode-hook #'haskell-indentation-mode) (add-hook 'haskell-mode-hook #'turn-on-haskell-doc-mode) (add-hook 'haskell-mode-hook #'subword-mode)) :config (progn (let ((my-cabal-path (expand-file-name "~/.cabal/bin"))) (setenv "PATH" (concat my-cabal-path ":" (getenv "PATH"))) (add-to-list 'exec-path my-cabal-path)) (custom-set-variables '(haskell-tags-on-save t)) (custom-set-variables '(haskell-process-suggest-remove-import-lines t) '(haskell-process-auto-import-loaded-modules t) '(haskell-process-log t)) (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-or-reload) (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch) (define-key haskell-mode-map (kbd "C-c C-n C-t") 'haskell-process-do-type) (define-key haskell-mode-map (kbd "C-c C-n C-i") 'haskell-process-do-info) (define-key haskell-mode-map (kbd "C-c C-n C-c") 'haskell-process-cabal-build) (define-key haskell-mode-map (kbd "C-c C-n c") 'haskell-process-cabal) (define-key haskell-mode-map (kbd "SPC") 'haskell-mode-contextual-space) (eval-after-load 'haskell-cabal '(progn (define-key haskell-cabal-mode-map (kbd "C-c C-z") 'haskell-interactive-switch) (define-key haskell-cabal-mode-map (kbd "C-c C-k") 'haskell-interactive-mode-clear) (define-key haskell-cabal-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build) (define-key haskell-cabal-mode-map (kbd "C-c c") 'haskell-process-cabal))) (custom-set-variables '(haskell-process-type 'cabal-repl)) (autoload 'ghc-init "ghc" nil t) (autoload 'ghc-debug "ghc" nil t) (add-hook 'haskell-mode-hook (lambda () (ghc-init)))))
Javascript
Bleh javascript. js2-mode is better than nothing.
(use-package js2-mode :init (progn (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode)) (defalias 'javascript-generic-mode 'js2-mode)) :config (progn (js2-imenu-extras-setup) (setq-default js-auto-indent-flag nil js-indent-level 2)))
There's tern
also, but I leave it turned off by default
(use-package tern :init ;;(add-hook 'js-mode-hook (lambda () (tern-mode t))) )
Elasticsearch (es-mode)
(es-mode) stuff, loaded from disk so I can develop on it quickly.
(if (file-exists-p "~/src/elisp/es-mode") (progn (add-to-list 'load-path "~/src/elisp/es-mode") (use-package es-mode :init (use-package ob-elasticsearch) ;; Don't warn me about delete statements :config (setq es-warn-on-delete-query nil)) (use-package org :config (org-babel-do-load-languages 'org-babel-load-languages '((elasticsearch . t))))) (progn (use-package es-mode :ensure t :init (use-package ob-elasticsearch) ;; Don't warn me about delete statements :config (setq es-warn-on-delete-query nil)) (use-package org :config (org-babel-do-load-languages 'org-babel-load-languages '((elasticsearch . t))))))
theme
Misc theme settings
color theme
For light-colored backgrounds, I used leuven-theme. For dark-colored backgrounds (most of the time), I use my own custom theme, called dakrone-theme. Sometimes I use moe-theme for a dark background also, although the magenta text annoys me somewhat. Lately I've also been checking out tangotango, which seems nice.
(setq ns-use-srgb-colorspace t) (defun dakrone-dark () (interactive) ;; (use-package color-theme-sanityinc-tomorrow ;; :init (color-theme-sanityinc-tomorrow-night)) (use-package material-theme :disabled t :init (load-theme 'material t)) (use-package apropospriate-theme :init (load-theme 'apropospriate-dark t))) (defun dakrone-light () (interactive) (use-package leuven-theme :init (load-theme 'leuven t) :config (set-background-color "#f0f0f0")) (use-package material-theme :disabled t :init (load-theme 'material-light t))) (if (eq my/background 'dark) (dakrone-dark) (dakrone-light))
fonts
I've been using Fantasque Sans Mono lately, it looks pretty nice to me. On Linux I've been using Bitstream Vera Sans Mono. I also use Anonymous Pro and Inconsolata a lot.
Config for OSX:
(defun my/setup-osx-fonts () (interactive) (when (eq system-type 'darwin) (set-fontset-font "fontset-default" 'symbol "Monaco") ;;(set-default-font "Fantasque Sans Mono") ;;(set-default-font "Monaco") ;;(set-default-font "Anonymous Pro") ;;(set-default-font "Inconsolata") (set-default-font "Bitstream Vera Sans Mono") ;;(set-default-font "Menlo") ;;(set-default-font "Source Code Pro") ;;(set-default-font "Mensch") (set-face-attribute 'default nil :height 120) (set-face-attribute 'fixed-pitch nil :height 120) ;; Anti-aliasing (setq mac-allow-anti-aliasing t))) (when (eq system-type 'darwin) (add-hook 'after-init-hook #'my/setup-osx-fonts))
Config for Linux/X11 systems:
(defun my/setup-x11-fonts () (interactive) (when (eq window-system 'x) ;; Font family (add-to-list 'default-frame-alist '(font . "DejaVu Sans Mono-9")) ;; Font size ;;(set-face-attribute 'default nil :height 90) )) (when (eq window-system 'x) (add-hook 'after-init-hook #'my/setup-x11-fonts))
modeline (mode-line)
Ehh.. I go back and forth.
(use-package powerline :disabled t :init (powerline-default-theme))
(use-package smart-mode-line :disabled t :init (progn (setq sml/theme my/background sml/name-width 20) (sml/setup)))
Finally, Amit's mode line
;; Mode line setup (setq-default mode-line-format '(; Position, including warning for 80 columns (:propertize "%4l:" face mode-line-position-face) (:eval (propertize "%3c" 'face (if (>= (current-column) 80) 'mode-line-80col-face 'mode-line-position-face))) ;; emacsclient [default -- keep?] mode-line-client " " ;; read-only or modified status (:eval (cond (buffer-read-only (propertize " RO " 'face 'mode-line-read-only-face)) ((buffer-modified-p) (propertize " ** " 'face 'mode-line-modified-face)) (t " "))) " " ;; directory and buffer/file name (:propertize (:eval (shorten-directory default-directory 30)) face mode-line-folder-face) (:propertize "%b" face mode-line-filename-face) ;; narrow [default -- keep?] ;;" %n " ;; mode indicators: vc, recursive edit, major mode, minor modes, process, global (vc-mode vc-mode) " %[" (:propertize mode-name face mode-line-mode-face) "%] " (:eval (propertize (format-mode-line minor-mode-alist) 'face 'mode-line-minor-mode-face)) (:propertize mode-line-process face mode-line-process-face) " " ;; mode-line-misc-info is better than Amit's version mode-line-misc-info " " ;; nyan-mode uses nyan cat as an alternative to %p (:eval (when nyan-mode (list (nyan-create)))) )) ;; Helper function (defun shorten-directory (dir max-length) "Show up to `max-length' characters of a directory name `dir'." (let ((path (reverse (split-string (abbreviate-file-name dir) "/"))) (output "")) (when (and path (equal "" (car path))) (setq path (cdr path))) (while (and path (< (length output) (- max-length 4))) (setq output (concat (car path) "/" output)) (setq path (cdr path))) (when path (setq output (concat ".../" output))) output)) ;; Extra mode line faces (make-face 'mode-line-read-only-face) (make-face 'mode-line-modified-face) (make-face 'mode-line-folder-face) (make-face 'mode-line-filename-face) (make-face 'mode-line-position-face) (make-face 'mode-line-mode-face) (make-face 'mode-line-minor-mode-face) (make-face 'mode-line-process-face) (make-face 'mode-line-80col-face) (set-face-attribute 'mode-line nil :foreground "gray60" :background "gray20" :inverse-video nil :box '(:line-width 2 :color "gray20" :style nil)) (set-face-attribute 'mode-line-inactive nil :foreground "gray80" :background "gray40" :inverse-video nil :box '(:line-width 2 :color "gray40" :style nil)) (set-face-attribute 'mode-line-read-only-face nil :inherit 'mode-line-face :foreground "#4271ae" :box '(:line-width 2 :color "#4271ae")) (set-face-attribute 'mode-line-modified-face nil :inherit 'mode-line-face :foreground "#c82829" :background "#ffffff" :box '(:line-width 2 :color "#c82829")) (set-face-attribute 'mode-line-folder-face nil :inherit 'mode-line-face :foreground "gray60") (set-face-attribute 'mode-line-filename-face nil :inherit 'mode-line-face :foreground "#eab700" :weight 'bold) (set-face-attribute 'mode-line-position-face nil :inherit 'mode-line-face :height 100) (set-face-attribute 'mode-line-mode-face nil :inherit 'mode-line-face :foreground "gray80") (set-face-attribute 'mode-line-minor-mode-face nil :inherit 'mode-line-mode-face :foreground "gray40" :height 110) (set-face-attribute 'mode-line-process-face nil :inherit 'mode-line-face :foreground "#718c00") (set-face-attribute 'mode-line-80col-face nil :inherit 'mode-line-position-face :foreground "black" :background "#eab700")
fringe
So, fringe is nice actually, but the background for it kind of sucks in
leuven
, so I set it to the same color as the background
(defun my/set-fringe-background () "Set the fringe background to the same color as the regular background." (interactive) (setq my/fringe-background-color (face-background 'default)) (custom-set-faces `(fringe ((t (:background ,my/fringe-background-color)))))) (add-hook 'after-init-hook #'my/set-fringe-background) ;; Indicate where a buffer stars and stops (setq-default indicate-buffer-boundaries 'right) (toggle-indicate-empty-lines)
org-mode
I use org-mode a ton, so it get's its own page here.
A great lot of this was taken from http://doc.norang.ca/org-mode.html, to which I owe almost all of the agenda configuration. The capture stuff and regular org settings are mine.
First, the hook that gets run every time org-mode is started, to turn on certain modes
(defun my/org-mode-hook () (interactive) (turn-on-auto-fill) (turn-on-flyspell) (yas-minor-mode-on) (when (fboundp 'my/enable-abbrev-mode) (my/enable-abbrev-mode)) ;; fix some bindings that org-mode overwrites (define-key org-mode-map [C-tab] 'other-window) (define-key org-mode-map [C-S-tab] (lambda () (interactive) (other-window -1))) (define-key org-mode-map (kbd "C-'") 'eyebrowse-next-window-config) (define-key org-mode-map (kbd "C-c C-x C-f") 'org-refile) (define-key org-agenda-mode-map (kbd "C-c C-x C-f") 'org-agenda-refile))
And now the huge org-mode configuration
(use-package org :bind (("C-c l" . org-store-link) ("C-c a" . org-agenda) ("C-c b" . org-iswitchb) ("C-c c" . org-capture) ("C-c M-p" . org-babel-previous-src-block) ("C-c M-n" . org-babel-next-src-block) ("C-c S" . org-babel-previous-src-block) ("C-c s" . org-babel-next-src-block)) :config (progn (use-package org-install) ;; org-export (use-package ox) ;; Enable archiving things (use-package org-archive) (add-hook 'org-mode-hook #'my/org-mode-hook) (setq org-directory (file-truename "~/org") ;; follow links by pressing ENTER on them org-return-follows-link t ;; allow changing between todo stats directly by hotkey org-use-fast-todo-selection t ;; syntax highlight code in source blocks org-src-fontify-natively t ;; for the leuven theme, fontify the whole heading line org-fontify-whole-heading-line t ;; force UTF-8 org-export-coding-system 'utf-8 ;; use ido completion when I can org-completion-use-ido t ;; don't indent source code org-edit-src-content-indentation 0 ;; don't adapt indentation org-adapt-indentation nil ;; preserve the indentation inside of source blocks org-src-preserve-indentation t ;; Imenu should use 3 depth instead of 2 org-imenu-depth 3 ;; always start the agenda on today org-agenda-start-on-weekday nil ;; Use sticky agenda's so they persist org-agenda-sticky t ;; show 4 agenda days org-agenda-span 4 ;; special begin/end of line to skip tags and stars org-special-ctrl-a/e t ;; special keys for killing a headline org-special-ctrl-k t ;; don't adjust subtrees that I copy org-yank-adjusted-subtrees nil ;; try to be smart when editing hidden things org-catch-invisible-edits 'smart ;; blank lines are removed when exiting the code edit buffer org-src-strip-leading-and-trailing-blank-lines t ;; how org-src windows are set up when hitting C-c ' org-src-window-setup 'current-window ;;org-src-window-setup 'other-window ;; Overwrite the current window with the agenda org-agenda-window-setup 'current-window ;; Use full outline paths for refile targets - we file directly with IDO org-refile-use-outline-path t ;; Targets complete directly with IDO org-outline-path-complete-in-steps nil ;; Allow refile to create parent tasks with confirmation org-refile-allow-creating-parent-nodes (quote confirm) ;; never leave empty lines in collapsed view org-cycle-separator-lines 0 ;; Use cider as the clojure backend org-babel-clojure-backend 'cider ;; don't run stuff automatically on export org-export-babel-evaluate nil ;; export tables as CSV instead of tab-delineated org-table-export-default-format "orgtbl-to-csv" ;; always enable noweb, results as code and exporting both org-babel-default-header-args (cons '(:noweb . "yes") (assq-delete-all :noweb org-babel-default-header-args)) org-babel-default-header-args (cons '(:exports . "both") (assq-delete-all :exports org-babel-default-header-args)) ;; I don't want to be prompted on every code block evaluation org-confirm-babel-evaluate nil ;; Do not dim blocked tasks org-agenda-dim-blocked-tasks nil ;; Compact the block agenda view org-agenda-compact-blocks t ;; Mark entries as done when archiving org-archive-mark-done nil ;; Where to put headlines when archiving them org-archive-location "%s_archive::* Archived Tasks" ;; Sorting order for tasks on the agenda org-agenda-sorting-strategy (quote ((agenda habit-down time-up priority-down user-defined-up effort-up category-keep) (todo priority-down category-up effort-up) (tags priority-down category-up effort-up) (search priority-down category-up))) ;; Enable display of the time grid so we can see the marker for the current time org-agenda-time-grid (quote ((daily today remove-match) #("----------------" 0 16 (org-heading t)) (0900 1100 1300 1500 1700))) ;; Include the diary file in the agenda org-agenda-include-diary t org-agenda-diary-file "~/diary" org-agenda-insert-diary-extract-time t ;; keep the agenda filter until manually removed org-agenda-persistent-filter t org-agenda-repeating-timestamp-show-all t ;; Show all agenda dates - even if they are empty org-agenda-show-all-dates t ;; Agenda org-mode files org-agenda-files `(,(file-truename "~/org/") ,(file-truename "~/org/es/") ,(file-truename "~/org/es/design/") ,(file-truename "~/org/book/"))) ;; Save all org-mode buffers every hour at :59 (run-at-time "00:59" 3600 'org-save-all-org-buffers) ;; Org todo keywords (setq org-todo-keywords (quote ((sequence "SOMEDAY(s)" "TODO(t)" "INPROGRESS(i)" "WAITING(w@/!)" "NEEDSREVIEW(n@/!)" "|" "DONE(d)") (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)")))) ;; Org faces (setq org-todo-keyword-faces (quote (("TODO" :foreground "red" :weight bold) ("INPROGRESS" :foreground "deep sky blue" :weight bold) ("SOMEDAY" :foreground "purple" :weight bold) ("NEEDSREVIEW" :foreground "#edd400" :weight bold) ("DONE" :foreground "forest green" :weight bold) ("WAITING" :foreground "orange" :weight bold) ("HOLD" :foreground "magenta" :weight bold) ("CANCELLED" :foreground "forest green" :weight bold)))) ;; add or remove tags on state change (setq org-todo-state-tags-triggers (quote (("CANCELLED" ("CANCELLED" . t)) ("WAITING" ("WAITING" . t)) ("HOLD" ("WAITING") ("HOLD" . t)) (done ("WAITING") ("HOLD")) ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) ("INPROGRESS" ("WAITING") ("CANCELLED") ("HOLD")) ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) ;; refile targets all level 1 and 2 headers in current file and agenda files (setq org-refile-targets '((nil :maxlevel . 2) (org-agenda-files :maxlevel . 2))) ;; quick access to common tags (setq org-tag-alist '(("oss" . ?o) ("home" . ?h) ("work" . ?w) ("book" . ?b) ("support" . ?s) ("docs" . ?d) ("export" . ?e) ("noexport" . ?n))) ;; capture templates (setq org-capture-templates (quote (("t" "Todo" entry (file "~/org/refile.org") "* TODO %?\n%U\n") ("n" "Notes" entry (file+headline "~/org/notes.org" "Notes") "* %? :NOTE:\n%U\n") ("j" "Journal" entry (file+datetree "~/org/journal.org") "* %?\n%U\n") ("b" "Book/Bibliography" entry (file+headline "~/org/bibliography.org" "Refile") "* %?%^{TITLE}p%^{AUTHOR}p%^{TYPE}p")))) ;; Custom agenda command definitions (setq org-agenda-custom-commands (quote (("N" "Notes" tags "NOTE" ((org-agenda-overriding-header "Notes") (org-tags-match-list-sublevels t))) (" " "Agenda" ((agenda "" nil) ;; All items with the "REFILE" tag, everything in refile.org ;; automatically gets that applied (tags "REFILE" ((org-agenda-overriding-header "Tasks to Refile") (org-tags-match-list-sublevels nil))) ;; All "INPROGRESS" todo items (todo "INPROGRESS" ((org-agenda-overriding-header "Current work"))) ;; All headings with the "support" tag (tags "support/!" ((org-agenda-overriding-header "Support cases"))) ;; All "NEESREVIEW" todo items (todo "NEEDSREVIEW" ((org-agenda-overriding-header "Waiting on reviews"))) ;; All "WAITING" items without a "support" tag (tags "WAITING-support" ((org-agenda-overriding-header "Waiting for feedback"))) ;; All TODO items (todo "TODO" ((org-agenda-overriding-header "Task list") (org-agenda-sorting-strategy '(time-up priority-down category-keep)))) ;; Everything on hold (todo "HOLD" ((org-agenda-overriding-header "On-hold"))) ;; Everything that's done and archivable ;; (todo "DONE" ;; ((org-agenda-overriding-header "Tasks for archive") ;; (org-agenda-skip-function 'my/skip-non-archivable-tasks))) ) nil)))) ;; Exclude DONE state tasks from refile targets (defun my/verify-refile-target () "Exclude todo keywords with a done state from refile targets" (not (member (nth 2 (org-heading-components)) org-done-keywords))) (setq org-refile-target-verify-function 'my/verify-refile-target) ;; org-mode bindings (define-key org-mode-map (kbd "C-M-<return>") 'org-insert-todo-heading) (define-key org-mode-map (kbd "C-c t") 'org-todo) (define-key org-mode-map (kbd "M-G") 'org-plot/gnuplot) (define-key org-mode-map (kbd "RET") 'org-return-indent) ;; swap C-RET and M-RET (define-key org-mode-map (kbd "C-<return>") 'org-insert-heading) (define-key org-mode-map (kbd "M-<return>") 'org-insert-heading-after-current) (local-unset-key (kbd "M-S-<return>")) ;; org-babel stuff (require 'ob-clojure) (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (clojure . t) (dot . t) (sh . t) (ruby . t) (R . t) (python . t) (gnuplot . t) (plantuml . t) (latex . t))) ;; plantuml jar path (setq org-plantuml-jar-path "/usr/local/Cellar/plantuml/8002/plantuml.8002.jar") ;; Use org.css from the :wq website for export document stylesheets (setq org-html-head-extra "<link rel=\"stylesheet\" href=\"https://dakrone.github.io/org.css\" type=\"text/css\" />") (setq org-html-head-include-default-style nil) ;; ensure this variable is defined (unless (boundp 'org-babel-default-header-args:sh) (setq org-babel-default-header-args:sh '())) ;; add a default shebang header argument shell scripts (add-to-list 'org-babel-default-header-args:sh '(:shebang . "#!/usr/bin/env zsh")) ;; add a default shebang header argument for python (add-to-list 'org-babel-default-header-args:python '(:shebang . "#!/usr/bin/env python")) ;; Clojure-specific org-babel stuff (defvar org-babel-default-header-args:clojure '((:results . "silent"))) (defun org-babel-execute:clojure (body params) "Execute a block of Clojure code with Babel." (let ((result-plist (nrepl-send-string-sync (org-babel-expand-body:clojure body params) nrepl-buffer-ns)) (result-type (cdr (assoc :result-type params)))) (org-babel-script-escape (cond ((eq result-type 'value) (plist-get result-plist :value)) ((eq result-type 'output) (plist-get result-plist :value)) (t (message "Unknown :results type!")))))) ;; Function declarations (defun my/skip-non-archivable-tasks () "Skip trees that are not available for archiving" (save-restriction (widen) ;; Consider only tasks with done todo headings as archivable candidates (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) (subtree-end (save-excursion (org-end-of-subtree t)))) (if (member (org-get-todo-state) org-todo-keywords-1) (if (member (org-get-todo-state) org-done-keywords) (let* ((daynr (string-to-int (format-time-string "%d" (current-time)))) (a-month-ago (* 60 60 24 (+ daynr 1))) (this-month (format-time-string "%Y-%m-" (current-time))) (subtree-is-current (save-excursion (forward-line 1) (and (< (point) subtree-end) (re-search-forward this-month subtree-end t))))) (if subtree-is-current subtree-end ; Has a date in this month, skip it nil)) ; available to archive (or subtree-end (point-max))) next-headline)))) (defun my/save-all-agenda-buffers () "Function used to save all agenda buffers that are currently open, based on `org-agenda-files'." (interactive) (save-current-buffer (dolist (buffer (buffer-list t)) (set-buffer buffer) (when (member (buffer-file-name) (mapcar 'expand-file-name (org-agenda-files t))) (save-buffer))))) ;; save all the agenda files after each capture (add-hook 'org-capture-after-finalize-hook 'my/save-all-agenda-buffers) (use-package org-id :config (progn (setq org-id-link-to-org-use-id t) (defun my/org-custom-id-get (&optional pom create prefix) "Get the CUSTOM_ID property of the entry at point-or-marker POM. If POM is nil, refer to the entry at point. If the entry does not have an CUSTOM_ID, the function returns nil. However, when CREATE is non nil, create a CUSTOM_ID if none is present already. PREFIX will be passed through to `org-id-new'. In any case, the CUSTOM_ID of the entry is returned." (interactive) (org-with-point-at pom (let ((id (org-entry-get nil "CUSTOM_ID"))) (cond ((and id (stringp id) (string-match "\\S-" id)) id) (create (setq id (org-id-new prefix)) (org-entry-put pom "CUSTOM_ID" id) (org-id-add-location id (buffer-file-name (buffer-base-buffer))) id))))) (defun my/org-add-ids-to-headlines-in-file () "Add CUSTOM_ID properties to all headlines in the current file which do not already have one." (interactive) (org-map-entries (lambda () (my/org-custom-id-get (point) 'create)))) ;; automatically add ids to captured headlines (add-hook 'org-capture-prepare-finalize-hook (lambda () (my/org-custom-id-get (point) 'create))))) (defun my/org-inline-css-hook (exporter) "Insert custom inline css to automatically set the background of code to whatever theme I'm using's background" (when (eq exporter 'html) (let* ((my-pre-bg (face-background 'default)) (my-pre-fg (face-foreground 'default))) ;;(setq org-html-head-include-default-style nil) (setq org-html-head-extra (concat org-html-head-extra (format "<style type=\"text/css\">\n pre.src {background-color: %s; color: %s;}</style>\n" my-pre-bg my-pre-fg)))))) (add-hook 'org-export-before-processing-hook #'my/org-inline-css-hook)))
org-clock
Now, my org-mode clocking configuration:
First, a function to use for clocking in
(defun my/org-clock-in () (interactive) (org-clock-in '(4))) (global-set-key (kbd "<f11>") #'my/org-clock-in) (global-set-key (kbd "<f12>") 'org-clock-out)
(use-package org :bind (("C-c C-x C-i" . my/org-clock-in) ("C-c C-x C-o" . org-clock-out)) :config (progn ;; Insinuate it everywhere (org-clock-persistence-insinuate) ;; Show lot of clocking history so it's easy to pick items off the C-F11 list (setq org-clock-history-length 23 ;; Resume clocking task on clock-in if the clock is open org-clock-in-resume t ;; Separate drawers for clocking and logs org-drawers '("PROPERTIES" "CLOCK" "LOGBOOK" "RESULTS" "HIDDEN") ;; Save clock data and state changes and notes in the LOGBOOK drawer org-clock-into-drawer t ;; Sometimes I change tasks I'm clocking quickly - ;; this removes clocked tasks with 0:00 duration org-clock-out-remove-zero-time-clocks t ;; Clock out when moving task to a done state org-clock-out-when-done t ;; Save the running clock and all clock history when exiting Emacs, load it on startup org-clock-persist t ;; Prompt to resume an active clock org-clock-persist-query-resume t ;; Enable auto clock resolution for finding open clocks org-clock-auto-clock-resolution #'when-no-clock-is-running ;; Include current clocking task in clock reports org-clock-report-include-clocking-task t ;; don't use pretty things for the clocktable org-pretty-entities nil ;; some default parameters for the clock report org-agenda-clockreport-parameter-plist '(:maxlevel 10 :fileskip0 t :score agenda :block thismonth :compact t :narrow 60))))
org-publishing
Publishing org-mode files to my hosting provider:
(use-package org :config (setq org-publish-project-alist `(;; Main website at http://writequit.org ("writequit-org" :base-directory ,(file-truename "~/www") :base-extension "org\\|html" :publishing-directory "/ssh:writequit.org:~/www/" :publishing-function org-html-publish-to-html :with-toc nil :html-preamble t) ("writequit-images" :base-directory ,(file-truename "~/www/images") :base-extension "png\\|jpg\\|gif" :publishing-directory "/ssh:writequit.org:~/www/images" :publishing-function org-publish-attachment) ("writequit-files" :base-directory ,(file-truename "~/www/files") :base-extension "*" :publishing-directory "/ssh:writequit.org:~/www/files/" :publishing-function org-publish-attachment) ("writequit" :components ("writequit-org" "writequit-images" "writequit-files")) ;; Org-mode files for ~/.emacs.d/settings.org ("emacs dotfiles" :base-directory ,(file-truename "~/.emacs.d/") :base-extension "org\\|html" :publishing-directory "/ssh:writequit.org:~/www/org/" :publishing-function org-html-publish-to-html :with-toc t :html-preamble t) ;; Org-mode files for ~/org files ("org-org" :base-directory ,(file-truename "~/org/") :base-extension "org\\|html" :publishing-directory "/ssh:writequit.org:~/www/org/" :publishing-function org-html-publish-to-html :with-toc t :html-preamble t) ("org-images" :base-directory ,(file-truename "~/org/images") :base-extension "png\\|jpg" :publishing-directory "/ssh:writequit.org:~/www/org/images" :publishing-function org-publish-attachment) ("org" :components ("org-org" "org-images")) ;; Org-mode for the ~/org/es files ("org-es-org" :base-directory ,(file-truename "~/org/es/") :base-extension "org\\|html" :publishing-directory "/ssh:writequit.org:~/www/org/es" :publishing-function org-html-publish-to-html :with-toc t :html-preamble t) ("org-es-files" :base-directory ,(file-truename "~/org/es/") :base-extension "css\\|pdf\\|sh\\|es\\|zsh\\|py\\|org" :publishing-directory "/ssh:writequit.org:~/www/org/es" :publishing-function org-publish-attachment) ("org-es-images" :base-directory ,(file-truename "~/org/es/images") :base-extension "png\\|jpg" :publishing-directory "/ssh:writequit.org:~/www/org/es/images" :publishing-function org-publish-attachment) ("org-es" :components ("org-es-org" "org-es-files" "org-es-images")) ;; Org-mode for the ~/org/es/design files ("org-es-design-org" :base-directory ,(file-truename "~/org/es/design") :base-extension "org\\|html" :publishing-directory "/ssh:writequit.org:~/www/org/es/design" :publishing-function org-html-publish-to-html :with-toc t :html-preamble t) ("org-es-design-files" :base-directory ,(file-truename "~/org/es/design") :base-extension "css\\|pdf\\|sh\\|es\\|zsh\\|py\\|org" :publishing-directory "/ssh:writequit.org:~/www/org/es/design" :publishing-function org-publish-attachment) ("org-es-designs-images" :base-directory ,(file-truename "~/org/es/design/images") :base-extension "png\\|jpg" :publishing-directory "/ssh:writequit.org:~/www/org/es/design/images" :publishing-function org-publish-attachment) ("org-es-design" :components ("org-es-design-org" "org-es-design-files" "org-es-design-images")) ;; Org-mode files for the book ("org-book-pastebin" :base-directory ,(file-truename "~/org/book/") :base-extension "org\\|zsh\\|html\\|png" :publishing-directory "/ssh:writequit.org:~/www/org/book/" :publishing-function org-html-publish-to-html :with-toc t :html-preamble t))))
Then, when I'm editing ~/org/es/feature-foo.org, I can hit C-c C-e P f
and
export the file to show up in http://p.writequit.org/org
org-reveal (ox-reveal)
Exporting org-mode to reveal.js presentations
(use-package ox-reveal :defer t :config (progn (setq org-reveal-root "http://cdn.jsdelivr.net/reveal.js/2.5.0/")))
exec-path-from-shell
This allows a GUI emacs to inherit $PATH
and other things from the shell when
run. I use it for the path on OSX and JAVA_HOME everywhere else.
(use-package exec-path-from-shell :defer t :init (progn (when (memq window-system '(mac ns)) (exec-path-from-shell-initialize)) (exec-path-from-shell-copy-env "JAVA_HOME")))
vkill
Visually kill programs and processes, I use helm-occur here (thanks John Wiegley!) because it makes selecting things much easier.
(use-package vkill :defer t :commands vkill :bind ("C-x L" . vkill-and-helm-occur) :init (defun vkill-and-helm-occur () (interactive) (vkill) (my/turn-on-hl-line-mode) (call-interactively #'helm-occur)))
alert (notifications)
Yep. I need to actually make this work for OSX, for Linux it's no problem though.
(use-package alert :defer t :config (progn (when (eq system-type 'darwin) (setq alert-default-style 'notifier)) (when (eq system-type 'gnu/linux) (setq alert-default-style 'notifications))))
To use this, I just need to do (alert "this is a message")
.
ERC Configuration (IRC)
ERC (IRC) configuration, requires the ERC package.
I use ercn for IRC notifications, written by the honorable Mr. Leatherman
And finally the giant setting of ERC configuration variables, only if running in windowed mode, because I don't use ERC otherwise:
(defun start-irc () (interactive) (when (file-exists-p "~/.ercpass") (load-file "~/.ercpass")) (use-package erc :config (progn (setq erc-fill-column 78 erc-server-coding-system '(utf-8 . utf-8) erc-hide-list '("JOIN" "PART" "QUIT" "NICK") erc-track-exclude-types (append '("324" "329" "332" "333" "353" "477" "MODE") erc-hide-list) erc-nick '("dakrone" "dakrone_" "dakrone__") erc-flood-protect nil erc-pals '("hiredman" "danlarkin" "drewr" "pjstadig" "scgilardi" "joegallo" "jimduey" "leathekd" "zkim" "imotov" "technomancy" "yazirian" "danielglauser") erc-pal-highlight-type 'nil erc-keywords '("dakrone" "dakrone_" "clj-http" "cheshire" "clojure-opennlp" "opennlp" "circuit breaker" "simple_query_string") erc-ignore-list '() erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE" "324" "329" "332" "333" "353" "477") erc-log-matches-types-alist '((keyword . "ERC keywords") (current-nick . "ERC messages for me")) erc-prompt-for-nickserv-password nil erc-server-reconnect-timeout 5 erc-fill-function 'erc-fill-static erc-fill-static-center 18 ;; update ERC prompt with room name erc-prompt (lambda () (if (and (boundp 'erc-default-recipients) (erc-default-target)) (erc-propertize (concat (erc-default-target) ">") 'read-only t 'rear-nonsticky t 'front-nonsticky t) (erc-propertize (concat "ERC>") 'read-only t 'rear-nonsticky t 'front-nonsticky t)))) ;; Turn on company-mode in ERC (add-hook 'erc-mode-hook 'company-mode) ;; other random services (spelling) (use-package erc-services :init (progn (add-to-list 'erc-modules 'spelling) (erc-services-mode 1) (erc-spelling-mode 1))) (erc-update-modules))) (use-package ercn :config (progn (setq ercn-notify-rules '((current-nick . all) (keyword . all) (pal . ("#84115")) (query-buffer . all))) (defun do-notify (nickname message) (alert message :title (concat (buffer-name) ": " nickname))) (add-hook 'ercn-notify-hook #'do-notify))) (let ((tls-program '("openssl s_client -connect %h:%p -no_ssl2 -ign_eof -cert ~/host.pem" "gnutls-cli --priority secure256 --x509certfile ~/host.pem -p %p %h" "gnutls-cli --priority secure256 -p %p %h"))) (erc-tls :server "freenode" :port 31425 :nick "dakrone" :password freenode-znc-pass) (erc-tls :server "oftc" :port 31425 :nick "dakrone" :password oftc-znc-pass)))
Email (mu4e) Configuration
I usually install mu from source, with ./configure --prefix=/usr/local
, I
unpack it to ~/src/mu-0.9.11 (or whatever version) so I can reference the mu4e
elisp files. Then run make
and make install
to install mu.
(defun mail () (interactive) (add-to-list 'load-path "~/src/mu-0.9.11/mu4e") (nyan-mode 1) ;; nyan-mode for mail! (use-package mu4e :config (progn (add-hook 'mu4e-compose-mode-hook 'turn-on-flyspell) ;; gpg stuff (use-package epa-file :init (epa-file-enable)) ;; Various mu4e settings (setq mu4e-mu-binary "/usr/local/bin/mu" ;;mu4e-sent-messages-behavior 'delete mu4e-user-mail-address-list '("matthew.hinman@gmail.com" "lee@writequit.org" "lee@elastic.co") ;; save attachments to the Downloads folder mu4e-attachment-dir "~/Downloads" ;; attempt to show images mu4e-view-show-images t mu4e-view-image-max-width 800 ;; start in non-queuing mode smtpmail-queue-mail nil smtpmail-queue-dir "~/.mail/queue/" mml2015-use 'epg pgg-default-user-id "3acecae0" epg-gpg-program "/usr/local/bin/gpg" message-kill-buffer-on-exit t ;; kill sent msg buffers ;; use msmtp message-send-mail-function 'message-send-mail-with-sendmail sendmail-program "/usr/local/bin/msmtp" ;; Look at the from header to determine the account from which ;; to send. Might not be needed b/c of kdl-msmtp mail-specify-envelope-from t mail-envelope-from 'header message-sendmail-envelope-from 'header ;; emacs email defaults user-mail-address "lee@writequit.org" user-full-name "Lee Hinman" mail-host-address "writequit.org" ;; no signature mu4e-compose-signature nil ;; mu4e defaults mu4e-maildir "~/.mail" ;; misc mu settings ;; Unicode FTW mu4e-use-fancy-chars nil ;; use the python html2text shell command to strip html ;; brew/apt-get install html2text ;; brew/apt-get install elinks mu4e-html2text-command "/usr/local/bin/elinks -dump" ;; mu4e-html2text-command "/usr/local/bin/html2text -nobs" ;; mu4e-html2text-command ;; "/usr/bin/html2markdown | fgrep -v ' _place_holder;'" ;; check for new messages every 600 seconds (10 min) mu4e-update-interval 600) (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode) (use-package gnus-dired :config (progn ;; make the `gnus-dired-mail-buffers' function also work on ;; message-mode derived modes, such as mu4e-compose-mode (defun gnus-dired-mail-buffers () "Return a list of active message buffers." (let (buffers) (save-current-buffer (dolist (buffer (buffer-list t)) (set-buffer buffer) (when (and (derived-mode-p 'message-mode) (null message-sent-message-via)) (push (buffer-name buffer) buffers)))) (nreverse buffers))) (setq gnus-dired-mail-mode 'mu4e-user-agent))) ;; Vars used below (defvar kdl-mu4e-new-mail nil "Boolean to represent if there is new mail.") (defvar kdl-mu4e-url-location-list '() "Stores the location of each link in a mu4e view buffer") ;; This is also defined in init.el, but b/c ESK runs all files in the ;; user-dir before init.el it must also be defined here (defvar message-filter-regexp-list '() "regexps to filter matched msgs from the echo area when message is called") ;; Multi-account support (defun kdl-mu4e-current-account (&optional msg ignore-message-at-point) "Figure out what the current account is based on the message being composed, the message under the point, or (optionally) the message passed in. Also supports ignoring the msg at the point." (let ((cur-msg (or msg mu4e-compose-parent-message (and (not ignore-message-at-point) (mu4e-message-at-point t))))) (when cur-msg (let ((maildir (mu4e-msg-field cur-msg :maildir))) (string-match "/\\(.*?\\)/" maildir) (match-string 1 maildir))))) (defun is-gmail-account? (acct) (if (or (equal "elastic" acct) (equal "gmail" acct)) t nil)) ;; my elisp is bad and I should feel bad (defun mlh-folder-for (acct g-folder-name other-folder-name) (if (or (equal "elastic" acct) (equal "gmail" acct)) (format "/%s/[Gmail].%s" acct g-folder-name) (format "/%s/INBOX.%s" acct other-folder-name))) ;; Support for multiple accounts (setq mu4e-sent-folder (lambda (msg) (mlh-folder-for (kdl-mu4e-current-account msg) "Sent Mail" "Sent")) mu4e-drafts-folder (lambda (msg) (mlh-folder-for (kdl-mu4e-current-account msg) "Drafts" "Drafts")) mu4e-trash-folder (lambda (msg) (mlh-folder-for (kdl-mu4e-current-account msg) "Trash" "Trash")) mu4e-refile-folder (lambda (msg) (mlh-folder-for (kdl-mu4e-current-account msg) "All Mail" "Archive")) ;; The following list represents the account followed by key / ;; value pairs of vars to set when the account is chosen kdl-mu4e-account-alist '(("gmail" (user-mail-address "matthew.hinman@gmail.com") (msmtp-account "gmail") (mu4e-sent-messages-behavior delete)) ("elastic" (user-mail-address "lee@elastic.co") (msmtp-account "elastic") (mu4e-sent-messages-behavior delete)) ;; ("writequit" ;; (user-mail-address "lee@writequit.org") ;; (msmtp-account "writequit") ;; (mu4e-sent-messages-behavior sent)) ) ;; These are used when mu4e checks for new messages mu4e-my-email-addresses (mapcar (lambda (acct) (cadr (assoc 'user-mail-address (cdr acct)))) kdl-mu4e-account-alist)) (defun kdl-mu4e-choose-account () "Prompt the user for an account to use" (completing-read (format "Compose with account: (%s) " (mapconcat #'(lambda (var) (car var)) kdl-mu4e-account-alist "/")) (mapcar #'(lambda (var) (car var)) kdl-mu4e-account-alist) nil t nil nil (caar kdl-mu4e-account-alist))) (defun kdl-mu4e-set-compose-account () "Set various vars when composing a message. The vars to set are defined in kdl-mu4e-account-alist." (let* ((account (or (kdl-mu4e-current-account nil t) (kdl-mu4e-choose-account))) (account-vars (cdr (assoc account kdl-mu4e-account-alist)))) (when account-vars (mapc #'(lambda (var) (set (car var) (cadr var))) account-vars)))) (add-hook 'mu4e-compose-pre-hook 'kdl-mu4e-set-compose-account) ;; Send mail through msmtp (setq stuff is below) (defun kdl-msmtp () "Add some arguments to the msmtp call in order to route the message through the right account." (if (message-mail-p) (save-excursion (let* ((from (save-restriction (message-narrow-to-headers) (message-fetch-field "from")))) (setq message-sendmail-extra-arguments (list "-a" msmtp-account)))))) (add-hook 'message-send-mail-hook 'kdl-msmtp) ;; Notification stuff (setq global-mode-string (if (string-match-p "kdl-mu4e-new-mail" (prin1-to-string global-mode-string)) global-mode-string (cons ;; '(kdl-mu4e-new-mail "✉" "") '(kdl-mu4e-new-mail "Mail" "") global-mode-string))) (defun kdl-mu4e-unread-mail-query () "The query to look for unread messages in all account INBOXes. More generally, change this code to affect not only when the envelope icon appears in the modeline, but also what shows up in mu4e under the Unread bookmark" (mapconcat (lambda (acct) (let ((name (car acct))) (format "%s" (mapconcat (lambda (fmt) (format fmt name)) '("flag:unread AND maildir:/%s/INBOX") " ")))) kdl-mu4e-account-alist " OR ")) (defun kdl-mu4e-new-mail-p () "Predicate for if there is new mail or not" (not (eq 0 (string-to-number (replace-regexp-in-string "[ \t\n\r]" "" (shell-command-to-string (concat "mu find " (kdl-mu4e-unread-mail-query) " | wc -l"))))))) (defun kdl-mu4e-notify () "Function called to update the new-mail flag used in the mode-line" ;; This delay is to give emacs and mu a chance to have changed the ;; status of the mail in the index (run-with-idle-timer 1 nil (lambda () (setq kdl-mu4e-new-mail (kdl-mu4e-new-mail-p))))) ;; I put a lot of effort (probably too much) into getting the ;; 'new mail' icon to go away by showing or hiding it: ;; - periodically (this runs even when mu4e isn't running) (setq kdl-mu4e-notify-timer (run-with-timer 0 500 'kdl-mu4e-notify)) ;; - when the index is updated (this runs when mu4e is running) (add-hook 'mu4e-index-updated-hook 'kdl-mu4e-notify) ;; - after mail is processed (try to make the icon go away) (defadvice mu4e-mark-execute-all (after mu4e-mark-execute-all-notify activate) 'kdl-mu4e-notify) ;; - when a message is opened (try to make the icon go away) (add-hook 'mu4e-view-mode-hook 'kdl-mu4e-notify) ;; wrap lines (add-hook 'mu4e-view-mode-hook 'visual-line-mode) (defun kdl-mu4e-quit-and-notify () "Bury the buffer and check for new messages. Mainly this is intended to clear out the envelope icon when done reading mail." (interactive) (bury-buffer) (kdl-mu4e-notify)) ;; Make 'quit' just bury the buffer (define-key mu4e-headers-mode-map "q" 'kdl-mu4e-quit-and-notify) (define-key mu4e-main-mode-map "q" 'kdl-mu4e-quit-and-notify) ;; View mode stuff ;; Make it possible to tab between links (defun kdl-mu4e-populate-url-locations (&optional force) "Scans the view buffer for the links that mu4e has identified and notes their locations" (when (or (null kdl-mu4e-url-location-list) force) (make-local-variable 'kdl-mu4e-url-location-list) (let ((pt (next-single-property-change (point-min) 'face))) (while pt (when (equal (get-text-property pt 'face) 'mu4e-view-link-face) (add-to-list 'kdl-mu4e-url-location-list pt t)) (setq pt (next-single-property-change pt 'face))))) kdl-mu4e-url-location-list) (defun kdl-mu4e-move-to-link (pt) (if pt (goto-char pt) (error "No link found."))) (defun kdl-mu4e-forward-url () "Move the point to the beginning of the next link in the buffer" (interactive) (let* ((pt-list (kdl-mu4e-populate-url-locations))) (kdl-mu4e-move-to-link (or (some (lambda (pt) (when (> pt (point)) pt)) pt-list) (some (lambda (pt) (when (> pt (point-min)) pt)) pt-list))))) (defun kdl-mu4e-backward-url () "Move the point to the beginning of the previous link in the buffer" (interactive) (let* ((pt-list (reverse (kdl-mu4e-populate-url-locations)))) (kdl-mu4e-move-to-link (or (some (lambda (pt) (when (< pt (point)) pt)) pt-list) (some (lambda (pt) (when (< pt (point-max)) pt)) pt-list))))) (define-key mu4e-view-mode-map (kbd "TAB") 'kdl-mu4e-forward-url) (define-key mu4e-view-mode-map (kbd "<backtab>") 'kdl-mu4e-backward-url) ;; Misc ;; The bookmarks for the main screen (setq mu4e-bookmarks `((,(kdl-mu4e-unread-mail-query) "New messages" ?b) ("maildir:/elastic/build" "Build failures" ?B) ("date:today..now" "Today's messages" ?t) ("date:7d..now" "Last 7 days" ?W) ;;("maildir:/writequit/INBOX" "Writequit" ?w) ("maildir:/elastic/INBOX" "Elastic" ?s) ("maildir:/gmail/INBOX" "Gmail" ?g) ;; ("maildir:/writequit/INBOX OR maildir:/elastic/INBOX OR maildir:/gmail/INBOX" ;; "All Mail" ?a) ("maildir:/elastic/INBOX OR maildir:/gmail/INBOX" "All Mail" ?a))) ;; Skip the main mu4e screen and go right to unread (defun kdl-mu4e-view-unread () "Open the Unread bookmark directly" (interactive) (mu4e~start) (mu4e-headers-search-bookmark (mu4e-get-bookmark-query ?b))) (global-set-key (kbd "C-c 2") 'kdl-mu4e-view-unread) ;; Don't echo some mu4e messages (add-to-list 'message-filter-regexp-list "mu4e.*Indexing.*processed") (add-to-list 'message-filter-regexp-list "mu4e.*Retrieving mail") (add-to-list 'message-filter-regexp-list "mu4e.*Started") ;; Start it up (when (eq window-system 'ns) ;; start mu4e (mu4e~start) ;; check for unread messages (kdl-mu4e-notify)) (add-to-list 'mu4e-view-actions '("ViewInBrowser" . mu4e-action-view-in-browser) t) (define-key mu4e-view-mode-map (kbd "j") 'next-line) (define-key mu4e-view-mode-map (kbd "k") 'previous-line) (define-key mu4e-headers-mode-map (kbd "J") 'mu4e~headers-jump-to-maildir) (define-key mu4e-headers-mode-map (kbd "j") 'next-line) (define-key mu4e-headers-mode-map (kbd "k") 'previous-line) (when (eq my/background 'light) (set-face-background 'mu4e-header-highlight-face "#e0e0e0")))) (global-set-key (kbd "C-c m") 'mu4e))
Email (gnus) configuration
See: ~/.gnus.el
ace-jump-mode
Jump quickly between words or lines, I mostly use it with eww.
(use-package ace-jump-mode :defer t :bind (("C-c SPC" . ace-jump-mode) ("C-c M-SPC" . ace-jump-line-mode)))
ediff
Ediff is fantastic for looking through diffs, a lot of these settings are taken from http://oremacs.com/2015/01/17/setting-up-ediff/
(defun my/setup-ediff () (interactive) (ediff-setup-keymap) (define-key ediff-mode-map "j" #'ediff-next-difference) (define-key ediff-mode-map "k" #'ediff-previous-difference)) (use-package ediff :defer t :init (add-hook 'ediff-mode-hook 'my/setup-ediff) :config (progn (setq ;; Always split nicely for wide screens ediff-split-window-function 'split-window-horizontally ;; Ignore whitespace ediff-diff-options "-w")))
smooth-scrolling
Smooth scrolling means when you hit C-n
to go to the next line at the bottom
of the page, instead of doing a page-down, it shifts down by a single line. The
margin means that much space is kept between the cursor and the bottom of the
buffer.
(use-package smooth-scrolling :defer t :config (setq smooth-scroll-margin 4))
paredit
Paredit for all the lisps.
(use-package paredit :defer t :diminish "()" :config (progn (define-key paredit-mode-map (kbd "M-)") 'paredit-forward-slurp-sexp) (define-key paredit-mode-map (kbd "C-(") 'paredit-forward-barf-sexp) (define-key paredit-mode-map (kbd "C-)") 'paredit-forward-slurp-sexp) (define-key paredit-mode-map (kbd ")") 'paredit-close-parenthesis) (define-key paredit-mode-map (kbd "M-\"") 'my/other-window-backwards)))
smartparens
So, paredit is great, however, it doesn't work for non-lisp modes. Smartparens works pretty well, so I use it everywhere paredit-mode doesn't work.
(use-package smartparens :defer t :diminish "" :bind (("M-9" . sp-backward-sexp) ("M-0" . sp-forward-sexp)) :init (progn (add-hook 'prog-mode-hook #'turn-on-smartparens-mode) ;; turn on showing the match for clojure and elisp (add-hook 'clojure-mode-hook #'turn-on-show-smartparens-mode) (add-hook 'emacs-lisp-mode-hook #'turn-on-show-smartparens-mode) (add-hook 'java-mode-hook #'turn-on-show-smartparens-mode) (add-hook 'c-mode-hook #'turn-on-show-smartparens-mode)) :config (progn (add-to-list 'sp-sexp-suffix '(json-mode regex "")) (add-to-list 'sp-sexp-suffix '(es-mode regex "")) (use-package smartparens-config) (add-hook 'sh-mode-hook (lambda () ;; Remove when https://github.com/Fuco1/smartparens/issues/257 ;; is fixed (setq sp-autoescape-string-quote nil))) ;; Remove the M-<backspace> binding that smartparens adds (let ((disabled '("M-<backspace>"))) (setq sp-smartparens-bindings (cl-remove-if (lambda (key-command) (member (car key-command) disabled)) sp-smartparens-bindings))) (define-key sp-keymap (kbd "C-(") 'sp-forward-barf-sexp) (define-key sp-keymap (kbd "C-)") 'sp-forward-slurp-sexp) (define-key sp-keymap (kbd "M-(") 'sp-forward-barf-sexp) (define-key sp-keymap (kbd "M-)") 'sp-forward-slurp-sexp) (define-key sp-keymap (kbd "C-M-f") 'sp-forward-sexp) (define-key sp-keymap (kbd "C-M-b") 'sp-backward-sexp) (define-key sp-keymap (kbd "C-M-f") 'sp-forward-sexp) (define-key sp-keymap (kbd "C-M-b") 'sp-backward-sexp) (define-key sp-keymap (kbd "C-M-d") 'sp-down-sexp) (define-key sp-keymap (kbd "C-M-a") 'sp-backward-down-sexp) (define-key sp-keymap (kbd "C-S-a") 'sp-beginning-of-sexp) (define-key sp-keymap (kbd "C-S-d") 'sp-end-of-sexp) (define-key sp-keymap (kbd "C-M-e") 'sp-up-sexp) (define-key emacs-lisp-mode-map (kbd ")") 'sp-up-sexp) (define-key sp-keymap (kbd "C-M-u") 'sp-backward-up-sexp) (define-key sp-keymap (kbd "C-M-t") 'sp-transpose-sexp) ;; (define-key sp-keymap (kbd "C-M-n") 'sp-next-sexp) ;; (define-key sp-keymap (kbd "C-M-p") 'sp-previous-sexp) (define-key sp-keymap (kbd "C-M-k") 'sp-kill-sexp) (define-key sp-keymap (kbd "C-M-w") 'sp-copy-sexp) (define-key sp-keymap (kbd "M-D") 'sp-splice-sexp) (define-key sp-keymap (kbd "C-]") 'sp-select-next-thing-exchange) (define-key sp-keymap (kbd "C-<left_bracket>") 'sp-select-previous-thing) (define-key sp-keymap (kbd "C-M-]") 'sp-select-next-thing) (define-key sp-keymap (kbd "M-F") 'sp-forward-symbol) (define-key sp-keymap (kbd "M-B") 'sp-backward-symbol) (define-key sp-keymap (kbd "H-t") 'sp-prefix-tag-object) (define-key sp-keymap (kbd "H-p") 'sp-prefix-pair-object) (define-key sp-keymap (kbd "H-s c") 'sp-convolute-sexp) (define-key sp-keymap (kbd "H-s a") 'sp-absorb-sexp) (define-key sp-keymap (kbd "H-s e") 'sp-emit-sexp) (define-key sp-keymap (kbd "H-s p") 'sp-add-to-previous-sexp) (define-key sp-keymap (kbd "H-s n") 'sp-add-to-next-sexp) (define-key sp-keymap (kbd "H-s j") 'sp-join-sexp) (define-key sp-keymap (kbd "H-s s") 'sp-split-sexp) (sp-local-pair 'minibuffer-inactive-mode "'" nil :actions nil) ;; Remove '' pairing in elisp because quoting is used a ton (sp-local-pair 'emacs-lisp-mode "'" nil :actions nil) (sp-with-modes '(html-mode sgml-mode) (sp-local-pair "<" ">")) (sp-with-modes sp--lisp-modes (sp-local-pair "(" nil :bind "C-("))))
golden-ratio
Automagically resizes the windows to be the golden ratio (1.618), nice when using a big font size and I need more eshell space
(use-package golden-ratio :diminish golden-ratio-mode :defer t :config (progn (defun my/helm-alive-p () (if (boundp 'helm-alive-p) (symbol-value 'helm-alive-p))) ;; Inhibit helm (add-to-list 'golden-ratio-inhibit-functions #'my/helm-alive-p) ;; Inhibit ERC and mu4e (setq golden-ratio-auto-scale t golden-ratio-exclude-modes '(erc-mode mu4e-headers-mode mu4e-view-mode))))
flycheck
Pretty minimally configured, but awesome tool for most dynamic languages.
(defun my/flycheck-customize () (interactive) (global-set-key (kbd "C-c C-n") 'flycheck-tip-cycle) (global-set-key (kbd "C-c C-p") 'flycheck-tip-cycle-reverse)) (use-package flycheck :defer t :bind (("M-g M-n" . flycheck-next-error) ("M-g M-p" . flycheck-previous-error) ("M-g M-=" . flycheck-list-errors)) :init (global-flycheck-mode) :diminish "" :config (progn (setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc)) (use-package flycheck-tip :config (add-hook 'flycheck-mode-hook #'my/flycheck-customize)) (use-package helm-flycheck :init (define-key flycheck-mode-map (kbd "C-c ! h") 'helm-flycheck)) (use-package flycheck-haskell :init (add-hook 'flycheck-mode-hook #'flycheck-haskell-setup))))
ggtags
See: https://github.com/leoliu/ggtags
If on OSX, you'll need to:
brew install ctags wget -c http://tamacom.com/global/global-6.3.1.tar.gz tar zxvf global-6.3.1.tar.gz cd global-6.3.1 ./configure --prefix=/usr/local --with-exuberant-ctags=/usr/local/bin/ctags make install
I also add this to my shell configuration:
export GTAGSCONF=/usr/local/share/gtags/gtags.conf export GTAGSLABEL=ctags
In order to get this to work also
(defun my/setup-helm-gtags () (interactive) ;; this variables must be set before load helm-gtags ;; you can change to any prefix key of your choice (setq helm-gtags-prefix-key "\C-cg") (setq helm-gtags-ignore-case t helm-gtags-auto-update t helm-gtags-use-input-at-cursor t helm-gtags-pulse-at-cursor t helm-gtags-suggested-key-mapping t) (use-package helm-gtags :init (helm-gtags-mode t) :diminish "") ;; key bindings (define-key helm-gtags-mode-map (kbd "M-s") 'helm-gtags-select) (define-key helm-gtags-mode-map (kbd "M-.") 'helm-gtags-dwim) (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack) (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history) (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)) (defun my/setup-ggtags () (interactive) (ggtags-mode 1) ;; turn on eldoc with ggtags (setq-local eldoc-documentation-function #'ggtags-eldoc-function) ;; add ggtags to the hippie completion (setq-local hippie-expand-try-functions-list (cons 'ggtags-try-complete-tag hippie-expand-try-functions-list)) ;; use helm for completion (setq ggtags-completing-read-function nil)) (use-package ggtags :defer t :init (progn (add-hook 'c-mode-common-hook (lambda () (when (derived-mode-p 'c-mode 'c++-mode 'java-mode 'asm-mode) (my/setup-semantic-mode) (my/setup-helm-gtags) ;; helm-gtags ;;(my/setup-ggtags) ;; regular gtags )))))
expand-region
Great for selecting the inside of Elasticsearch queries
(use-package expand-region :defer t :bind (("C-c e" . er/expand-region) ("C-M-@" . er/contract-region)))
with-editor
Sets up the with-editor
package so things that invoke $EDITOR
will use the
current emacs if I'm already inside of emacs
(use-package with-editor :init (progn (add-hook 'shell-mode-hook 'with-editor-export-editor) (add-hook 'eshell-mode-hook 'with-editor-export-editor)))
magit
I use M-g M-g
everywhere to go directly to Magit.
(use-package magit :defer t :bind ("M-g M-g" . magit-status) :init (defvar magit-emacsclient-executable nil) ;; fix for emacs-mac :config (progn (setq magit-last-seen-setup-instructions "1.4.0") (if (file-exists-p "/usr/local/bin/emacsclient") (setq magit-emacsclient-executable "/usr/local/bin/emacsclient") (setq magit-emacsclient-executable (executable-find "emacsclient"))) (defun magit-browse () "Browse to the project's github URL, if available" (interactive) (let ((url (with-temp-buffer (unless (zerop (call-process-shell-command "git remote -v" nil t)) (error "Failed: 'git remote -v'")) (goto-char (point-min)) (when (re-search-forward "github\\.com[:/]\\(.+?\\)\\.git" nil t) (format "https://github.com/%s" (match-string 1)))))) (unless url (error "Can't find repository URL")) (browse-url url))) (when (and (boundp 'moe-theme-which-enabled) (eq moe-theme-which-enabled 'dark)) ;; Moe's magit colors are baaaaaaad (set-face-attribute 'magit-item-highlight nil :inherit nil :foreground 'unspecified)) (define-key magit-mode-map (kbd "C-c C-b") 'magit-browse) (define-key magit-mode-map (kbd "M-1") #'my/create-or-switch-to-eshell-1) (define-key magit-mode-map (kbd "M-2") #'my/create-or-switch-to-eshell-2) (define-key magit-mode-map (kbd "M-3") #'my/create-or-switch-to-eshell-3) (define-key magit-status-mode-map (kbd "W") 'magit-toggle-whitespace) (custom-set-variables '(magit-set-upstream-on-push (quote dontask))) (setq magit-completing-read-function 'magit-ido-completing-read)))
projectile
Per-project navigation
(use-package projectile :defer t :bind (;;("C-x f" . projectile-find-file) ("C-c p s" . projectile-switch-project) ("C-c p a" . projectile-ag) ("C-c p g" . projectile-grep) ("C-c p b" . projectile-switch-to-buffer) ("C-c p K" . projectile-kill-buffers)) :config (progn (defconst projectile-mode-line-lighter " P")))
prodigy
I basically use this to start up ES when I need to test something really quickly
I have been trying out esvm for this lately also, with this config in
~/.esvmrc
:
{ "defaults": { "plugins": [], "config": { "node.add_id_to_custom_path": false, "node.enable_custom_paths": true, "script.disable_dynamic": false, "cluster.name": "es-lee" } }, "clusters": { "1node": { "branch": "1.6", "nodes": 1 }, "2node": { "branch": "1.6", "nodes": 2 }, "3node": { "branch": "1.6", "nodes": 3 }, "10node": { "branch": "1.6", "nodes": 10 } } }
So I configure prodigy like so:
(use-package prodigy :defer t :bind ("C-x P" . prodigy) :config (progn (prodigy-define-service :name "ES 1.6, 10 nodes" :cwd "~/ies/" :command "esvm" :args '("10node") :tags '(work test es) :port 9200) (prodigy-define-service :name "ES 1.6, 3 nodes" :cwd "~/ies/" :command "esvm" :args '("3node") :tags '(work test es) :port 9200) (prodigy-define-service :name "ES 1.6, 2 nodes" :cwd "~/ies/" :command "esvm" :args '("2node") :tags '(work test es) :port 9200) (prodigy-define-service :name "Elasticsearch 1.6.0" :cwd "~/ies/elasticsearch-1.6.0" :command "~/ies/elasticsearch-1.6.0/bin/elasticsearch" :tags '(work test es) :port 9200) (prodigy-define-service :name "Elasticsearch 1.5.2" :cwd "~/ies/elasticsearch-1.5.2" :command "~/ies/elasticsearch-1.5.2/bin/elasticsearch" :tags '(work test es) :port 9200) (prodigy-define-service :name "Elasticsearch 1.4.5" :cwd "~/ies/elasticsearch-1.4.5" :command "~/ies/elasticsearch-1.4.5/bin/elasticsearch" :tags '(work test es) :port 9200)))
git-gutter
Only enabled in a few modes, but quite useful, as well as the C-x n
and C-x
p
bindings.
(use-package git-gutter :disabled t :defer t :bind (("C-x =" . git-gutter:popup-hunk) ("C-c P" . git-gutter:previous-hunk) ("C-c N" . git-gutter:next-hunk) ("C-x p" . git-gutter:previous-hunk) ("C-x n" . git-gutter:next-hunk) ("C-c G" . git-gutter:popup-hunk)) :diminish "" :init (progn ;; Only a few programming modes (add-hook 'java-mode-hook 'git-gutter-mode) (add-hook 'clojure-mode-hook 'git-gutter-mode) (add-hook 'ruby-mode-hook 'git-gutter-mode) (add-hook 'python-mode-hook 'git-gutter-mode)))
diff-hl
This provides basically the same functionality as git-gutter
, but using the
fringe, so I'm trying it out…
(use-package diff-hl :defer t :bind (("C-c G" . diff-hl-diff-goto-hunk)) :init (if (window-system) (global-diff-hl-mode 1) (diff-hl-margin-mode 1)))
anzu
Anzu shows the number of search hits in the modeline, which is handy.
It can also be used for a "refactor-like" thing similar to query-replace.
(use-package anzu :defer t :bind ("M-%" . anzu-query-replace-regexp) :config (progn (use-package thingatpt) (setq anzu-mode-lighter "") (set-face-attribute 'anzu-mode-line nil :foreground "yellow"))) (add-hook 'prog-mode-hook #'anzu-mode)
Also, add a thing for yanking the entire symbol into the query while searching:
(defun isearch-yank-symbol () (interactive) (isearch-yank-internal (lambda () (forward-symbol 1) (point)))) (define-key isearch-mode-map (kbd "C-M-w") 'isearch-yank-symbol)
helm
There are many helm things. I use it a lot.
A lot of things are taken from taken from https://tuhdo.github.io/helm-intro.html
(use-package helm :bind (("C-M-z" . helm-resume) ("C-x C-f" . helm-find-files) ("C-h b" . helm-descbinds) ("C-x C-r" . helm-mini) ("C-x M-o" . helm-occur) ("M-y" . helm-show-kill-ring) ("C-h a" . helm-apropos) ("C-h m" . helm-man-woman) ("M-g >" . helm-ag-this-file) ("M-g ," . helm-ag-pop-stack) ("M-g ." . helm-do-grep) ("C-x C-i" . helm-semantic-or-imenu) ("M-x" . helm-M-x) ("C-x C-b" . helm-buffers-list) ("C-x C-r" . helm-mini) ("C-x b" . helm-mini) ("C-h t" . helm-world-time)) :init (progn ;;(helm-autoresize-mode 1) (helm-mode 1)) :diminish "" :config (progn (use-package helm-config) (use-package helm-files :config (progn (setq helm-ff-file-compressed-list '("gz" "bz2" "zip" "7z" "tgz")))) (use-package helm-grep :config (progn (define-key helm-grep-mode-map (kbd "<return>") 'helm-grep-mode-jump-other-window) (define-key helm-grep-mode-map (kbd "n") 'helm-grep-mode-jump-other-window-forward) (define-key helm-grep-mode-map (kbd "p") 'helm-grep-mode-jump-other-window-backward))) (use-package helm-man) (use-package helm-misc) (use-package helm-aliases) (use-package helm-elisp) (use-package helm-imenu) (use-package helm-semantic) (use-package helm-ring) (use-package helm-bookmark :bind (("C-x M-b" . helm-bookmarks))) (use-package helm-projectile :bind (("C-x f" . helm-projectile) ("C-c p f" . helm-projectile-find-file) ("C-c p s" . helm-projectile-switch-project))) (use-package helm-eshell :init (add-hook 'eshell-mode-hook (lambda () (define-key eshell-mode-map (kbd "M-l") 'helm-eshell-history)))) (use-package helm-descbinds :init (helm-descbinds-mode t)) (use-package helm-ag :bind ("C-M-s" . helm-ag-this-file)) ;; Via: http://www.reddit.com/r/emacs/comments/3asbyn/new_and_very_useful_helm_feature_enter_search/ (setq helm-echo-input-in-header-line t) (defun helm-hide-minibuffer-maybe () (when (with-helm-buffer helm-echo-input-in-header-line) (let ((ov (make-overlay (point-min) (point-max) nil nil t))) (overlay-put ov 'window (selected-window)) (overlay-put ov 'face (let ((bg-color (face-background 'default nil))) `(:background ,bg-color :foreground ,bg-color))) (setq-local cursor-type nil)))) (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe) ;; The default "C-x c" is quite close to "C-x C-c", which quits Emacs. ;; Changed to "C-c h". Note: We must set "C-c h" globally, because we ;; cannot change `helm-command-prefix-key' once `helm-config' is loaded. (global-set-key (kbd "C-c h") 'helm-command-prefix) (global-unset-key (kbd "C-x c")) (setq helm-idle-delay 0.01 helm-exit-idle-delay 0.1 helm-input-idle-delay 0.01 helm-buffers-fuzzy-matching t ;; truncate long lines in helm completion helm-truncate-lines t ;; may be overridden if 'ggrep' is in path (see below) helm-grep-default-command "grep -a -d skip %e -n%cH -e %p %f" helm-grep-default-recurse-command "grep -a -d recurse %e -n%cH -e %p %f" ;; do not display invisible candidates helm-quick-update t ;; be idle for this many seconds, before updating in delayed sources. helm-idle-delay 0.01 ;; be idle for this many seconds, before updating candidate buffer helm-input-idle-delay 0.01 ;; open helm buffer in another window helm-split-window-default-side 'other ;; open helm buffer inside current window, don't occupy whole other window helm-split-window-in-side-p t ;; limit the number of displayed canidates helm-candidate-number-limit 200 ;; don't use recentf stuff in helm-ff helm-ff-file-name-history-use-recentf nil ;; move to end or beginning of source when reaching top or bottom ;; of source helm-move-to-line-cycle-in-source t ;; don't displace the header line helm-display-header-line nil ;; fuzzy matching helm-buffers-fuzzy-matching t helm-semantic-fuzzy-match t helm-imenu-fuzzy-match t helm-completion-in-region-fuzzy-match t ;; Here are the things helm-mini shows, I add `helm-source-bookmarks' ;; here to the regular default list helm-mini-default-sources '(helm-source-buffers-list helm-source-recentf helm-source-bookmarks helm-source-buffer-not-found)) ;; List of times to show in helm-world-time (setq display-time-world-list '(("PST8PDT" "Los Altos") ("America/Denver" "Denver") ("EST5EDT" "Boston") ("UTC" "UTC") ("Europe/London" "London") ("Europe/Amsterdam" "Amsterdam") ("Asia/Bangkok" "Bangkok") ("Asia/Tokyo" "Tokyo") ("Australia/Sydney" "Sydney"))) (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action) ; rebind tab to do persistent action (define-key helm-map (kbd "C-i") 'helm-execute-persistent-action) ; make TAB works in terminal (define-key helm-map (kbd "C-z") 'helm-select-action) ; list actions using C-z (define-key helm-map (kbd "C-p") 'helm-previous-line) (define-key helm-map (kbd "C-n") 'helm-next-line) (define-key helm-map (kbd "C-M-n") 'helm-next-source) (define-key helm-map (kbd "C-M-p") 'helm-previous-source) ;; The normal binding is C-c h M-g s which is insane (global-set-key (kbd "C-c h g") 'helm-do-grep) (global-set-key (kbd "C-c h a") 'helm-do-ag) (when (executable-find "curl") (setq helm-google-suggest-use-curl-p t)) ;; ggrep is gnu grep on OSX (when (executable-find "ggrep") (setq helm-grep-default-command "ggrep -a -d skip %e -n%cH -e %p %f" helm-grep-default-recurse-command "ggrep -a -d recurse %e -n%cH -e %p %f")) (define-key helm-map (kbd "C-x 2") 'helm-select-2nd-action) (define-key helm-map (kbd "C-x 3") 'helm-select-3rd-action) (define-key helm-map (kbd "C-x 4") 'helm-select-4rd-action) ;; helm-mini instead of recentf (define-key 'help-command (kbd "C-f") 'helm-apropos) (define-key 'help-command (kbd "r") 'helm-info-emacs) ;; use helm to list eshell history (add-hook 'eshell-mode-hook #'(lambda () (define-key eshell-mode-map (kbd "M-l") 'helm-eshell-history))) ;; Save current position to mark ring ;; (add-hook 'helm-goto-line-before-hook 'helm-save-current-pos-to-mark-ring) (defvar helm-httpstatus-source '((name . "HTTP STATUS") (candidates . (("100 Continue") ("101 Switching Protocols") ("102 Processing") ("200 OK") ("201 Created") ("202 Accepted") ("203 Non-Authoritative Information") ("204 No Content") ("205 Reset Content") ("206 Partial Content") ("207 Multi-Status") ("208 Already Reported") ("300 Multiple Choices") ("301 Moved Permanently") ("302 Found") ("303 See Other") ("304 Not Modified") ("305 Use Proxy") ("307 Temporary Redirect") ("400 Bad Request") ("401 Unauthorized") ("402 Payment Required") ("403 Forbidden") ("404 Not Found") ("405 Method Not Allowed") ("406 Not Acceptable") ("407 Proxy Authentication Required") ("408 Request Timeout") ("409 Conflict") ("410 Gone") ("411 Length Required") ("412 Precondition Failed") ("413 Request Entity Too Large") ("414 Request-URI Too Large") ("415 Unsupported Media Type") ("416 Request Range Not Satisfiable") ("417 Expectation Failed") ("418 I'm a teapot") ("422 Unprocessable Entity") ("423 Locked") ("424 Failed Dependency") ("425 No code") ("426 Upgrade Required") ("428 Precondition Required") ("429 Too Many Requests") ("431 Request Header Fields Too Large") ("449 Retry with") ("500 Internal Server Error") ("501 Not Implemented") ("502 Bad Gateway") ("503 Service Unavailable") ("504 Gateway Timeout") ("505 HTTP Version Not Supported") ("506 Variant Also Negotiates") ("507 Insufficient Storage") ("509 Bandwidth Limit Exceeded") ("510 Not Extended") ("511 Network Authentication Required"))) (action . message))) (defvar helm-clj-http-source '((name . "clj-http options") (candidates . ((":accept - keyword for content type to accept") (":as - output coercion: :json, :json-string-keys, :clojure, :stream, :auto or string") (":basic-auth - string or vector of basic auth creds") (":body - body of request") (":body-encoding - encoding type for body string") (":client-params - apache http client params") (":coerce - when to coerce response body: :always, :unexceptional, :exceptional") (":conn-timeout - timeout for connection") (":connection-manager - connection pooling manager") (":content-type - content-type for request") (":cookie-store - CookieStore object to store/retrieve cookies") (":cookies - map of cookie name to cookie map") (":debug - boolean to print info to stdout") (":debug-body - boolean to print body debug info to stdout") (":decode-body-headers - automatically decode body headers") (":decompress-body - whether to decompress body automatically") (":digest-auth - vector of digest authentication") (":follow-redirects - boolean whether to follow HTTP redirects") (":form-params - map of form parameters to send") (":headers - map of headers") (":ignore-unknown-host? - whether to ignore inability to resolve host") (":insecure? - boolean whether to accept invalid SSL certs") (":json-opts - map of json options to be used for form params") (":keystore - file path to SSL keystore") (":keystore-pass - password for keystore") (":keystore-type - type of SSL keystore") (":length - manually specified length of body") (":max-redirects - maximum number of redirects to follow") (":multipart - vector of multipart options") (":oauth-token - oauth token") (":proxy-host - hostname of proxy server") (":proxy-ignore-hosts - set of hosts to ignore for proxy") (":proxy-post - port for proxy server") (":query-params - map of query parameters") (":raw-headers - boolean whether to return raw headers with response") (":response-interceptor - function called for each redirect") (":retry-handler - function to handle HTTP retries on IOException") (":save-request? - boolean to return original request with response") (":socket-timeout - timeout for establishing socket") (":throw-entire-message? - whether to throw the entire response on errors") (":throw-exceptions - boolean whether to throw exceptions on 5xx & 4xx") (":trust-store - file path to trust store") (":trust-store-pass - password for trust store") (":trust-store-type - type of trust store"))) (action . message))) (defun helm-httpstatus () (interactive) (helm-other-buffer '(helm-httpstatus-source) "*helm httpstatus*")) (defun helm-clj-http () (interactive) (helm-other-buffer '(helm-clj-http-source) "*helm clj-http flags*")) (global-set-key (kbd "C-c M-C-h") 'helm-httpstatus) (global-set-key (kbd "C-c M-h") 'helm-clj-http) (use-package helm-swoop :bind (("M-i" . helm-swoop) ("M-I" . helm-swoop-back-to-last-point) ("C-c M-i" . helm-multi-swoop)) :config (progn ;; When doing isearch, hand the word over to helm-swoop (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch) ;; From helm-swoop to helm-multi-swoop-all (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop) ;; Save buffer when helm-multi-swoop-edit complete (setq helm-multi-swoop-edit-save t ;; If this value is t, split window inside the current window helm-swoop-split-with-multiple-windows nil ;; Split direcion. 'split-window-vertically or 'split-window-horizontally helm-swoop-split-direction 'split-window-vertically ;; If nil, you can slightly boost invoke speed in exchange for text color helm-swoop-speed-or-color nil))) ))
helm-ls-git
Uses git grep
for that
(use-package helm-ls-git :defer t :bind ("C-x C-d" . helm-browse-project))
helm-dash
helm-dash
allows querying and loading Dash docsets from helm, without
requiring the Dash app or online connectivity (great for planes).
(use-package helm-dash :init (progn ;; Use the Java and Elasticsearch common docsets everywhere (setq helm-dash-common-docsets '(Java_SE7 ElasticSearch))))
hydra
I'm not really a huge fan of hydra, mostly because I don't need popups for every little thing under the sun. I'm only using it for my toggle map right now, so I can remember what all I can toggle.
(use-package hydra :init (progn (defhydra hydra-toggle-map nil " ^Toggle^ ^^^^^^^^-------------------- _d_: debug-on-error _D_: debug-on-quit _f_: auto-fill-mode _l_: toggle-truncate-lines _h_: hl-line-mode _r_: read-only-mode _v_: viewing-mode _n_: narrow-or-widen-dwim _g_: golden-ratio-mode _q_: quit " ("d" toggle-debug-on-error :exit t) ("D" toggle-debug-on-quit :exit t) ("g" golden-ratio-mode :exit t) ("f" auto-fill-mode :exit t) ("l" toggle-truncate-lines :exit t) ("r" read-only-mode :exit t) ("h" hl-line-mode :exit t) ("v" my/turn-on-viewing-mode :exit t) ("n" my/narrow-or-widen-dwim :exit t) ("q" nil :exit t)) (global-set-key (kbd "C-x t") 'hydra-toggle-map/body)))
Jump between errors in a buffer:
(defhydra hydra-next-error (global-map "C-x") "next-error" ("`" next-error "next") ("j" next-error "next" :bind nil) ("n" next-error "next" :bind nil) ("k" previous-error "previous" :bind nil) ("p" previous-error "previous" :bind nil) ("l" flycheck-list-errors "list-errors" :exit t))
yasnippet
Snippets for coding, loading while idle so startup is faster.
(use-package yasnippet :defer t :diminish yas-minor-mode :init (progn (yas-global-mode 1) (yas-reload-all)))
And some niceties to allow choosing a snippet using helm:
(use-package helm-config :defer t :config (use-package yasnippet :bind ("M-=" . yas-insert-snippet) :config (progn (defun my-yas/prompt (prompt choices &optional display-fn) (let* ((names (loop for choice in choices collect (or (and display-fn (funcall display-fn choice)) choice))) (selected (helm-other-buffer `(((name . ,(format "%s" prompt)) (candidates . names) (action . (("Insert snippet" . (lambda (arg) arg)))))) "*helm yas/prompt*"))) (if selected (let ((n (position selected names :test 'equal))) (nth n choices)) (signal 'quit "user quit!")))) (custom-set-variables '(yas/prompt-functions '(my-yas/prompt))))))
log4j-mode
Need hl-line-mode
for this
(use-package log4j-mode :init (add-hook 'log4j-mode-hook #'my/turn-on-viewing-mode))
bookmark+
Extended bookmarks, which I've started used for dired buffers and so on
(use-package bookmark+ :config (progn (setq bookmark-version-control t ;; auto-save bookmarks bookmark-save-flag 1)))
editorconfig
EditorConfig is a per-project cross-editor way of specifying settings. See: http://editorconfig.org/
Mainly used by non-Emacs people, but we should always try to play nice :)
(use-package editorconfig)
company-mode (auto-complete)
Standard auto-completion configuration with company-mode
(use-package company :defer t :diminish "" :bind ("C-." . company-complete) :init (add-hook 'prog-mode-hook 'company-mode) :config (progn (setq company-idle-delay 0.1 ;; min prefix of 1 chars company-minimum-prefix-length 1 company-selection-wrap-around t company-show-numbers t company-dabbrev-downcase nil company-transformers '(company-sort-by-occurrence)) (bind-keys :map company-active-map ("C-n" . company-select-next) ("C-p" . company-select-previous) ("C-d" . company-show-doc-buffer) ("<tab>" . company-complete))))
smart-tab
Used smart-tab to complete everywhere except for ERC, shell and mu4e.
(use-package smart-tab :defer t :diminish "" :init (global-smart-tab-mode 1) :config (progn (add-to-list 'smart-tab-disabled-major-modes 'mu4e-compose-mode) (add-to-list 'smart-tab-disabled-major-modes 'erc-mode) (add-to-list 'smart-tab-disabled-major-modes 'shell-mode)))
undo-tree
Undo-tree allows me to have sane undo defaults, as well as being able to visualize it in ascii art if needed.
(use-package undo-tree :init (global-undo-tree-mode t) :defer t :diminish "" :config (progn (define-key undo-tree-map (kbd "C-x u") 'undo-tree-visualize) (define-key undo-tree-map (kbd "C-/") 'undo-tree-undo)))
popwin
Popwin handles little popup windows at the bottom of the screen, which is very helpful for documentation buffers and so on.
(use-package popwin :commands popwin-mode :init (popwin-mode 1) :config (progn (defvar popwin:special-display-config-backup popwin:special-display-config) (setq display-buffer-function 'popwin:display-buffer) ;; basic (push '("*Help*" :stick t :noselect t) popwin:special-display-config) (push '("*helm world time*" :stick t :noselect t) popwin:special-display-config) (push '("*Pp Eval Output*" :stick t) popwin:special-display-config) ;; magit (push '("*magit-process*" :stick t) popwin:special-display-config) ;; quickrun (push '("*quickrun*" :stick t) popwin:special-display-config) ;; dictionaly (push '("*dict*" :stick t) popwin:special-display-config) (push '("*sdic*" :stick t) popwin:special-display-config) ;; popwin for slime (push '(slime-repl-mode :stick t) popwin:special-display-config) ;; man (push '(Man-mode :stick t :height 20) popwin:special-display-config) ;; Elisp (push '("*ielm*" :stick t) popwin:special-display-config) (push '("*eshell pop*" :stick t) popwin:special-display-config) ;; pry (push '(inf-ruby-mode :stick t :height 20) popwin:special-display-config) ;; python (push '("*Python*" :stick t) popwin:special-display-config) (push '("*Python Help*" :stick t :height 20) popwin:special-display-config) (push '("*jedi:doc*" :stick t :noselect t) popwin:special-display-config) ;; Haskell (push '("*haskell*" :stick t) popwin:special-display-config) (push '("*GHC Info*") popwin:special-display-config) ;; sgit (push '("*sgit*" :position right :width 0.5 :stick t) popwin:special-display-config) ;; git-gutter (push '("*git-gutter:diff*" :width 0.5 :stick t) popwin:special-display-config) ;; es-results-mode (push '(es-result-mode :stick t :width 0.5) popwin:special-display-config) ;; direx (push '(direx:direx-mode :position left :width 40 :dedicated t) popwin:special-display-config) (push '("*Occur*" :stick t) popwin:special-display-config) ;; prodigy (push '("*prodigy*" :stick t) popwin:special-display-config) ;; malabar-mode (push '("*Malabar Compilation*" :stick t :height 30) popwin:special-display-config) ;; org-mode (push '("*Org tags*" :stick t :height 30) popwin:special-display-config) ;; Completions (push '("*Completions*" :stick t :noselect t) popwin:special-display-config) ;; ggtags (push '("*ggtags-global*" :stick t :noselect t :height 30) popwin:special-display-config) ;; async shell commands (push '("*Async Shell Command*" :stick t) popwin:special-display-config) (defun my/popup-downloads () "Pop up the downloads buffer (3rd eshell buffer for me" (interactive) (popwin:popup-buffer "*eshell*<3>")) ;; eshell 3 is always my "download stuff" buffer (global-set-key (kbd "C-x M-d") #'my/popup-downloads) (global-set-key (kbd "C-h e") 'popwin:messages)))
paren-face
Paren-face adds a face for parentheses, which is used by themes to darken the parens.
(use-package paren-face :init (global-paren-face-mode))
ido-mode
First, turn on ido-mode everywhere, and if flx-ido is installed, enable it everywhere as well.
Ido gives really nice completion while flx-ido makes everything more flexible instead of rigid completions
(use-package ido :config (progn (setq ido-use-virtual-buffers nil ;; this setting causes weird TRAMP connections, don't set it! ;;ido-enable-tramp-completion nil ido-enable-flex-matching t ido-auto-merge-work-directories-length nil ido-create-new-buffer 'always ido-use-filename-at-point 'guess ido-max-prospects 10))) (use-package flx-ido :init (flx-ido-mode 1) :config (setq ido-use-faces nil)) (use-package ido-vertical-mode :init (ido-vertical-mode t)) (use-package ido-ubiquitous)
multiple-cursors
Mulitple cursors is like rectangular selection/insertion but on steroids
(use-package multiple-cursors :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)))
twittering-mode
Load up twittering mode, but defer it since I'm probably not loading emacs to immediately use Twitter :P
(use-package twittering-mode :defer t :config (progn (setq twittering-icon-mode t twittering-use-master-password t)))
scpaste
scp-ing an HTML version of the current buffer somewhere
(use-package scpaste :defer t :config (setq scpaste-http-destination "http://p.writequit.org" scpaste-scp-destination "writequit:public_html/wq/paste/"))
smex
Smex is IDO, but for M-x
(use-package smex :bind (("M-x" . smex) ("M-X" . smex-major-mode-commands)))
volatile-highlights
Highlights things like undo, copy, paste, etc.
(defun my/turn-on-volatile-highlights () (interactive) (volatile-highlights-mode t) (diminish 'volatile-highlights-mode)) (use-package volatile-highlights :defer t :init (progn (require 'volatile-highlights) ;; vh has a problem with autoloads (add-hook 'org-mode-hook #'my/turn-on-volatile-highlights) (add-hook 'prog-mode-hook #'my/turn-on-volatile-highlights)))
color-identifiers-mode
Color-identifiers-mode gives colors to unique variables passed into functions. Can be really handy to see if you've misspelled a variable name.
(use-package color-identifiers-mode)
iedit
Iedit is interactive edit, where if you are on a word and you enter iedit-mode, you're basically editing every instance of that word/variable in the buffer.
(use-package iedit :bind ("C-;" . iedit-mode))
eyebrowse
Eyebrowse is a great package for workspaces in Emacs.
(use-package eyebrowse :diminish eyebrowse-mode :init (progn (defun my/create-eyebrowse-setup () (interactive) "Create a default window config, if none is present" (when (not (eyebrowse--window-config-present-p 2)) ;; there's probably a better way to do this, creating two workspaces (eyebrowse-switch-to-window-config-2) (eyebrowse-switch-to-window-config-1))) (setq eyebrowse-wrap-around t eyebrowse-new-workspace t) (eyebrowse-mode 1) (global-set-key (kbd "C-'") 'eyebrowse-next-window-config) (add-hook 'after-init-hook #'my/create-eyebrowse-setup)))
origami
Origami is a folding mode that supports a pretty good subset of languages, so I'm giving it a try.
(use-package origami :bind (("C-c TAB" . origami-recursively-toggle-node) ("C-\\" . origami-recursively-toggle-node) ("M-\\" . origami-close-all-nodes) ("M-+" . origami-open-all-nodes)) :init (global-origami-mode))
hideshow
Kind of like Vim's folding, but manually done right now.
I'm in the process of trying out Origami as a replacement, since it's a bit easier on the brain and has nicer functions (supposedly), so this is disabled for now.
(use-package hideshow :disabled t :bind (("C-c TAB" . hs-toggle-hiding) ("C-\\" . hs-toggle-hiding) ("M-\\" . hs-hide-all) ("M-+" . hs-show-all)) :init (progn (defun my/enable-hs-minor-mode () (interactive) (hs-minor-mode t)) ;; (add-hook 'javascript-mode-hook 'my/enable-hs-minor-mode) ;; (add-hook 'js-mode-hook 'my/enable-hs-minor-mode) ;; (add-hook 'java-mode-hook 'my/enable-hs-minor-mode) (add-hook 'prog-mode-hook 'my/enable-hs-minor-mode)) :config (progn (defvar hs-special-modes-alist (mapcar 'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (javascript-mode "{" "}" "/[*/]" nil))))))
abbrev
I use abbrev-mode to automatically correct misspellings I usually make. In this case, I misspell elasticsearch all the time, and I type it all the time, so it's helpful to auto-correct.
(use-package abbrev :diminish "" :config (progn (define-key ctl-x-map "\C-a" 'my/ispell-word-then-abbrev) (defun my/ispell-word-then-abbrev (p) "Call `ispell-word'. Then create an abbrev for the correction made. With prefix P, create local abbrev. Otherwise it will be global." (interactive "P") (let ((bef (downcase (or (thing-at-point 'word) ""))) aft) (call-interactively 'ispell-word) (setq aft (downcase (or (thing-at-point 'word) ""))) (unless (string= aft bef) (message "\"%s\" now expands to \"%s\" %sally" bef aft (if p "loc" "glob")) (define-abbrev (if p local-abbrev-table global-abbrev-table) bef aft)))) (setq save-abbrevs t) (setq-default abbrev-mode t))) (defun my/enable-abbrev-mode () (interactive) (abbrev-mode t)) (add-hook 'prog-mode-hook #'my/enable-abbrev-mode)
From https://github.com/purcell/emacs.d/blob/master/lisp/init-auto-complete.el - Exclude very large buffers from dabbrev
(defun sanityinc/dabbrev-friend-buffer (other-buffer) (< (buffer-size other-buffer) (* 1 1024 1024))) (setq dabbrev-friend-buffer-function 'sanityinc/dabbrev-friend-buffer)
vlf (view large files)
VLF lets me handle things like 2gb files gracefully.
(use-package vlf-setup)
eww
Ewwwwww…
Wait, no, I mean the Emacs web browser built in to 24.4
(use-package eww :defer t :init (progn (define-prefix-command 'my/eww-map) (define-key ctl-x-map "w" 'my/eww-map) (define-key my/eww-map "t" 'eww) (define-key my/eww-map "o" 'eww) (define-key my/eww-map "w" 'my/eww-wiki) (define-key my/eww-map "e" 'my/search-es-docs) (defun my/eww-wiki (text) "Function used to search wikipedia for the given text." (interactive (list (read-string "Wiki for: "))) (eww (format "https://en.m.wikipedia.org/wiki/Special:Search?search=%s" (url-encode-url text))))) :config (progn (define-key eww-mode-map "o" 'eww) (define-key eww-mode-map "O" 'eww-browse-with-external-browser) (use-package eww-lnum :init (eval-after-load "eww" '(progn (define-key eww-mode-map "f" 'eww-lnum-follow) (define-key eww-mode-map "F" 'eww-lnum-universal))))))
visible-mark
(defface visible-mark-active ;; put this before (use-package visible-mark) '((((type tty) (class mono))) (t (:background "magenta"))) "") (use-package visible-mark :init (global-visible-mark-mode 1) :config (progn (setq visible-mark-max 2) (setq visible-mark-faces `(visible-mark-face1 visible-mark-face2))))
fill-column-indicator
While I would love to enable this, it's disabled because of https://github.com/alpaker/Fill-Column-Indicator/issues/45
(defun my/turn-on-fill-column-indicator () (interactive) (fci-mode 1)) (use-package fill-column-indicator :disabled t :init (add-hook 'prog-mode-hook #'my/turn-on-fill-column-indicator) :config (progn (setq fci-rule-column 80)))
idle-highlight-mode
Highlight idle things, but only in certain modes
(use-package idle-highlight-mode :init (progn (defun turn-on-idle-highlight-mode () (interactive) (idle-highlight-mode 1)) (add-hook 'java-mode-hook #'turn-on-idle-highlight-mode) (add-hook 'emacs-lisp-mode-hook #'turn-on-idle-highlight-mode) (add-hook 'clojure-lisp-mode-hook #'turn-on-idle-highlight-mode)))
Bindings
These are miscellaneous bindings used all over the place that don't really fit in anywhere else.
(global-set-key (kbd "C-x +") 'balance-windows-area) (global-set-key (kbd "C-x C-l") 'toggle-truncate-lines) (defun my/turn-on-viewing-mode () "Turn on the viewing mode, to make looking through logs easier" (interactive) (read-only-mode 1) (view-mode 1) (hl-line-mode 1)) ;; join on killing lines (defun kill-and-join-forward (&optional arg) "If at end of line, join with following; otherwise kill line. Deletes whitespace at join." (interactive "P") (if (and (eolp) (not (bolp))) (delete-indentation t) (kill-line arg))) (global-set-key (kbd "C-k") 'kill-and-join-forward) ;; You know, like Readline. (global-set-key (kbd "C-M-h") 'backward-kill-word) ;; Completion that uses many different methods to find options. (global-set-key (kbd "M-/") 'hippie-expand) ;; Perform general cleanup. (global-set-key (kbd "C-c n") #'cleanup-buffer) ;; Font size (define-key global-map (kbd "C-+") 'text-scale-increase) (define-key global-map (kbd "C--") 'text-scale-decrease) ;; Use regex searches by default. (global-set-key (kbd "C-s") 'isearch-forward-regexp) (global-set-key (kbd "\C-r") 'isearch-backward-regexp) (global-set-key (kbd "C-c y") 'bury-buffer) (global-set-key (kbd "C-c r") 'revert-buffer) ;; Start eshell or switch to it if it's active. (global-set-key (kbd "C-x m") 'eshell) ;; Start a new eshell even if one is active. (global-set-key (kbd "C-x M") (lambda () (interactive) (eshell t))) ;; Start a regular shell if you prefer that. (global-set-key (kbd "C-x C-m") 'shell) ;; If you want to be able to M-x without meta (phones, etc) (global-set-key (kbd "C-c C-x") 'execute-extended-command) ;; Activate occur easily inside isearch (define-key isearch-mode-map (kbd "C-o") (lambda () (interactive) (let ((case-fold-search isearch-case-fold-search)) (occur (if isearch-regexp isearch-string (regexp-quote isearch-string)))))) ;; ==== Window switching ==== (defun my/other-window-backwards () (interactive) (other-window -1)) (global-set-key (kbd "M-'") 'other-window) (global-set-key (kbd "M-\"") 'my/other-window-backwards) (global-set-key (kbd "H-'") 'other-window) (global-set-key [C-tab] 'other-window) (global-set-key [C-S-tab] 'my/other-window-backwards) ;; ==== transpose buffers ==== (defun transpose-buffers (arg) "Transpose the buffers shown in two windows." (interactive "p") (let ((selector (if (>= arg 0) 'next-window 'previous-window))) (while (/= arg 0) (let ((this-win (window-buffer)) (next-win (window-buffer (funcall selector)))) (set-window-buffer (selected-window) next-win) (set-window-buffer (funcall selector) this-win) (select-window (funcall selector))) (setq arg (if (plusp arg) (1- arg) (1+ arg)))))) (global-set-key (kbd "C-x 4 t") 'transpose-buffers)
Utility methods
Various methods I call interactively for things.
Fixing SSH agent settings
This is for correctly finding the SSH agent:
(defun find-agent () (first (split-string (shell-command-to-string (concat "ls -t1 " "$(find /tmp/ -uid $UID -path \\*ssh\\* -type s 2> /dev/null)" "|" "head -1"))))) (defun fix-agent () (interactive) (let ((agent (find-agent))) (setenv "SSH_AUTH_SOCK" agent) (message agent)))
Format JSON more beautifully
I work with a ton of JSON, so I need to be able to format it nicely. Fortunately this is really easy with Python:
(defun beautify-json () (interactive) (let ((b (if mark-active (min (point) (mark)) (point-min))) (e (if mark-active (max (point) (mark)) (point-max)))) (shell-command-on-region b e "python -mjson.tool" (current-buffer) t)))
Recompile startup elisp files
Byte-compile startup stuff.
(defun byte-recompile-init-files () "Recompile all of the startup files" (interactive) (byte-recompile-directory "~/.emacs.d" 0))
Adding directories to $PATH
A utility method to add things to the $PATH, if needed.
(defun add-to-path (path-element) "Add the specified path element to the Emacs PATH" (interactive "DEnter directory to be added to path: ") (if (file-directory-p path-element) (setenv "PATH" (concat (expand-file-name path-element) path-separator (getenv "PATH")))))
Misc methods for cleaning up a buffer
(defun untabify-buffer () (interactive) (untabify (point-min) (point-max))) (defun indent-buffer () (interactive) (indent-region (point-min) (point-max))) (defun cleanup-buffer () "Perform a bunch of operations on the whitespace content of a buffer." (interactive) (indent-buffer) (untabify-buffer) (delete-trailing-whitespace))
Browsing URLs
Search backwards, prompting to open any URL found. This is
fantastic for ERC buffers. I bind this to C-c u
because I use it
a lot.
(defun browse-last-url-in-brower () (interactive) (save-excursion (let ((ffap-url-regexp (concat "\\(" "news\\(post\\)?:\\|mailto:\\|file:" "\\|" "\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://" "\\)."))) (ffap-next t t)))) (global-set-key (kbd "C-c u") 'browse-last-url-in-brower)
Numbering rectangles
Let's say you have a list like:
First Item Second Item Third Item Fourth Item
And you want to number it to look like:
1. First Item 2. Second Item 3. Third Item 4. Fourth Item
This function allows you to hit C-x r N
and specify the pattern
and starting offset to number lines in rectangular-selection mode:
(defun number-rectangle (start end format-string from) "Delete (don't save) text in the region-rectangle, then number it." (interactive (list (region-beginning) (region-end) (read-string "Number rectangle: " (if (looking-back "^ *") "%d. " "%d")) (read-number "From: " 1))) (save-excursion (goto-char start) (setq start (point-marker)) (goto-char end) (setq end (point-marker)) (delete-rectangle start end) (goto-char start) (loop with column = (current-column) while (and (<= (point) end) (not (eobp))) for i from from do (move-to-column column t) (insert (format format-string i)) (forward-line 1))) (goto-char start)) (global-set-key (kbd "C-x r N") 'number-rectangle)
Insert look of disapproval
Used more often than you'd think…
(defun my/insert-lod () "Well. This is disappointing." (interactive) (insert "ಠ_ಠ")) (global-set-key (kbd "C-c M-d") 'my/insert-lod)
Browse Elasticsearch documentation
A function to search/browse ES docs from Emacs using eww
(defun my/search-es-docs (text) "Search ES docs for `text'." (interactive (list (read-string "Search for: "))) (eww (url-encode-url (format "http://www.elastic.co/?q=%s" text)))) (global-set-key (kbd "C-c d") 'my/search-es-docs)
Narrow-widen DWIM (do what I mean)
(defun my/narrow-or-widen-dwim (p) "If the buffer is narrowed, it widens. Otherwise, it narrows intelligently. Intelligently means: region, org-src-block, org-subtree, or defun, whichever applies first. Narrowing to org-src-block actually calls `org-edit-src-code'. With prefix P, don't widen, just narrow even if buffer is already narrowed." (interactive "P") (declare (interactive-only)) (cond ((and (buffer-narrowed-p) (not p)) (widen)) ((region-active-p) (narrow-to-region (region-beginning) (region-end))) ((derived-mode-p 'org-mode) ;; `org-edit-src-code' is not a real narrowing command. ;; Remove this first conditional if you don't want it. (cond ((org-in-src-block-p) (org-edit-src-code) (delete-other-windows)) ((org-at-block-p) (org-narrow-to-block)) (t (org-narrow-to-subtree)))) (t (narrow-to-defun))))
Move by block of text
See: http://ergoemacs.org/emacs/emacs_move_by_paragraph.html
(defun xah-forward-block (&optional φn) "Move cursor forward to the beginning of next text block. A text block is separated by blank lines. In most major modes, this is similar to `forward-paragraph', but this command's behavior is the same regardless of syntax table." (interactive "p") (search-forward-regexp "\n[\t\n ]*\n+" nil "NOERROR" φn)) (defun xah-backward-block (&optional φn) "Move cursor backward to previous text block. See: `xah-forward-block'" (interactive "p") (dotimes (ξn φn) (if (search-backward-regexp "\n[\t\n ]*\n+" nil "NOERROR") (progn (skip-chars-backward "\n\t ")) (progn (goto-char (point-min)))))) (global-set-key (kbd "<C-up>") 'xah-backward-block) (global-set-key (kbd "<C-down>") 'xah-forward-block)
File previews
Taken from …
(defun my/quick-view-file-at-point () "Preview the file at point then jump back after some idle time. In order for this to work you need to bind this function to a key combo, you cannot call it from the minibuffer and let it work. The reason it works is that by holding the key combo down, you inhibit idle timers from running so as long as you hold the key combo, the buffer preview will still display." (interactive) (setq-local lexical-binding t) (let* ((buffer (current-buffer)) (file (thing-at-point 'filename t)) (file-buffer-name (format "*preview of %s*" file))) (if (and file (file-exists-p file)) (let ((contents)) (if (get-buffer file) (setq contents (save-excursion (with-current-buffer (get-buffer file) (font-lock-fontify-buffer) (buffer-substring (point-min) (point-max))))) (let ((new-buffer (find-file-noselect file))) (with-current-buffer new-buffer (font-lock-mode t) (font-lock-fontify-buffer) (setq contents (buffer-substring (point-min) (point-max)))) (kill-buffer new-buffer))) (switch-to-buffer (get-buffer-create file-buffer-name)) (setq-local header-line-format "%60b") (delete-region (point-min) (point-max)) (save-excursion (insert contents)) (local-set-key (kbd "C-M-v") (lambda () (interactive) (sit-for .2))) (run-with-idle-timer .7 nil (lambda () (switch-to-buffer buffer) (kill-buffer file-buffer-name)))) (message "no file to preview at point!")))) (global-set-key (kbd "C-M-v") 'my/quick-view-file-at-point)
Replace smart quotes
I hate smart quotes
(defcustom smart-to-ascii '(("\x201C" . "\"") ("\x201D" . "\"") ("\x2018" . "'") ("\x2019" . "'") ;; en-dash ("\x2013" . "-") ;; em-dash ("\x2014" . "-")) "Map of smart quotes to their replacements" :type '(repeat (cons (string :tag "Smart Character ") (string :tag "Ascii Replacement")))) (defun my/smart-to-ascii (beg end) "Replace smart quotes and dashes with their ASCII equivalents" (interactive "r") (format-replace-strings smart-to-ascii nil beg end))
Change number of replicas for an index
So, I'd like something to prompt me for an index name and the number of replicas to change to, because I do this quite a bit…
(defun my/change-replica-count (index replicas) (interactive (list (read-string "Index (_all for all): ") (read-string "Number of replicas: "))) (async-shell-command (concat "curl -XPUT 'localhost:9200/" index "/_settings' -d'{\"index\": {\"number_of_replicas\": " replicas "}}'")))