changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / emacs/default.el

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