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 ;; (require 'bandali-magit)
573 ;; recently opened files
574 (csetq recentf-max-saved-items
2000
575 recentf-save-file
(b/var
"recentf-save.el"))
576 (run-with-idle-timer 0.2 nil
#'require
'recentf
)
577 (with-eval-after-load 'recentf
578 ;; (add-to-list 'recentf-keep #'file-remote-p)
583 (require 'bandali-eshell
)
585 (require 'bandali-ibuffer
)
588 ;; (with-eval-after-load 'outline
589 ;; (when (featurep 'which-key)
590 ;; (which-key-add-key-based-replacements
593 ;; (define-key outline-minor-mode-map (kbd "<s-tab>")
594 ;; #'outline-toggle-children)
595 ;; (define-key outline-minor-mode-map (kbd "M-p")
596 ;; #'outline-previous-visible-heading)
597 ;; (define-key outline-minor-mode-map (kbd "M-n")
598 ;; #'outline-next-visible-heading)
599 ;; (defvar b/outline-prefix-map)
600 ;; (define-prefix-command 'b/outline-prefix-map)
601 ;; (define-key outline-minor-mode-map (kbd "s-O")
602 ;; 'b/outline-prefix-map)
603 ;; (define-key b/outline-prefix-map (kbd "TAB")
604 ;; #'outline-toggle-children)
605 ;; (define-key b/outline-prefix-map (kbd "a")
606 ;; #'outline-hide-body)
607 ;; (define-key b/outline-prefix-map (kbd "H")
608 ;; #'outline-hide-body)
609 ;; (define-key b/outline-prefix-map (kbd "S")
610 ;; #'outline-show-all)
611 ;; (define-key b/outline-prefix-map (kbd "h")
612 ;; #'outline-hide-subtree)
613 ;; (define-key b/outline-prefix-map (kbd "s")
614 ;; #'outline-show-subtree))
615 ;; (add-hook 'prog-mode-hook #'outline-minor-mode)
617 (require 'bandali-dired
)
619 (with-eval-after-load 'help
620 (temp-buffer-resize-mode)
621 (csetq help-window-select t
))
623 (with-eval-after-load 'help-mode
624 ;; local key bindings
625 (define-key help-mode-map
(kbd "p") #'backward-button
)
626 (define-key help-mode-map
(kbd "n") #'forward-button
))
628 (with-eval-after-load 'tramp
629 (csetq tramp-auto-save-directory
(b/var
"tramp/auto-save/")
630 tramp-persistency-file-name
(b/var
"tramp/persistency.el"))
631 (add-to-list 'tramp-default-proxies-alist
'(nil "\\`root\\'" "/ssh:%h:"))
632 (add-to-list 'tramp-default-proxies-alist
'("localhost" nil nil
))
633 (add-to-list 'tramp-default-proxies-alist
634 (list (regexp-quote (system-name)) nil nil
)))
636 (with-eval-after-load 'doc-view
637 (define-key doc-view-mode-map
(kbd "M-RET") #'image-previous-line
))
639 (csetq shr-max-width
80)
641 ;; Email (with Gnus, message, and EBDB)
642 (require 'bandali-gnus
)
643 (with-eval-after-load 'sendmail
644 (csetq sendmail-program
(executable-find "msmtp")
645 ;; message-sendmail-extra-arguments '("-v" "-d")
646 mail-specify-envelope-from t
647 mail-envelope-from
'header
))
648 (require 'bandali-message
)
649 (require 'bandali-ebdb
)
652 (require 'bandali-erc
)
654 ;; 'paste' service (aka scp + web server)
655 (add-to-list 'load-path
(b/lisp
"scpaste"))
656 (with-eval-after-load 'scpaste
657 (csetq scpaste-http-destination
"https://p.bndl.org"
658 scpaste-scp-destination
"p:~"))
659 (autoload 'scpaste
"scpaste" nil t
)
660 (autoload 'scpaste-region
"scpaste" nil t
)
661 (global-set-key (kbd "C-c a p p") #'scpaste
)
662 (global-set-key (kbd "C-c a p r") #'scpaste-region
)
667 ;; display Lisp objects at point in the echo area
668 (when (version< "25" emacs-version
)
669 (with-eval-after-load 'eldoc
670 (csetq eldoc-minor-mode-string
" eldoc")
671 (global-eldoc-mode)))
673 ;; highlight matching parens
677 ;; (require 'elec-pair)
678 ;; (electric-pair-mode)
681 ;; Save what I copy into clipboard from other applications into Emacs'
682 ;; kill-ring, which would allow me to still be able to easily access
683 ;; it in case I kill (cut or copy) something else inside Emacs before
684 ;; yanking (pasting) what I'd originally intended to.
685 save-interprogram-paste-before-kill t
)
686 (with-eval-after-load 'simple
687 (column-number-mode 1))
689 ;; save minibuffer history
691 (csetq savehist-file
(b/var
"savehist.el"))
693 (add-to-list 'savehist-additional-variables
'kill-ring
)
695 ;; automatically save place in files
696 (when (version< "25" emacs-version
)
697 (csetq save-place-file
(b/var
"save-place.el"))
700 (defun indicate-buffer-boundaries-left ()
701 (csetq indicate-buffer-boundaries
'left
))
702 (with-eval-after-load 'prog-mode
703 (global-prettify-symbols-mode))
704 (add-hook 'prog-mode-hook
#'indicate-buffer-boundaries-left
)
706 (define-key text-mode-map
(kbd "C-<return>") #'b
/insert-asterism
)
707 (add-hook 'text-mode-hook
#'indicate-buffer-boundaries-left
)
708 (add-hook 'text-mode-hook
#'flyspell-mode
)
710 (add-to-list 'auto-mode-alist
'("\\.*rc$" . conf-mode
))
712 (add-to-list 'auto-mode-alist
'("\\.bashrc$" . sh-mode
))
714 (with-eval-after-load 'flyspell
715 (csetq flyspell-mode-line-string
" fly"))
718 ;; (run-with-idle-timer 0.6 nil #'require 'flycheck)
719 ;; (with-eval-after-load 'flycheck
721 ;; ;; Use the load-path from running Emacs when checking elisp files
722 ;; flycheck-emacs-lisp-load-path 'inherit
723 ;; ;; Only flycheck when I actually save the buffer
724 ;; flycheck-check-syntax-automatically '(mode-enabled save)
725 ;; flycheck-mode-line-prefix "flyc"))
726 ;; (define-key flycheck-mode-map (kbd "M-P") #'flycheck-previous-error)
727 ;; (define-key flycheck-mode-map (kbd "M-N") #'flycheck-next-error)
728 ;; (add-hook 'prog-mode-hook #'flycheck-mode)
731 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
732 ;; (run-with-idle-timer 0.6 nil #'require 'ispell)
733 ;; (with-eval-after-load 'ispell
734 ;; ;; ’ can be part of a word
735 ;; (csetq ispell-local-dictionary-alist
736 ;; `((nil "[[:alpha:]]" "[^[:alpha:]]"
737 ;; "['\x2019]" nil ("-B") nil utf-8))
738 ;; ispell-program-name (executable-find "hunspell"))
739 ;; ;; don't send ’ to the subprocess
740 ;; (defun endless/replace-apostrophe (args)
741 ;; (cons (replace-regexp-in-string
742 ;; "’" "'" (car args))
744 ;; (advice-add #'ispell-send-string :filter-args
745 ;; #'endless/replace-apostrophe)
746 ;; ;; convert ' back to ’ from the subprocess
747 ;; (defun endless/replace-quote (args)
748 ;; (if (not (derived-mode-p 'org-mode))
750 ;; (cons (replace-regexp-in-string
751 ;; "'" "’" (car args))
753 ;; (advice-add #'ispell-parse-output :filter-args
754 ;; #'endless/replace-quote))
757 (csetq abbrev-file-name
(b/etc
"abbrev.el"))
758 (add-hook 'text-mode-hook
#'abbrev-mode
)
761 ;;; Programming modes
763 (with-eval-after-load 'lisp-mode
764 (defun indent-spaces-mode ()
765 (setq indent-tabs-mode nil
))
766 (add-hook 'lisp-interaction-mode-hook
#'indent-spaces-mode
))
769 (add-to-list 'load-path
(b/lisp
"alloy-mode"))
770 (autoload 'alloy-mode
"alloy-mode" nil t
)
771 (with-eval-after-load 'alloy-mode
772 (csetq alloy-basic-offset
2)
773 ;; (defun b/alloy-simple-indent (start end)
775 ;; ;; (if (region-active-p)
776 ;; ;; (indent-rigidly start end alloy-basic-offset)
778 ;; ;; (indent-rigidly (line-beginning-position)
779 ;; ;; (line-end-position)
780 ;; ;; alloy-basic-offset)))
781 ;; (indent-to (+ (current-column) alloy-basic-offset)))
782 ;; local key bindings
783 (define-key alloy-mode-map
(kbd "RET") #'electric-newline-and-maybe-indent
)
784 ;; (define-key alloy-mode-map (kbd "TAB") #'b/alloy-simple-indent)
785 (define-key alloy-mode-map
(kbd "TAB") #'indent-for-tab-command
))
786 (add-to-list 'auto-mode-alist
'("\\.\\(als\\|dsh\\)\\'" . alloy-mode
))
787 (add-hook 'alloy-mode-hook
(lambda nil
(setq-local indent-tabs-mode nil
)))
790 ;; (eval-when-compile (defvar lean-mode-map))
791 ;; (run-with-idle-timer 0.4 nil #'require 'lean-mode)
792 ;; (with-eval-after-load 'lean-mode
793 ;; (require 'lean-input)
794 ;; (csetq default-input-method "Lean"
795 ;; lean-input-tweak-all '(lean-input-compose
796 ;; (lean-input-prepend "/")
797 ;; (lean-input-nonempty))
798 ;; lean-input-user-translations '(("/" "/")))
799 ;; (lean-input-setup)
800 ;; ;; local key bindings
801 ;; (define-key lean-mode-map (kbd "S-SPC") #'company-complete))
803 (with-eval-after-load 'sgml-mode
804 (csetq sgml-basic-offset
0))
806 (with-eval-after-load 'css-mode
807 (csetq css-indent-offset
2))
810 ;; (add-hook 'po-mode-hook (lambda nil (run-with-timer 0.1 nil 'View-exit)))
813 ;; (csetq font-latex-fontify-sectioning 'color)
815 (with-eval-after-load 'tex-mode
817 (lambda (p) (string-match "^---?" (car p
)))
818 tex--prettify-symbols-alist
))
819 (add-hook 'tex-mode-hook
#'auto-fill-mode
)
820 (add-hook 'tex-mode-hook
#'flyspell-mode
)
823 ;;; Emacs enhancements & auxiliary packages
825 (with-eval-after-load 'man
826 (csetq Man-width
80))
828 (defun b/*scratch
* ()
829 "Switch to `*scratch*' buffer, creating it if it does not exist."
832 (or (get-buffer "*scratch*")
833 (with-current-buffer (get-buffer-create "*scratch*")
834 (set-buffer-major-mode (current-buffer))
836 (global-set-key (kbd "C-c s") #'b
/*scratch
*)
839 ;; | make pretty boxed quotes like this
841 (add-to-list 'load-path
(b/lisp
"boxquote"))
842 (run-with-idle-timer 0.6 nil
#'require
'boxquote
)
843 (with-eval-after-load 'boxquote
844 (defvar b
/boxquote-prefix-map
)
845 (define-prefix-command 'b
/boxquote-prefix-map
)
846 (global-set-key (kbd "C-c q") 'b
/boxquote-prefix-map
)
847 (define-key b
/boxquote-prefix-map
(kbd "b") #'boxquote-buffer
)
848 (define-key b
/boxquote-prefix-map
(kbd "B") #'boxquote-insert-buffer
)
849 (define-key b
/boxquote-prefix-map
(kbd "d") #'boxquote-defun
)
850 (define-key b
/boxquote-prefix-map
(kbd "F") #'boxquote-insert-file
)
851 (define-key b
/boxquote-prefix-map
(kbd "hf") #'boxquote-describe-function
)
852 (define-key b
/boxquote-prefix-map
(kbd "hk") #'boxquote-describe-key
)
853 (define-key b
/boxquote-prefix-map
(kbd "hv") #'boxquote-describe-variable
)
854 (define-key b
/boxquote-prefix-map
(kbd "hw") #'boxquote-where-is
)
855 (define-key b
/boxquote-prefix-map
(kbd "k") #'boxquote-kill
)
856 (define-key b
/boxquote-prefix-map
(kbd "p") #'boxquote-paragraph
)
857 (define-key b
/boxquote-prefix-map
(kbd "q") #'boxquote-boxquote
)
858 (define-key b
/boxquote-prefix-map
(kbd "r") #'boxquote-region
)
859 (define-key b
/boxquote-prefix-map
(kbd "s") #'boxquote-shell-command
)
860 (define-key b
/boxquote-prefix-map
(kbd "t") #'boxquote-text
)
861 (define-key b
/boxquote-prefix-map
(kbd "T") #'boxquote-title
)
862 (define-key b
/boxquote-prefix-map
(kbd "u") #'boxquote-unbox
)
863 (define-key b
/boxquote-prefix-map
(kbd "U") #'boxquote-unbox-region
)
864 (define-key b
/boxquote-prefix-map
(kbd "y") #'boxquote-yank
)
865 (define-key b
/boxquote-prefix-map
(kbd "M-q") #'boxquote-fill-paragraph
)
866 (define-key b
/boxquote-prefix-map
(kbd "M-w") #'boxquote-kill-ring-save
))
868 (add-to-list 'load-path
(b/lisp
"hl-todo"))
869 (run-with-idle-timer 0.5 nil
#'require
'hl-todo
)
870 (with-eval-after-load 'hl-todo
871 ;; highlight TODOs in buffers
872 (global-hl-todo-mode))
874 (add-to-list 'load-path
(b/lisp
"page-break-lines"))
875 (run-with-idle-timer 0.5 nil
#'require
'page-break-lines
)
876 (with-eval-after-load 'page-break-lines
877 (csetq page-break-lines-max-width fill-column
)
878 (global-page-break-lines-mode))
881 (global-set-key (kbd "C-=") #'er
/expand-region
)
883 (run-with-idle-timer 0.6 nil
#'require
'yasnippet
)
884 (with-eval-after-load 'yasnippet
885 (declare-function yas-reload-all
886 "yasnippet" (&optional no-jit interactive
))
887 (declare-function yas-maybe-expand-abbrev-key-filter
890 (defconst yas-verbosity-cur yas-verbosity
)
891 (setq yas-verbosity
2)
892 (csetq yas-snippet-dirs
`(,(b/etc
"yasnippet/snippets")))
893 ;; (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets" t)
895 (setq yas-verbosity yas-verbosity-cur
)
897 (defun b/yas-maybe-expand-abbrev-key-filter
(cmd)
898 (when (and (yas-maybe-expand-abbrev-key-filter cmd
)
899 (not (bound-and-true-p git-commit-mode
)))
901 (defconst b
/yas-maybe-expand
902 '(menu-item "" yas-expand
903 :filter b
/yas-maybe-expand-abbrev-key-filter
))
904 (define-key yas-minor-mode-map
(kbd "SPC") b
/yas-maybe-expand
)
909 (global-set-key (kbd "C-c D d") #'debbugs-gnu
)
910 (global-set-key (kbd "C-c D b") #'debbugs-gnu-bugs
)
911 (global-set-key (kbd "C-c D e") ; bug-gnu-emacs
914 (setq debbugs-gnu-current-suppress t
)
915 (debbugs-gnu debbugs-gnu-default-severities
917 (global-set-key (kbd "C-c D g") ; bug-gnuzilla
920 (setq debbugs-gnu-current-suppress t
)
921 (debbugs-gnu debbugs-gnu-default-severities
923 (global-set-key (kbd "C-c D G b") ; bug-guix
926 (setq debbugs-gnu-current-suppress t
)
927 (debbugs-gnu debbugs-gnu-default-severities
929 (global-set-key (kbd "C-c D G p") ; guix-patches
932 (setq debbugs-gnu-current-suppress t
)
933 (debbugs-gnu debbugs-gnu-default-severities
938 url-configuration-directory
(b/var
"url/configuration/")
939 url-cache-directory
(b/var
"url/cache/"))
942 (csetq eww-download-directory
(file-name-as-directory
943 (getenv "XDG_DOWNLOAD_DIR")))
944 (global-set-key (kbd "C-c a e w") #'eww
)
948 ;; reftex-default-bibliography '("~/usr/org/references.bib")
949 ;; org-ref-default-bibliography '("~/usr/org/references.bib")
950 ;; org-ref-bibliography-notes "~/usr/org/notes.org"
951 ;; org-ref-pdf-directory "~/usr/org/bibtex-pdfs/")
953 ;; fill-column-indicator ?
956 (csetq split-width-threshold
150)
957 (global-set-key (kbd "C-c w s l")
962 (global-set-key (kbd "C-c w s j")
967 (global-set-key (kbd "C-c w q") #'quit-window
)
970 ;; (global-set-key (kbd "C-c a p") #'pass)
971 ;; (add-hook 'pass-mode-hook #'View-exit)
974 ;; uncomment to disable reftex-cite's default choice of previous word
975 ;; (with-eval-after-load 'reftex
976 ;; (require 'reftex-cite)
977 ;; (defun reftex-get-bibkey-default ()
978 ;; "If the cursor is in a citation macro, return the word before the macro."
979 ;; (let* ((macro (reftex-what-macro 1)))
981 ;; (when (and macro (string-match "cite" (car macro)))
982 ;; (goto-char (cdr macro)))
983 ;; (reftex-this-word)))))
984 (add-hook 'latex-mode-hook
#'reftex-mode
)
987 (add-to-list 'load-path
(b/lisp
"dmenu"))
988 (with-eval-after-load 'dmenu
989 (csetq dmenu-prompt-string
"run: "
990 dmenu-save-file
(b/var
"dmenu-items")))
991 (autoload 'dmenu
"dmenu" nil t
)
996 (run-with-idle-timer 0.5 nil
#'require
'delight
)
997 (with-eval-after-load 'delight
998 (delight 'auto-fill-function
" f" "simple")
999 (delight 'abbrev-mode
"" "abbrev")
1000 (delight 'page-break-lines-mode
"" "page-break-lines")
1001 (delight 'mml-mode
" mml" "mml")
1002 (delight 'yas-minor-mode
"" "yasnippet"))
1005 ;;; Post initialization
1007 (message "Loading %s...done (%.3fs)" user-init-file
1008 (float-time (time-subtract (current-time)
1009 b
/before-user-init-time
)))
1011 ;;; init.el ends here