├── Ensime.png ├── Movement.png ├── README.md ├── Scrolling.png ├── Spectacle.png ├── cheatsheet.pdf ├── emacs ├── emacs.d.zip ├── emacs2.png ├── emacsclient ├── emacsserver └── init.el /Ensime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/Ensime.png -------------------------------------------------------------------------------- /Movement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/Movement.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | emacs-for-scala 2 | =============== 3 | 4 | My Emacs setup for Scala development, including a fully-configured Ensime. 5 | 6 | ![What does it look like?] 7 | (./emacs2.png) 8 | 9 | This latest version uses MELPA to download packages instead of installing them directly, and excludes a bunch of packages I've experimented with, but that didn't find their way into my day-to-day workflow. 10 | 11 | Intended for use with Emacs for OSX version 24.4 (but likely adapted for other combinations easily enough) 12 | 13 | To install additional packages not included by default on startup: 14 | 15 | Use M-x package-list-packages 16 | Select the package you want and select "install" 17 | 18 | Or edit the .emacs.d/init.el file to taste. 19 | 20 | The first time you run load Emacs, it will download the internet. No, it will only feel that way - it will download all package you don't already have installed from MELPA and install them: this only happens the first time. 21 | 22 | The .emacs.d contained in this repo has a specific set of keybindings set up for Emacs. Mostly these are the defaults from whatever included modules have been used, but in a few cases they've been customized to play well together. 23 | 24 | Please see here for a series of articles describing the Emacs config I've published here. 25 | 26 | By default, the "emacs" launch script here is set up to launch Emacs in GUI mode, using the Emacs for OSX, and not to use client-server mode. If you want to use character-mode, add the param "-nw" to the startup script. This is useful if you want to use Emacs on a remote system, or to use it with Tmux or Screen. 27 | 28 | For faster startup of Emacs, you can do two things: Compile the elisp, or use Emacs in client-server mode. 29 | 30 | For client-server mode, put the scripts 'emacsserver' and 'emacsclient' found in this repo in your path (before any other emacs), and then run "emacs ." - if the server is not running, it will start it, then subsequent launches of emacs will be very quick. 31 | 32 | The scripts are intended for OSX, but again could easily be adapted. 33 | 34 | Other apps 35 | ---------- 36 | If your an Emacs user on OSX, you might also want to check out 37 | - the Emacsome add-on for Chrome 38 | - the Amethyst window manager 39 | - Spectacles (a simpler window manager) 40 | - Alfred 41 | 42 | With a bit of work, you can work mostly rodent-free. On OSX the keys map as follows: 43 | 44 | | Abbreviation | OSX Key | Notes | 45 | |--------------|---------|---------| 46 | | M | Option | Meta | 47 | | S | Command | Super | 48 | | C | Control | Control | 49 | 50 | 51 | # Movement Keys 52 | 53 | ![Movement](Movement.png) 54 | 55 | # Files, Windows, Scrolling Keys 56 | 57 | ![Scrolling](Scrolling.png) 58 | 59 | # Ensime 60 | 61 | ![Ensime](Ensime.png) 62 | 63 | # Spectacle 64 | 65 | ![Spectacle](Spectacle.png) 66 | 67 | 68 | ------- 69 | 70 | Emacs.d Unplugged 71 | ----------------- 72 | There is a file emacs.d.zip that contains a snapshot of a .emacs.d directory with all of the above installed 73 | and configured. In envronments where it is not possible for Emacs to contact melpa and download all the 74 | dependencies directly, you can unzip this file and be up and running immediately - no further downloads should be needed. 75 | 76 | -------------------------------------------------------------------------------- /Scrolling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/Scrolling.png -------------------------------------------------------------------------------- /Spectacle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/Spectacle.png -------------------------------------------------------------------------------- /cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/cheatsheet.pdf -------------------------------------------------------------------------------- /emacs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /Applications/Emacs.app/Contents/MacOS/Emacs "$@" 3 | 4 | -------------------------------------------------------------------------------- /emacs.d.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/emacs.d.zip -------------------------------------------------------------------------------- /emacs2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelpnash/emacs-for-scala/7cd566335068a42eed197c6e0b9df57a84e108c4/emacs2.png -------------------------------------------------------------------------------- /emacsclient: -------------------------------------------------------------------------------- 1 | SERVERS=`ps -fe | grep Emacs | grep Applications | wc -l` 2 | if [ $SERVERS == 0 ]; then 3 | echo "Server not running - starting up..." 4 | emacsserver 5 | fi 6 | /Applications/Emacs.app/Contents/MacOS/bin/emacsclient -c -s ~/.emacs.d/server/server $* 7 | -------------------------------------------------------------------------------- /emacsserver: -------------------------------------------------------------------------------- 1 | SERVERS=`ps -fe | grep Emacs | grep Applications | wc -l` 2 | if [ "$1" == "stop" ]; then 3 | echo "Stopping emacs server..." 4 | /Applications/Emacs.app/Contents/MacOS/bin/emacsclient -nw -s ~/.emacs.d/server/server -e "(kill-emacs)" 5 | else 6 | if [ $SERVERS != 0 ]; then 7 | echo "Server already running" 8 | else 9 | echo "Starting emacs server..." 10 | /Applications/Emacs.app/Contents/MacOS/Emacs --daemon 11 | fi 12 | fi 13 | -------------------------------------------------------------------------------- /init.el: -------------------------------------------------------------------------------- 1 | (x-focus-frame nil) 2 | (setq mac-command-modifier 'super) 3 | 4 | (global-unset-key (kbd "C-z")) 5 | 6 | ;; Org mode 7 | (require 'org) 8 | (define-key global-map "\C-cl" 'org-store-link) 9 | (define-key global-map "\C-ca" 'org-agenda) 10 | (setq org-log-done t) 11 | 12 | (require 'package) 13 | (add-to-list 'package-archives 14 | '("melpa" . "http://melpa.org/packages/") t) 15 | (when (< emacs-major-version 24) 16 | ;; For important compatibility libraries like cl-lib 17 | (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/"))) 18 | 19 | ;; Automatically close brackets/braces - I found this more annoying than helpful 20 | ;; (electric-pair-mode 1) 21 | 22 | ;; List the package we want 23 | (setq package-list '(ensime magit multiple-cursors find-file-in-repository ace-jump-mode yasnippet window-numbering expand-region neotree monokai-theme rainbow-delimiters markdown-mode slime yafolding ido-grid-mode dumb-jump ag)) 24 | 25 | (autoload 'findr "findr" "Find file name." t) 26 | (define-key global-map [(meta control S)] 'findr) 27 | 28 | (autoload 'findr-search "findr" "Find text in files." t) 29 | (define-key global-map [(meta control s)] 'findr-search) 30 | 31 | (autoload 'findr-query-replace "findr" "Replace text in files." t) 32 | (define-key global-map [(meta control r)] 'findr-query-replace) 33 | 34 | (package-initialize) 35 | 36 | ;; Fetch list of packages available 37 | (unless package-archive-contents 38 | (package-refresh-contents)) 39 | 40 | ;; install the packages that are missing, if any 41 | (dolist (package package-list) 42 | (unless (package-installed-p package) 43 | (package-install package))) 44 | 45 | (require 'ensime) 46 | ;; Start ensime mode whenever we open scala mode, e.g. open a .scala file 47 | (add-hook 'scala-mode-hook 'ensime-scala-mode-hook) 48 | ;; Start ensime with Super-e 49 | (global-set-key (kbd "C-c C-c c") 'ensime) 50 | 51 | ;; Don't show the magit instructions every time 52 | (setq magit-last-seen-setup-instructions "1.4.0") 53 | 54 | (require 'multiple-cursors) 55 | (require 'multiple-cursors) 56 | (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines) 57 | (global-set-key (kbd "C->") 'mc/mark-next-like-this) 58 | (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) 59 | (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this) 60 | 61 | (custom-set-variables 62 | ;; custom-set-variables was added by Custom. 63 | ;; If you edit it by hand, you could mess it up, so be careful. 64 | ;; Your init file should contain only one such instance. 65 | ;; If there is more than one, they won't work right. 66 | '(custom-safe-themes 67 | (quote 68 | ("fc5fcb6f1f1c1bc01305694c59a1a861b008c534cae8d0e48e4d5e81ad718bc6" default))) 69 | '(org-agenda-files 70 | (quote 71 | ("~/Dropbox/org/business.org" "~/Dropbox/org/personal.org"))) 72 | '(org-support-shift-select t) 73 | '(send-mail-function (quote smtpmail-send-it)) 74 | '(tool-bar-mode nil)) 75 | (custom-set-faces 76 | ;; custom-set-faces was added by Custom. 77 | ;; If you edit it by hand, you could mess it up, so be careful. 78 | ;; Your init file should contain only one such instance. 79 | ;; If there is more than one, they won't work right. 80 | '(default ((((class color) (min-colors 257)) (:foreground "#F8F8F2" :background "#272822")) (((class color) (min-colors 89)) (:foreground "#F5F5F5" :background "#1B1E1C"))))) 81 | 82 | (set-face-attribute 'default nil :height 160) 83 | 84 | (setq ensime-sem-high-faces 85 | '( 86 | (implicitConversion nil) 87 | (var . (:foreground "#ff2222")) 88 | (val . (:foreground "#dddddd")) 89 | (varField . (:foreground "#ff3333")) 90 | (valField . (:foreground "#dddddd")) 91 | (functionCall . (:foreground "#dc9157")) 92 | (param . (:foreground "#ffffff")) 93 | (object . (:foreground "#D884E3")) 94 | (class . (:foreground "green")) 95 | (trait . (:foreground "#009933")) ;; "#084EA8")) 96 | (operator . (:foreground "#cc7832")) 97 | (object . (:foreground "#6897bb" :slant italic)) 98 | (package . (:foreground "yellow")) 99 | (implicitConversion . (:underline (:style wave :color "blue"))) 100 | (implicitParams . (:underline (:style wave :color "blue"))) 101 | (deprecated . (:strike-through "#a9b7c6")) 102 | (implicitParams nil) 103 | ) 104 | ;; ensime-completion-style 'company 105 | ;; ensime-sem-high-enabled-p nil ;; disable semantic highlighting 106 | ensime-tooltip-hints t ;; disable type-inspecting tooltips 107 | ensime-tooltip-type-hints t ;; disable typeinspecting tooltips 108 | ) 109 | 110 | ;; Highlight current line - mostly useful for demos, etc 111 | ;;(set-face-background hl-line-face "gold") 112 | 113 | (require 'find-file-in-repository) 114 | 115 | (global-linum-mode 1) 116 | (global-set-key [f7] 'kill-whole-line) 117 | (global-set-key (kbd "M-s M-m") 'magit-status) 118 | (global-set-key (kbd "M-s M-/") 'comment-or-uncomment-region) 119 | (global-set-key (kbd "C-x C-M-f") 'find-file-in-repository) 120 | (global-set-key (kbd "C-c C-r r") 'ensime-refactor-rename) 121 | (global-set-key (kbd "C-c C-o i") 'ensime-refactor-organize-imports) 122 | (global-set-key (kbd "C-c C-i l") 'ensime-refactor-inline-local) 123 | (global-set-key (kbd "C-c C-t i") 'ensime-inspect-by-path) 124 | (put 'dired-find-alternate-file 'disabled nil) 125 | 126 | ;;Uncomment the below to hide the menu 127 | ;;(menu-bar-mode -1) 128 | 129 | ;; Uncomment below if you want to disable compile on save 130 | ;; (setq ensime-sbt-compile-on-save nil) 131 | 132 | ;; Some general-purpose key bindings 133 | (global-set-key [kp-subtract] 'undo) ; [Undo] 134 | (global-set-key (kbd "S-z") 'undo) 135 | (global-set-key [insert] 'overwrite-mode) ; [Ins] 136 | (global-set-key [kp-insert] 'overwrite-mode) ; [Ins] 137 | (global-set-key (kbd "M-g") 'goto-line) ; [Ctrl]-l] 138 | (global-set-key (kbd "C-L") 'recenter-top-bottom) 139 | (global-set-key [f2] 'split-window-vertically) 140 | (global-set-key [f1] 'remove-split) 141 | 142 | (setq ido-enable-flex-matching t) 143 | (setq ido-everywhere t) 144 | (ido-mode 1) 145 | (setq ido-use-filename-at-point 'guess) 146 | (setq ido-create-new-buffer 'always) 147 | (setq ido-file-extensions-order '(".scala" ".org" ".txt" ".py" ".emacs" ".xml" ".el" ".ini" ".cfg" ".cnf")) 148 | 149 | (require 'ace-jump-mode) 150 | (define-key global-map (kbd "C-c SPC") 'ace-jump-mode) 151 | (autoload 152 | 'ace-jump-mode 153 | "ace-jump-mode" 154 | "Emacs quick move minor mode" 155 | t) 156 | (autoload 157 | 'ace-jump-mode-pop-mark 158 | "ace-jump-mode" 159 | "Ace jump back:-)" 160 | t) 161 | 162 | (define-key global-map (kbd "RET") 'newline-and-indent) 163 | 164 | (defun search-to-brace () 165 | "Jump to the next open brace" 166 | (interactive) 167 | (search-forward "{")) 168 | (define-key global-map (kbd "M-s {") 'search-to-brace) 169 | 170 | (defun search-to-prev-brace () 171 | "Jump to the previous brace" 172 | (interactive) 173 | (search-backward "{")) 174 | (define-key global-map (kbd "M-S {") 'search-to-prev-brace) 175 | 176 | (defun search-to-close-brace () 177 | "Jump to the next close brace" 178 | (interactive) 179 | (search-forward "}")) 180 | (define-key global-map (kbd "M-s }") 'search-to-close-brace) 181 | 182 | (defun search-to-prev-close-brace () 183 | "Jump to the previous close brace" 184 | (interactive) 185 | (search-backward "}")) 186 | (define-key global-map (kbd "M-S }") 'search-to-prev-brace) 187 | 188 | (defun search-to-next-def () 189 | "Jump to the next def" 190 | (interactive) 191 | (search-forward "def ")) 192 | (define-key global-map (kbd "M-s d") 'search-to-next-def) 193 | 194 | (defun search-to-prev-def () 195 | "Jump to the previous def" 196 | (interactive) 197 | (search-backward "def ")) 198 | (define-key global-map (kbd "M-S d") 'search-to-prev-def) 199 | 200 | (setq-default indent-tabs-mode nil) 201 | (setq-default tab-width 2) 202 | (setq indent-line-function 'insert-tab) 203 | 204 | (define-key global-map (kbd "") 'scala-indent:indent-with-reluctant-strategy) 205 | 206 | ;; Solarized theme 207 | ;; (require 'color-theme) 208 | ;; (require 'color-theme-solarized) 209 | ;;(load-theme 'solarized t) 210 | ;; Use M-x customize-variable frame-background-mode to change 211 | ;;(color-theme-solarized) 212 | 213 | ;; Un-comment below lines for Monokai theme 214 | (require 'monokai-theme) 215 | (load-theme 'monokai t) 216 | (setq frame-background-mode 'dark) 217 | 218 | 219 | ;; Always pick up the most recent file from the filesystem 220 | (global-auto-revert-mode 1) 221 | 222 | (global-set-key (kbd "s-j") 'dired-jump) 223 | 224 | (setq server-socket-dir "~/.emacs.d/server") 225 | 226 | ;; window command shortcuts 227 | (global-set-key (kbd "s-|") 'split-window-horizontally) 228 | (global-set-key (kbd "C-x 9") 'split-window-horizontally) 229 | (global-set-key (kbd "s--") 'split-window-vertically) 230 | (global-set-key (kbd "s-+") 'remove-split) 231 | (global-set-key (kbd "s-") 'enlarge-window) 232 | (global-set-key (kbd "s-") 'shrink-window) 233 | (global-set-key (kbd "s-") 'enlarge-window-horizontally) 234 | (global-set-key (kbd "s-") 'shrink-window-horizontally) 235 | (global-set-key (kbd "M-k") 'kill-whole-line) 236 | 237 | (global-set-key (kbd "s-1") 'ace-jump-line-mode) 238 | (global-set-key (kbd "s-2") 'ace-jump-word-mode) 239 | 240 | (global-set-key (kbd "s-f") 'find-file-in-repository) 241 | 242 | ;; Put temporary and backup files elsewhere 243 | (setq auto-save-file-name-transforms 244 | `((".*" ,(concat user-emacs-directory "auto-save/") t))) 245 | (setq backup-directory-alist 246 | `(("." . ,(expand-file-name 247 | (concat user-emacs-directory "backups"))))) 248 | (setq create-lockfiles nil) 249 | 250 | (require 'yasnippet) 251 | (yas-global-mode 1) 252 | 253 | (require 'window-numbering) 254 | (window-numbering-mode 1) 255 | 256 | (require 'expand-region) 257 | (global-set-key (kbd "C-=") 'er/expand-region) 258 | 259 | (defun save-all () (interactive) (save-some-buffers t)) 260 | (global-set-key (kbd "S-s") 'save-all) 261 | 262 | (global-set-key (kbd "s-R") 'ensime-inf-eval-buffer) 263 | (global-set-key (kbd "s-r") 'ensime-inf-eval-region) 264 | 265 | (require 'neotree) 266 | (global-set-key (kbd "s-d") 'neotree-toggle) 267 | ;;uncomment to have a neotree window open initially 268 | ;;(neotree) 269 | 270 | (require 'whitespace) 271 | (setq whitespace-line-column 120) 272 | (setq whitespace-style '(face lines-tail)) 273 | (global-whitespace-mode +1) 274 | 275 | (setq show-paren-delay 0) 276 | (setq blink-matching-paren 1) 277 | (show-paren-mode 1) 278 | 279 | (defun bf-pretty-print-xml-region (begin end) 280 | "Pretty format XML markup in region. You need to have nxml-mode 281 | http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do 282 | this. The function inserts linebreaks to separate tags that have 283 | nothing but whitespace between them. It then indents the markup 284 | by using nxml's indentation rules." 285 | (interactive "r") 286 | (save-excursion 287 | (nxml-mode) 288 | (goto-char begin) 289 | (while (search-forward-regexp "\>[ \\t]*\<" nil t) 290 | (backward-char) (insert "\n")) 291 | (indent-region begin end)) 292 | (message "Ah, much better!")) 293 | 294 | (require 'rainbow-delimiters) 295 | (add-hook 'scala-mode-hook #'rainbow-delimiters-mode) 296 | (add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode) 297 | 298 | ;; Save on focus-out 299 | (defun save-all () 300 | (interactive) 301 | (save-some-buffers t)) 302 | (add-hook 'focus-out-hook 'save-all) 303 | 304 | (set-frame-font "Source Code Pro-18" nil t) 305 | 306 | ;; Exit emacs w/o prompts 307 | (require 'cl) 308 | (defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate) 309 | (flet ((process-list ())) ad-do-it)) 310 | 311 | (add-hook 'markdown-mode-hook (lambda () (electric-indent-local-mode -1))) 312 | 313 | ;; Control and mouse-wheel-up to increase font size in buffer, down to decrease 314 | (global-set-key [C-wheel-up] '(lambda () (interactive) (text-scale-increase 1))) 315 | (global-set-key [C-wheel-down] '(lambda () (interactive) (text-scale-decrease 1))) 316 | 317 | ;; Super wheel-up to increase font size in all buffers 318 | (defun change-font-height (delta) 319 | (set-face-attribute 'default 320 | (selected-frame) 321 | :height (+ (face-attribute 'default :height) delta))) 322 | (global-set-key [M-wheel-up] '(lambda () (interactive) (change-font-height +4))) 323 | (global-set-key [M-wheel-down] '(lambda () (interactive) (change-font-height -4))) 324 | 325 | (setq inferior-lisp-program "/usr/local/bin/sbcl") 326 | 327 | ;; Turn on yafolding-mode for scala files 328 | (add-hook 'prog-mode-hook 329 | (lambda () (yafolding-mode))) 330 | ;; Uncomment below to start with all elements folded 331 | ;; (add-hook 'scala-mode-hook 332 | ;; (lambda () (yafolding-mode) (yafolding-toggle-all))) 333 | 334 | 335 | (defun jump-to-test () 336 | "Jump to correspnding test file" 337 | (interactive) 338 | (find-file-other-window (format "%s%sTest.scala" (replace-regexp-in-string "app\/" "test\/" (file-name-directory buffer-file-name)) (file-name-nondirectory (file-name-sans-extension buffer-file-name))))) 339 | 340 | (global-set-key (kbd "s-T") 'jump-to-test) 341 | 342 | (ido-grid-mode 1) 343 | 344 | (global-set-key (kbd "s-b") 'ido-display-buffer) 345 | 346 | --------------------------------------------------------------------------------