1 ;;; init.el --- bandali's emacs configuration -*- lexical-binding: t -*-
3 ;; Copyright (C) 2018-2020 Amin Bandali <bandali@gnu.org>
5 ;; This program is free software: you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation, either version 3 of the License, or
8 ;; (at your option) any later version.
10 ;; This program is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20 ;; GNU Emacs configuration of Amin Bandali, computer scientist,
21 ;; Free Software activist, and GNU maintainer & webmaster. Packages
22 ;; are installed through using Borg for a fully reproducible setup.
24 ;; Over the years, I've taken inspiration from configurations of many
25 ;; great people. Some that I can remember off the top of my head are:
27 ;; - https://github.com/dieggsy/dotfiles
28 ;; - https://github.com/dakra/dmacs
29 ;; - http://pages.sachachua.com/.emacs.d/Sacha.html
30 ;; - https://github.com/dakrone/eos
31 ;; - http://doc.rix.si/cce/cce.html
32 ;; - https://github.com/jwiegley/dot-emacs
33 ;; - https://github.com/wasamasa/dotemacs
34 ;; - https://github.com/hlissner/doom-emacs
38 ;;; Emacs initialization
40 (defvar b
/before-user-init-time
(current-time)
41 "Value of `current-time' when Emacs begins loading `user-init-file'.")
42 (defvar b
/emacs-initialized nil
43 "Whether Emacs has been initialized.")
45 (when (not (bound-and-true-p b
/emacs-initialized
))
46 (message "Loading Emacs...done (%.3fs)"
47 (float-time (time-subtract b
/before-user-init-time
50 ;; temporarily increase `gc-cons-threshhold' and `gc-cons-percentage'
51 ;; during startup to reduce garbage collection frequency. clearing
52 ;; `file-name-handler-alist' seems to help reduce startup time too.
53 (defvar b
/gc-cons-threshold gc-cons-threshold
)
54 (defvar b
/gc-cons-percentage gc-cons-percentage
)
55 (defvar b
/file-name-handler-alist file-name-handler-alist
)
56 (setq gc-cons-threshold
(* 30 1024 1024) ; 30 MiB
57 gc-cons-percentage
0.6
58 file-name-handler-alist nil
59 ;; sidesteps a bug when profiling with esup
60 esup-child-profile-require-level
0)
62 ;; set them back to their defaults once we're done initializing
64 "My post-initialize function, run after loading `user-init-file'."
65 (setq b
/emacs-initialized t
66 gc-cons-threshold b
/gc-cons-threshold
67 gc-cons-percentage b
/gc-cons-percentage
68 file-name-handler-alist b
/file-name-handler-alist
)
69 (when (featurep 'exwm-workspace
)
70 (with-eval-after-load 'exwm-workspace
77 "[%s]" (number-to-string
78 exwm-workspace-current-index
))))))))
80 ;; make some mode-line spaces smaller
85 (if (and (stringp x
) (or (string= x
" ") (string= x
" ")))
89 mode-line-buffer-identification
90 (propertized-buffer-identification "%10b")))
91 (add-hook 'after-init-hook
#'b
/post-init
)
93 ;; increase number of lines kept in *Messages* log
94 (setq message-log-max
20000)
96 ;; optionally, uncomment to supress some byte-compiler warnings
97 ;; (see C-h v byte-compile-warnings RET for more info)
98 ;; (setq byte-compile-warnings
99 ;; '(not free-vars unresolved noruntime lexical make-local))
104 (setq user-full-name
"Amin Bandali"
105 user-mail-address
"bandali@gnu.org")
108 ;;; csetq (`custom' setq)
112 (defmacro csetq
(&rest args
)
113 "Set the value of user option VAR to VALUE.
115 More generally, you can use multiple variables and values, as in
116 (csetq VAR VALUE VAR VALUE...)
117 This sets each user option VAR's value to the corresponding VALUE.
119 \(fn [VAR VALUE]...)"
120 (declare (debug setq
))
122 ,@(cl-loop for
(var value
) on args by
'cddr
124 `(funcall (or (get ',var
'custom-set
) #'set-default
)
128 ;;; Package management
130 ;; variables of interest:
131 ;; package-archive-priorities
133 ;; package-pinned-packages
135 ;; (let* ((b (find-file-noselect "refinery-theme.el"))
136 ;; (d (with-current-buffer b (package-buffer-info))))
137 ;; (package-generate-description-file d "refinery-theme-pkg.el"))
138 (run-with-idle-timer 0.01 nil
#'require
'package
)
139 (with-eval-after-load 'package
140 (when (= (length package-archives
) 1)
144 ;; ("bndl" . "https://p.bndl.org/elpa/")
145 ("org" .
"https://orgmode.org/elpa/"))
152 (rt-liberation "1.31")
154 (expand-region "0.11.0")
156 ;; (refinery-theme "0.1.1")
158 (org-plus-contrib "20201012"))))
159 (package-initialize))
161 (csetq package-archive-upload-base
"/ssh:caffeine:~/www/p/elpa")
166 ;; keep ~/.emacs.d clean
169 (convert-standard-filename "etc/") user-emacs-directory
)
170 "The directory where packages place their configuration files.")
173 (convert-standard-filename "var/") user-emacs-directory
)
174 "The directory where packages place their persistent data files.")
177 (convert-standard-filename "lisp/") user-emacs-directory
)
178 "The directory where packages place their persistent data files.")
180 "Expand filename FILE relative to `b/etc-dir'."
181 (expand-file-name (convert-standard-filename file
) b
/etc-dir
))
183 "Expand filename FILE relative to `b/var-dir'."
184 (expand-file-name (convert-standard-filename file
) b
/var-dir
))
186 "Expand filename FILE relative to `b/lisp-dir'."
187 (expand-file-name (convert-standard-filename file
) b
/lisp-dir
))
190 auto-save-list-file-prefix
(b/var
"auto-save/sessions/")
191 nsm-settings-file
(b/var
"nsm-settings.el"))
193 ;; separate custom file (don't want it mixing with init.el)
194 (with-eval-after-load 'custom
195 (setq custom-file
(b/etc
"custom.el"))
196 (when (file-exists-p custom-file
)
198 ;; while at it, treat themes as safe
199 ;; (setf custom-safe-themes t)
200 ;; only one custom theme at a time
201 ;; (defadvice load-theme (before clear-previous-themes activate)
202 ;; "Clear existing theme settings instead of layering them"
203 ;; (mapc #'disable-theme custom-enabled-themes))
206 ;; load the secrets file if it exists, otherwise show a warning
207 ;; (with-demoted-errors
208 ;; (load (b/etc "secrets")))
210 ;; start up emacs server. see
211 ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server
212 (run-with-idle-timer 0.5 nil
#'require
'server
)
213 (with-eval-after-load 'server
214 (declare-function server-edit
"server")
215 (global-set-key (kbd "C-c F D") #'server-edit
)
216 (declare-function server-running-p
"server")
217 (or (server-running-p) (server-mode)))
222 ;;;; C-level customizations
226 enable-recursive-minibuffers t
227 resize-mini-windows t
228 ;; more useful frame titles
229 ;; frame-title-format '("" invocation-name " - "
231 ;; (if (buffer-file-name)
232 ;; (abbreviate-file-name (buffer-file-name))
234 ;; i don't feel like jumping out of my chair every now and again; so
235 ;; don't BEEP! at me, emacs
236 ring-bell-function
'ignore
239 ;; scroll-conservatively 10000
241 scroll-conservatively
101
242 scroll-preserve-screen-position
1
243 ;; focus follows mouse
244 mouse-autoselect-window t
)
247 ;; always use space for indentation
250 ;; case-sensitive search (and `dabbrev-expand')
251 ;; case-fold-search nil
255 (set-fontset-font t
'arabic
"Vazir")
258 ;; (dolist (ft (fontset-list))
262 ;; (font-spec :name "Source Code Pro" :size 14))
266 ;; (font-spec :name "DejaVu Sans Mono")
269 ;; ;; (set-fontset-font
273 ;; ;; :name "Symbola monospacified for DejaVu Sans Mono")
276 ;; ;; (set-fontset-font
279 ;; ;; (font-spec :name "DejaVu Sans Mono")
285 ;; (font-spec :name "DejaVu Sans Mono" :size 14)
289 ;;;; Elisp-level customizations
292 ;; don't need to see the startup echo area message
293 (advice-add #'display-startup-echo-area-message
:override
#'ignore
)
295 ;; i want *scratch* as my startup buffer
296 initial-buffer-choice t
297 ;; i don't need the default hint
298 initial-scratch-message nil
299 ;; use customizable text-mode as major mode for *scratch*
300 ;; (initial-major-mode 'text-mode)
301 ;; inhibit buffer list when more than 2 files are loaded
302 inhibit-startup-buffer-menu t
303 ;; don't need to see the startup screen or echo area message
304 inhibit-startup-screen t
305 inhibit-startup-echo-area-message user-login-name
)
309 ;; backups (C-h v make-backup-files RET)
311 backup-directory-alist
(list (cons "." (b/var
"backup/")))
313 delete-old-versions t
315 auto-save-file-name-transforms
`((".*" ,(b/var
"auto-save/") t
))
316 ;; insert newline at the end of files
317 require-final-newline t
318 ;; open read-only file buffers in view-mode
319 ;; (enables niceties like `q' for quit)
323 ;; disable disabled commands
324 (csetq disabled-command-function nil
)
326 ;; lazy-person-friendly yes/no prompts
327 (defalias 'yes-or-no-p
#'y-or-n-p
)
329 ;; autorevert: enable automatic reloading of changed buffers and files
330 (csetq auto-revert-verbose nil
331 global-auto-revert-non-file-buffers nil
)
332 (require 'autorevert
)
333 (global-auto-revert-mode 1)
335 ;; time and battery in mode-line
337 display-time-default-load-average nil
338 display-time-format
" %a %b %-e %-l:%M%P"
339 display-time-mail-icon
'(image :type xpm
340 :file
"gnus/gnus-pointer.xpm"
342 display-time-use-mail-icon t
)
346 (csetq battery-mode-line-format
" %p%% %t")
348 (display-battery-mode)
352 ;; (fringe-mode '(3 . 1))
356 ;; enable winner-mode (C-h f winner-mode RET)
359 (with-eval-after-load 'compile
360 ;; don't display *compilation* buffer on success. based on
361 ;; https://stackoverflow.com/a/17788551, with changes to use `cl-letf'
362 ;; instead of the now obsolete `flet'.
363 (defun b/compilation-finish-function
(buffer outstr
)
364 (unless (string-match "finished" outstr
)
365 (switch-to-buffer-other-window buffer
))
368 (setq compilation-finish-functions
#'b
/compilation-finish-function
)
372 (defadvice compilation-start
373 (around inhibit-display
374 (command &optional mode name-function highlight-regexp
))
375 (if (not (string-match "^\\(find\\|grep\\)" command
))
376 (cl-letf (((symbol-function 'display-buffer
) #'ignore
))
377 (save-window-excursion ad-do-it
))
379 (ad-activate 'compilation-start
))
383 ;; allow scrolling in Isearch
384 isearch-allow-scroll t
385 ;; search for non-ASCII characters: i’d like non-ASCII characters such
386 ;; as ‘’“”«»‹›áⓐ𝒶 to be selected when i search for their ASCII
387 ;; counterpart. shoutout to
388 ;; http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html
389 search-default-mode
#'char-fold-to-regexp
)
392 ;; uncomment to extend the above behaviour to query-replace
393 ;; (csetq replace-char-fold t)
396 (global-set-key (kbd "C-x v C-=") #'vc-ediff
)
398 (with-eval-after-load 'vc-git
399 (csetq vc-git-print-log-follow t
400 vc-git-show-stash
0))
402 (csetq ediff-window-setup-function
'ediff-setup-windows-plain
403 ediff-split-window-function
'split-window-horizontally
)
404 (with-eval-after-load 'ediff
405 (add-hook 'ediff-after-quit-hook-internal
#'winner-undo
))
409 ;; gentler font resizing
410 text-scale-mode-step
1.05)
412 (run-with-idle-timer 0.4 nil
#'require
'mwheel
)
413 (csetq mouse-wheel-scroll-amount
'(1 ((shift) .
1)) ; one line at a time
414 mouse-wheel-progressive-speed nil
; don't accelerate scrolling
415 mouse-wheel-follow-mouse t
) ; scroll window under mouse
417 (run-with-idle-timer 0.4 nil
#'require
'pixel-scroll
)
418 (with-eval-after-load 'pixel-scroll
419 (pixel-scroll-mode 1))
423 epg-gpg-program
(executable-find "gpg")
424 ;; ask for GPG passphrase in minibuffer
425 ;; this will fail if gpg>=2.1 is not available
426 epg-pinentry-mode
'loopback
)
428 ;; (require 'pinentry)
429 ;; workaround for systemd-based distros:
430 ;; (setq pinentry--socket-dir server-socket-dir)
435 auth-sources
'("~/.authinfo.gpg")
436 authinfo-hidden
(regexp-opt '("password" "client-secret" "token")))
441 (defun b/add-elisp-section
()
445 (insert "\n\f\n;;; "))
447 (defun b/insert-asterism
()
448 "Insert a centred asterism."
450 (let ((asterism "* * *"))
455 (floor (/ (- fill-column
(length asterism
)) 2))
460 (defun b/start-process
(program &rest args
)
461 "Same as `start-process', but doesn't bother about name and buffer."
462 (let ((process-name (concat program
"_process"))
463 (buffer-name (generate-new-buffer-name
464 (concat program
"_output"))))
465 (apply #'start-process
466 process-name buffer-name program args
)))
468 (defun b/no-mouse-autoselect-window
()
469 "Conveniently disable `focus-follows-mouse'.
470 For disabling the behaviour for certain buffers and/or modes."
471 (make-local-variable 'mouse-autoselect-window
)
472 (setq mouse-autoselect-window nil
))
474 (defun b/kill-current-buffer
()
475 "Kill the current buffer."
476 ;; also see https://redd.it/64xb3q
478 (kill-buffer (current-buffer)))
480 (defun b/move-indentation-or-beginning-of-line
(arg)
481 "Move to the indentation or to the beginning of line."
484 ;; (back-to-indentation)
485 ;; (move-beginning-of-line arg))
487 (progn (back-to-indentation)
489 (move-beginning-of-line arg
)))
491 (defun b/join-line-top
()
492 "Like `join-line', but join next line to the current line."
496 (defun b/duplicate-line-or-region
(&optional n
)
497 "Duplicate the current line, or region (if active).
498 Make N (default: 1) copies of the current line or region."
500 (let ((u-r-p (use-region-p)) ; if region is active
505 (buffer-substring (region-beginning) (region-end))
506 (prog1 (thing-at-point 'line
)
510 (forward-line 1))))))
511 (dotimes (_ (abs n1
))
515 ;;; General key bindings
517 (global-set-key (kbd "C-a") #'b
/move-indentation-or-beginning-of-line
)
518 (global-set-key (kbd "C-c a i") #'ielm
)
519 (global-set-key (kbd "C-c d") #'b
/duplicate-line-or-region
)
520 (global-set-key (kbd "C-S-j") #'b
/join-line-top
)
521 (global-set-key (kbd "C-c x") #'execute-extended-command
)
523 ;; evaling and macro-expanding
524 (global-set-key (kbd "C-c e b") #'eval-buffer
)
525 (global-set-key (kbd "C-c e e") #'eval-last-sexp
)
526 (global-set-key (kbd "C-c e p") #'pp-macroexpand-last-sexp
)
527 (global-set-key (kbd "C-c e r") #'eval-region
)
530 (global-set-key (kbd "C-c e i") #'emacs-init-time
)
531 (global-set-key (kbd "C-c e u") #'emacs-uptime
)
532 (global-set-key (kbd "C-c e v") #'emacs-version
)
535 (global-set-key (kbd "C-c f .") #'find-file
)
536 (global-set-key (kbd "C-c f d") #'find-name-dired
)
537 (global-set-key (kbd "C-c f l") #'find-library
)
540 (global-set-key (kbd "C-c F m") #'make-frame-command
)
541 (global-set-key (kbd "C-c F d") #'delete-frame
)
544 (global-set-key (kbd "C-S-h C") #'describe-char
)
545 (global-set-key (kbd "C-S-h F") #'describe-face
)
547 ;; (global-set-key (kbd "C-x k") #'b/kill-current-buffer)
548 ;; (global-set-key (kbd "C-x K") #'kill-buffer)
549 ;; (global-set-key (kbd "C-x s") #'save-buffer)
550 ;; (global-set-key (kbd "C-x S") #'save-some-buffers)
552 (define-key emacs-lisp-mode-map
(kbd "<C-return>") #'b
/add-elisp-section
)
554 (when (display-graphic-p)
555 (global-unset-key (kbd "C-z")))
558 ;;; Essential packages
563 (convert-standard-filename "lisp") user-emacs-directory
))
565 (require 'bandali-exwm
)
567 (require 'bandali-org
)
569 (require 'bandali-theme
)
571 ;; recently opened files
572 (csetq recentf-max-saved-items
2000
573 recentf-save-file
(b/var
"recentf-save.el"))
574 (run-with-idle-timer 0.2 nil
#'require
'recentf
)
575 (with-eval-after-load 'recentf
576 ;; (add-to-list 'recentf-keep #'file-remote-p)
581 (require 'bandali-eshell
)
583 (require 'bandali-ibuffer
)
586 ;; (with-eval-after-load 'outline
587 ;; (when (featurep 'which-key)
588 ;; (which-key-add-key-based-replacements
591 ;; (define-key outline-minor-mode-map (kbd "<s-tab>")
592 ;; #'outline-toggle-children)
593 ;; (define-key outline-minor-mode-map (kbd "M-p")
594 ;; #'outline-previous-visible-heading)
595 ;; (define-key outline-minor-mode-map (kbd "M-n")
596 ;; #'outline-next-visible-heading)
597 ;; (defvar b/outline-prefix-map)
598 ;; (define-prefix-command 'b/outline-prefix-map)
599 ;; (define-key outline-minor-mode-map (kbd "s-O")
600 ;; 'b/outline-prefix-map)
601 ;; (define-key b/outline-prefix-map (kbd "TAB")
602 ;; #'outline-toggle-children)
603 ;; (define-key b/outline-prefix-map (kbd "a")
604 ;; #'outline-hide-body)
605 ;; (define-key b/outline-prefix-map (kbd "H")
606 ;; #'outline-hide-body)
607 ;; (define-key b/outline-prefix-map (kbd "S")
608 ;; #'outline-show-all)
609 ;; (define-key b/outline-prefix-map (kbd "h")
610 ;; #'outline-hide-subtree)
611 ;; (define-key b/outline-prefix-map (kbd "s")
612 ;; #'outline-show-subtree))
613 ;; (add-hook 'prog-mode-hook #'outline-minor-mode)
615 (require 'bandali-dired
)
617 (with-eval-after-load 'help
618 (temp-buffer-resize-mode)
619 (csetq help-window-select t
))
621 (with-eval-after-load 'help-mode
622 ;; local key bindings
623 (define-key help-mode-map
(kbd "p") #'backward-button
)
624 (define-key help-mode-map
(kbd "n") #'forward-button
))
626 (with-eval-after-load 'tramp
627 (csetq tramp-auto-save-directory
(b/var
"tramp/auto-save/")
628 tramp-persistency-file-name
(b/var
"tramp/persistency.el"))
629 (add-to-list 'tramp-default-proxies-alist
'(nil "\\`root\\'" "/ssh:%h:"))
630 (add-to-list 'tramp-default-proxies-alist
'("localhost" nil nil
))
631 (add-to-list 'tramp-default-proxies-alist
632 (list (regexp-quote (system-name)) nil nil
)))
634 (with-eval-after-load 'doc-view
635 (define-key doc-view-mode-map
(kbd "M-RET") #'image-previous-line
))
637 (csetq shr-max-width
80)
639 ;; Email (with Gnus, message, and EBDB)
640 (require 'bandali-gnus
)
641 (with-eval-after-load 'sendmail
642 (csetq sendmail-program
(executable-find "msmtp")
643 ;; message-sendmail-extra-arguments '("-v" "-d")
644 mail-specify-envelope-from t
645 mail-envelope-from
'header
))
646 (require 'bandali-message
)
647 (require 'bandali-ebdb
)
650 (require 'bandali-erc
)
652 ;; 'paste' service (aka scp + web server)
653 (add-to-list 'load-path
(b/lisp
"scpaste"))
654 (with-eval-after-load 'scpaste
655 (csetq scpaste-http-destination
"https://p.bndl.org"
656 scpaste-scp-destination
"p:~"))
657 (autoload 'scpaste
"scpaste" nil t
)
658 (autoload 'scpaste-region
"scpaste" nil t
)
659 (global-set-key (kbd "C-c a p p") #'scpaste
)
660 (global-set-key (kbd "C-c a p r") #'scpaste-region
)
665 ;; display Lisp objects at point in the echo area
666 (when (version< "25" emacs-version
)
667 (with-eval-after-load 'eldoc
668 (csetq eldoc-minor-mode-string
" eldoc")
669 (global-eldoc-mode)))
671 ;; highlight matching parens
675 ;; (require 'elec-pair)
676 ;; (electric-pair-mode)
679 ;; Save what I copy into clipboard from other applications into Emacs'
680 ;; kill-ring, which would allow me to still be able to easily access
681 ;; it in case I kill (cut or copy) something else inside Emacs before
682 ;; yanking (pasting) what I'd originally intended to.
683 save-interprogram-paste-before-kill t
)
684 (with-eval-after-load 'simple
685 (column-number-mode 1))
687 ;; save minibuffer history
689 (csetq savehist-file
(b/var
"savehist.el"))
691 (add-to-list 'savehist-additional-variables
'kill-ring
)
693 ;; automatically save place in files
694 (when (version< "25" emacs-version
)
695 (csetq save-place-file
(b/var
"save-place.el"))
698 (defun indicate-buffer-boundaries-left ()
699 (csetq indicate-buffer-boundaries
'left
))
700 (with-eval-after-load 'prog-mode
701 (global-prettify-symbols-mode))
702 (add-hook 'prog-mode-hook
#'indicate-buffer-boundaries-left
)
704 (define-key text-mode-map
(kbd "C-<return>") #'b
/insert-asterism
)
705 (add-hook 'text-mode-hook
#'indicate-buffer-boundaries-left
)
706 (add-hook 'text-mode-hook
#'flyspell-mode
)
708 (add-to-list 'auto-mode-alist
'("\\.*rc$" . conf-mode
))
710 (add-to-list 'auto-mode-alist
'("\\.bashrc$" . sh-mode
))
712 (with-eval-after-load 'flyspell
713 (csetq flyspell-mode-line-string
" fly"))
716 ;; (run-with-idle-timer 0.6 nil #'require 'flycheck)
717 ;; (with-eval-after-load 'flycheck
719 ;; ;; Use the load-path from running Emacs when checking elisp files
720 ;; flycheck-emacs-lisp-load-path 'inherit
721 ;; ;; Only flycheck when I actually save the buffer
722 ;; flycheck-check-syntax-automatically '(mode-enabled save)
723 ;; flycheck-mode-line-prefix "flyc"))
724 ;; (define-key flycheck-mode-map (kbd "M-P") #'flycheck-previous-error)
725 ;; (define-key flycheck-mode-map (kbd "M-N") #'flycheck-next-error)
726 ;; (add-hook 'prog-mode-hook #'flycheck-mode)
729 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
730 ;; (run-with-idle-timer 0.6 nil #'require 'ispell)
731 ;; (with-eval-after-load 'ispell
732 ;; ;; ’ can be part of a word
733 ;; (csetq ispell-local-dictionary-alist
734 ;; `((nil "[[:alpha:]]" "[^[:alpha:]]"
735 ;; "['\x2019]" nil ("-B") nil utf-8))
736 ;; ispell-program-name (executable-find "hunspell"))
737 ;; ;; don't send ’ to the subprocess
738 ;; (defun endless/replace-apostrophe (args)
739 ;; (cons (replace-regexp-in-string
740 ;; "’" "'" (car args))
742 ;; (advice-add #'ispell-send-string :filter-args
743 ;; #'endless/replace-apostrophe)
744 ;; ;; convert ' back to ’ from the subprocess
745 ;; (defun endless/replace-quote (args)
746 ;; (if (not (derived-mode-p 'org-mode))
748 ;; (cons (replace-regexp-in-string
749 ;; "'" "’" (car args))
751 ;; (advice-add #'ispell-parse-output :filter-args
752 ;; #'endless/replace-quote))
755 (csetq abbrev-file-name
(b/etc
"abbrev.el"))
756 (add-hook 'text-mode-hook
#'abbrev-mode
)
759 ;;; Programming modes
761 (with-eval-after-load 'lisp-mode
762 (defun indent-spaces-mode ()
763 (setq indent-tabs-mode nil
))
764 (add-hook 'lisp-interaction-mode-hook
#'indent-spaces-mode
))
767 (add-to-list 'load-path
(b/lisp
"alloy-mode"))
768 (autoload 'alloy-mode
"alloy-mode" nil t
)
769 (with-eval-after-load 'alloy-mode
770 (csetq alloy-basic-offset
2)
771 ;; (defun b/alloy-simple-indent (start end)
773 ;; ;; (if (region-active-p)
774 ;; ;; (indent-rigidly start end alloy-basic-offset)
776 ;; ;; (indent-rigidly (line-beginning-position)
777 ;; ;; (line-end-position)
778 ;; ;; alloy-basic-offset)))
779 ;; (indent-to (+ (current-column) alloy-basic-offset)))
780 ;; local key bindings
781 (define-key alloy-mode-map
(kbd "RET") #'electric-newline-and-maybe-indent
)
782 ;; (define-key alloy-mode-map (kbd "TAB") #'b/alloy-simple-indent)
783 (define-key alloy-mode-map
(kbd "TAB") #'indent-for-tab-command
))
784 (add-to-list 'auto-mode-alist
'("\\.\\(als\\|dsh\\)\\'" . alloy-mode
))
785 (add-hook 'alloy-mode-hook
(lambda nil
(setq-local indent-tabs-mode nil
)))
788 ;; (eval-when-compile (defvar lean-mode-map))
789 ;; (run-with-idle-timer 0.4 nil #'require 'lean-mode)
790 ;; (with-eval-after-load 'lean-mode
791 ;; (require 'lean-input)
792 ;; (csetq default-input-method "Lean"
793 ;; lean-input-tweak-all '(lean-input-compose
794 ;; (lean-input-prepend "/")
795 ;; (lean-input-nonempty))
796 ;; lean-input-user-translations '(("/" "/")))
797 ;; (lean-input-setup)
798 ;; ;; local key bindings
799 ;; (define-key lean-mode-map (kbd "S-SPC") #'company-complete))
801 (with-eval-after-load 'sgml-mode
802 (csetq sgml-basic-offset
0))
804 (with-eval-after-load 'css-mode
805 (csetq css-indent-offset
2))
808 ;; (add-hook 'po-mode-hook (lambda nil (run-with-timer 0.1 nil 'View-exit)))
811 ;; (csetq font-latex-fontify-sectioning 'color)
813 (with-eval-after-load 'tex-mode
815 (lambda (p) (string-match "^---?" (car p
)))
816 tex--prettify-symbols-alist
))
817 (add-hook 'tex-mode-hook
#'auto-fill-mode
)
818 (add-hook 'tex-mode-hook
#'flyspell-mode
)
821 ;;; Emacs enhancements & auxiliary packages
823 (with-eval-after-load 'man
824 (csetq Man-width
80))
826 (defun b/*scratch
* ()
827 "Switch to `*scratch*' buffer, creating it if it does not exist."
830 (or (get-buffer "*scratch*")
831 (with-current-buffer (get-buffer-create "*scratch*")
832 (set-buffer-major-mode (current-buffer))
834 (global-set-key (kbd "C-c s") #'b
/*scratch
*)
837 ;; | make pretty boxed quotes like this
839 (add-to-list 'load-path
(b/lisp
"boxquote"))
840 (run-with-idle-timer 0.6 nil
#'require
'boxquote
)
841 (with-eval-after-load 'boxquote
842 (defvar b
/boxquote-prefix-map
)
843 (define-prefix-command 'b
/boxquote-prefix-map
)
844 (global-set-key (kbd "C-c q") 'b
/boxquote-prefix-map
)
845 (define-key b
/boxquote-prefix-map
(kbd "b") #'boxquote-buffer
)
846 (define-key b
/boxquote-prefix-map
(kbd "B") #'boxquote-insert-buffer
)
847 (define-key b
/boxquote-prefix-map
(kbd "d") #'boxquote-defun
)
848 (define-key b
/boxquote-prefix-map
(kbd "F") #'boxquote-insert-file
)
849 (define-key b
/boxquote-prefix-map
(kbd "hf") #'boxquote-describe-function
)
850 (define-key b
/boxquote-prefix-map
(kbd "hk") #'boxquote-describe-key
)
851 (define-key b
/boxquote-prefix-map
(kbd "hv") #'boxquote-describe-variable
)
852 (define-key b
/boxquote-prefix-map
(kbd "hw") #'boxquote-where-is
)
853 (define-key b
/boxquote-prefix-map
(kbd "k") #'boxquote-kill
)
854 (define-key b
/boxquote-prefix-map
(kbd "p") #'boxquote-paragraph
)
855 (define-key b
/boxquote-prefix-map
(kbd "q") #'boxquote-boxquote
)
856 (define-key b
/boxquote-prefix-map
(kbd "r") #'boxquote-region
)
857 (define-key b
/boxquote-prefix-map
(kbd "s") #'boxquote-shell-command
)
858 (define-key b
/boxquote-prefix-map
(kbd "t") #'boxquote-text
)
859 (define-key b
/boxquote-prefix-map
(kbd "T") #'boxquote-title
)
860 (define-key b
/boxquote-prefix-map
(kbd "u") #'boxquote-unbox
)
861 (define-key b
/boxquote-prefix-map
(kbd "U") #'boxquote-unbox-region
)
862 (define-key b
/boxquote-prefix-map
(kbd "y") #'boxquote-yank
)
863 (define-key b
/boxquote-prefix-map
(kbd "M-q") #'boxquote-fill-paragraph
)
864 (define-key b
/boxquote-prefix-map
(kbd "M-w") #'boxquote-kill-ring-save
))
866 (add-to-list 'load-path
(b/lisp
"hl-todo"))
867 (run-with-idle-timer 0.5 nil
#'require
'hl-todo
)
868 (with-eval-after-load 'hl-todo
869 ;; highlight TODOs in buffers
870 (global-hl-todo-mode))
872 (add-to-list 'load-path
(b/lisp
"page-break-lines"))
873 (run-with-idle-timer 0.5 nil
#'require
'page-break-lines
)
874 (with-eval-after-load 'page-break-lines
875 (csetq page-break-lines-max-width fill-column
)
876 (global-page-break-lines-mode))
879 (global-set-key (kbd "C-=") #'er
/expand-region
)
881 (run-with-idle-timer 0.6 nil
#'require
'yasnippet
)
882 (with-eval-after-load 'yasnippet
883 (declare-function yas-reload-all
884 "yasnippet" (&optional no-jit interactive
))
885 (declare-function yas-maybe-expand-abbrev-key-filter
888 (defconst yas-verbosity-cur yas-verbosity
)
889 (setq yas-verbosity
2)
890 (csetq yas-snippet-dirs
`(,(b/etc
"yasnippet/snippets")))
891 ;; (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets" t)
893 (setq yas-verbosity yas-verbosity-cur
)
895 (defun b/yas-maybe-expand-abbrev-key-filter
(cmd)
896 (when (and (yas-maybe-expand-abbrev-key-filter cmd
)
897 (not (bound-and-true-p git-commit-mode
)))
899 (defconst b
/yas-maybe-expand
900 '(menu-item "" yas-expand
901 :filter b
/yas-maybe-expand-abbrev-key-filter
))
902 (define-key yas-minor-mode-map
(kbd "SPC") b
/yas-maybe-expand
)
907 (global-set-key (kbd "C-c D d") #'debbugs-gnu
)
908 (global-set-key (kbd "C-c D b") #'debbugs-gnu-bugs
)
909 (global-set-key (kbd "C-c D e") ; bug-gnu-emacs
912 (setq debbugs-gnu-current-suppress t
)
913 (debbugs-gnu debbugs-gnu-default-severities
915 (global-set-key (kbd "C-c D g") ; bug-gnuzilla
918 (setq debbugs-gnu-current-suppress t
)
919 (debbugs-gnu debbugs-gnu-default-severities
921 (global-set-key (kbd "C-c D G b") ; bug-guix
924 (setq debbugs-gnu-current-suppress t
)
925 (debbugs-gnu debbugs-gnu-default-severities
927 (global-set-key (kbd "C-c D G p") ; guix-patches
930 (setq debbugs-gnu-current-suppress t
)
931 (debbugs-gnu debbugs-gnu-default-severities
936 url-configuration-directory
(b/var
"url/configuration/")
937 url-cache-directory
(b/var
"url/cache/"))
940 (csetq eww-download-directory
(file-name-as-directory
941 (getenv "XDG_DOWNLOAD_DIR")))
942 (global-set-key (kbd "C-c a e w") #'eww
)
946 ;; reftex-default-bibliography '("~/usr/org/references.bib")
947 ;; org-ref-default-bibliography '("~/usr/org/references.bib")
948 ;; org-ref-bibliography-notes "~/usr/org/notes.org"
949 ;; org-ref-pdf-directory "~/usr/org/bibtex-pdfs/")
951 ;; fill-column-indicator ?
954 (csetq split-width-threshold
150)
955 (global-set-key (kbd "C-c w s l")
960 (global-set-key (kbd "C-c w s j")
965 (global-set-key (kbd "C-c w q") #'quit-window
)
968 ;; (global-set-key (kbd "C-c a p") #'pass)
969 ;; (add-hook 'pass-mode-hook #'View-exit)
972 ;; uncomment to disable reftex-cite's default choice of previous word
973 ;; (with-eval-after-load 'reftex
974 ;; (require 'reftex-cite)
975 ;; (defun reftex-get-bibkey-default ()
976 ;; "If the cursor is in a citation macro, return the word before the macro."
977 ;; (let* ((macro (reftex-what-macro 1)))
979 ;; (when (and macro (string-match "cite" (car macro)))
980 ;; (goto-char (cdr macro)))
981 ;; (reftex-this-word)))))
982 (add-hook 'latex-mode-hook
#'reftex-mode
)
985 (add-to-list 'load-path
(b/lisp
"dmenu"))
986 (with-eval-after-load 'dmenu
987 (csetq dmenu-prompt-string
"run: "
988 dmenu-save-file
(b/var
"dmenu-items")))
989 (autoload 'dmenu
"dmenu" nil t
)
994 (run-with-idle-timer 0.5 nil
#'require
'delight
)
995 (with-eval-after-load 'delight
996 (delight 'auto-fill-function
" f" "simple")
997 (delight 'abbrev-mode
"" "abbrev")
998 (delight 'page-break-lines-mode
"" "page-break-lines")
999 (delight 'mml-mode
" mml" "mml")
1000 (delight 'yas-minor-mode
"" "yasnippet"))
1003 ;;; Post initialization
1005 (message "Loading %s...done (%.3fs)" user-init-file
1006 (float-time (time-subtract (current-time)
1007 b
/before-user-init-time
)))
1009 ;;; init.el ends here