21
|
1
|
;;; default.el --- default config -*- lexical-binding: t -*- |
27
|
2
|
|
|
3
|
;;; Code: |
30
|
4
|
;;; Settings |
21
|
5
|
(put 'upcase-region 'disabled nil) |
30
|
6
|
(put 'list-threads 'disabled nil) |
|
7
|
(put 'list-timers 'disabled nil) |
34
|
8
|
(setq show-paren-context-when-offscreen 'overlay) |
|
9
|
(setopt |
|
10
|
;; tabs = bad |
|
11
|
indent-tabs-mode nil |
31
|
12
|
make-backup-files nil |
|
13
|
auto-save-list-file-prefix (expand-file-name "auto-save/." user-emacs-directory) |
|
14
|
tramp-auto-save-directory (expand-file-name "auto-save/tramp/" user-emacs-directory) |
|
15
|
dired-free-space nil |
34
|
16
|
mml-attach-file-at-the-end t |
|
17
|
dired-mouse-drag-files t |
31
|
18
|
confirm-kill-emacs nil |
|
19
|
confirm-kill-processes nil |
|
20
|
use-short-answers t |
|
21
|
display-time-format "%Y-%m-%d %H:%M" |
|
22
|
ring-bell-function 'ignore |
|
23
|
completion-ignore-case t |
33
|
24
|
;; NOTE 2023-11-04: you need to add the following lines to ~/.gnupg/gpg-agent.conf: |
|
25
|
;; allow-emacs-pinentry |
|
26
|
;; allow-loopback-pinentry |
41
|
27
|
epg-pinentry-mode 'loopback |
31
|
28
|
shr-use-colors nil |
|
29
|
shr-use-fonts nil |
|
30
|
shr-max-image-proportion 0.6 |
|
31
|
shr-image-animate nil |
|
32
|
shr-discard-aria-hidden t |
|
33
|
bookmark-default-file (expand-file-name "bookmarks" user-emacs-directory) |
|
34
|
project-list-file (expand-file-name "projects" user-emacs-directory) |
|
35
|
emms-directory (expand-file-name "emms" user-emacs-directory) |
|
36
|
gnus-cache-directory (expand-file-name "gnus" user-emacs-directory) |
|
37
|
url-cache-directory (expand-file-name "url" user-emacs-directory) |
|
38
|
tab-always-indent 'complete |
|
39
|
shr-cookie-policy nil |
34
|
40
|
;; NOTE 2023-11-04: EXPERIMENTAL |
|
41
|
shr-use-xwidgets-for-media t |
31
|
42
|
browse-url-browser-function 'browse-url-default-browser |
34
|
43
|
eww-auto-rename-buffer 'title |
31
|
44
|
eww-search-prefix "https://duckduckgo.com/html?q=" |
34
|
45
|
view-read-only t) |
27
|
46
|
|
30
|
47
|
;;; Variables |
33
|
48
|
(defvar user-custom-file (expand-file-name (format "%s.el" user-login-name) user-emacs-directory)) |
32
|
49
|
(defvar user-home-directory (expand-file-name "~")) |
|
50
|
(defvar user-lab-directory (expand-file-name "lab" user-home-directory)) |
|
51
|
(defvar user-stash-directory (expand-file-name "stash" user-home-directory)) |
|
52
|
(defvar user-store-directory (expand-file-name "store" user-home-directory)) |
|
53
|
(defvar user-shed-directory (expand-file-name "shed" user-home-directory)) |
|
54
|
(defvar user-mail-directory (expand-file-name "mail" user-home-directory)) |
|
55
|
(defvar user-media-directory (expand-file-name "media" user-home-directory)) |
|
56
|
|
41
|
57
|
(defvar default-theme 'leuven-dark) |
|
58
|
(defvar company-source-directory (join-paths user-lab-directory "comp")) |
|
59
|
(defvar company-domain "compiler.company") |
|
60
|
(defvar company-name "The Compiler Company, LLC") |
|
61
|
(defvar company-vc-domain "vc.compiler.company") |
|
62
|
(defvar company-home "the.compiler.company") |
|
63
|
|
30
|
64
|
;;; Theme |
34
|
65
|
(defun load-default-theme () (interactive) (load-theme default-theme)) |
|
66
|
|
|
67
|
(add-hook 'after-init-hook #'load-default-theme) |
27
|
68
|
|
|
69
|
;;; Packages |
|
70
|
(package-initialize) |
28
|
71
|
|
27
|
72
|
(with-eval-after-load 'package |
34
|
73
|
(setq package-archives |
|
74
|
'(("gnu" . "https://elpa.gnu.org/packages/") |
|
75
|
("nongnu" . "https://elpa.nongnu.org/nongnu/") |
|
76
|
("melpa" . "https://melpa.org/packages/")) |
|
77
|
use-package-always-ensure t |
|
78
|
use-package-expand-minimally t) |
28
|
79
|
(add-packages |
33
|
80
|
org-web-tools ;; web parsing |
|
81
|
citeproc ;; citations |
|
82
|
all-the-icons all-the-icons-dired all-the-icons-ibuffer ;; icons |
44
|
83
|
corfu orderless cape ;; completion |
33
|
84
|
slime ;; common lisp server |
44
|
85
|
slime-company |
33
|
86
|
which-key ;; key helper |
|
87
|
;; langs |
|
88
|
rust-mode) |
28
|
89
|
(package-install-selected-packages t)) |
26
|
90
|
|
45
|
91
|
;;; Env |
62
|
92
|
(require 'exec-path-from-shell) |
|
93
|
(exec-path-from-shell-copy-env "SSH_AGENT_PID") |
|
94
|
(exec-path-from-shell-copy-env "SSH_AUTH_SOCK") |
|
95
|
(exec-path-from-shell-copy-env "PATH") |
45
|
96
|
(add-to-list 'exec-path (expand-file-name "~/.cargo/bin/")) |
|
97
|
(add-to-list 'exec-path (expand-file-name "~/.local/bin/")) |
|
98
|
(add-to-list 'exec-path "/bin/") |
|
99
|
(add-to-list 'exec-path "/usr/local/sbin/") |
|
100
|
|
33
|
101
|
;;; Completions |
|
102
|
(use-package corfu |
44
|
103
|
:init (global-corfu-mode)) |
|
104
|
|
|
105
|
(use-package cape |
|
106
|
;; Bind dedicated completion commands |
|
107
|
;; Alternative prefix keys: C-c p, M-p, M-+, ... |
|
108
|
:bind (("C-c p p" . completion-at-point) ;; capf |
|
109
|
("C-c p t" . complete-tag) ;; etags |
|
110
|
("C-c p d" . cape-dabbrev) ;; or dabbrev-completion |
|
111
|
("C-c p h" . cape-history) |
|
112
|
("C-c p f" . cape-file) |
|
113
|
("C-c p k" . cape-keyword) |
|
114
|
("C-c p s" . cape-elisp-symbol) |
|
115
|
("C-c p e" . cape-elisp-block) |
|
116
|
("C-c p a" . cape-abbrev) |
|
117
|
("C-c p l" . cape-line) |
|
118
|
("C-c p w" . cape-dict) |
|
119
|
("C-c p :" . cape-emoji) |
|
120
|
("C-c p \\" . cape-tex) |
|
121
|
("C-c p _" . cape-tex) |
|
122
|
("C-c p ^" . cape-tex) |
|
123
|
("C-c p &" . cape-sgml) |
|
124
|
("C-c p r" . cape-rfc1345)) |
|
125
|
:init |
|
126
|
;; Add to the global default value of `completion-at-point-functions' which is |
|
127
|
;; used by `completion-at-point'. The order of the functions matters, the |
|
128
|
;; first function returning a result wins. Note that the list of buffer-local |
|
129
|
;; completion functions takes precedence over the global list. |
60
|
130
|
;; (add-to-list 'completion-at-point-functions #'cape-dabbrev) |
|
131
|
;; (add-to-list 'completion-at-point-functions #'cape-abbrev) |
59
|
132
|
;; (add-to-list 'completion-at-point-functions #'cape-history) |
60
|
133
|
;; (add-to-list 'completion-at-point-functions #'cape-keyword) |
|
134
|
;; (add-to-list 'completion-at-point-functions #'cape-file) |
59
|
135
|
;; (add-to-list 'completion-at-point-functions #'cape-line) |
|
136
|
;; (add-to-list 'completion-at-point-functions #'cape-elisp-block) |
60
|
137
|
;; (add-to-list 'completion-at-point-functions #'cape-tex) |
59
|
138
|
;; (add-to-list 'completion-at-point-functions #'cape-sgml) |
|
139
|
;; (add-to-list 'completion-at-point-functions #'cape-rfc1345) |
|
140
|
;; (add-to-list 'completion-at-point-functions #'cape-dict) |
|
141
|
;; (add-to-list 'completion-at-point-functions #'cape-elisp-symbol) |
|
142
|
;; (add-to-list 'completion-at-point-functions #'cape-emoji) |
|
143
|
) |
33
|
144
|
|
|
145
|
(use-package orderless |
34
|
146
|
:custom |
33
|
147
|
(completion-styles '(orderless basic)) |
|
148
|
(completion-category-overrides '((file (styles basic partial-completion))))) |
|
149
|
|
30
|
150
|
;;; Desktop |
34
|
151
|
(setopt desktop-dirname (expand-file-name "sessions" user-emacs-directory)) |
33
|
152
|
|
30
|
153
|
;;; Multisession |
|
154
|
(setq multisession-storage 'sqlite) |
|
155
|
|
21
|
156
|
;;; VC |
|
157
|
;; use rhg, fallback to hg. see hgrc |
|
158
|
(if (file-exists-p "~/.local/bin/rhg") |
34
|
159
|
(setq hg-binary "~/.local/bin/rhg")) |
21
|
160
|
|
|
161
|
;;; Dired |
29
|
162
|
(add-hook 'dired-mode-hook #'all-the-icons-dired-mode) |
|
163
|
(add-hook 'ibuffer-mode-hook #'all-the-icons-ibuffer-mode) |
26
|
164
|
|
21
|
165
|
;;; Lisp |
26
|
166
|
(use-package lisp-mode |
|
167
|
:ensure nil |
33
|
168
|
:custom |
|
169
|
inferior-lisp-program "sbcl" |
|
170
|
scheme-program-name "gsi" |
|
171
|
guile-program "guile" |
|
172
|
cmulisp-program "lisp" |
|
173
|
scsh-program "scsh") |
26
|
174
|
|
|
175
|
(use-package slime |
44
|
176
|
:ensure t |
26
|
177
|
:config |
44
|
178
|
(setq slime-contribs '(slime-fancy slime-quicklisp)) |
53
|
179
|
|
|
180
|
(put 'make-instance 'common-lisp-indent-function 1) |
|
181
|
(put 'reinitialize-instance 'common-lisp-indent-function 1) |
|
182
|
|
26
|
183
|
(defvar slime-toggle nil) |
|
184
|
(defun slime-toggle () |
|
185
|
"toggle between lisp file and slime-repl" |
|
186
|
(interactive) |
|
187
|
(if (eq major-mode 'slime-repl-mode) |
34
|
188
|
(setq slime-toggle (pop-to-buffer (or slime-toggle (read-buffer "lisp file: ")))) |
21
|
189
|
(progn |
44
|
190
|
(setq slime-toggle (current-buffer)) |
53
|
191
|
(slime-repl)))) |
|
192
|
|
|
193
|
(defun clouseau-inspect (string) |
|
194
|
"Inspect a lisp value with Clouseau. make sure to load clouseau |
|
195
|
with a custom core or in your init file before using this |
|
196
|
function: '(ql:quickload :clouseau)'." |
|
197
|
(interactive |
|
198
|
(list (slime-read-from-minibuffer |
|
199
|
"Inspect value (evaluated): " |
|
200
|
(slime-sexp-at-point)))) |
|
201
|
(let ((inspector 'cl-user::*clouseau-inspector*)) |
|
202
|
(slime-eval-async |
|
203
|
`(cl:progn |
|
204
|
(cl:defvar ,inspector nil) |
|
205
|
;; (Re)start the inspector if necessary. |
|
206
|
(cl:unless (cl:and (clim:application-frame-p ,inspector) |
|
207
|
(clim-internals::frame-process ,inspector)) |
|
208
|
(cl:setf ,inspector (cl:nth-value 1 (clouseau:inspect nil :new-process t)))) |
|
209
|
;; Tell the inspector to visualize the correct datum. |
|
210
|
(cl:setf (clouseau:root-object ,inspector :run-hook-p t) |
|
211
|
(cl:eval (cl:read-from-string ,string))) |
|
212
|
;; Return nothing. |
|
213
|
(cl:values))))) |
|
214
|
|
|
215
|
(define-key slime-prefix-map (kbd "i") 'clouseau-inspect)) |
21
|
216
|
|
|
217
|
;;; Rust |
|
218
|
(add-hook 'rust-mode-hook 'eglot-ensure) |
30
|
219
|
(setq rust-rustfmt-switches nil |
|
220
|
rust-indent-offset 2) |
|
221
|
|
26
|
222
|
(with-eval-after-load 'eglot |
|
223
|
(add-to-list 'eglot-server-programs '(rust-mode . ("rust-analyzer")))) |
21
|
224
|
|
30
|
225
|
;;; Python |
|
226
|
(setq python-indent-offset 2) |
|
227
|
(add-hook 'python-mode-hook 'eglot-ensure) |
|
228
|
|
|
229
|
;;; Bash |
|
230
|
(setq sh-basic-offset 2) |
|
231
|
|
31
|
232
|
;;; Comments |
|
233
|
(defcustom prog-comment-keywords |
|
234
|
'("TODO" "REVIEW" "FIX" "HACK" "RESEARCH") |
|
235
|
"List of strings with comment keywords." |
|
236
|
:group 'default) |
|
237
|
|
|
238
|
(defcustom prog-comment-timestamp-format-concise "%F" |
|
239
|
"Specifier for date in `prog-comment-timestamp-keyword'. |
|
240
|
Refer to the doc string of `format-time-string' for the available |
|
241
|
options." |
|
242
|
:group 'default) |
|
243
|
|
|
244
|
(defcustom prog-comment-timestamp-format-verbose "%F %T %z" |
|
245
|
"Like `prog-comment-timestamp-format-concise', but longer." |
|
246
|
:group 'default) |
|
247
|
|
|
248
|
;;;###autoload |
|
249
|
(defun prog-comment-dwim (arg) |
|
250
|
"Flexible, do-what-I-mean commenting. |
|
251
|
|
|
252
|
If region is active and ARG is either a numeric argument greater |
|
253
|
than one or a universal prefix (\\[universal-argument]), then |
|
254
|
apply `comment-kill' on all comments in the region. |
|
255
|
|
|
256
|
If the region is active and no ARG is supplied, or is equal to a |
|
257
|
numeric prefix of 1, then toggle the comment status of the region. |
|
258
|
|
|
259
|
Else toggle the comment status of the line at point. With a |
|
260
|
numeric prefix ARG, do so for ARGth lines (negative prefix |
|
261
|
operates on the lines before point)." |
|
262
|
(interactive "p") |
|
263
|
(cond |
|
264
|
((and (> arg 1) (use-region-p)) |
|
265
|
(let* ((beg (region-beginning)) |
|
266
|
(end (region-end)) |
|
267
|
(num (count-lines beg end))) |
|
268
|
(save-excursion |
|
269
|
(goto-char beg) |
|
270
|
(comment-kill num)))) |
|
271
|
((use-region-p) |
|
272
|
(comment-or-uncomment-region (region-beginning) (region-end))) |
|
273
|
(t |
|
274
|
(save-excursion (comment-line (or arg 1)))))) |
|
275
|
|
|
276
|
(defvar prog-comment--keyword-hist '() |
|
277
|
"Input history of selected comment keywords.") |
|
278
|
|
|
279
|
(defun prog-comment--keyword-prompt (keywords) |
|
280
|
"Prompt for candidate among KEYWORDS." |
|
281
|
(let ((def (car prog-comment--keyword-hist))) |
|
282
|
(completing-read |
|
283
|
(format "Select keyword [%s]: " def) |
|
284
|
keywords nil nil nil 'prog-comment--keyword-hist def))) |
|
285
|
|
|
286
|
|
|
287
|
;;;###autoload |
|
288
|
(defun prog-comment-timestamp-keyword (keyword &optional verbose) |
|
289
|
"Add timestamped comment with KEYWORD. |
|
290
|
|
|
291
|
When called interactively, the list of possible keywords is that |
|
292
|
of `prog-comment-keywords', though it is possible to |
|
293
|
input arbitrary text. |
|
294
|
|
|
295
|
If point is at the beginning of the line or if line is empty (no |
|
296
|
characters at all or just indentation), the comment is started |
|
297
|
there in accordance with `comment-style'. Any existing text |
|
298
|
after the point will be pushed to a new line and will not be |
|
299
|
turned into a comment. |
|
300
|
|
|
301
|
If point is anywhere else on the line, the comment is indented |
|
302
|
with `comment-indent'. |
|
303
|
|
|
304
|
The comment is always formatted as 'DELIMITER KEYWORD DATE:', |
|
305
|
with the date format being controlled by the variable |
|
306
|
`prog-comment-timestamp-format-concise'. |
|
307
|
|
|
308
|
With optional VERBOSE argument (such as a prefix argument |
|
309
|
`\\[universal-argument]'), use an alternative date format, as |
|
310
|
specified by `prog-comment-timestamp-format-verbose'." |
|
311
|
(interactive |
|
312
|
(list |
|
313
|
(prog-comment--keyword-prompt prog-comment-keywords) |
|
314
|
current-prefix-arg)) |
|
315
|
(let* ((date (if verbose |
|
316
|
comment-timestamp-format-verbose |
34
|
317
|
prog-comment-timestamp-format-concise)) |
|
318
|
(string (format "%s %s: " keyword (format-time-string date))) |
31
|
319
|
(beg (point))) |
|
320
|
(cond |
|
321
|
((or (eq beg (point-at-bol)) |
|
322
|
(default-line-regexp-p 'empty)) |
|
323
|
(let* ((maybe-newline (unless (default-line-regexp-p 'empty 1) "\n"))) |
|
324
|
;; NOTE 2021-07-24: we use this `insert' instead of |
|
325
|
;; `comment-region' because of a yet-to-be-determined bug that |
|
326
|
;; traps `undo' to the two states between the insertion of the |
|
327
|
;; string and its transformation into a comment. |
|
328
|
(insert |
|
329
|
(concat comment-start |
|
330
|
;; NOTE 2021-07-24: See function `comment-add' for |
|
331
|
;; why we need this. |
|
332
|
(make-string |
|
333
|
(comment-add nil) |
|
334
|
(string-to-char comment-start)) |
|
335
|
comment-padding |
|
336
|
string |
|
337
|
comment-end)) |
|
338
|
(indent-region beg (point)) |
|
339
|
(when maybe-newline |
|
340
|
(save-excursion (insert maybe-newline))))) |
|
341
|
(t |
|
342
|
(comment-indent t) |
|
343
|
(insert (concat " " string)))))) |
|
344
|
|
34
|
345
|
(setq hexl-bits 8) |
31
|
346
|
(setq tab-width 4) |
|
347
|
|
21
|
348
|
;;; Keyboard Macros |
|
349
|
(defun toggle-macro-recording () |
|
350
|
(interactive) |
|
351
|
(if defining-kbd-macro |
|
352
|
(end-kbd-macro) |
|
353
|
(start-kbd-macro nil))) |
|
354
|
|
|
355
|
(defun play-macro-if-not-playing () |
|
356
|
(interactive) |
|
357
|
(if defining-kbd-macro |
|
358
|
(end-kbd-macro) |
|
359
|
(call-last-kbd-macro))) |
30
|
360
|
|
|
361
|
;;; Registers |
|
362
|
;; - additional register vtypes: buffer |
|
363
|
(defun decrement-register (number register) |
|
364
|
"Subtract NUMBER from the contents of register REGISTER. |
|
365
|
Interactively, NUMBER is the prefix arg." |
|
366
|
(interactive "p\ncDecrement register: ") |
|
367
|
(increment-register (- number) register)) |
|
368
|
|
|
369
|
(defun copy-register (a b) |
|
370
|
"Copy register A to B." |
|
371
|
(interactive |
|
372
|
(list (register-read-with-preview "From register: ") |
34
|
373
|
(register-read-with-preview "To register: "))) |
30
|
374
|
(set-register b (get-register a))) |
|
375
|
|
|
376
|
(defun buffer-to-register (register &optional delete) |
|
377
|
"Put current buffer in register - this would also work for |
|
378
|
just buffers, as switch-to-buffer can use both, but it |
|
379
|
facilitates for easier saving/restoring of registers." |
|
380
|
(interactive "cPut current buffername in register: \nP.") |
|
381
|
(set-register register (cons 'buffer (buffer-name (current-buffer))))) |
34
|
382
|
|
30
|
383
|
(defun file-to-register (register &optional delete) |
|
384
|
"This is better than put-buffer-in-register for file-buffers, because a closed |
|
385
|
file can be opened again, but does not work for no-file-buffers." |
|
386
|
(interactive "cPut the filename of current buffer in register: \nP") |
|
387
|
(set-register register (cons 'file (buffer-file-name (current-buffer))))) |
34
|
388
|
|
30
|
389
|
(defun file-query-to-register (register &optional delete) |
34
|
390
|
(interactive |
|
391
|
(list |
30
|
392
|
(register-read-with-preview "File query to register: "))) |
|
393
|
(set-register register (list 'file-query (buffer-file-name (current-buffer)) (point)))) |
|
394
|
|
|
395
|
;; additional register-val handlers |
|
396
|
;; (cl-defmethod register-val-jump-to :around ((val cons) delete) |
|
397
|
;; (cond |
|
398
|
;; (t (cl-call-next-method val delete)))) |
|
399
|
|
21
|
400
|
;;; Outlines |
34
|
401
|
(defun outline-hook (&optional rx) |
21
|
402
|
"Enable `outline-minor-mode' and set `outline-regexp'." |
57
|
403
|
(when rx (setq-local outline-regexp rx)) |
|
404
|
(outline-minor-mode 1)) |
21
|
405
|
|
57
|
406
|
(setq outline-minor-mode-use-buttons nil) |
34
|
407
|
|
|
408
|
(defun add-outline-hook (mode &optional rx) |
|
409
|
(let ((sym (symb mode "-hook"))) |
|
410
|
(add-hook sym (lambda () (outline-hook rx))))) |
21
|
411
|
|
|
412
|
(defmacro outline-hooks (&rest pairs) |
|
413
|
`(mapc (lambda (x) (add-outline-hook (car x) (cadr x))) ',pairs)) |
|
414
|
|
|
415
|
(outline-hooks (asm-mode ";;;+") |
34
|
416
|
(nasm-mode ";;;+") |
|
417
|
(rust-mode "\\(//!\\|////+\\)") |
|
418
|
(sh-mode "###+") |
|
419
|
(sh-script-mode "###+") |
|
420
|
(makefile-mode "###+") |
57
|
421
|
(conf-mode "###+") |
|
422
|
(common-lisp-mode) |
|
423
|
(emacs-lisp-mode) |
|
424
|
(lisp-data-mode) |
|
425
|
(org-mode) |
|
426
|
(css-mode) |
|
427
|
(html-mode) |
|
428
|
(skel-mode)) |
30
|
429
|
|
21
|
430
|
;;; Scratch |
|
431
|
(defcustom default-scratch-buffer-mode 'lisp-interaction-mode |
34
|
432
|
"Default major mode for new scratch buffers" |
|
433
|
:group 'default) |
21
|
434
|
|
30
|
435
|
;; Adapted from the `scratch.el' package by Ian Eure. |
|
436
|
(defun default-scratch-list-modes () |
|
437
|
"List known major modes." |
|
438
|
(cl-loop for sym the symbols of obarray |
|
439
|
for name = (symbol-name sym) |
|
440
|
when (and (functionp sym) |
|
441
|
(not (member sym minor-mode-list)) |
|
442
|
(string-match "-mode$" name) |
|
443
|
(not (string-match "--" name))) |
|
444
|
collect name)) |
|
445
|
|
|
446
|
(defun default-scratch-buffer-setup (region &optional mode) |
|
447
|
"Add contents to `scratch' buffer and name it accordingly. |
|
448
|
|
|
449
|
REGION is added to the contents to the new buffer. |
|
450
|
|
|
451
|
Use the current buffer's major mode by default. With optional |
|
452
|
MODE use that major mode instead." |
|
453
|
(let* ((major (or mode major-mode)) |
|
454
|
(string (format "Scratch buffer for: %s\n\n" major)) |
|
455
|
(text (concat string region)) |
|
456
|
(buf (format "*Scratch for %s*" major))) |
|
457
|
(with-current-buffer (get-buffer-create buf) |
|
458
|
(funcall major) |
34
|
459
|
(save-excursion |
30
|
460
|
(insert text) |
|
461
|
(goto-char (point-min)) |
|
462
|
(comment-region (point-at-bol) (point-at-eol))) |
34
|
463
|
(vertical-motion 2)) |
30
|
464
|
(pop-to-buffer buf))) |
|
465
|
|
|
466
|
;;;###autoload |
|
467
|
(defun default-scratch-buffer (&optional arg) |
|
468
|
"Produce a bespoke scratch buffer matching current major mode. |
|
469
|
|
|
470
|
With optional ARG as a prefix argument (\\[universal-argument]), |
|
471
|
use `default-scratch-buffer-mode'. |
|
472
|
|
|
473
|
With ARG as a double prefix argument, prompt for a major mode |
|
474
|
with completion. |
|
475
|
|
|
476
|
If region is active, copy its contents to the new scratch |
|
477
|
buffer." |
|
478
|
(interactive "P") |
|
479
|
(let* ((default-mode default-scratch-buffer-mode) |
|
480
|
(modes (default-scratch-list-modes)) |
|
481
|
(region (with-current-buffer (current-buffer) |
|
482
|
(if (region-active-p) |
|
483
|
(buffer-substring-no-properties |
|
484
|
(region-beginning) |
|
485
|
(region-end)) |
|
486
|
""))) |
|
487
|
(m)) |
|
488
|
(pcase (prefix-numeric-value arg) |
|
489
|
(16 (progn |
|
490
|
(setq m (intern (completing-read "Select major mode: " modes nil t))) |
|
491
|
(default-scratch-buffer-setup region m))) |
|
492
|
(4 (default-scratch-buffer-setup region default-mode)) |
|
493
|
(_ (default-scratch-buffer-setup region))))) |
|
494
|
|
|
495
|
;;;###autoload |
|
496
|
(defun scratch-new () |
|
497
|
"create a new scratch buffer. (could be *scratch* - *scratchN*)" |
|
498
|
(interactive) |
|
499
|
(let ((n 0) |
|
500
|
bufname) |
|
501
|
(while (progn |
|
502
|
(setq bufname |
34
|
503
|
(concat "*scratch" |
30
|
504
|
(if (= n 0) "" (int-to-string n)) |
|
505
|
"*")) |
|
506
|
(setq n (1+ n)) |
|
507
|
(get-buffer bufname))) |
|
508
|
(switch-to-buffer (get-buffer-create bufname)) |
|
509
|
(insert initial-scratch-message) |
|
510
|
(lisp-interaction-mode))) |
|
511
|
|
21
|
512
|
;;; Shell |
|
513
|
(defun set-no-process-query-on-exit () |
|
514
|
(let ((proc (get-buffer-process (current-buffer)))) |
|
515
|
(when (processp proc) |
|
516
|
(set-process-query-on-exit-flag proc nil)))) |
|
517
|
|
|
518
|
(add-hook 'shell-mode-hook 'set-no-process-query-on-exit) |
|
519
|
(add-hook 'term-exec-hook 'set-no-process-query-on-exit) |
30
|
520
|
|
21
|
521
|
;;; Eshell |
|
522
|
(defun eshell-new() |
|
523
|
"Open a new instance of eshell." |
|
524
|
(interactive) |
|
525
|
(eshell 'Z)) |
|
526
|
|
30
|
527
|
(setq eshell-highlight-prompt t |
21
|
528
|
eshell-hist-ignoredups t |
|
529
|
eshell-save-history-on-exit t |
|
530
|
eshell-prefer-lisp-functions nil |
|
531
|
eshell-destroy-buffer-when-process-dies t) |
|
532
|
|
|
533
|
(add-hook 'eshell-mode-hook |
34
|
534
|
(lambda () |
|
535
|
(eshell/alias "d" "dired $1") |
|
536
|
(eshell/alias "ff" "find-file $1") |
41
|
537
|
(eshell/alias "hgfe" "hg-fast-export.sh"))) |
21
|
538
|
|
|
539
|
(defun eshell/clear () |
|
540
|
"Clear the eshell buffer." |
|
541
|
(let ((inhibit-read-only t)) |
|
542
|
(erase-buffer) |
|
543
|
(eshell-send-input))) |
|
544
|
|
|
545
|
(defun eshell-quit-or-delete-char (arg) |
34
|
546
|
(interactive "p") |
|
547
|
(if (and (eolp) (looking-back eshell-prompt-regexp)) |
|
548
|
(progn |
|
549
|
(eshell-life-is-too-much) ; Why not? (eshell/exit) |
|
550
|
(ignore-errors |
|
551
|
(delete-window))) |
|
552
|
(delete-forward-char arg))) |
21
|
553
|
|
|
554
|
(add-hook 'eshell-mode-hook |
|
555
|
(lambda () |
|
556
|
(bind-keys :map eshell-mode-map |
|
557
|
("C-d" . eshell-quit-or-delete-char)))) |
|
558
|
|
|
559
|
(defun eshell-next-prompt (n) |
|
560
|
"Move to end of Nth next prompt in the buffer. See `eshell-prompt-regexp'." |
|
561
|
(interactive "p") |
|
562
|
(re-search-forward eshell-prompt-regexp nil t n) |
|
563
|
(when eshell-highlight-prompt |
|
564
|
(while (not (get-text-property (line-beginning-position) 'read-only) ) |
|
565
|
(re-search-forward eshell-prompt-regexp nil t n))) |
|
566
|
(eshell-skip-prompt)) |
|
567
|
|
|
568
|
(defun eshell-previous-prompt (n) |
|
569
|
"Move to end of Nth previous prompt in the buffer. See `eshell-prompt-regexp'." |
|
570
|
(interactive "p") |
|
571
|
(backward-char) |
|
572
|
(eshell-next-prompt (- n))) |
|
573
|
|
|
574
|
(defun eshell-insert-history () |
|
575
|
"Displays the eshell history to select and insert back into your eshell." |
|
576
|
(interactive) |
|
577
|
(insert (ido-completing-read "Eshell history: " |
|
578
|
(delete-dups |
|
579
|
(ring-elements eshell-history-ring))))) |
34
|
580
|
;;; Tramp |
|
581
|
|
|
582
|
(setopt tramp-default-method "ssh" |
|
583
|
tramp-default-user user-login-name |
|
584
|
tramp-default-host "localhost") |
21
|
585
|
;;; Org |
|
586
|
;; todos |
|
587
|
(setq org-todo-keywords |
|
588
|
'((type "TBD(0!)" "TODO(t!)" "|") |
93
|
589
|
(type "WIP(w!)" "|") |
|
590
|
(sequence "FIND(q!)" "READ(r@!)" "WATCH(W@!)" "|") |
|
591
|
(sequence "RESEARCH(s!)" "RECORD(e!)" "|") |
|
592
|
(sequence "OUTLINE(O!)" "RESEARCH(A!)" "DRAFT(M!)" "REVIEW(R!)" "|") |
|
593
|
(sequence "FIX(i!)" "TEST(t!)" "|") |
|
594
|
(type "GOTO(g!)" "HACK(h!)" "NOTE(n!)" "CODE(c!)" "LINK(l!)" "|") |
|
595
|
(type "KLUDGE(k@!)" "|") |
|
596
|
(sequence "|" "DONE(d!)" "NOPE(x@!)" "FOUND(f@!)"))) |
21
|
597
|
;; captures |
|
598
|
(setq org-capture-templates |
|
599
|
'(("t" "task" entry (file "inbox.org") "* %^{title}\n- %?" :prepend t) |
34
|
600
|
("1" "current-task-item" item (clock) "%i%?") |
|
601
|
("2" "current-task-checkbox" checkitem (clock) "%i%?") |
|
602
|
("3" "current-task-region" plain (clock) "%i" :immediate-finish t :empty-lines 1) |
|
603
|
("4" "current-task-kill" plain (clock) "%c" :immediate-finish t :empty-lines 1) |
|
604
|
("l" "log" item (file+headline "log.org" "log") "%U %?" :prepend t) |
|
605
|
("s" "secret" table-line (file+function "krypt" org-ask-location) "| %^{key} | %^{val} |" :immediate-finish t :kill-buffer t) |
|
606
|
("n" "note" plain (file+function "notes.org" org-ask-location) "%?") |
|
607
|
("i" "idea" entry (file "inbox.org") "* OUTLINE %?\n:notes:\n:end:\n- _outline_ [/]\n - [ ] \n - [ ] \n- _refs_" :prepend t) |
|
608
|
("b" "bug" entry (file "inbox.org") "* FIX %?\n- _review_\n- _fix_\n- _test_" :prepend t) |
|
609
|
("r" "research" entry (file "inbox.org") "* RESEARCH %?\n:notes:\n:end:\n- _refs_" :prepend t))) |
21
|
610
|
(setq org-html-htmlize-output-type 'css |
41
|
611
|
org-html-head-include-default-style nil |
|
612
|
;; comp2 default |
|
613
|
org-ascii-text-width 80) |
21
|
614
|
|
|
615
|
(org-crypt-use-before-save-magic) |
|
616
|
|
|
617
|
(setq org-structure-template-alist |
|
618
|
'(("s" . "src") |
34
|
619
|
("e" . "src emacs-lisp") |
|
620
|
("x" . "src shell") |
|
621
|
("l" . "src lisp") |
|
622
|
("h" . "export html") |
|
623
|
("p" . "src python") |
|
624
|
("r" . "src rust") |
|
625
|
("E" . "example") |
|
626
|
("q" . "quote") |
|
627
|
("c" . "center") |
|
628
|
("C" . "comment") |
|
629
|
("v" . "verse"))) |
21
|
630
|
|
96
|
631
|
(setopt org-preview-latex-image-directory "~/.emacs.d/.cache/ltximg" |
|
632
|
org-latex-image-default-width "8cm" |
|
633
|
org-refile-use-cache t |
|
634
|
org-refile-allow-creating-parent-nodes 'confirm |
21
|
635
|
|
96
|
636
|
org-refile-targets '((nil :maxlevel . 3) |
|
637
|
(org-agenda-files :maxlevel . 3)) |
|
638
|
org-confirm-babel-evaluate nil |
|
639
|
org-src-fontify-natively t |
|
640
|
org-src-tabs-act-natively t |
|
641
|
org-footnote-section nil |
|
642
|
org-log-into-drawer t |
|
643
|
org-log-states-order-reversed nil |
|
644
|
org-clock-persist 'history) |
21
|
645
|
|
96
|
646
|
(add-hook 'after-init-hook #'org-clock-persistence-insinuate) |
21
|
647
|
|
|
648
|
(defun org-todo-at-date (date) |
|
649
|
"create a todo entry for a given date." |
|
650
|
(interactive (list (org-time-string-to-time (org-read-date)))) |
|
651
|
(cl-flet ((org-current-effective-time (&rest r) date) |
|
652
|
(org-today (&rest r) (time-to-days date))) |
|
653
|
(cond ((eq major-mode 'org-mode) (org-todo)) |
|
654
|
((eq major-mode 'org-agenda-mode) (org-agenda-todo))))) |
|
655
|
|
|
656
|
(defun org-ask-location () |
|
657
|
"prompt for a location\"\"" |
|
658
|
(let* ((org-refile-targets '((nil :maxlevel . 9))) |
|
659
|
(hd (condition-case nil |
|
660
|
(car (org-refile-get-location)) |
|
661
|
(error (car org-refile-history))))) |
|
662
|
(goto-char (point-min)) |
|
663
|
(outline-next-heading) |
|
664
|
(if (re-search-forward |
|
665
|
(format org-complex-heading-regexp-format (regexp-quote hd)) |
|
666
|
nil t) |
|
667
|
(goto-char (point-at-bol)) |
|
668
|
(goto-char (point-max)) |
|
669
|
(or (bolp) (insert "\n")) |
|
670
|
(insert "* " hd "\n"))) |
|
671
|
(end-of-line)) |
|
672
|
|
|
673
|
(defun org-capture-fileref-snippet (f type headers func-name) |
|
674
|
(let* ((code-snippet |
|
675
|
(buffer-substring-no-properties (mark) (- (point) 1))) |
|
676
|
(file-name (buffer-file-name)) |
|
677
|
(file-base (file-name-nondirectory file-name)) |
|
678
|
(line-number (line-number-at-pos (region-beginning))) |
|
679
|
(initial-txt (if (null func-name) |
|
680
|
(format "From [[file:%s::%s][%s]]:" |
|
681
|
file-name line-number file-base) |
|
682
|
(format "From ~%s~ (in [[file:%s::%s][%s]]):" |
|
683
|
func-name file-name line-number |
|
684
|
file-base)))) |
|
685
|
(format " |
|
686
|
%s |
|
687
|
#+BEGIN_%s %s |
|
688
|
%s |
|
689
|
#+END_%s" initial-txt type headers code-snippet type))) |
|
690
|
|
|
691
|
(defun org-capture-clip-snippet (f) |
|
692
|
"Given a file, F, this captures the currently selected text |
|
693
|
within an Org EXAMPLE block and a backlink to the file." |
|
694
|
(with-current-buffer (find-buffer-visiting f) |
|
695
|
(org-capture-fileref-snippet f "EXAMPLE" "" nil))) |
|
696
|
|
|
697
|
(defun org-capture-code-snippet (f) |
|
698
|
"Given a file, F, this captures the currently selected text |
|
699
|
within an Org SRC block with a language based on the current mode |
|
700
|
and a backlink to the function and the file." |
|
701
|
(with-current-buffer (find-buffer-visiting f) |
|
702
|
(let ((org-src-mode (replace-regexp-in-string "-mode" "" (format "%s" major-mode))) |
|
703
|
(func-name (which-function))) |
|
704
|
(org-capture-fileref-snippet f "SRC" org-src-mode func-name)))) |
|
705
|
|
|
706
|
(defun region-to-clocked-task (start end) |
|
707
|
"Copies the selected text to the currently clocked in org-mode task." |
|
708
|
(interactive "r") |
|
709
|
(org-capture-string (buffer-substring-no-properties start end) "3")) |
|
710
|
|
|
711
|
(setq org-global-properties |
|
712
|
'(quote (("EFFORT_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00") |
|
713
|
("STYLE_ALL" . "habit")))) |
|
714
|
|
|
715
|
(defun org-mode-ask-effort () |
|
716
|
"Ask for an effort estimate when clocking in." |
|
717
|
(unless (org-entry-get (point) "Effort") |
|
718
|
(let ((effort |
|
719
|
(completing-read |
|
720
|
"Effort: " |
|
721
|
(org-entry-get-multivalued-property (point) "Effort")))) |
|
722
|
(unless (equal effort "") |
|
723
|
(org-set-property "Effort" effort))))) |
|
724
|
|
|
725
|
(add-hook 'org-clock-in-prepare-hook |
|
726
|
'org-mode-ask-effort) |
|
727
|
|
|
728
|
;;;###autoload |
|
729
|
(defun org-adjust-tags-column-reset-tags () |
|
730
|
"In org-mode buffers it will reset tag position according to |
|
731
|
`org-tags-column'." |
|
732
|
(when (and |
|
733
|
(not (string= (buffer-name) "*Remember*")) |
|
734
|
(eql major-mode 'org-mode)) |
|
735
|
(let ((b-m-p (buffer-modified-p))) |
|
736
|
(condition-case nil |
|
737
|
(save-excursion |
|
738
|
(goto-char (point-min)) |
|
739
|
(command-execute 'outline-next-visible-heading) |
|
740
|
;; disable (message) that org-set-tags generates |
|
741
|
(flet ((message (&rest ignored) nil)) |
34
|
742
|
(org-set-tags 1 t)) |
21
|
743
|
(set-buffer-modified-p b-m-p)) |
|
744
|
(error nil))))) |
|
745
|
|
|
746
|
;;;###autoload |
|
747
|
(defun org-align-all-tables () |
|
748
|
"align all tables in current buffer" |
|
749
|
(interactive) |
|
750
|
(org-table-map-tables 'org-table-align 'quietly)) |
|
751
|
|
|
752
|
(defun org-remove-redundant-tags () |
|
753
|
"Remove redundant tags of headlines in current buffer. |
|
754
|
|
|
755
|
A tag is considered redundant if it is local to a headline and |
|
756
|
inherited by a parent headline." |
|
757
|
(interactive) |
|
758
|
(when (eq major-mode 'org-mode) |
|
759
|
(save-excursion |
|
760
|
(org-map-entries |
|
761
|
(lambda () |
|
762
|
(let ((alltags (split-string (or (org-entry-get (point) "ALLTAGS") "") ":")) |
|
763
|
local inherited tag) |
|
764
|
(dolist (tag alltags) |
|
765
|
(if (get-text-property 0 'inherited tag) |
|
766
|
(push tag inherited) (push tag local))) |
|
767
|
(dolist (tag local) |
|
768
|
(if (member tag inherited) (org-toggle-tag tag 'off))))) |
|
769
|
t nil)))) |
|
770
|
;;;; Agenda |
|
771
|
(defvar org-agenda-overriding-header) |
|
772
|
(defvar org-agenda-sorting-strategy) |
|
773
|
(defvar org-agenda-restrict) |
|
774
|
(defvar org-agenda-restrict-begin) |
|
775
|
(defvar org-agenda-restrict-end) |
|
776
|
|
|
777
|
;;;###autoload |
|
778
|
(defun org-agenda-reschedule-to-today () |
|
779
|
(interactive) |
|
780
|
(flet ((org-read-date (&rest rest) (current-time))) |
34
|
781
|
(call-interactively 'org-agenda-schedule))) |
21
|
782
|
|
|
783
|
;; Patch org-mode to use vertical splitting |
|
784
|
(defadvice org-prepare-agenda (after org-fix-split) |
|
785
|
(toggle-window-split)) |
|
786
|
(ad-activate 'org-prepare-agenda) |
|
787
|
|
|
788
|
(add-hook 'org-agenda-mode-hook (lambda () (hl-line-mode 1))) |
|
789
|
|
|
790
|
(defun org-agenda-log-mode-colorize-block () |
|
791
|
"Set different line spacing based on clock time duration." |
|
792
|
(save-excursion |
|
793
|
(let* ((colors (cl-case (alist-get 'background-mode (frame-parameters)) |
|
794
|
(light |
|
795
|
(list "#F6B1C3" "#FFFF9D" "#BEEB9F" "#ADD5F7")) |
|
796
|
(dark |
|
797
|
(list "#aa557f" "DarkGreen" "DarkSlateGray" "DarkSlateBlue")))) |
|
798
|
pos |
|
799
|
duration) |
|
800
|
(nconc colors colors) |
|
801
|
(goto-char (point-min)) |
|
802
|
(while (setq pos (next-single-property-change (point) 'duration)) |
|
803
|
(goto-char pos) |
|
804
|
(when (and (not (equal pos (point-at-eol))) |
|
805
|
(setq duration (org-get-at-bol 'duration))) |
|
806
|
;; larger duration bar height |
|
807
|
(let ((line-height (if (< duration 15) 1.0 (+ 0.5 (/ duration 30)))) |
|
808
|
(ov (make-overlay (point-at-bol) (1+ (point-at-eol))))) |
|
809
|
(overlay-put ov 'face `(:background ,(car colors) :foreground "black")) |
|
810
|
(setq colors (cdr colors)) |
|
811
|
(overlay-put ov 'line-height line-height) |
|
812
|
(overlay-put ov 'line-spacing (1- line-height)))))))) |
|
813
|
|
|
814
|
(add-hook 'org-agenda-finalize-hook #'org-agenda-log-mode-colorize-block) |
|
815
|
|
|
816
|
;;;###autoload |
|
817
|
(defun org-agenda-current-subtree-or-region (only-todos) |
|
818
|
"Display an agenda view for the current subtree or region. |
|
819
|
With prefix, display only TODO-keyword items." |
|
820
|
(interactive "P") |
|
821
|
(let ((starting-point (point)) |
|
822
|
header) |
|
823
|
(with-current-buffer (or (buffer-base-buffer (current-buffer)) |
|
824
|
(current-buffer)) |
|
825
|
(if (use-region-p) |
|
826
|
(progn |
|
827
|
(setq header "Region") |
|
828
|
(put 'org-agenda-files 'org-restrict (list (buffer-file-name (current-buffer)))) |
|
829
|
(setq org-agenda-restrict (current-buffer)) |
|
830
|
(move-marker org-agenda-restrict-begin (region-beginning)) |
|
831
|
(move-marker org-agenda-restrict-end |
|
832
|
(save-excursion |
|
833
|
;; If point is at beginning of line, include |
|
834
|
;; heading on that line by moving forward 1. |
|
835
|
(goto-char (1+ (region-end))) |
|
836
|
(org-end-of-subtree)))) |
|
837
|
;; No region; restrict to subtree. |
|
838
|
(save-excursion |
|
839
|
(save-restriction |
|
840
|
;; In case the command was called from an indirect buffer, set point |
|
841
|
;; in the base buffer to the same position while setting restriction. |
|
842
|
(widen) |
|
843
|
(goto-char starting-point) |
|
844
|
(setq header "Subtree") |
|
845
|
(org-agenda-set-restriction-lock)))) |
|
846
|
;; NOTE: Unlike other agenda commands, binding `org-agenda-sorting-strategy' |
|
847
|
;; around `org-search-view' seems to have no effect. |
|
848
|
(let ((org-agenda-sorting-strategy '(priority-down timestamp-up)) |
|
849
|
(org-agenda-overriding-header header)) |
|
850
|
(org-search-view (if only-todos t nil) "*")) |
|
851
|
(org-agenda-remove-restriction-lock t) |
|
852
|
(message nil)))) |
|
853
|
|
24
|
854
|
;;; Tempo |
|
855
|
(setq tempo-interactive t) |
26
|
856
|
|
|
857
|
(provide 'default) |
27
|
858
|
;; default.el ends here |