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
139 ;; ;; package-archives
140 ;; ;; `(,@package-archives
141 ;; ;; ("bndl" . "https://p.bndl.org/elpa/"))
147 ;; (expand-region "0.11.0")
148 ;; (rt-liberation "2.4")
149 ;; (yasnippet "0.14.0")))
150 (package-initialize))
152 (csetq package-archive-upload-base
"/ssh:caffeine:~/www/p/elpa")
157 ;; keep ~/.emacs.d clean
160 (convert-standard-filename "etc/") user-emacs-directory
)
161 "The directory where packages place their configuration files.")
164 (convert-standard-filename "var/") user-emacs-directory
)
165 "The directory where packages place their persistent data files.")
168 (convert-standard-filename "lisp/") user-emacs-directory
)
169 "The directory where packages place their persistent data files.")
171 "Expand filename FILE relative to `b/etc-dir'."
172 (expand-file-name (convert-standard-filename file
) b
/etc-dir
))
174 "Expand filename FILE relative to `b/var-dir'."
175 (expand-file-name (convert-standard-filename file
) b
/var-dir
))
177 "Expand filename FILE relative to `b/lisp-dir'."
178 (expand-file-name (convert-standard-filename file
) b
/lisp-dir
))
181 auto-save-list-file-prefix
(b/var
"auto-save/sessions/")
182 nsm-settings-file
(b/var
"nsm-settings.el"))
184 ;; separate custom file (don't want it mixing with init.el)
185 (with-eval-after-load 'custom
186 (setq custom-file
(b/etc
"custom.el"))
187 (when (file-exists-p custom-file
)
189 ;; while at it, treat themes as safe
190 ;; (setf custom-safe-themes t)
191 ;; only one custom theme at a time
192 ;; (defadvice load-theme (before clear-previous-themes activate)
193 ;; "Clear existing theme settings instead of layering them"
194 ;; (mapc #'disable-theme custom-enabled-themes))
197 ;; load the secrets file if it exists, otherwise show a warning
198 ;; (with-demoted-errors
199 ;; (load (b/etc "secrets")))
201 ;; start up emacs server. see
202 ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server
203 (run-with-idle-timer 0.5 nil
#'require
'server
)
204 (with-eval-after-load 'server
205 (declare-function server-edit
"server")
206 (global-set-key (kbd "C-c F D") #'server-edit
)
207 (declare-function server-running-p
"server")
208 (or (server-running-p) (server-mode)))
213 ;;;; C-level customizations
217 ;; completion case sensitivity
218 completion-ignore-case t
219 read-buffer-completion-ignore-case t
221 enable-recursive-minibuffers t
222 resize-mini-windows t
225 ;; i don't feel like jumping out of my chair every now and again;
226 ;; so...don't *BEEP* at me, emacs =)
227 ring-bell-function
'ignore
229 ;; scroll-conservatively 101
230 scroll-conservatively
15
231 ;; scroll-preserve-screen-position 1
232 ;; focus follows mouse
233 ;; mouse-autoselect-window t
237 ;; case-sensitive search (and `dabbrev-expand')
238 ;; case-fold-search nil
239 ;; always use space for indentation
243 (when (display-graphic-p)
244 (set-fontset-font t
'arabic
"Vazir"))
245 ;; ;; (set-frame-font "Drafting Mono-14:weight=light" nil t)
246 ;; (set-frame-font "Drafting Mono:pixelsize=16" nil t)
247 ;; (set-face-attribute 'bold nil :weight 'semi-bold)
249 ;;;; Elisp-level customizations
251 ;; (define-key minibuffer-local-completion-map
252 ;; "\t" #'minibuffer-force-complete)
254 ;; (with-eval-after-load 'icomplete
256 ;; (setq icomplete-on-del-error-function #'abort-recursive-edit)
258 ;; (defun b/icomplete-fido-backward-updir ()
259 ;; "Delete char before or go up directory, like `ido-mode'."
261 ;; (if (and (eq (char-before) ?/)
262 ;; (eq (icomplete--category) 'file))
264 ;; (goto-char (1- (point)))
265 ;; (when (search-backward "/" (point-min) t)
266 ;; (delete-region (1+ (point)) (point-max))))
267 ;; (condition-case nil
268 ;; (call-interactively #'delete-backward-char)
270 ;; (when icomplete-on-del-error-function
271 ;; (funcall icomplete-on-del-error-function))))))
273 ;; (define-key icomplete-fido-mode-map
274 ;; (kbd "DEL") #'b/icomplete-fido-backward-updir))
276 ;; (with-eval-after-load 'subr
277 ;; (keyboard-translate ?\( ?\[)
278 ;; (keyboard-translate ?\) ?\])
279 ;; (keyboard-translate ?\[ ?\()
280 ;; (keyboard-translate ?\] ?\))
282 ;; ;; (keyboard-translate ?\( ?\()
283 ;; ;; (keyboard-translate ?\) ?\))
284 ;; ;; (keyboard-translate ?\[ ?\[)
285 ;; ;; (keyboard-translate ?\] ?\])
289 (csetq read-file-name-completion-ignore-case t
)
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
336 (run-with-idle-timer 0.1 nil
#'require
'time
)
337 (with-eval-after-load 'time
339 display-time-default-load-average nil
340 display-time-format
" %a %b %-e %-l:%M%P"
341 display-time-mail-icon
'(image :type xpm
342 :file
"gnus/gnus-pointer.xpm"
344 display-time-use-mail-icon t
345 zoneinfo-style-world-list
346 `(,@zoneinfo-style-world-list
348 ("Asia/Tehran" "Tehran")
349 ("Australia/Melbourne" "Melbourne")))
352 (run-with-idle-timer 0.1 nil
#'require
'battery
)
353 (with-eval-after-load 'battery
354 (csetq battery-mode-line-format
" %p%% %t")
355 (display-battery-mode))
357 ;; (with-eval-after-load 'fringe
359 ;; (fringe-mode '(3 . 1)))
361 ;; enable winner-mode (C-h f winner-mode RET)
365 (run-with-idle-timer 0.1 nil
#'require
'windmove
)
366 (with-eval-after-load 'windmove
367 (csetq windmove-wrap-around t
)
368 (global-set-key (kbd "M-H") #'windmove-left
)
369 (global-set-key (kbd "M-L") #'windmove-right
)
370 (global-set-key (kbd "M-K") #'windmove-up
)
371 (global-set-key (kbd "M-J") #'windmove-down
))
373 (with-eval-after-load 'compile
374 ;; don't display *compilation* buffer on success. based on
375 ;; https://stackoverflow.com/a/17788551, with changes to use `cl-letf'
376 ;; instead of the now obsolete `flet'.
377 (defun b/compilation-finish-function
(buffer outstr
)
378 (unless (string-match "finished" outstr
)
379 (switch-to-buffer-other-window buffer
))
382 (setq compilation-finish-functions
#'b
/compilation-finish-function
)
386 (defadvice compilation-start
387 (around inhibit-display
388 (command &optional mode name-function highlight-regexp
))
389 (if (not (string-match "^\\(find\\|grep\\)" command
))
390 (cl-letf (((symbol-function 'display-buffer
) #'ignore
))
391 (save-window-excursion ad-do-it
))
393 (ad-activate 'compilation-start
))
397 ;; allow scrolling in Isearch
398 isearch-allow-scroll t
400 ;; search for non-ASCII characters: i’d like non-ASCII characters such
401 ;; as ‘’“”«»‹›áⓐ𝒶 to be selected when i search for their ASCII
402 ;; counterpart. shoutout to
403 ;; http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html
404 search-default-mode
#'char-fold-to-regexp
)
407 ;; uncomment to extend the above behaviour to query-replace
408 ;; (csetq replace-char-fold t)
411 (global-set-key (kbd "C-x v C-=") #'vc-ediff
)
413 (with-eval-after-load 'vc-git
414 (csetq vc-git-print-log-follow t
415 vc-git-show-stash
0))
417 (csetq ediff-window-setup-function
'ediff-setup-windows-plain
418 ediff-split-window-function
'split-window-horizontally
)
419 (with-eval-after-load 'ediff
420 (add-hook 'ediff-after-quit-hook-internal
#'winner-undo
))
424 ;; gentler font resizing
425 text-scale-mode-step
1.05)
427 (run-with-idle-timer 0.4 nil
#'require
'mwheel
)
428 (csetq mouse-wheel-scroll-amount
'(1 ((shift) .
1)) ; one line at a time
429 mouse-wheel-progressive-speed nil
; don't accelerate scrolling
430 mouse-wheel-follow-mouse t
) ; scroll window under mouse
432 (run-with-idle-timer 0.4 nil
#'require
'pixel-scroll
)
433 (with-eval-after-load 'pixel-scroll
434 (pixel-scroll-mode 1))
438 epg-gpg-program
(executable-find "gpg")
439 ;; ask for GPG passphrase in minibuffer
440 ;; this will fail if gpg>=2.1 is not available
441 epg-pinentry-mode
'loopback
)
445 auth-sources
'("~/.authinfo.gpg")
446 authinfo-hidden
(regexp-opt '("password" "client-secret" "token")))
449 (with-eval-after-load 'info
452 `(,@Info-directory-list
454 (convert-standard-filename "info/") source-directory
)
455 "/usr/share/info/")))
458 (when (display-graphic-p)
459 (with-eval-after-load 'faces
460 (let* ((grey "#e7e7e7")
461 ;; (darker-grey "#d9d9d9")
462 ;; (box ;; 'unspecified
463 ;; `(;; :line-width -1
464 ;; :style released-button))
466 ;; (set-face-attribute 'fixed-pitch nil :family "Source Code Pro")
467 (set-face-attribute 'fixed-pitch nil
:family
"Inconsolata")
468 (set-face-attribute 'mode-line nil
469 :background grey
;; :box box
470 :inherit
'fixed-pitch
)
471 ;; (set-face-attribute 'mode-line-inactive nil
472 ;; :background darker-grey :box box)
478 (defun b/add-elisp-section
()
482 (insert "\n\f\n;;; "))
484 (defun b/insert-asterism
()
485 "Insert a centred asterism."
487 (let ((asterism "* * *"))
492 (floor (/ (- fill-column
(length asterism
)) 2))
497 (defun b/start-process
(program &rest args
)
498 "Same as `start-process', but doesn't bother about name and buffer."
499 (let ((process-name (concat program
"_process"))
500 (buffer-name (generate-new-buffer-name
501 (concat program
"_output"))))
502 (apply #'start-process
503 process-name buffer-name program args
)))
505 (defun b/no-mouse-autoselect-window
()
506 "Conveniently disable `focus-follows-mouse'.
507 For disabling the behaviour for certain buffers and/or modes."
508 (make-local-variable 'mouse-autoselect-window
)
509 (setq mouse-autoselect-window nil
))
511 (defun b/kill-current-buffer
()
512 "Kill the current buffer."
513 ;; also see https://redd.it/64xb3q
515 (kill-buffer (current-buffer)))
517 (defun b/move-indentation-or-beginning-of-line
(arg)
518 "Move to the indentation or to the beginning of line."
521 ;; (back-to-indentation)
522 ;; (move-beginning-of-line arg))
524 (progn (back-to-indentation)
526 (move-beginning-of-line arg
)))
528 (defun b/join-line-top
()
529 "Like `join-line', but join next line to the current line."
533 (defun b/duplicate-line-or-region
(&optional n
)
534 "Duplicate the current line, or region (if active).
535 Make N (default: 1) copies of the current line or region."
537 (let ((u-r-p (use-region-p)) ; if region is active
542 (buffer-substring (region-beginning) (region-end))
543 (prog1 (thing-at-point 'line
)
547 (forward-line 1))))))
548 (dotimes (_ (abs n1
))
551 (defun b/invert-default-face
()
552 "Invert the `default' face (swap its background and foreground).
553 Effectively a very simple light/dark theme toggle switch."
555 (invert-face 'default
))
558 ;;; General key bindings
560 (global-set-key (kbd "C-a") #'b
/move-indentation-or-beginning-of-line
)
561 (global-set-key (kbd "C-c a i") #'ielm
)
562 (global-set-key (kbd "C-c d") #'b
/duplicate-line-or-region
)
563 (global-set-key (kbd "C-c j") #'b
/join-line-top
)
564 (global-set-key (kbd "C-S-j") #'b
/join-line-top
)
565 (global-set-key (kbd "C-c x") #'execute-extended-command
)
566 (global-set-key (kbd "C-c v") #'b
/invert-default-face
)
568 ;; evaling and macro-expanding
569 (global-set-key (kbd "C-c e b") #'eval-buffer
)
570 (global-set-key (kbd "C-c e e") #'eval-last-sexp
)
571 (global-set-key (kbd "C-c e m") #'pp-macroexpand-last-sexp
)
572 (global-set-key (kbd "C-c e r") #'eval-region
)
575 (global-set-key (kbd "C-c e i") #'emacs-init-time
)
576 (global-set-key (kbd "C-c e u") #'emacs-uptime
)
577 (global-set-key (kbd "C-c e v") #'emacs-version
)
580 (global-set-key (kbd "C-c f .") #'find-file
)
581 (global-set-key (kbd "C-c f d") #'find-name-dired
)
582 (global-set-key (kbd "C-c f l") #'find-library
)
583 (global-set-key (kbd "C-c f p") #'find-file-at-point
)
586 (global-set-key (kbd "C-c F m") #'make-frame-command
)
587 (global-set-key (kbd "C-c F d") #'delete-frame
)
590 (global-set-key (kbd "C-S-h F") #'describe-face
)
592 ;; (global-set-key (kbd "C-x k") #'b/kill-current-buffer)
593 ;; (global-set-key (kbd "C-x K") #'kill-buffer)
595 (define-key emacs-lisp-mode-map
(kbd "C-<return>") #'b
/add-elisp-section
)
597 (when (display-graphic-p)
598 (global-unset-key (kbd "C-z")))
601 ;;; Essential packages
606 (convert-standard-filename "lisp") user-emacs-directory
))
608 ;; (require 'bandali-exwm)
610 (require 'bandali-org
)
612 ;; (require 'bandali-theme)
614 ;; recently opened files
615 (csetq recentf-max-saved-items
2000
616 recentf-save-file
(b/var
"recentf-save.el"))
617 (run-with-idle-timer 0.2 nil
#'require
'recentf
)
618 (with-eval-after-load 'recentf
619 ;; (add-to-list 'recentf-keep #'file-remote-p)
622 (defun b/recentf-open
()
623 "Use `completing-read' to \\[find-file] a recent file."
626 (completing-read "Find recent file: " recentf-list
)))
627 (global-set-key (kbd "C-c f r") #'b
/recentf-open
))
630 ;; (defun b/icomplete--fido-mode-setup ()
631 ;; "Customizations to `fido-mode''s minibuffer."
632 ;; (when (and icomplete-mode (icomplete-simple-completing-p))
634 ;; ;; icomplete-compute-delay 0.1
635 ;; ;; icomplete-hide-common-prefix t
636 ;; icomplete-separator " · "
637 ;; completion-styles '(basic substring partial-completion flex))))
638 ;; (add-hook 'minibuffer-setup-hook #'b/icomplete--fido-mode-setup 1)
640 (require 'bandali-eshell
)
642 (require 'bandali-ibuffer
)
644 (require 'bandali-dired
)
646 (with-eval-after-load 'help
647 (temp-buffer-resize-mode)
648 (csetq help-window-select t
))
650 (with-eval-after-load 'help-mode
651 ;; local key bindings
652 (define-key help-mode-map
(kbd "p") #'backward-button
)
653 (define-key help-mode-map
(kbd "n") #'forward-button
))
655 (with-eval-after-load 'tramp
656 (csetq tramp-auto-save-directory
(b/var
"tramp/auto-save/")
657 tramp-persistency-file-name
(b/var
"tramp/persistency.el"))
658 (add-to-list 'tramp-default-proxies-alist
'(nil "\\`root\\'" "/ssh:%h:"))
659 (add-to-list 'tramp-default-proxies-alist
'("localhost" nil nil
))
660 (add-to-list 'tramp-default-proxies-alist
661 (list (regexp-quote (system-name)) nil nil
)))
663 (with-eval-after-load 'doc-view
664 (define-key doc-view-mode-map
(kbd "M-RET") #'image-previous-line
))
666 (csetq shr-max-width
80)
668 ;; Email (with Gnus, message, and smtpmail)
669 (require 'bandali-gnus
)
670 (require 'bandali-message
)
671 ;; (with-eval-after-load 'smtpmail
672 ;; (csetq smtpmail-queue-mail t
673 ;; smtpmail-queue-dir (concat b/maildir "queue/")))
676 (require 'bandali-erc
)
678 ;; 'paste' service (aka scp + web server)
679 (add-to-list 'load-path
(b/lisp
"scpaste"))
680 (with-eval-after-load 'scpaste
681 (csetq scpaste-http-destination
"https://p.bndl.org"
682 scpaste-scp-destination
"p:~"))
683 (autoload 'scpaste
"scpaste" nil t
)
684 (autoload 'scpaste-region
"scpaste" nil t
)
685 (global-set-key (kbd "C-c a p p") #'scpaste
)
686 (global-set-key (kbd "C-c a p r") #'scpaste-region
)
691 ;; display Lisp objects at point in the echo area
692 (when (version< "25" emacs-version
)
693 (with-eval-after-load 'eldoc
694 (csetq eldoc-minor-mode-string
" eldoc")
695 (global-eldoc-mode)))
697 ;; highlight matching parens
701 ;; (require 'elec-pair)
702 ;; (electric-pair-mode)
705 ;; Save what I copy into clipboard from other applications into Emacs'
706 ;; kill-ring, which would allow me to still be able to easily access
707 ;; it in case I kill (cut or copy) something else inside Emacs before
708 ;; yanking (pasting) what I'd originally intended to.
709 save-interprogram-paste-before-kill t
)
710 (with-eval-after-load 'simple
711 (column-number-mode 1)
712 (line-number-mode 1))
714 ;; save minibuffer history
716 (csetq savehist-file
(b/var
"savehist.el"))
718 (add-to-list 'savehist-additional-variables
'kill-ring
)
720 ;; automatically save place in files
721 (when (version< "25" emacs-version
)
722 (csetq save-place-file
(b/var
"save-place.el"))
725 (defun indicate-buffer-boundaries-left ()
726 (csetq indicate-buffer-boundaries
'left
))
727 (with-eval-after-load 'prog-mode
728 (global-prettify-symbols-mode))
729 (add-hook 'prog-mode-hook
#'indicate-buffer-boundaries-left
)
731 (define-key text-mode-map
(kbd "C-<return>") #'b
/insert-asterism
)
732 (add-hook 'text-mode-hook
#'indicate-buffer-boundaries-left
)
733 (add-hook 'text-mode-hook
#'flyspell-mode
)
735 (add-to-list 'auto-mode-alist
'("\\.*rc$" . conf-mode
))
737 (add-to-list 'auto-mode-alist
'("\\.bashrc$" . sh-mode
))
739 (with-eval-after-load 'flyspell
740 (csetq flyspell-mode-line-string
" fly"))
743 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
744 ;; (run-with-idle-timer 0.6 nil #'require 'ispell)
745 ;; (with-eval-after-load 'ispell
746 ;; ;; ’ can be part of a word
747 ;; (csetq ispell-local-dictionary-alist
748 ;; `((nil "[[:alpha:]]" "[^[:alpha:]]"
749 ;; "['\x2019]" nil ("-B") nil utf-8))
750 ;; ispell-program-name (executable-find "hunspell"))
751 ;; ;; don't send ’ to the subprocess
752 ;; (defun endless/replace-apostrophe (args)
753 ;; (cons (replace-regexp-in-string
754 ;; "’" "'" (car args))
756 ;; (advice-add #'ispell-send-string :filter-args
757 ;; #'endless/replace-apostrophe)
758 ;; ;; convert ' back to ’ from the subprocess
759 ;; (defun endless/replace-quote (args)
760 ;; (if (not (derived-mode-p 'org-mode))
762 ;; (cons (replace-regexp-in-string
763 ;; "'" "’" (car args))
765 ;; (advice-add #'ispell-parse-output :filter-args
766 ;; #'endless/replace-quote))
769 (csetq abbrev-file-name
(b/etc
"abbrev.el"))
770 (add-hook 'text-mode-hook
#'abbrev-mode
)
773 ;;; Programming modes
775 (with-eval-after-load 'lisp-mode
776 (defun indent-spaces-mode ()
777 (setq indent-tabs-mode nil
))
778 (add-hook 'lisp-interaction-mode-hook
#'indent-spaces-mode
))
781 (add-to-list 'load-path
(b/lisp
"alloy-mode"))
782 (autoload 'alloy-mode
"alloy-mode" nil t
)
783 (with-eval-after-load 'alloy-mode
784 (csetq alloy-basic-offset
2)
785 ;; (defun b/alloy-simple-indent (start end)
787 ;; ;; (if (region-active-p)
788 ;; ;; (indent-rigidly start end alloy-basic-offset)
790 ;; ;; (indent-rigidly (line-beginning-position)
791 ;; ;; (line-end-position)
792 ;; ;; alloy-basic-offset)))
793 ;; (indent-to (+ (current-column) alloy-basic-offset)))
794 ;; local key bindings
795 (define-key alloy-mode-map
(kbd "RET") #'electric-newline-and-maybe-indent
)
796 ;; (define-key alloy-mode-map (kbd "TAB") #'b/alloy-simple-indent)
797 (define-key alloy-mode-map
(kbd "TAB") #'indent-for-tab-command
))
798 (add-to-list 'auto-mode-alist
'("\\.\\(als\\|dsh\\)\\'" . alloy-mode
))
799 (add-hook 'alloy-mode-hook
(lambda nil
(setq-local indent-tabs-mode nil
)))
802 ;; (eval-when-compile (defvar lean-mode-map))
803 ;; (run-with-idle-timer 0.4 nil #'require 'lean-mode)
804 ;; (with-eval-after-load 'lean-mode
805 ;; (require 'lean-input)
806 ;; (csetq default-input-method "Lean"
807 ;; lean-input-tweak-all '(lean-input-compose
808 ;; (lean-input-prepend "/")
809 ;; (lean-input-nonempty))
810 ;; lean-input-user-translations '(("/" "/")))
811 ;; (lean-input-setup)
812 ;; ;; local key bindings
813 ;; (define-key lean-mode-map (kbd "S-SPC") #'company-complete))
815 (with-eval-after-load 'sgml-mode
816 (csetq sgml-basic-offset
0))
818 (with-eval-after-load 'css-mode
819 (csetq css-indent-offset
2))
822 ;; (csetq font-latex-fontify-sectioning 'color)
824 (with-eval-after-load 'tex-mode
826 (lambda (p) (string-match "^---?" (car p
)))
827 tex--prettify-symbols-alist
))
828 (add-hook 'tex-mode-hook
#'auto-fill-mode
)
829 (add-hook 'tex-mode-hook
#'flyspell-mode
)
832 ;;; Emacs enhancements & auxiliary packages
834 (with-eval-after-load 'man
835 (csetq Man-width
80))
837 (defun b/*scratch
* ()
838 "Switch to `*scratch*' buffer, creating it if it does not exist."
841 (or (get-buffer "*scratch*")
842 (with-current-buffer (get-buffer-create "*scratch*")
843 (set-buffer-major-mode (current-buffer))
845 (global-set-key (kbd "C-c s") #'b
/*scratch
*)
848 ;; | make pretty boxed quotes like this
850 (add-to-list 'load-path
(b/lisp
"boxquote"))
851 (run-with-idle-timer 0.6 nil
#'require
'boxquote
)
852 (with-eval-after-load 'boxquote
853 (defvar b
/boxquote-prefix-map
)
854 (define-prefix-command 'b
/boxquote-prefix-map
)
855 (global-set-key (kbd "C-c q") 'b
/boxquote-prefix-map
)
856 (define-key b
/boxquote-prefix-map
(kbd "b") #'boxquote-buffer
)
857 (define-key b
/boxquote-prefix-map
(kbd "B") #'boxquote-insert-buffer
)
858 (define-key b
/boxquote-prefix-map
(kbd "d") #'boxquote-defun
)
859 (define-key b
/boxquote-prefix-map
(kbd "F") #'boxquote-insert-file
)
860 (define-key b
/boxquote-prefix-map
(kbd "hf") #'boxquote-describe-function
)
861 (define-key b
/boxquote-prefix-map
(kbd "hk") #'boxquote-describe-key
)
862 (define-key b
/boxquote-prefix-map
(kbd "hv") #'boxquote-describe-variable
)
863 (define-key b
/boxquote-prefix-map
(kbd "hw") #'boxquote-where-is
)
864 (define-key b
/boxquote-prefix-map
(kbd "k") #'boxquote-kill
)
865 (define-key b
/boxquote-prefix-map
(kbd "p") #'boxquote-paragraph
)
866 (define-key b
/boxquote-prefix-map
(kbd "q") #'boxquote-boxquote
)
867 (define-key b
/boxquote-prefix-map
(kbd "r") #'boxquote-region
)
868 (define-key b
/boxquote-prefix-map
(kbd "s") #'boxquote-shell-command
)
869 (define-key b
/boxquote-prefix-map
(kbd "t") #'boxquote-text
)
870 (define-key b
/boxquote-prefix-map
(kbd "T") #'boxquote-title
)
871 (define-key b
/boxquote-prefix-map
(kbd "u") #'boxquote-unbox
)
872 (define-key b
/boxquote-prefix-map
(kbd "U") #'boxquote-unbox-region
)
873 (define-key b
/boxquote-prefix-map
(kbd "y") #'boxquote-yank
)
874 (define-key b
/boxquote-prefix-map
(kbd "M-q") #'boxquote-fill-paragraph
)
875 (define-key b
/boxquote-prefix-map
(kbd "M-w") #'boxquote-kill-ring-save
))
877 (add-to-list 'load-path
(b/lisp
"hl-todo"))
878 (run-with-idle-timer 0.5 nil
#'require
'hl-todo
)
879 (with-eval-after-load 'hl-todo
880 ;; highlight TODOs in buffers
881 (global-hl-todo-mode))
884 (global-set-key (kbd "C-=") #'er
/expand-region
)
886 (run-with-idle-timer 0.6 nil
#'require
'yasnippet
)
887 (with-eval-after-load 'yasnippet
888 (declare-function yas-reload-all
889 "yasnippet" (&optional no-jit interactive
))
890 (declare-function yas-maybe-expand-abbrev-key-filter
893 (defconst yas-verbosity-cur yas-verbosity
)
894 (setq yas-verbosity
2)
895 (csetq yas-snippet-dirs
`(,(b/etc
"yasnippet/snippets")))
896 ;; (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets" t)
898 (setq yas-verbosity yas-verbosity-cur
)
900 (defun b/yas-maybe-expand-abbrev-key-filter
(cmd)
901 (when (and (yas-maybe-expand-abbrev-key-filter cmd
)
902 (not (bound-and-true-p git-commit-mode
)))
904 (defconst b
/yas-maybe-expand
905 '(menu-item "" yas-expand
906 :filter b
/yas-maybe-expand-abbrev-key-filter
))
907 (define-key yas-minor-mode-map
(kbd "SPC") b
/yas-maybe-expand
)
912 (global-set-key (kbd "C-c D d") #'debbugs-gnu
)
913 (global-set-key (kbd "C-c D b") #'debbugs-gnu-bugs
)
914 (global-set-key (kbd "C-c D e") ; bug-gnu-emacs
917 (setq debbugs-gnu-current-suppress t
)
918 (debbugs-gnu debbugs-gnu-default-severities
920 (global-set-key (kbd "C-c D g") ; bug-gnuzilla
923 (setq debbugs-gnu-current-suppress t
)
924 (debbugs-gnu debbugs-gnu-default-severities
929 url-configuration-directory
(b/var
"url/configuration/")
930 url-cache-directory
(b/var
"url/cache/"))
933 (csetq eww-download-directory
(file-name-as-directory
934 (getenv "XDG_DOWNLOAD_DIR")))
935 (global-set-key (kbd "C-c a e w") #'eww
)
939 ;; reftex-default-bibliography '("~/usr/org/references.bib")
940 ;; org-ref-default-bibliography '("~/usr/org/references.bib")
941 ;; org-ref-bibliography-notes "~/usr/org/notes.org"
942 ;; org-ref-pdf-directory "~/usr/org/bibtex-pdfs/")
944 ;; fill-column-indicator ?
947 (csetq split-width-threshold
150)
948 (global-set-key (kbd "C-c w s l")
953 (global-set-key (kbd "C-c w s j")
958 (global-set-key (kbd "C-c w q") #'quit-window
)
961 ;; (global-set-key (kbd "C-c a p") #'pass)
962 ;; (add-hook 'pass-mode-hook #'View-exit)
965 ;; uncomment to disable reftex-cite's default choice of previous word
966 ;; (with-eval-after-load 'reftex
967 ;; (require 'reftex-cite)
968 ;; (defun reftex-get-bibkey-default ()
969 ;; "If the cursor is in a citation macro, return the word before the macro."
970 ;; (let* ((macro (reftex-what-macro 1)))
972 ;; (when (and macro (string-match "cite" (car macro)))
973 ;; (goto-char (cdr macro)))
974 ;; (reftex-this-word)))))
975 (add-hook 'latex-mode-hook
#'reftex-mode
)
978 (add-to-list 'load-path
(b/lisp
"dmenu"))
979 (with-eval-after-load 'dmenu
980 (csetq dmenu-prompt-string
"run: "
981 dmenu-save-file
(b/var
"dmenu-items")))
982 (autoload 'dmenu
"dmenu" nil t
)
987 (run-with-idle-timer 0.5 nil
#'require
'delight
)
988 (with-eval-after-load 'delight
989 (delight 'auto-fill-function
" f" "simple")
990 (delight 'abbrev-mode
"" "abbrev")
991 (delight 'mml-mode
" mml" "mml")
992 (delight 'yas-minor-mode
"" "yasnippet"))
995 (require 'bandali-po
)
997 (with-eval-after-load 'emms
998 (csetq emms-directory
(b/var
"emms")))
1001 ;;; Post initialization
1003 (message "Loading %s...done (%.3fs)" user-init-file
1004 (float-time (time-subtract (current-time)
1005 b
/before-user-init-time
)))
1007 ;;; init.el ends here