forked from purcell/emacs.d
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit-lisp.el
264 lines (195 loc) · 8.91 KB
/
init-lisp.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
(require-package 'elisp-slime-nav)
(dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
(add-hook hook 'elisp-slime-nav-mode))
(require-package 'lively)
(setq-default initial-scratch-message
(concat ";; Happy hacking " (or user-login-name "") "!\n\n"))
;; Make C-x C-e run 'eval-region if the region is active
(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)))
(global-set-key (kbd "M-:") 'pp-eval-expression)
(after-load 'lisp-mode
(define-key emacs-lisp-mode-map (kbd "C-x C-e") 'sanityinc/eval-last-sexp-or-region))
(require-package 'ipretty)
(ipretty-mode 1)
(defadvice pp-display-expression (after make-read-only (expression out-buffer-name) activate)
"Enable `view-mode' in the output buffer - if any - so it can be closed with `\"q\"."
(when (get-buffer out-buffer-name)
(with-current-buffer out-buffer-name
(view-mode 1))))
;; Use C-c C-z to toggle between elisp files and an ielm session
;; I might generalise this to ruby etc., or even just adopt the repl-toggle package.
(defvar sanityinc/repl-original-buffer nil
"Buffer from which we jumped to this REPL.")
(make-variable-buffer-local 'sanityinc/repl-original-buffer)
(defvar sanityinc/repl-switch-function 'switch-to-buffer-other-window)
(defun sanityinc/switch-to-ielm ()
(interactive)
(let ((orig-buffer (current-buffer)))
(if (get-buffer "*ielm*")
(funcall sanityinc/repl-switch-function "*ielm*")
(ielm))
(setq sanityinc/repl-original-buffer orig-buffer)))
(defun sanityinc/repl-switch-back ()
"Switch back to the buffer from which we reached this REPL."
(interactive)
(if sanityinc/repl-original-buffer
(funcall sanityinc/repl-switch-function sanityinc/repl-original-buffer)
(error "No original buffer.")))
(after-load 'lisp-mode
(define-key emacs-lisp-mode-map (kbd "C-c C-z") 'sanityinc/switch-to-ielm))
(after-load 'ielm
(define-key ielm-map (kbd "C-c C-z") 'sanityinc/repl-switch-back))
;; ----------------------------------------------------------------------------
;; Hippie-expand
;; ----------------------------------------------------------------------------
(defun my/emacs-lisp-module-name ()
"Search the buffer for `provide' declaration."
(save-excursion
(goto-char (point-min))
(when (search-forward-regexp "^(provide '" nil t)
(symbol-name (symbol-at-point)))))
;; Credit to Chris Done for this one.
(defun my/try-complete-lisp-symbol-without-namespace (old)
"Hippie expand \"try\" function which expands \"-foo\" to \"modname-foo\" in elisp."
(unless old
(he-init-string (he-lisp-symbol-beg) (point))
(when (string-prefix-p "-" he-search-string)
(let ((mod-name (my/emacs-lisp-module-name)))
(when mod-name
(setq he-expand-list (list (concat mod-name he-search-string)))))))
(when he-expand-list
(he-substitute-string (car he-expand-list))
(setq he-expand-list nil)
t))
(defun set-up-hippie-expand-for-elisp ()
"Locally set `hippie-expand' completion functions for use with Emacs Lisp."
(make-local-variable 'hippie-expand-try-functions-list)
(add-to-list 'hippie-expand-try-functions-list 'try-complete-lisp-symbol t)
(add-to-list 'hippie-expand-try-functions-list 'try-complete-lisp-symbol-partially t)
(add-to-list 'hippie-expand-try-functions-list 'my/try-complete-lisp-symbol-without-namespace t))
;; ----------------------------------------------------------------------------
;; Automatic byte compilation
;; ----------------------------------------------------------------------------
(require-package 'auto-compile)
(auto-compile-on-save-mode 1)
(auto-compile-on-load-mode 1)
;; ----------------------------------------------------------------------------
;; Load .el if newer than corresponding .elc
;; ----------------------------------------------------------------------------
(setq load-prefer-newer t)
;; ----------------------------------------------------------------------------
;; Highlight current sexp
;; ----------------------------------------------------------------------------
(require-package 'hl-sexp)
;; Prevent flickery behaviour due to hl-sexp-mode unhighlighting before each command
(after-load 'hl-sexp
(defadvice hl-sexp-mode (after unflicker (&optional turn-on) activate)
(when turn-on
(remove-hook 'pre-command-hook #'hl-sexp-unhighlight))))
;;; Support byte-compilation in a sub-process, as
;;; required by highlight-cl
(defun sanityinc/byte-compile-file-batch (filename)
"Byte-compile FILENAME in batch mode, ie. a clean sub-process."
(interactive "fFile to byte-compile in batch mode: ")
(let ((emacs (car command-line-args)))
(compile
(concat
emacs " "
(mapconcat
'shell-quote-argument
(list "-Q" "-batch" "-f" "batch-byte-compile" filename)
" ")))))
;; ----------------------------------------------------------------------------
;; Enable desired features for all lisp modes
;; ----------------------------------------------------------------------------
(require-package 'rainbow-delimiters)
(require-package 'redshank)
(after-load 'redshank
(diminish 'redshank-mode))
(maybe-require-package 'aggressive-indent)
(defun sanityinc/lisp-setup ()
"Enable features useful in any Lisp mode."
(rainbow-delimiters-mode t)
(enable-paredit-mode)
(when (fboundp 'aggressive-indent-mode)
(aggressive-indent-mode))
(turn-on-eldoc-mode)
(redshank-mode)
(add-hook 'after-save-hook #'check-parens nil t))
(defun sanityinc/emacs-lisp-setup ()
"Enable features useful when working with elisp."
(elisp-slime-nav-mode t)
(set-up-hippie-expand-for-elisp)
(ac-emacs-lisp-mode-setup))
(defconst sanityinc/elispy-modes
'(emacs-lisp-mode ielm-mode)
"Major modes relating to elisp.")
(defconst sanityinc/lispy-modes
(append sanityinc/elispy-modes
'(lisp-mode inferior-lisp-mode lisp-interaction-mode))
"All lispy major modes.")
(require 'derived)
(dolist (hook (mapcar #'derived-mode-hook-name sanityinc/lispy-modes))
(add-hook hook 'sanityinc/lisp-setup))
(dolist (hook (mapcar #'derived-mode-hook-name sanityinc/elispy-modes))
(add-hook hook 'sanityinc/emacs-lisp-setup))
(if (boundp 'eval-expression-minibuffer-setup-hook)
(add-hook 'eval-expression-minibuffer-setup-hook #'eldoc-mode)
(require-package 'eldoc-eval)
(require 'eldoc-eval)
(eldoc-in-minibuffer-mode 1))
(add-to-list 'auto-mode-alist '("\\.emacs-project\\'" . emacs-lisp-mode))
(add-to-list 'auto-mode-alist '("archive-contents\\'" . emacs-lisp-mode))
(require-package 'cl-lib-highlight)
(after-load 'lisp-mode
(cl-lib-highlight-initialize))
;; ----------------------------------------------------------------------------
;; Delete .elc files when reverting the .el from VC or magit
;; ----------------------------------------------------------------------------
;; When .el files are open, we can intercept when they are modified
;; by VC or magit in order to remove .elc files that are likely to
;; be out of sync.
;; This is handy while actively working on elisp files, though
;; obviously it doesn't ensure that unopened files will also have
;; their .elc counterparts removed - VC hooks would be necessary for
;; that.
(defvar sanityinc/vc-reverting nil
"Whether or not VC or Magit is currently reverting buffers.")
(defadvice revert-buffer (after sanityinc/maybe-remove-elc activate)
"If reverting from VC, delete any .elc file that will now be out of sync."
(when sanityinc/vc-reverting
(when (and (eq 'emacs-lisp-mode major-mode)
buffer-file-name
(string= "el" (file-name-extension buffer-file-name)))
(let ((elc (concat buffer-file-name "c")))
(when (file-exists-p elc)
(message "Removing out-of-sync elc file %s" (file-name-nondirectory elc))
(delete-file elc))))))
(defadvice magit-revert-buffers (around sanityinc/reverting activate)
(let ((sanityinc/vc-reverting t))
ad-do-it))
(defadvice vc-revert-buffer-internal (around sanityinc/reverting activate)
(let ((sanityinc/vc-reverting t))
ad-do-it))
(require-package 'macrostep)
(after-load 'lisp-mode
(define-key emacs-lisp-mode-map (kbd "C-c e") 'macrostep-expand))
;; A quick way to jump to the definition of a function given its key binding
(global-set-key (kbd "C-h K") 'find-function-on-key)
(when (maybe-require-package 'rainbow-mode)
(defun sanityinc/enable-rainbow-mode-if-theme ()
(when (string-match "\\(color-theme-\\|-theme\\.el\\)" (buffer-name))
(rainbow-mode 1)))
(add-hook 'emacs-lisp-mode-hook 'sanityinc/enable-rainbow-mode-if-theme))
(when (maybe-require-package 'highlight-quoted)
(add-hook 'emacs-lisp-mode-hook 'highlight-quoted-mode))
(when (maybe-require-package 'flycheck)
(require-package 'flycheck-package)
(after-load 'flycheck
(flycheck-package-setup)))
(provide 'init-lisp)