1 ;;; init.el --- bandali's emacs configuration -*- lexical-binding: t -*-
3 ;; Copyright (C) 2018-2021 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 bandali, free software activist,
21 ;; computing scientist, and GNU maintainer and volunteer.
23 ;; Over the years, I've taken inspiration from configurations of many
24 ;; great people. Some that I can remember off the top of my head are:
26 ;; - https://github.com/dieggsy/dotfiles
27 ;; - https://github.com/dakra/dmacs
28 ;; - http://pages.sachachua.com/.emacs.d/Sacha.html
29 ;; - https://github.com/dakrone/eos
30 ;; - http://doc.rix.si/cce/cce.html
31 ;; - https://github.com/jwiegley/dot-emacs
32 ;; - https://github.com/wasamasa/dotemacs
33 ;; - https://github.com/hlissner/doom-emacs
37 ;;; Emacs initialization
39 (defvar b
/before-user-init-time
(current-time)
40 "Value of `current-time' when Emacs begins loading `user-init-file'.")
41 (defvar b
/emacs-initialized nil
42 "Whether Emacs has been initialized.")
44 (when (not (bound-and-true-p b
/emacs-initialized
))
45 (message "Loading Emacs...done (%.3fs)"
46 (float-time (time-subtract b
/before-user-init-time
49 ;; temporarily increase `gc-cons-threshhold' and `gc-cons-percentage'
50 ;; during startup to reduce garbage collection frequency. clearing
51 ;; `file-name-handler-alist' seems to help reduce startup time too.
52 (defvar b
/gc-cons-threshold gc-cons-threshold
)
53 (defvar b
/gc-cons-percentage gc-cons-percentage
)
54 (defvar b
/file-name-handler-alist file-name-handler-alist
)
55 (setq gc-cons-threshold
(* 30 1024 1024) ; 30 MiB
56 gc-cons-percentage
0.6
57 file-name-handler-alist nil
58 ;; sidesteps a bug when profiling with esup
59 esup-child-profile-require-level
0)
61 ;; set them back to their defaults once we're done initializing
63 "My post-initialize function, run after loading `user-init-file'."
64 (setq b
/emacs-initialized t
65 gc-cons-threshold b
/gc-cons-threshold
66 gc-cons-percentage b
/gc-cons-percentage
67 file-name-handler-alist b
/file-name-handler-alist
)
68 (when (featurep 'exwm-workspace
)
69 (with-eval-after-load 'exwm-workspace
76 "[%s]" (number-to-string
77 exwm-workspace-current-index
))))))))
78 (when (version< emacs-version
"28")
79 ;; manually make some mode-line spaces smaller
80 ;; (version<= "28" emacs-version) can do an awesome job at this
81 ;; out of the box if `mode-line-compact' is set to t (see below)
92 mode-line-buffer-identification
93 (propertized-buffer-identification "%10b"))))
94 (add-hook 'after-init-hook
#'b
/post-init
)
96 ;; increase number of lines kept in *Messages* log
97 (setq message-log-max
20000)
102 (setq user-full-name
"Amin Bandali"
103 user-mail-address
"bandali@gnu.org")
106 ;;; csetq (`custom' setq)
110 (defmacro csetq
(&rest args
)
111 "Set the value of user option VAR to VALUE.
113 More generally, you can use multiple variables and values, as in
114 (csetq VAR VALUE VAR VALUE...)
115 This sets each user option VAR's value to the corresponding VALUE.
117 \(fn [VAR VALUE]...)"
118 (declare (debug setq
))
120 ,@(cl-loop for
(var value
) on args by
'cddr
122 `(funcall (or (get ',var
'custom-set
) #'set-default
)
126 ;;; Package management
128 ;; variables of interest:
129 ;; package-archive-priorities
131 ;; package-pinned-packages
133 ;; (let* ((b (find-file-noselect "refinery-theme.el"))
134 ;; (d (with-current-buffer b (package-buffer-info))))
135 ;; (package-generate-description-file d "refinery-theme-pkg.el"))
136 (run-with-idle-timer 0.01 nil
#'require
'package
)
137 (with-eval-after-load 'package
138 (when (= (length package-archives
) 1)
142 ;; ("bndl" . "https://p.bndl.org/elpa/")
143 ("org" .
"https://orgmode.org/elpa/"))
150 (rt-liberation "1.31")
152 (expand-region "0.11.0")
155 ;; (refinery-theme "0.1.1")
157 (org-plus-contrib "20201109"))))
158 (package-initialize))
160 (csetq package-archive-upload-base
"/ssh:caffeine:~/www/p/elpa")
165 ;; keep ~/.emacs.d clean
168 (convert-standard-filename "etc/") user-emacs-directory
)
169 "The directory where packages place their configuration files.")
172 (convert-standard-filename "var/") user-emacs-directory
)
173 "The directory where packages place their persistent data files.")
176 (convert-standard-filename "lisp/") user-emacs-directory
)
177 "The directory where packages place their persistent data files.")
179 "Expand filename FILE relative to `b/etc-dir'."
180 (expand-file-name (convert-standard-filename file
) b
/etc-dir
))
182 "Expand filename FILE relative to `b/var-dir'."
183 (expand-file-name (convert-standard-filename file
) b
/var-dir
))
185 "Expand filename FILE relative to `b/lisp-dir'."
186 (expand-file-name (convert-standard-filename file
) b
/lisp-dir
))
189 auto-save-list-file-prefix
(b/var
"auto-save/sessions/")
190 nsm-settings-file
(b/var
"nsm-settings.el"))
192 ;; separate custom file (don't want it mixing with init.el)
193 (with-eval-after-load 'custom
194 (setq custom-file
(b/etc
"custom.el"))
195 (when (file-exists-p custom-file
)
197 ;; while at it, treat themes as safe
198 ;; (setf custom-safe-themes t)
199 ;; only one custom theme at a time
200 ;; (defadvice load-theme (before clear-previous-themes activate)
201 ;; "Clear existing theme settings instead of layering them"
202 ;; (mapc #'disable-theme custom-enabled-themes))
205 ;; load the secrets file if it exists, otherwise show a warning
206 ;; (with-demoted-errors
207 ;; (load (b/etc "secrets")))
209 ;; start up emacs server. see
210 ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server
211 (run-with-idle-timer 0.5 nil
#'require
'server
)
212 (with-eval-after-load 'server
213 (declare-function server-edit
"server")
214 (global-set-key (kbd "C-c F D") #'server-edit
)
215 (declare-function server-running-p
"server")
216 (or (server-running-p) (server-mode)))
221 ;;;; C-level customizations
224 ;; completion case sensitivity
225 completion-ignore-case t
227 enable-recursive-minibuffers t
228 resize-mini-windows t
231 ;; i don't feel like jumping out of my chair every now and again;
232 ;; so...don't *BEEP* at me, emacs =)
233 ring-bell-function
'ignore
235 ;; scroll-conservatively 101
236 scroll-conservatively
15
237 ;; scroll-preserve-screen-position 1
238 ;; focus follows mouse
239 ;; mouse-autoselect-window t
243 ;; case-sensitive search (and `dabbrev-expand')
244 ;; case-fold-search nil
245 ;; always use space for indentation
249 (set-fontset-font t
'arabic
"Vazir")
251 ;;;; Elisp-level customizations
253 ;; (define-key minibuffer-local-completion-map
254 ;; "\t" #'minibuffer-force-complete)
256 ;; (with-eval-after-load 'icomplete
258 ;; (setq icomplete-on-del-error-function #'abort-recursive-edit)
260 ;; (defun b/icomplete-fido-backward-updir ()
261 ;; "Delete char before or go up directory, like `ido-mode'."
263 ;; (if (and (eq (char-before) ?/)
264 ;; (eq (icomplete--category) 'file))
266 ;; (goto-char (1- (point)))
267 ;; (when (search-backward "/" (point-min) t)
268 ;; (delete-region (1+ (point)) (point-max))))
269 ;; (condition-case nil
270 ;; (call-interactively #'delete-backward-char)
272 ;; (when icomplete-on-del-error-function
273 ;; (funcall icomplete-on-del-error-function))))))
275 ;; (define-key icomplete-fido-mode-map
276 ;; (kbd "DEL") #'b/icomplete-fido-backward-updir))
278 ;; (with-eval-after-load 'subr
279 ;; (keyboard-translate ?\( ?\[)
280 ;; (keyboard-translate ?\) ?\])
281 ;; (keyboard-translate ?\[ ?\()
282 ;; (keyboard-translate ?\] ?\))
284 ;; ;; (keyboard-translate ?\( ?\()
285 ;; ;; (keyboard-translate ?\) ?\))
286 ;; ;; (keyboard-translate ?\[ ?\[)
287 ;; ;; (keyboard-translate ?\] ?\])
291 ;; don't need to see the startup echo area message
292 (advice-add #'display-startup-echo-area-message
:override
#'ignore
)
294 ;; i want *scratch* as my startup buffer
295 initial-buffer-choice t
296 ;; i don't need the default hint
297 initial-scratch-message nil
298 ;; use customizable text-mode as major mode for *scratch*
299 ;; (initial-major-mode 'text-mode)
300 ;; inhibit buffer list when more than 2 files are loaded
301 inhibit-startup-buffer-menu t
302 ;; don't need to see the startup screen or echo area message
303 inhibit-startup-screen t
304 inhibit-startup-echo-area-message user-login-name
)
308 ;; backups (C-h v make-backup-files RET)
310 backup-directory-alist
(list (cons "." (b/var
"backup/")))
312 delete-old-versions t
314 auto-save-file-name-transforms
`((".*" ,(b/var
"auto-save/") t
))
315 ;; insert newline at the end of files
316 ;; require-final-newline t
317 ;; open read-only file buffers in view-mode
318 ;; (enables niceties like `q' for quit)
322 ;; disable disabled commands
323 (csetq disabled-command-function nil
)
325 ;; lazy-person-friendly yes/no prompts
326 (defalias 'yes-or-no-p
#'y-or-n-p
)
328 ;; autorevert: enable automatic reloading of changed buffers and files
329 (csetq auto-revert-verbose nil
330 global-auto-revert-non-file-buffers nil
)
331 (require 'autorevert
)
332 (global-auto-revert-mode 1)
334 ;; time and battery in mode-line
335 (run-with-idle-timer 0.1 nil
#'require
'time
)
336 (with-eval-after-load 'time
338 display-time-default-load-average nil
339 display-time-format
" %a %b %-e %-l:%M%P"
340 display-time-mail-icon
'(image :type xpm
341 :file
"gnus/gnus-pointer.xpm"
343 display-time-use-mail-icon t
)
346 (run-with-idle-timer 0.1 nil
#'require
'battery
)
347 (with-eval-after-load 'battery
348 (csetq battery-mode-line-format
" %p%% %t")
349 (display-battery-mode))
351 ;; (with-eval-after-load 'fringe
353 ;; (fringe-mode '(3 . 1)))
355 ;; 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
386 ;; search for non-ASCII characters: i’d like non-ASCII characters such
387 ;; as ‘’“”«»‹›áⓐ𝒶 to be selected when i search for their ASCII
388 ;; counterpart. shoutout to
389 ;; http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html
390 search-default-mode
#'char-fold-to-regexp
)
393 ;; uncomment to extend the above behaviour to query-replace
394 ;; (csetq replace-char-fold t)
397 (global-set-key (kbd "C-x v C-=") #'vc-ediff
)
399 (with-eval-after-load 'vc-git
400 (csetq vc-git-print-log-follow t
401 vc-git-show-stash
0))
403 (csetq ediff-window-setup-function
'ediff-setup-windows-plain
404 ediff-split-window-function
'split-window-horizontally
)
405 (with-eval-after-load 'ediff
406 (add-hook 'ediff-after-quit-hook-internal
#'winner-undo
))
410 ;; gentler font resizing
411 text-scale-mode-step
1.05)
413 (run-with-idle-timer 0.4 nil
#'require
'mwheel
)
414 (csetq mouse-wheel-scroll-amount
'(1 ((shift) .
1)) ; one line at a time
415 mouse-wheel-progressive-speed nil
; don't accelerate scrolling
416 mouse-wheel-follow-mouse t
) ; scroll window under mouse
418 (run-with-idle-timer 0.4 nil
#'require
'pixel-scroll
)
419 (with-eval-after-load 'pixel-scroll
420 (pixel-scroll-mode 1))
424 epg-gpg-program
(executable-find "gpg")
425 ;; ask for GPG passphrase in minibuffer
426 ;; this will fail if gpg>=2.1 is not available
427 epg-pinentry-mode
'loopback
)
429 ;; (require 'pinentry)
430 ;; workaround for systemd-based distros:
431 ;; (setq pinentry--socket-dir server-socket-dir)
436 auth-sources
'("~/.authinfo.gpg")
437 authinfo-hidden
(regexp-opt '("password" "client-secret" "token")))
440 (with-eval-after-load 'info
444 (convert-standard-filename "info/") source-directory
)))
447 (when (display-graphic-p)
448 (with-eval-after-load 'faces
449 (let* ((grey "#e7e7e7")
450 (darker-grey "#d9d9d9")
451 (box ;; `(:line-width -1 :style released-button)
453 (set-face-attribute 'mode-line nil
454 :background grey
:box box
)
455 (set-face-attribute 'mode-line-inactive nil
456 :background darker-grey
:box box
))))
461 (defun b/add-elisp-section
()
465 (insert "\n\f\n;;; "))
467 (defun b/insert-asterism
()
468 "Insert a centred asterism."
470 (let ((asterism "* * *"))
475 (floor (/ (- fill-column
(length asterism
)) 2))
480 (defun b/start-process
(program &rest args
)
481 "Same as `start-process', but doesn't bother about name and buffer."
482 (let ((process-name (concat program
"_process"))
483 (buffer-name (generate-new-buffer-name
484 (concat program
"_output"))))
485 (apply #'start-process
486 process-name buffer-name program args
)))
488 (defun b/no-mouse-autoselect-window
()
489 "Conveniently disable `focus-follows-mouse'.
490 For disabling the behaviour for certain buffers and/or modes."
491 (make-local-variable 'mouse-autoselect-window
)
492 (setq mouse-autoselect-window nil
))
494 (defun b/kill-current-buffer
()
495 "Kill the current buffer."
496 ;; also see https://redd.it/64xb3q
498 (kill-buffer (current-buffer)))
500 (defun b/move-indentation-or-beginning-of-line
(arg)
501 "Move to the indentation or to the beginning of line."
504 ;; (back-to-indentation)
505 ;; (move-beginning-of-line arg))
507 (progn (back-to-indentation)
509 (move-beginning-of-line arg
)))
511 (defun b/join-line-top
()
512 "Like `join-line', but join next line to the current line."
516 (defun b/duplicate-line-or-region
(&optional n
)
517 "Duplicate the current line, or region (if active).
518 Make N (default: 1) copies of the current line or region."
520 (let ((u-r-p (use-region-p)) ; if region is active
525 (buffer-substring (region-beginning) (region-end))
526 (prog1 (thing-at-point 'line
)
530 (forward-line 1))))))
531 (dotimes (_ (abs n1
))
535 ;;; General key bindings
537 (global-set-key (kbd "C-a") #'b
/move-indentation-or-beginning-of-line
)
538 (global-set-key (kbd "C-c a i") #'ielm
)
539 (global-set-key (kbd "C-c d") #'b
/duplicate-line-or-region
)
540 (global-set-key (kbd "C-c j") #'b
/join-line-top
)
541 (global-set-key (kbd "C-S-j") #'b
/join-line-top
)
542 (global-set-key (kbd "C-c x") #'execute-extended-command
)
544 ;; evaling and macro-expanding
545 (global-set-key (kbd "C-c e b") #'eval-buffer
)
546 (global-set-key (kbd "C-c e e") #'eval-last-sexp
)
547 (global-set-key (kbd "C-c e m") #'pp-macroexpand-last-sexp
)
548 (global-set-key (kbd "C-c e r") #'eval-region
)
551 (global-set-key (kbd "C-c e i") #'emacs-init-time
)
552 (global-set-key (kbd "C-c e u") #'emacs-uptime
)
553 (global-set-key (kbd "C-c e v") #'emacs-version
)
556 (global-set-key (kbd "C-c f .") #'find-file
)
557 (global-set-key (kbd "C-c f d") #'find-name-dired
)
558 (global-set-key (kbd "C-c f l") #'find-library
)
561 (global-set-key (kbd "C-c F m") #'make-frame-command
)
562 (global-set-key (kbd "C-c F d") #'delete-frame
)
565 (global-set-key (kbd "C-S-h F") #'describe-face
)
567 ;; (global-set-key (kbd "C-x k") #'b/kill-current-buffer)
568 ;; (global-set-key (kbd "C-x K") #'kill-buffer)
570 (define-key emacs-lisp-mode-map
(kbd "C-<return>") #'b
/add-elisp-section
)
572 (when (display-graphic-p)
573 (global-unset-key (kbd "C-z")))
576 ;;; Essential packages
581 (convert-standard-filename "lisp") user-emacs-directory
))
583 ;; (require 'bandali-exwm)
585 (require 'bandali-org
)
587 ;; (require 'bandali-theme)
589 ;; recently opened files
590 (csetq recentf-max-saved-items
2000
591 recentf-save-file
(b/var
"recentf-save.el"))
592 (run-with-idle-timer 0.2 nil
#'require
'recentf
)
593 (with-eval-after-load 'recentf
594 ;; (add-to-list 'recentf-keep #'file-remote-p)
597 (defun b/recentf-open
()
598 "Use `completing-read' to \\[find-file] a recent file."
601 (completing-read "Find recent file: " recentf-list
)))
602 (global-set-key (kbd "C-c f r") #'b
/recentf-open
))
605 (defun b/icomplete--fido-mode-setup
()
606 "Customizations to `fido-mode''s minibuffer."
607 (when (and icomplete-mode
(icomplete-simple-completing-p))
609 ;; icomplete-compute-delay 0.1
610 ;; icomplete-hide-common-prefix t
611 icomplete-separator
" · "
612 completion-styles
'(basic substring partial-completion flex
))))
613 (add-hook 'minibuffer-setup-hook
#'b
/icomplete--fido-mode-setup
1)
615 (require 'bandali-eshell
)
617 (require 'bandali-ibuffer
)
620 ;; (with-eval-after-load 'outline
621 ;; (when (featurep 'which-key)
622 ;; (which-key-add-key-based-replacements
625 ;; (define-key outline-minor-mode-map (kbd "<s-tab>")
626 ;; #'outline-toggle-children)
627 ;; (define-key outline-minor-mode-map (kbd "M-p")
628 ;; #'outline-previous-visible-heading)
629 ;; (define-key outline-minor-mode-map (kbd "M-n")
630 ;; #'outline-next-visible-heading)
631 ;; (defvar b/outline-prefix-map)
632 ;; (define-prefix-command 'b/outline-prefix-map)
633 ;; (define-key outline-minor-mode-map (kbd "s-O")
634 ;; 'b/outline-prefix-map)
635 ;; (define-key b/outline-prefix-map (kbd "TAB")
636 ;; #'outline-toggle-children)
637 ;; (define-key b/outline-prefix-map (kbd "a")
638 ;; #'outline-hide-body)
639 ;; (define-key b/outline-prefix-map (kbd "H")
640 ;; #'outline-hide-body)
641 ;; (define-key b/outline-prefix-map (kbd "S")
642 ;; #'outline-show-all)
643 ;; (define-key b/outline-prefix-map (kbd "h")
644 ;; #'outline-hide-subtree)
645 ;; (define-key b/outline-prefix-map (kbd "s")
646 ;; #'outline-show-subtree))
647 ;; (add-hook 'prog-mode-hook #'outline-minor-mode)
649 (require 'bandali-dired
)
651 (with-eval-after-load 'help
652 (temp-buffer-resize-mode)
653 (csetq help-window-select t
))
655 (with-eval-after-load 'help-mode
656 ;; local key bindings
657 (define-key help-mode-map
(kbd "p") #'backward-button
)
658 (define-key help-mode-map
(kbd "n") #'forward-button
))
660 (with-eval-after-load 'tramp
661 (csetq tramp-auto-save-directory
(b/var
"tramp/auto-save/")
662 tramp-persistency-file-name
(b/var
"tramp/persistency.el"))
663 (add-to-list 'tramp-default-proxies-alist
'(nil "\\`root\\'" "/ssh:%h:"))
664 (add-to-list 'tramp-default-proxies-alist
'("localhost" nil nil
))
665 (add-to-list 'tramp-default-proxies-alist
666 (list (regexp-quote (system-name)) nil nil
)))
668 (with-eval-after-load 'doc-view
669 (define-key doc-view-mode-map
(kbd "M-RET") #'image-previous-line
))
671 (csetq shr-max-width
80)
673 ;; Email (with Gnus, message, and EBDB)
674 (require 'bandali-gnus
)
675 (with-eval-after-load 'sendmail
676 (csetq sendmail-program
(executable-find "msmtp")
677 ;; message-sendmail-extra-arguments '("-v" "-d")
678 mail-specify-envelope-from t
679 mail-envelope-from
'header
))
680 (require 'bandali-message
)
681 (require 'bandali-ebdb
)
684 (require 'bandali-erc
)
686 ;; 'paste' service (aka scp + web server)
687 (add-to-list 'load-path
(b/lisp
"scpaste"))
688 (with-eval-after-load 'scpaste
689 (csetq scpaste-http-destination
"https://p.bndl.org"
690 scpaste-scp-destination
"p:~"))
691 (autoload 'scpaste
"scpaste" nil t
)
692 (autoload 'scpaste-region
"scpaste" nil t
)
693 (global-set-key (kbd "C-c a p p") #'scpaste
)
694 (global-set-key (kbd "C-c a p r") #'scpaste-region
)
699 ;; display Lisp objects at point in the echo area
700 (when (version< "25" emacs-version
)
701 (with-eval-after-load 'eldoc
702 (csetq eldoc-minor-mode-string
" eldoc")
703 (global-eldoc-mode)))
705 ;; highlight matching parens
709 ;; (require 'elec-pair)
710 ;; (electric-pair-mode)
713 ;; Save what I copy into clipboard from other applications into Emacs'
714 ;; kill-ring, which would allow me to still be able to easily access
715 ;; it in case I kill (cut or copy) something else inside Emacs before
716 ;; yanking (pasting) what I'd originally intended to.
717 save-interprogram-paste-before-kill t
)
718 (with-eval-after-load 'simple
719 (column-number-mode 1)
720 (line-number-mode 1))
722 ;; save minibuffer history
724 (csetq savehist-file
(b/var
"savehist.el"))
726 (add-to-list 'savehist-additional-variables
'kill-ring
)
728 ;; automatically save place in files
729 (when (version< "25" emacs-version
)
730 (csetq save-place-file
(b/var
"save-place.el"))
733 (defun indicate-buffer-boundaries-left ()
734 (csetq indicate-buffer-boundaries
'left
))
735 (with-eval-after-load 'prog-mode
736 (global-prettify-symbols-mode))
737 (add-hook 'prog-mode-hook
#'indicate-buffer-boundaries-left
)
739 (define-key text-mode-map
(kbd "C-<return>") #'b
/insert-asterism
)
740 (add-hook 'text-mode-hook
#'indicate-buffer-boundaries-left
)
741 (add-hook 'text-mode-hook
#'flyspell-mode
)
743 (add-to-list 'auto-mode-alist
'("\\.*rc$" . conf-mode
))
745 (add-to-list 'auto-mode-alist
'("\\.bashrc$" . sh-mode
))
747 (with-eval-after-load 'flyspell
748 (csetq flyspell-mode-line-string
" fly"))
751 ;; (run-with-idle-timer 0.6 nil #'require 'flycheck)
752 ;; (with-eval-after-load 'flycheck
754 ;; ;; Use the load-path from running Emacs when checking elisp files
755 ;; flycheck-emacs-lisp-load-path 'inherit
756 ;; ;; Only flycheck when I actually save the buffer
757 ;; flycheck-check-syntax-automatically '(mode-enabled save)
758 ;; flycheck-mode-line-prefix "flyc"))
759 ;; (define-key flycheck-mode-map (kbd "M-P") #'flycheck-previous-error)
760 ;; (define-key flycheck-mode-map (kbd "M-N") #'flycheck-next-error)
761 ;; (add-hook 'prog-mode-hook #'flycheck-mode)
764 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
765 ;; (run-with-idle-timer 0.6 nil #'require 'ispell)
766 ;; (with-eval-after-load 'ispell
767 ;; ;; ’ can be part of a word
768 ;; (csetq ispell-local-dictionary-alist
769 ;; `((nil "[[:alpha:]]" "[^[:alpha:]]"
770 ;; "['\x2019]" nil ("-B") nil utf-8))
771 ;; ispell-program-name (executable-find "hunspell"))
772 ;; ;; don't send ’ to the subprocess
773 ;; (defun endless/replace-apostrophe (args)
774 ;; (cons (replace-regexp-in-string
775 ;; "’" "'" (car args))
777 ;; (advice-add #'ispell-send-string :filter-args
778 ;; #'endless/replace-apostrophe)
779 ;; ;; convert ' back to ’ from the subprocess
780 ;; (defun endless/replace-quote (args)
781 ;; (if (not (derived-mode-p 'org-mode))
783 ;; (cons (replace-regexp-in-string
784 ;; "'" "’" (car args))
786 ;; (advice-add #'ispell-parse-output :filter-args
787 ;; #'endless/replace-quote))
790 (csetq abbrev-file-name
(b/etc
"abbrev.el"))
791 (add-hook 'text-mode-hook
#'abbrev-mode
)
794 ;;; Programming modes
796 (with-eval-after-load 'lisp-mode
797 (defun indent-spaces-mode ()
798 (setq indent-tabs-mode nil
))
799 (add-hook 'lisp-interaction-mode-hook
#'indent-spaces-mode
))
802 (add-to-list 'load-path
(b/lisp
"alloy-mode"))
803 (autoload 'alloy-mode
"alloy-mode" nil t
)
804 (with-eval-after-load 'alloy-mode
805 (csetq alloy-basic-offset
2)
806 ;; (defun b/alloy-simple-indent (start end)
808 ;; ;; (if (region-active-p)
809 ;; ;; (indent-rigidly start end alloy-basic-offset)
811 ;; ;; (indent-rigidly (line-beginning-position)
812 ;; ;; (line-end-position)
813 ;; ;; alloy-basic-offset)))
814 ;; (indent-to (+ (current-column) alloy-basic-offset)))
815 ;; local key bindings
816 (define-key alloy-mode-map
(kbd "RET") #'electric-newline-and-maybe-indent
)
817 ;; (define-key alloy-mode-map (kbd "TAB") #'b/alloy-simple-indent)
818 (define-key alloy-mode-map
(kbd "TAB") #'indent-for-tab-command
))
819 (add-to-list 'auto-mode-alist
'("\\.\\(als\\|dsh\\)\\'" . alloy-mode
))
820 (add-hook 'alloy-mode-hook
(lambda nil
(setq-local indent-tabs-mode nil
)))
823 ;; (eval-when-compile (defvar lean-mode-map))
824 ;; (run-with-idle-timer 0.4 nil #'require 'lean-mode)
825 ;; (with-eval-after-load 'lean-mode
826 ;; (require 'lean-input)
827 ;; (csetq default-input-method "Lean"
828 ;; lean-input-tweak-all '(lean-input-compose
829 ;; (lean-input-prepend "/")
830 ;; (lean-input-nonempty))
831 ;; lean-input-user-translations '(("/" "/")))
832 ;; (lean-input-setup)
833 ;; ;; local key bindings
834 ;; (define-key lean-mode-map (kbd "S-SPC") #'company-complete))
836 (with-eval-after-load 'sgml-mode
837 (csetq sgml-basic-offset
0))
839 (with-eval-after-load 'css-mode
840 (csetq css-indent-offset
2))
843 ;; (add-hook 'po-mode-hook (lambda nil (run-with-timer 0.1 nil 'View-exit)))
846 ;; (csetq font-latex-fontify-sectioning 'color)
848 (with-eval-after-load 'tex-mode
850 (lambda (p) (string-match "^---?" (car p
)))
851 tex--prettify-symbols-alist
))
852 (add-hook 'tex-mode-hook
#'auto-fill-mode
)
853 (add-hook 'tex-mode-hook
#'flyspell-mode
)
856 ;;; Emacs enhancements & auxiliary packages
858 (with-eval-after-load 'man
859 (csetq Man-width
80))
861 (defun b/*scratch
* ()
862 "Switch to `*scratch*' buffer, creating it if it does not exist."
865 (or (get-buffer "*scratch*")
866 (with-current-buffer (get-buffer-create "*scratch*")
867 (set-buffer-major-mode (current-buffer))
869 (global-set-key (kbd "C-c s") #'b
/*scratch
*)
872 ;; | make pretty boxed quotes like this
874 (add-to-list 'load-path
(b/lisp
"boxquote"))
875 (run-with-idle-timer 0.6 nil
#'require
'boxquote
)
876 (with-eval-after-load 'boxquote
877 (defvar b
/boxquote-prefix-map
)
878 (define-prefix-command 'b
/boxquote-prefix-map
)
879 (global-set-key (kbd "C-c q") 'b
/boxquote-prefix-map
)
880 (define-key b
/boxquote-prefix-map
(kbd "b") #'boxquote-buffer
)
881 (define-key b
/boxquote-prefix-map
(kbd "B") #'boxquote-insert-buffer
)
882 (define-key b
/boxquote-prefix-map
(kbd "d") #'boxquote-defun
)
883 (define-key b
/boxquote-prefix-map
(kbd "F") #'boxquote-insert-file
)
884 (define-key b
/boxquote-prefix-map
(kbd "hf") #'boxquote-describe-function
)
885 (define-key b
/boxquote-prefix-map
(kbd "hk") #'boxquote-describe-key
)
886 (define-key b
/boxquote-prefix-map
(kbd "hv") #'boxquote-describe-variable
)
887 (define-key b
/boxquote-prefix-map
(kbd "hw") #'boxquote-where-is
)
888 (define-key b
/boxquote-prefix-map
(kbd "k") #'boxquote-kill
)
889 (define-key b
/boxquote-prefix-map
(kbd "p") #'boxquote-paragraph
)
890 (define-key b
/boxquote-prefix-map
(kbd "q") #'boxquote-boxquote
)
891 (define-key b
/boxquote-prefix-map
(kbd "r") #'boxquote-region
)
892 (define-key b
/boxquote-prefix-map
(kbd "s") #'boxquote-shell-command
)
893 (define-key b
/boxquote-prefix-map
(kbd "t") #'boxquote-text
)
894 (define-key b
/boxquote-prefix-map
(kbd "T") #'boxquote-title
)
895 (define-key b
/boxquote-prefix-map
(kbd "u") #'boxquote-unbox
)
896 (define-key b
/boxquote-prefix-map
(kbd "U") #'boxquote-unbox-region
)
897 (define-key b
/boxquote-prefix-map
(kbd "y") #'boxquote-yank
)
898 (define-key b
/boxquote-prefix-map
(kbd "M-q") #'boxquote-fill-paragraph
)
899 (define-key b
/boxquote-prefix-map
(kbd "M-w") #'boxquote-kill-ring-save
))
901 (add-to-list 'load-path
(b/lisp
"hl-todo"))
902 (run-with-idle-timer 0.5 nil
#'require
'hl-todo
)
903 (with-eval-after-load 'hl-todo
904 ;; highlight TODOs in buffers
905 (global-hl-todo-mode))
908 (global-set-key (kbd "C-=") #'er
/expand-region
)
910 (run-with-idle-timer 0.6 nil
#'require
'yasnippet
)
911 (with-eval-after-load 'yasnippet
912 (declare-function yas-reload-all
913 "yasnippet" (&optional no-jit interactive
))
914 (declare-function yas-maybe-expand-abbrev-key-filter
917 (defconst yas-verbosity-cur yas-verbosity
)
918 (setq yas-verbosity
2)
919 (csetq yas-snippet-dirs
`(,(b/etc
"yasnippet/snippets")))
920 ;; (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets" t)
922 (setq yas-verbosity yas-verbosity-cur
)
924 (defun b/yas-maybe-expand-abbrev-key-filter
(cmd)
925 (when (and (yas-maybe-expand-abbrev-key-filter cmd
)
926 (not (bound-and-true-p git-commit-mode
)))
928 (defconst b
/yas-maybe-expand
929 '(menu-item "" yas-expand
930 :filter b
/yas-maybe-expand-abbrev-key-filter
))
931 (define-key yas-minor-mode-map
(kbd "SPC") b
/yas-maybe-expand
)
936 (global-set-key (kbd "C-c D d") #'debbugs-gnu
)
937 (global-set-key (kbd "C-c D b") #'debbugs-gnu-bugs
)
938 (global-set-key (kbd "C-c D e") ; bug-gnu-emacs
941 (setq debbugs-gnu-current-suppress t
)
942 (debbugs-gnu debbugs-gnu-default-severities
944 (global-set-key (kbd "C-c D g") ; bug-gnuzilla
947 (setq debbugs-gnu-current-suppress t
)
948 (debbugs-gnu debbugs-gnu-default-severities
953 url-configuration-directory
(b/var
"url/configuration/")
954 url-cache-directory
(b/var
"url/cache/"))
957 (csetq eww-download-directory
(file-name-as-directory
958 (getenv "XDG_DOWNLOAD_DIR")))
959 (global-set-key (kbd "C-c a e w") #'eww
)
963 ;; reftex-default-bibliography '("~/usr/org/references.bib")
964 ;; org-ref-default-bibliography '("~/usr/org/references.bib")
965 ;; org-ref-bibliography-notes "~/usr/org/notes.org"
966 ;; org-ref-pdf-directory "~/usr/org/bibtex-pdfs/")
968 ;; fill-column-indicator ?
971 (csetq split-width-threshold
150)
972 (global-set-key (kbd "C-c w s l")
977 (global-set-key (kbd "C-c w s j")
982 (global-set-key (kbd "C-c w q") #'quit-window
)
985 ;; (global-set-key (kbd "C-c a p") #'pass)
986 ;; (add-hook 'pass-mode-hook #'View-exit)
989 ;; uncomment to disable reftex-cite's default choice of previous word
990 ;; (with-eval-after-load 'reftex
991 ;; (require 'reftex-cite)
992 ;; (defun reftex-get-bibkey-default ()
993 ;; "If the cursor is in a citation macro, return the word before the macro."
994 ;; (let* ((macro (reftex-what-macro 1)))
996 ;; (when (and macro (string-match "cite" (car macro)))
997 ;; (goto-char (cdr macro)))
998 ;; (reftex-this-word)))))
999 (add-hook 'latex-mode-hook
#'reftex-mode
)
1002 (add-to-list 'load-path
(b/lisp
"dmenu"))
1003 (with-eval-after-load 'dmenu
1004 (csetq dmenu-prompt-string
"run: "
1005 dmenu-save-file
(b/var
"dmenu-items")))
1006 (autoload 'dmenu
"dmenu" nil t
)
1011 (run-with-idle-timer 0.5 nil
#'require
'delight
)
1012 (with-eval-after-load 'delight
1013 (delight 'auto-fill-function
" f" "simple")
1014 (delight 'abbrev-mode
"" "abbrev")
1015 (delight 'mml-mode
" mml" "mml")
1016 (delight 'yas-minor-mode
"" "yasnippet"))
1019 ;;; Post initialization
1021 (message "Loading %s...done (%.3fs)" user-init-file
1022 (float-time (time-subtract (current-time)
1023 b
/before-user-init-time
)))
1025 ;;; init.el ends here