1 ;;; init.el --- Amin Bandali's Emacs config -*- lexical-binding: t -*-
3 ;; Copyright (C) 2018 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 ;; Emacs configuration of Amin Bandali, computer scientist and functional
23 ;; THIS FILE IS AUTO-GENERATED FROM `init.org'.
25 ;; Naming conventions:
27 ;; amin-... public variables or non-interactive functions
28 ;; amin--... private anything (non-interactive), not safe for direct use
29 ;; amin/... an interactive function; safe for M-x or keybinding
30 ;; amin|... a hook function
31 ;; amin*... an advising function
32 ;; amin@... a hydra command
40 (defvar amin--before-user-init-time
(current-time)
41 "Value of `current-time' when Emacs begins loading `user-init-file'.")
42 (message "Loading Emacs...done (%.3fs)"
43 (float-time (time-subtract amin--before-user-init-time
46 (defvar amin--gc-cons-threshold gc-cons-threshold
)
47 (defvar amin--gc-cons-percentage gc-cons-percentage
)
48 (defvar amin--file-name-handler-alist file-name-handler-alist
)
49 (setq gc-cons-threshold
(* 400 1024 1024) ; 400 MiB
50 gc-cons-percentage
0.6
51 file-name-handler-alist nil
52 ;; sidesteps a bug when profiling with esup
53 esup-child-profile-require-level
0)
58 (setq gc-cons-threshold amin--gc-cons-threshold
59 gc-cons-percentage amin--gc-cons-percentage
60 file-name-handler-alist amin--file-name-handler-alist
)))
62 (setq message-log-max
20000)
64 ;; (setq byte-compile-warnings
65 ;; '(not free-vars unresolved noruntime lexical make-local))
67 (setq user-full-name
"Amin Bandali"
68 user-mail-address
"amin@aminb.org")
70 (setq package-enable-at-startup nil
)
71 ;; (package-initialize)
73 (setq user-init-file
(or load-file-name buffer-file-name
)
74 user-emacs-directory
(file-name-directory user-init-file
))
75 (add-to-list 'load-path
76 (expand-file-name "lib/borg" user-emacs-directory
))
80 ;; (require 'borg-nix-shell)
81 ;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
83 (with-eval-after-load 'bind-key
86 ("C-c b A" . borg-activate
)
87 ("C-c b a" . borg-assimilate
)
88 ("C-c b b" . borg-build
)
89 ("C-c b c" . borg-clone
)
90 ("C-c b r" . borg-remove
)))
92 (require 'use-package
)
93 (if nil
; set to t when need to debug init
94 (setq use-package-verbose t
95 use-package-expand-minimally nil
96 use-package-compute-statistics t
98 (setq use-package-verbose nil
99 use-package-expand-minimally t
))
104 (("C-c b d" . epkg-describe-package
)
105 ("C-c b p" . epkg-list-packages
)
106 ("C-c b u" . epkg-update
)))
108 (use-package no-littering
112 (add-to-list 'savehist-additional-variables
'kill-ring
)
114 (setq auto-save-file-name-transforms
115 `((".*" ,(no-littering-expand-var-file-name "auto-save/") t
))))
120 (setq custom-file
(no-littering-expand-etc-file-name "custom.el"))
121 (when (file-exists-p custom-file
)
123 (setf custom-safe-themes t
))
126 (load (no-littering-expand-etc-file-name "secrets")))
128 (use-package exec-path-from-shell
131 (setq exec-path-from-shell-check-startup-files nil
)
133 (exec-path-from-shell-initialize)
134 ;; while we're at it, let's fix access to our running ssh-agent
135 (exec-path-from-shell-copy-env "SSH_AGENT_PID")
136 (exec-path-from-shell-copy-env "SSH_AUTH_SOCK"))
138 ;; only one custom theme at a time
140 ;; (defadvice load-theme (before clear-previous-themes activate)
141 ;; "Clear existing theme settings instead of layering them"
142 ;; (mapc #'disable-theme custom-enabled-themes))
146 :config
(or (server-running-p) (server-mode)))
150 ;; (dolist (ft (fontset-list))
154 ;; (font-spec :name "Source Code Pro" :size 14))
158 ;; (font-spec :name "DejaVu Sans Mono")
161 ;; ;; (set-fontset-font
165 ;; ;; :name "Symbola monospacified for DejaVu Sans Mono")
168 ;; ;; (set-fontset-font
171 ;; ;; (font-spec :name "DejaVu Sans Mono")
177 ;; (font-spec :name "DejaVu Sans Mono" :size 14)
181 (setq text-scale-mode-step
1.05)
183 (setq mouse-autoselect-window t
)
185 (defun amin--no-mouse-autoselect-window ()
186 (make-local-variable 'mouse-autoselect-window
)
187 (setq mouse-autoselect-window nil
))
192 (defun amin-enlist (exp)
193 "Return EXP wrapped in a list, or as-is if already a list."
194 (if (listp exp
) exp
(list exp
)))
196 ; from https://github.com/hlissner/doom-emacs/commit/589108fdb270f24a98ba6209f6955fe41530b3ef
197 (defmacro after
! (features &rest body
)
198 "A smart wrapper around `with-eval-after-load'. Supresses warnings during
200 (declare (indent defun
) (debug t
))
201 (list (if (or (not (bound-and-true-p byte-compile-current-file
))
202 (dolist (next (amin-enlist features
))
204 (require next nil
:no-error
)
205 (load next
:no-message
:no-error
))))
208 (cond ((symbolp features
)
209 `(eval-after-load ',features
'(progn ,@body
)))
210 ((and (consp features
)
211 (memq (car features
) '(:or
:any
)))
213 ,@(cl-loop for next in
(cdr features
)
214 collect
`(after! ,next
,@body
))))
215 ((and (consp features
)
216 (memq (car features
) '(:and
:all
)))
217 (dolist (next (cdr features
))
218 (setq body
`(after! ,next
,@body
)))
221 `(after! (:all
,@features
) ,@body
)))))
223 (defmacro setq-every
! (value &rest vars
)
224 "Set all the variables from VARS to value VALUE."
225 (declare (indent defun
) (debug t
))
226 `(progn ,@(mapcar (lambda (x) (list 'setq x value
)) vars
)))
231 ;; (fringe-mode '(3 . 1))
234 (setq disabled-command-function nil
)
236 (setq save-interprogram-paste-before-kill t
)
238 (setq enable-recursive-minibuffers t
239 resize-mini-windows t
)
241 (defalias 'yes-or-no-p
#'y-or-n-p
)
243 (setq initial-buffer-choice t
)
245 (setq initial-scratch-message nil
)
247 (setq initial-major-mode
'text-mode
)
249 (setq inhibit-startup-buffer-menu t
)
251 (advice-add #'display-startup-echo-area-message
:override
#'ignore
)
252 (setq inhibit-startup-screen t
253 inhibit-startup-echo-area-message user-login-name
)
255 (setq frame-title-format
256 '("" invocation-name
" - "
257 (:eval
(if (buffer-file-name)
258 (abbreviate-file-name (buffer-file-name))
261 (setq backup-by-copying t
263 delete-old-versions t
)
265 (global-auto-revert-mode 1)
266 (setq auto-revert-verbose nil
267 global-auto-revert-non-file-buffers nil
)
271 require-final-newline t
276 (setq compilation-exit-message-function
277 (lambda (status code msg
)
278 "Close the compilation window if successful."
279 ;; if M-x compile exits with 0
280 (when (and (eq status
'exit
) (zerop code
))
282 (delete-window (get-buffer-window (get-buffer "*compilation*"))))
283 ;; return the result of compilation-exit-message-function
286 (setq search-default-mode
#'char-fold-to-regexp
)
288 ;; uncomment to extend this behaviour to query-replace
289 ;; (setq replace-char-fold t)
294 ("C-c e b" . eval-buffer
)
295 ("C-c e r" . eval-region
)
297 ("C-c F m" . make-frame-command
)
298 ("C-c F d" . delete-frame
)
299 ("C-c F D" . delete-other-frames
)
301 ("C-c o" . other-window
)
303 ("C-c Q" . save-buffers-kill-terminal
)
305 ("C-S-h C" . describe-char
)
306 ("C-S-h F" . describe-face
)
308 ("C-x K" . kill-this-buffer
)
310 ("s-p" . beginning-of-buffer
)
311 ("s-n" . end-of-buffer
))
313 (use-package auto-compile
316 (auto-compile-on-load-mode)
317 (auto-compile-on-save-mode)
318 (setq auto-compile-display-buffer nil
319 auto-compile-mode-line-counter t
320 auto-compile-source-recreate-deletes-dest t
321 auto-compile-toggle-deletes-nonlib-dest t
322 auto-compile-update-autoloads t
)
323 (add-hook 'auto-compile-inhibit-compile-hook
324 'auto-compile-inhibit-compile-detached-git-head
))
329 (setq org-src-tab-acts-natively t
330 org-src-preserve-indentation nil
331 org-edit-src-content-indentation
0
332 org-email-link-description-format
"Email %c: %s" ; %.30s
333 org-highlight-latex-and-related
'(entities)
335 (add-to-list 'org-structure-template-alist
'("L" .
"src emacs-lisp") t
)
336 (font-lock-add-keywords
338 '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
339 (1 '(:foreground
"#5a5b5a" :background
"#292b2b") t
) ; directive
340 (3 '(:foreground
"#81a2be" :background
"#292b2b") t
) ; kind
341 (4 '(:foreground
"#c5c8c6") t
))) ; title
343 :bind
(:map org-mode-map
("M-L" . org-insert-last-stored-link
))
344 :hook
((org-mode . org-indent-mode
)
345 (org-mode . auto-fill-mode
)
346 (org-mode . flyspell-mode
))
348 (org-latex-packages-alist '(("" "listings") ("" "color")))
350 '(org-block-begin-line ((t (:foreground
"#5a5b5a" :background
"#1d1f21"))))
351 '(org-block ((t (:background
"#1d1f21"))))
352 '(org-latex-and-related ((t (:foreground
"#b294bb")))))
354 (use-package ox-latex
357 (setq org-latex-listings
'listings
358 ;; org-latex-prefer-user-labels t
360 (add-to-list 'org-latex-packages-alist
'("" "listings"))
361 (add-to-list 'org-latex-packages-alist
'("" "color"))
362 (add-to-list 'org-latex-classes
363 '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
364 ("\\section{%s}" .
"\\section*{%s}")
365 ("\\subsection{%s}" .
"\\subsection*{%s}")
366 ("\\subsubsection{%s}" .
"\\subsubsection*{%s}")
367 ("\\paragraph{%s}" .
"\\paragraph*{%s}")
368 ("\\subparagraph{%s}" .
"\\subparagraph*{%s}"))
371 (use-package ox-beamer
374 (use-package orgalist
376 :hook
(message-mode . orgalist-mode
))
379 (defvar amin-show-async-tangle-results nil
380 "Keep *emacs* async buffers around for later inspection.")
382 (defvar amin-show-async-tangle-time nil
383 "Show the time spent tangling the file.")
385 (defvar amin-async-tangle-post-compile
"make ti"
386 "If non-nil, pass to `compile' after successful tangle.")
388 (defun amin/async-babel-tangle
()
389 "Tangle org file asynchronously."
391 (let* ((file-tangle-start-time (current-time))
392 (file (buffer-file-name))
393 (file-nodir (file-name-nondirectory file
))
394 (async-quiet-switch "-q"))
398 (org-babel-tangle-file ,file
))
399 (unless amin-show-async-tangle-results
403 (message "Tangled %s%s"
405 (if amin-show-async-tangle-time
407 (float-time (time-subtract (current-time)
408 ',file-tangle-start-time
)))
410 (when amin-async-tangle-post-compile
411 (compile amin-async-tangle-post-compile
)))
412 (message "Tangling %s failed" ,file-nodir
))))))))
415 'safe-local-variable-values
416 '(eval add-hook
'after-save-hook
#'amin
/async-babel-tangle
'append
'local
))
420 :bind
(("C-x g" . magit-status
)
421 ("s-g s" . magit-status
)
422 ("s-g l" . magit-log-buffer-file
))
424 (magit-add-section-hook 'magit-status-sections-hook
425 'magit-insert-modules
426 'magit-insert-stashes
429 magit-repository-directories
'(("~/.emacs.d/" .
0)
431 (nconc magit-section-initial-visibility-alist
432 '(([unpulled status
] . show
)
433 ([unpushed status
] . show
)))
434 :custom-face
(magit-diff-file-heading ((t (:weight normal
)))))
439 (:map ivy-minibuffer-map
440 ([escape] . keyboard-escape-quit)
441 ([S-up] . ivy-previous-history-element)
442 ([S-down] . ivy-next-history-element)
443 ("DEL" . ivy-backward-delete-char))
448 ;; (ivy-minibuffer-match-face-2 ((t (:background "#e99ce8" :weight semi-bold))))
449 ;; (ivy-minibuffer-match-face-3 ((t (:background "#bbbbff" :weight semi-bold))))
450 ;; (ivy-minibuffer-match-face-4 ((t (:background "#ffbbff" :weight semi-bold))))
454 :bind (("C-s" . swiper)
459 :bind (([remap execute-extended-command] . counsel-M-x)
460 ([remap find-file] . counsel-find-file)
461 ("s-r" . counsel-recentf)
462 ("C-c x" . counsel-M-x)
463 ("C-c f ." . counsel-find-file)
464 :map minibuffer-local-map
465 ("C-r" . counsel-minibuffer-history))
468 (defalias 'locate #'counsel-locate))
474 (eval-when-compile (defvar eshell-prompt-regexp))
475 (defun amin/eshell-quit-or-delete-char (arg)
477 (if (and (eolp) (looking-back eshell-prompt-regexp nil))
478 (eshell-life-is-too-much)
481 (defun amin/eshell-clear ()
483 (let ((inhibit-read-only t))
487 (defun amin|eshell-setup ()
488 (make-local-variable 'company-idle-delay)
489 (setq company-idle-delay nil)
490 (bind-keys :map eshell-mode-map
491 ("C-d" . amin/eshell-quit-or-delete-char)
492 ("C-S-l" . amin/eshell-clear)
493 ("M-r" . counsel-esh-history)
494 ([tab] . company-complete)))
496 :hook (eshell-mode . amin|eshell-setup)
498 (eshell-hist-ignoredups t)
499 (eshell-input-filter 'eshell-input-filter-initial-space))
504 (("C-x C-b" . ibuffer-other-window)
505 :map ibuffer-mode-map
506 ("P" . ibuffer-backward-filter-group)
507 ("N" . ibuffer-forward-filter-group)
508 ("M-p" . ibuffer-do-print)
509 ("M-n" . ibuffer-do-shell-command-pipe-replace))
511 ;; Use human readable Size column instead of original one
512 (define-ibuffer-column size-h
513 (:name "Size" :inline t)
515 ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
516 ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
517 ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
518 (t (format "%8d" (buffer-size)))))
520 (ibuffer-saved-filter-groups
522 ("dired" (mode . dired-mode))
523 ("org" (mode . org-mode))
533 (mode . shell-mode)))
534 ("notmuch" (name . "\*notmuch\*"))
539 (mode . emacs-lisp-mode)))
542 (name . "^\\*scratch\\*$")
543 (name . "^\\*Messages\\*$")))
546 (name . "^\\*Slack*"))))))
548 '((mark modified read-only locked " "
549 (name 18 18 :left :elide)
553 (mode 16 16 :left :elide)
554 " " filename-and-process)
558 :hook (ibuffer . (lambda () (ibuffer-switch-to-saved-filter-groups "default"))))
562 :hook (prog-mode . outline-minor-mode)
565 outline-minor-mode-map
566 ("<s-tab>" . outline-toggle-children)
567 ("M-p" . outline-previous-visible-heading)
568 ("M-n" . outline-next-visible-heading)
569 :prefix-map amin--outline-prefix-map
571 ("TAB" . outline-toggle-children)
572 ("a" . outline-hide-body)
573 ("H" . outline-hide-body)
574 ("S" . outline-show-all)
575 ("h" . outline-hide-subtree)
576 ("s" . outline-show-subtree)))
579 ;; * Borg's `layer/essentials'
582 :config (dash-enable-font-lock))
586 (setq diff-hl-draw-borders nil)
587 (global-diff-hl-mode)
588 (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh t))
592 :config (setq dired-listing-switches "-alh"))
595 :when (version< "25" emacs-version)
596 :config (global-eldoc-mode))
601 (temp-buffer-resize-mode)
602 (setq help-window-select t))
605 (setq isearch-allow-scroll t))
607 (use-package lisp-mode
609 (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
610 (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
611 (defun indent-spaces-mode ()
612 (setq indent-tabs-mode nil))
613 (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
617 :config (setq Man-width 80))
620 :config (show-paren-mode))
622 (use-package prog-mode
623 :config (global-prettify-symbols-mode)
624 (defun indicate-buffer-boundaries-left ()
625 (setq indicate-buffer-boundaries 'left))
626 (add-hook 'prog-mode-hook #'indicate-buffer-boundaries-left))
631 (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
632 (setq recentf-max-saved-items 40))
634 (use-package savehist
635 :config (savehist-mode))
637 (use-package saveplace
638 :when (version< "25" emacs-version)
639 :config (save-place-mode))
642 :config (column-number-mode))
645 (add-hook 'text-mode-hook #'indicate-buffer-boundaries-left)
646 (add-hook 'text-mode-hook #'abbrev-mode))
651 (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
652 (add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
653 (add-to-list 'tramp-default-proxies-alist
654 (list (regexp-quote (system-name)) nil nil)))
662 (:map company-active-map
663 ([tab] . company-complete-common-or-cycle)
664 ([escape] . company-abort
))
666 (company-minimum-prefix-length 1)
667 (company-selection-wrap-around t
)
668 (company-dabbrev-char-regexp "\\sw\\|\\s_\\|[-_]")
669 (company-dabbrev-downcase nil
)
670 (company-dabbrev-ignore-case nil
)
672 (global-company-mode t
))
675 ;; * Syntax and spell checking
677 (use-package flycheck
679 :hook
(prog-mode . flycheck-mode
)
681 (:map flycheck-mode-map
682 ("M-P" . flycheck-previous-error
)
683 ("M-N" . flycheck-next-error
))
685 ;; Use the load-path from running Emacs when checking elisp files
686 (setq flycheck-emacs-lisp-load-path
'inherit
)
688 ;; Only flycheck when I actually save the buffer
689 (setq flycheck-check-syntax-automatically
'(mode-enabled save
)))
691 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
695 ;; ’ can be part of a word
696 (setq ispell-local-dictionary-alist
697 `((nil "[[:alpha:]]" "[^[:alpha:]]"
698 "['\x2019]" nil
("-B") nil utf-8
)))
699 ;; don't send ’ to the subprocess
700 (defun endless/replace-apostrophe
(args)
701 (cons (replace-regexp-in-string
704 (advice-add #'ispell-send-string
:filter-args
705 #'endless
/replace-apostrophe
)
707 ;; convert ' back to ’ from the subprocess
708 (defun endless/replace-quote
(args)
709 (if (not (derived-mode-p 'org-mode
))
711 (cons (replace-regexp-in-string
714 (advice-add #'ispell-parse-output
:filter-args
715 #'endless
/replace-quote
))
718 ;; * Programming modes
720 (use-package alloy-mode
722 :config
(setq alloy-basic-offset
2))
724 (use-package proof-site
; Proof General
726 :load-path
"lib/proof-site/generic/")
728 (eval-when-compile (defvar lean-mode-map
))
729 (use-package lean-mode
731 :bind
(:map lean-mode-map
732 ("S-SPC" . company-complete
))
734 (require 'lean-input
)
735 (setq default-input-method
"Lean"
736 lean-input-tweak-all
'(lean-input-compose
737 (lean-input-prepend "/")
738 (lean-input-nonempty))
739 lean-input-user-translations
'(("/" "/")))
742 (use-package haskell-mode
745 (setq haskell-indentation-layout-offset
4
746 haskell-indentation-left-offset
4
747 flycheck-checker
'haskell-hlint
748 flycheck-disabled-checkers
'(haskell-stack-ghc haskell-ghc
)))
753 :hook
(haskell-mode . dante-mode
))
755 (use-package hlint-refactor
757 :bind
(:map hlint-refactor-mode-map
758 ("C-c l b" . hlint-refactor-refactor-buffer
)
759 ("C-c l r" . hlint-refactor-refactor-at-point
))
760 :hook
(haskell-mode . hlint-refactor-mode
))
762 (use-package flycheck-haskell
765 (use-package sgml-mode
768 (setq sgml-basic-offset
2))
770 (use-package css-mode
773 (setq css-indent-offset
2))
775 (use-package web-mode
780 web-mode-code-indent-offset
781 web-mode-css-indent-offset
782 web-mode-markup-indent-offset
))
784 (use-package emmet-mode
785 :after
(:any web-mode css-mode sgml-mode
)
786 :bind
* (("C-)" . emmet-next-edit-point
)
787 ("C-(" . emmet-prev-edit-point
))
789 (unbind-key "C-j" emmet-mode-keymap
)
790 (setq emmet-move-cursor-between-quotes t
)
791 :hook
(web-mode css-mode html-mode sgml-mode
))
793 (use-package nix-mode
798 ;; * Emacs Enhancements
800 (use-package which-key
802 :config
(which-key-mode))
804 (add-to-list 'custom-theme-load-path
"~/.emacs.d/lisp")
805 (load-theme 'tangomod t
)
807 (use-package doom-modeline
809 :config
(setq doom-modeline-height
32)
810 :hook
(after-init . doom-modeline-init
))
812 (use-package doom-themes
)
814 (defun amin/lights-on
()
815 "Enable my favourite light theme."
818 (mapc #'disable-theme custom-enabled-themes
)
819 (load-theme 'tangomod t
)))
821 (defun amin/lights-off
()
825 (mapc #'disable-theme custom-enabled-themes
)
826 (load-theme 'doom-tomorrow-night t
)))
829 ("s-t d" . amin
/lights-off
)
830 ("s-t l" . amin
/lights-on
))
834 :bind
(("C-c b k" . crux-kill-other-buffers
)
835 ("C-c d" . crux-duplicate-current-line-or-region
)
836 ("C-c D" . crux-duplicate-and-comment-current-line-or-region
)
837 ("C-c f c" . crux-copy-file-preserve-attributes
)
838 ("C-c f d" . crux-delete-file-and-buffer
)
839 ("C-c f r" . crux-rename-file-and-buffer
)
840 ("C-c j" . crux-top-join-line
)
841 ("C-S-j" . crux-top-join-line
)))
844 :bind
(("C-a" . mwim-beginning-of-code-or-line
)
845 ("C-e" . mwim-end-of-code-or-line
)
846 ("<home>" . mwim-beginning-of-line-or-code
)
847 ("<end>" . mwim-end-of-line-or-code
)))
849 (use-package projectile
851 :bind-keymap
("C-c p" . projectile-command-map
)
855 (defun my-projectile-invalidate-cache (&rest _args
)
856 ;; ignore the args to `magit-checkout'
857 (projectile-invalidate-cache nil
))
859 (eval-after-load 'magit-branch
861 (advice-add 'magit-checkout
862 :after
#'my-projectile-invalidate-cache
)
863 (advice-add 'magit-branch-and-checkout
864 :after
#'my-projectile-invalidate-cache
))))
869 (("C-S-h c" . helpful-command
)
870 ("C-S-h f" . helpful-callable
) ; helpful-function
871 ("C-S-h v" . helpful-variable
)
872 ("C-S-h k" . helpful-key
)
873 ("C-S-h p" . helpful-at-point
)))
875 (use-package shell-toggle
877 :bind
("C-c a s e" . amin
/shell-toggle
)
879 (defun amin/shell-toggle
(make-cd)
880 "Toggle between the shell buffer and whatever buffer you are editing.
881 With a prefix argument MAKE-CD also insert a \"cd DIR\" command
882 into the shell, where DIR is the directory of the current buffer.
884 When called in the shell buffer returns you to the buffer you were editing
885 before calling this the first time.
887 Options: `shell-toggle-goto-eob'"
889 ;; Try to decide on one of three possibilities:
890 ;; If not in shell-buffer, switch to it.
891 ;; If in shell-buffer, return to state before going to the shell-buffer
892 (if (eq (current-buffer) shell-toggle-shell-buffer
)
893 (shell-toggle-buffer-return-from-shell)
895 (shell-toggle-buffer-goto-shell make-cd
)
896 (if shell-toggle-full-screen-window-only
(delete-other-windows)))))
898 ;; override to split horizontally instead
899 (defun shell-toggle-buffer-switch-to-other-window ()
900 "Switch to other window.
901 If the current window is the only window in the current frame,
902 create a new window and switch to it.
904 \(This is less intrusive to the current window configuration than
905 `switch-buffer-other-window')"
906 (let ((this-window (selected-window)))
908 ;; If we did not switch window then we only have one window and need to
910 (if (eq this-window
(selected-window))
912 (split-window-horizontally)
916 (shell-toggle-launch-shell 'shell-toggle-eshell
))
918 (use-package unkillable-scratch
921 (unkillable-scratch 1)
923 (unkillable-scratch-behavior 'do-nothing
)
924 (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
926 (use-package boxquote
929 (:prefix-map amin--boxquote-prefix-map
931 ("b" . boxquote-buffer
)
932 ("B" . boxquote-insert-buffer
)
933 ("d" . boxquote-defun
)
934 ("F" . boxquote-insert-file
)
935 ("hf" . boxquote-describe-function
)
936 ("hk" . boxquote-describe-key
)
937 ("hv" . boxquote-describe-variable
)
938 ("hw" . boxquote-where-is
)
939 ("k" . boxquote-kill
)
940 ("p" . boxquote-paragraph
)
941 ("q" . boxquote-boxquote
)
942 ("r" . boxquote-region
)
943 ("s" . boxquote-shell-command
)
944 ("t" . boxquote-text
)
945 ("T" . boxquote-title
)
946 ("u" . boxquote-unbox
)
947 ("U" . boxquote-unbox-region
)
948 ("y" . boxquote-yank
)
949 ("M-q" . boxquote-fill-paragraph
)
950 ("M-w" . boxquote-kill-ring-save
)))
952 (use-package highlight-indent-guides
955 :hook
((prog-mode . highlight-indent-guides-mode
)
956 ;; (org-mode . highlight-indent-guides-mode)
959 (setq highlight-indent-guides-character ?\|
)
960 (setq highlight-indent-guides-auto-enabled nil
)
961 (setq highlight-indent-guides-method
'character
)
962 (setq highlight-indent-guides-responsive
'top
)
963 (set-face-foreground 'highlight-indent-guides-character-face
"gainsboro")
964 (set-face-foreground 'highlight-indent-guides-top-character-face
"grey40")) ; grey13 is nice too
966 (use-package pdf-tools
968 :magic
("%PDF" . pdf-view-mode
)
970 (setq pdf-view-resize-factor
1.05)
973 (:map pdf-view-mode-map
974 ("C-s" . isearch-forward
)
975 ("C-r" . isearch-backward
)
976 ("j" . pdf-view-next-line-or-next-page
)
977 ("k" . pdf-view-previous-line-or-previous-page
)
978 ("h" . image-backward-hscroll
)
979 ("l" . image-forward-hscroll
)))
987 :hook
(text-mode . typo-mode
))
992 (global-hl-todo-mode))
994 (use-package shrink-path
997 (setq eshell-prompt-regexp
"\\(.*\n\\)*λ "
998 eshell-prompt-function
#'+eshell
/prompt
)
1000 (defun +eshell
/prompt
()
1001 (let ((base/dir
(shrink-path-prompt default-directory
)))
1002 (concat (propertize (car base
/dir
)
1003 'face
'font-lock-comment-face
)
1004 (propertize (cdr base
/dir
)
1005 'face
'font-lock-constant-face
)
1006 (propertize (+eshell--current-git-branch
)
1007 'face
'font-lock-function-name-face
)
1009 (propertize "λ" 'face
'eshell-prompt-face
)
1010 ;; needed for the input text to not have prompt face
1011 (propertize " " 'face
'default
))))
1013 (defun +eshell--current-git-branch
()
1014 (let ((branch (car (loop for match in
(split-string (shell-command-to-string "git branch") "\n")
1015 when
(string-match "^\*" match
)
1017 (if (not (eq branch nil
))
1018 (concat " " (substring branch
2))
1023 :commands
(slack-start)
1025 (eval-when-compile ; silence the byte-compiler
1026 (defvar url-http-data nil
)
1027 (defvar url-http-extra-headers nil
)
1028 (defvar url-http-method nil
)
1029 (defvar url-callback-function nil
)
1030 (defvar url-callback-arguments nil
)
1031 (defvar oauth--token-data nil
))
1032 (setq slack-buffer-emojify t
1033 slack-prefer-current-team t
)
1035 (slack-register-team
1038 :client-id uw-apv-client-id
1039 :client-secret uw-apv-client-secret
1041 :subscribed-channels
'(general)
1042 :full-and-display-names t
)
1043 (slack-register-team
1046 :client-id watform-client-id
1047 :client-secret watform-client-secret
1048 :token watform-token
1049 :subscribed-channels
'(general)
1050 :full-and-display-names t
)
1051 (add-to-list 'swiper-font-lock-exclude
'slack-message-buffer-mode t
)
1052 (setq lui-time-stamp-format
"[%Y-%m-%d %H:%M:%S]"
1053 lui-time-stamp-only-when-changed-p t
1054 lui-time-stamp-position
'right
)
1056 (("C-c s s" . slack-start
)
1057 ("C-c s u" . slack-select-unread-rooms
)
1058 ("C-c s b" . slack-select-rooms
)
1059 ("C-c s t" . slack-change-current-team
)
1060 ("C-c s c" . slack-ws-close
)
1062 ("M-p" . slack-buffer-goto-prev-message
)
1063 ("M-n" . slack-buffer-goto-next-message
)
1064 ("C-c e" . slack-message-edit
)
1065 ("C-c k" . slack-message-delete
)
1066 ("C-c C-k" . slack-channel-leave
)
1067 ("C-c r a" . slack-message-add-reaction
)
1068 ("C-c r r" . slack-message-remove-reaction
)
1069 ("C-c r s" . slack-message-show-reaction-users
)
1070 ("C-c p l" . slack-room-pins-list
)
1071 ("C-c p a" . slack-message-pins-add
)
1072 ("C-c p r" . slack-message-pins-remove
)
1073 ("@" . slack-message-embed-mention
)
1074 ("#" . slack-message-embed-channel
)))
1079 (setq alert-default-style
'notifier
))
1081 (use-package eshell-up
1084 (use-package multi-term
1086 :bind
(("C-c C-j" . term-line-mode
)
1087 ("C-c a s m m" . multi-term
)
1088 ("C-c a s m p" . multi-term-dedicated-toggle
))
1090 (setq multi-term-program
"/bin/screen"
1091 ;; TODO: add separate bindings for connecting to existing
1092 ;; session vs. always creating a new one
1093 multi-term-dedicated-select-after-open-p t
1094 multi-term-dedicated-window-height
20
1095 multi-term-dedicated-max-window-height
30
1097 '(("C-c C-c" . term-interrupt-subjob
)
1098 ("C-c C-e" . term-send-esc
)
1100 ("C-y" . term-paste
)
1101 ("M-f" . term-send-forward-word
)
1102 ("M-b" . term-send-backward-word
)
1103 ("M-p" . term-send-up
)
1104 ("M-n" . term-send-down
)
1105 ("<C-backspace>" . term-send-backward-kill-word
)
1106 ("<M-DEL>" . term-send-backward-kill-word
)
1107 ("M-d" . term-send-delete-word
)
1108 ("M-," . term-send-raw
)
1109 ("M-." . comint-dynamic-complete
))
1110 term-unbind-key-alist
1111 '("C-z" "C-x" "C-c" "C-h" "C-y" "<ESC>")))
1113 (use-package page-break-lines
1115 (global-page-break-lines-mode))
1120 (defvar amin-maildir
(expand-file-name "~/mail/"))
1122 (add-to-list 'recentf-exclude amin-maildir
))
1125 amin-gnus-init-file
(no-littering-expand-etc-file-name "gnus")
1126 mail-user-agent
'gnus-user-agent
1127 read-mail-command
'gnus
)
1130 :bind
(("s-m" . gnus
)
1131 ("s-M" . gnus-unplugged
))
1134 gnus-select-method
'(nnnil "")
1135 gnus-secondary-select-methods
1137 (nnimap-stream plain
)
1138 (nnimap-address "127.0.0.1")
1139 (nnimap-server-port 143)
1140 (nnimap-authenticator plain
)
1141 (nnimap-user "amin@aminb.org"))
1143 (nnimap-stream plain
)
1144 (nnimap-address "127.0.0.1")
1145 (nnimap-server-port 143)
1146 (nnimap-authenticator plain
)
1147 (nnimap-user "abandali@uwaterloo.ca")))
1148 gnus-message-archive-group
"nnimap+amin:Sent"
1152 gnus-large-newsgroup
50
1153 gnus-home-directory
(no-littering-expand-var-file-name "gnus/")
1154 gnus-directory
(concat gnus-home-directory
"news/")
1155 message-directory
(concat gnus-home-directory
"mail/")
1156 nndraft-directory
(concat gnus-home-directory
"drafts/")
1157 gnus-save-newsrc-file nil
1158 gnus-read-newsrc-file nil
1159 gnus-interactive-exit nil
1160 gnus-gcc-mark-as-read t
))
1162 (use-package gnus-art
1165 gnus-visible-headers
1166 (concat gnus-visible-headers
"\\|^List-Id:\\|^X-RT-Originator:\\|^User-Agent:")
1167 gnus-sorted-header-list
1168 '("^From:" "^Subject:" "^Summary:" "^Keywords:"
1169 "^Followup-To:" "^To:" "^Cc:" "X-RT-Originator"
1170 "^Newsgroups:" "List-Id:" "^Organization:"
1171 "^User-Agent:" "^Date:")
1172 ;; local-lapsed article dates
1173 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
1174 gnus-article-date-headers
'(user-defined)
1175 gnus-article-time-format
1177 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time
))
1178 (local (article-make-date-line date
'local
))
1179 (combined-lapsed (article-make-date-line date
1182 (string-match " (.+" combined-lapsed
)
1183 (match-string 0 combined-lapsed
))))
1184 (concat local lapsed
))))
1186 :map gnus-article-mode-map
1187 ("r" . gnus-article-reply-with-original
)
1188 ("R" . gnus-article-wide-reply-with-original
)
1189 ("M-L" . org-store-link
)))
1191 (use-package gnus-sum
1192 :bind
(:map gnus-summary-mode-map
1193 :prefix-map amin--gnus-summary-prefix-map
1195 ("r" . gnus-summary-reply
)
1196 ("w" . gnus-summary-wide-reply
)
1197 ("v" . gnus-summary-show-raw-article
))
1200 :map gnus-summary-mode-map
1201 ("r" . gnus-summary-reply-with-original
)
1202 ("R" . gnus-summary-wide-reply-with-original
)
1203 ("M-L" . org-store-link
))
1204 :hook
(gnus-summary-mode . amin--no-mouse-autoselect-window
))
1206 (use-package gnus-msg
1208 (setq gnus-posting-styles
1210 (address "amin@aminb.org")
1211 (body "\nBest,\namin\n")
1212 (eval (setq amin--message-cite-say-hi t
)))
1214 (address "bandali@gnu.org"))
1215 ((header "subject" "ThankCRM")
1216 (to "webmasters-comment@gnu.org")
1217 (body "\nAdded to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
1218 (eval (setq amin--message-cite-say-hi nil
)))
1219 ("nnimap\\+uwaterloo:.*"
1220 (address "abandali@uwaterloo.ca")
1221 (gcc "\"nnimap+uwaterloo:Sent Items\"")))))
1223 (use-package gnus-topic
1224 :hook
(gnus-group-mode . gnus-topic-mode
))
1226 (use-package gnus-agent
1228 (setq gnus-agent-synchronize-flags
'ask
)
1229 :hook
(gnus-group-mode . gnus-agent-mode
))
1231 (use-package gnus-group
1233 (setq gnus-permanently-visible-groups
"\\((INBOX\\|gnu$\\)"))
1235 (use-package mm-decode
1237 (setq mm-discouraged-alternatives
'("text/html" "text/richtext")))
1239 (use-package sendmail
1241 (setq sendmail-program
"/usr/bin/msmtp"
1242 ;; message-sendmail-extra-arguments '("-v" "-d")
1243 mail-specify-envelope-from t
1244 mail-envelope-from
'header
))
1246 (use-package message
1248 (defconst amin--message-cite-style-format
"On %Y-%m-%d %l:%M %p, %N wrote:")
1249 (defconst message-cite-style-bandali
1250 '((message-cite-function 'message-cite-original
)
1251 (message-citation-line-function 'message-insert-formatted-citation-line
)
1252 (message-cite-reply-position 'traditional
)
1253 (message-yank-prefix "> ")
1254 (message-yank-cited-prefix ">")
1255 (message-yank-empty-prefix ">")
1256 (message-citation-line-format
1257 (if amin--message-cite-say-hi
1258 (concat "Hi %F,\n\n" amin--message-cite-style-format
)
1259 amin--message-cite-style-format
)))
1260 "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.")
1261 (setq message-cite-style
'message-cite-style-bandali
1262 message-kill-buffer-on-exit t
1263 message-send-mail-function
'message-send-mail-with-sendmail
1264 message-sendmail-envelope-from
'header
1265 message-dont-reply-to-names
1266 "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)"
1267 message-user-fqdn
"aminb.org")
1268 :hook
(;; (message-setup . mml-secure-message-sign-pgpmime)
1269 (message-mode . flyspell-mode
)
1270 (message-mode .
(lambda ()
1271 ;; (setq fill-column 65
1272 ;; message-fill-column 65)
1273 (make-local-variable 'company-idle-delay
)
1274 (setq company-idle-delay
0.2))))
1276 ;; (message-header-subject ((t (:foreground "#111" :weight semi-bold))))
1277 ;; (message-header-to ((t (:foreground "#111" :weight normal))))
1278 ;; (message-header-cc ((t (:foreground "#333" :weight normal))))
1282 (setq mml-secure-openpgp-encrypt-to-self t
1283 mml-secure-openpgp-sign-with-sender t
))
1285 (use-package footnote
1288 (:map message-mode-map
1289 :prefix-map amin--footnote-prefix-map
1291 ("a" . footnote-add-footnote
)
1292 ("b" . footnote-back-to-message
)
1293 ("c" . footnote-cycle-style
)
1294 ("d" . footnote-delete-footnote
)
1295 ("g" . footnote-goto-footnote
)
1296 ("r" . footnote-renumber-footnotes
)
1297 ("s" . footnote-set-style
))
1299 (setq footnote-start-tag
""
1301 footnote-style
'unicode
))
1304 :load-path
"lisp/bbdb"
1306 (load (expand-file-name "lisp/bbdb/bbdb-autoloads.el" user-emacs-directory
))
1307 ;; (bbdb-mua-auto-update-init 'message)
1308 (setq bbdb-mua-auto-update-p
'query
1309 bbdb-complete-mail nil
)
1310 (bbdb-initialize 'gnus
'message
))
1312 (use-package message-x
1315 (message-x-completion-alist
1317 (("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" . gnus-harvest-find-address
)
1320 (quote message-newgroups-header-regexp
))
1321 message-newgroups-header-regexp message-newsgroups-header-regexp
)
1322 . message-expand-group
)))))
1324 (use-package gnus-harvest
1326 :commands gnus-harvest-install
1329 (if (featurep 'message-x
)
1330 (gnus-harvest-install 'message-x
)
1331 (gnus-harvest-install)))
1336 (use-package ox-hugo
1339 (use-package ox-hugo-auto-export
1340 :load-path
"lib/ox-hugo")
1343 ;; * Post initialization
1345 (message "Loading %s...done (%.3fs)" user-init-file
1346 (float-time (time-subtract (current-time)
1347 amin--before-user-init-time
)))
1349 ;;; init.el ends here