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)))
656 (use-package undo-tree
658 (global-undo-tree-mode -1))
659 ;; :bind (("C-?" . undo-tree-undo)
660 ;; ("M-_" . undo-tree-redo))
662 ;; (global-undo-tree-mode)
663 ;; (setq undo-tree-mode-lighter ""
664 ;; undo-tree-auto-save-history t))
672 (:map company-active-map
673 ([tab] . company-complete-common-or-cycle)
674 ([escape] . company-abort
))
676 (company-minimum-prefix-length 1)
677 (company-selection-wrap-around t
)
678 (company-dabbrev-char-regexp "\\sw\\|\\s_\\|[-_]")
679 (company-dabbrev-downcase nil
)
680 (company-dabbrev-ignore-case nil
)
682 (global-company-mode t
))
685 ;; * Syntax and spell checking
687 (use-package flycheck
689 :hook
(prog-mode . flycheck-mode
)
691 (:map flycheck-mode-map
692 ("M-P" . flycheck-previous-error
)
693 ("M-N" . flycheck-next-error
))
695 ;; Use the load-path from running Emacs when checking elisp files
696 (setq flycheck-emacs-lisp-load-path
'inherit
)
698 ;; Only flycheck when I actually save the buffer
699 (setq flycheck-check-syntax-automatically
'(mode-enabled save
)))
701 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
705 ;; ’ can be part of a word
706 (setq ispell-local-dictionary-alist
707 `((nil "[[:alpha:]]" "[^[:alpha:]]"
708 "['\x2019]" nil
("-B") nil utf-8
)))
709 ;; don't send ’ to the subprocess
710 (defun endless/replace-apostrophe
(args)
711 (cons (replace-regexp-in-string
714 (advice-add #'ispell-send-string
:filter-args
715 #'endless
/replace-apostrophe
)
717 ;; convert ' back to ’ from the subprocess
718 (defun endless/replace-quote
(args)
719 (if (not (derived-mode-p 'org-mode
))
721 (cons (replace-regexp-in-string
724 (advice-add #'ispell-parse-output
:filter-args
725 #'endless
/replace-quote
))
728 ;; * Programming modes
730 (use-package alloy-mode
732 :config
(setq alloy-basic-offset
2))
734 (use-package proof-site
; Proof General
736 :load-path
"lib/proof-site/generic/")
738 (eval-when-compile (defvar lean-mode-map
))
739 (use-package lean-mode
741 :bind
(:map lean-mode-map
742 ("S-SPC" . company-complete
))
744 (require 'lean-input
)
745 (setq default-input-method
"Lean"
746 lean-input-tweak-all
'(lean-input-compose
747 (lean-input-prepend "/")
748 (lean-input-nonempty))
749 lean-input-user-translations
'(("/" "/")))
752 (use-package haskell-mode
755 (setq haskell-indentation-layout-offset
4
756 haskell-indentation-left-offset
4
757 flycheck-checker
'haskell-hlint
758 flycheck-disabled-checkers
'(haskell-stack-ghc haskell-ghc
)))
763 :hook
(haskell-mode . dante-mode
))
765 (use-package hlint-refactor
767 :bind
(:map hlint-refactor-mode-map
768 ("C-c l b" . hlint-refactor-refactor-buffer
)
769 ("C-c l r" . hlint-refactor-refactor-at-point
))
770 :hook
(haskell-mode . hlint-refactor-mode
))
772 (use-package flycheck-haskell
775 (use-package sgml-mode
778 (setq sgml-basic-offset
2))
780 (use-package css-mode
783 (setq css-indent-offset
2))
785 (use-package web-mode
790 web-mode-code-indent-offset
791 web-mode-css-indent-offset
792 web-mode-markup-indent-offset
))
794 (use-package emmet-mode
795 :after
(:any web-mode css-mode sgml-mode
)
796 :bind
* (("C-)" . emmet-next-edit-point
)
797 ("C-(" . emmet-prev-edit-point
))
799 (unbind-key "C-j" emmet-mode-keymap
)
800 (setq emmet-move-cursor-between-quotes t
)
801 :hook
(web-mode css-mode html-mode sgml-mode
))
803 (use-package nix-mode
808 ;; * Emacs Enhancements
810 (use-package which-key
812 :config
(which-key-mode))
814 (add-to-list 'custom-theme-load-path
"~/.emacs.d/lisp")
815 (load-theme 'tangomod t
)
817 (use-package doom-modeline
819 :config
(setq doom-modeline-height
32)
820 :hook
(after-init . doom-modeline-init
))
822 (use-package doom-themes
)
824 (defun amin/lights-on
()
825 "Enable my favourite light theme."
828 (mapc #'disable-theme custom-enabled-themes
)
829 (load-theme 'tangomod t
)))
831 (defun amin/lights-off
()
835 (mapc #'disable-theme custom-enabled-themes
)
836 (load-theme 'doom-tomorrow-night t
)))
839 ("s-t d" . amin
/lights-off
)
840 ("s-t l" . amin
/lights-on
))
844 :bind
(("C-c b k" . crux-kill-other-buffers
)
845 ("C-c d" . crux-duplicate-current-line-or-region
)
846 ("C-c D" . crux-duplicate-and-comment-current-line-or-region
)
847 ("C-c f c" . crux-copy-file-preserve-attributes
)
848 ("C-c f d" . crux-delete-file-and-buffer
)
849 ("C-c f r" . crux-rename-file-and-buffer
)
850 ("C-c j" . crux-top-join-line
)
851 ("C-S-j" . crux-top-join-line
)))
854 :bind
(("C-a" . mwim-beginning-of-code-or-line
)
855 ("C-e" . mwim-end-of-code-or-line
)
856 ("<home>" . mwim-beginning-of-line-or-code
)
857 ("<end>" . mwim-end-of-line-or-code
)))
859 (use-package projectile
861 :bind-keymap
("C-c p" . projectile-command-map
)
865 (defun my-projectile-invalidate-cache (&rest _args
)
866 ;; ignore the args to `magit-checkout'
867 (projectile-invalidate-cache nil
))
869 (eval-after-load 'magit-branch
871 (advice-add 'magit-checkout
872 :after
#'my-projectile-invalidate-cache
)
873 (advice-add 'magit-branch-and-checkout
874 :after
#'my-projectile-invalidate-cache
))))
879 (("C-S-h c" . helpful-command
)
880 ("C-S-h f" . helpful-callable
) ; helpful-function
881 ("C-S-h v" . helpful-variable
)
882 ("C-S-h k" . helpful-key
)
883 ("C-S-h p" . helpful-at-point
)))
885 (use-package shell-toggle
887 :bind
("C-c a s e" . amin
/shell-toggle
)
889 (defun amin/shell-toggle
(make-cd)
890 "Toggle between the shell buffer and whatever buffer you are editing.
891 With a prefix argument MAKE-CD also insert a \"cd DIR\" command
892 into the shell, where DIR is the directory of the current buffer.
894 When called in the shell buffer returns you to the buffer you were editing
895 before calling this the first time.
897 Options: `shell-toggle-goto-eob'"
899 ;; Try to decide on one of three possibilities:
900 ;; If not in shell-buffer, switch to it.
901 ;; If in shell-buffer, return to state before going to the shell-buffer
902 (if (eq (current-buffer) shell-toggle-shell-buffer
)
903 (shell-toggle-buffer-return-from-shell)
905 (shell-toggle-buffer-goto-shell make-cd
)
906 (if shell-toggle-full-screen-window-only
(delete-other-windows)))))
908 ;; override to split horizontally instead
909 (defun shell-toggle-buffer-switch-to-other-window ()
910 "Switch to other window.
911 If the current window is the only window in the current frame,
912 create a new window and switch to it.
914 \(This is less intrusive to the current window configuration than
915 `switch-buffer-other-window')"
916 (let ((this-window (selected-window)))
918 ;; If we did not switch window then we only have one window and need to
920 (if (eq this-window
(selected-window))
922 (split-window-horizontally)
926 (shell-toggle-launch-shell 'shell-toggle-eshell
))
928 (use-package unkillable-scratch
931 (unkillable-scratch 1)
933 (unkillable-scratch-behavior 'do-nothing
)
934 (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
936 (use-package boxquote
939 (:prefix-map amin--boxquote-prefix-map
941 ("b" . boxquote-buffer
)
942 ("B" . boxquote-insert-buffer
)
943 ("d" . boxquote-defun
)
944 ("F" . boxquote-insert-file
)
945 ("hf" . boxquote-describe-function
)
946 ("hk" . boxquote-describe-key
)
947 ("hv" . boxquote-describe-variable
)
948 ("hw" . boxquote-where-is
)
949 ("k" . boxquote-kill
)
950 ("p" . boxquote-paragraph
)
951 ("q" . boxquote-boxquote
)
952 ("r" . boxquote-region
)
953 ("s" . boxquote-shell-command
)
954 ("t" . boxquote-text
)
955 ("T" . boxquote-title
)
956 ("u" . boxquote-unbox
)
957 ("U" . boxquote-unbox-region
)
958 ("y" . boxquote-yank
)
959 ("M-q" . boxquote-fill-paragraph
)
960 ("M-w" . boxquote-kill-ring-save
)))
962 (use-package highlight-indent-guides
965 :hook
((prog-mode . highlight-indent-guides-mode
)
966 ;; (org-mode . highlight-indent-guides-mode)
969 (setq highlight-indent-guides-character ?\|
)
970 (setq highlight-indent-guides-auto-enabled nil
)
971 (setq highlight-indent-guides-method
'character
)
972 (setq highlight-indent-guides-responsive
'top
)
973 (set-face-foreground 'highlight-indent-guides-character-face
"gainsboro")
974 (set-face-foreground 'highlight-indent-guides-top-character-face
"grey40")) ; grey13 is nice too
976 (use-package pdf-tools
978 :magic
("%PDF" . pdf-view-mode
)
980 (setq pdf-view-resize-factor
1.05)
983 (:map pdf-view-mode-map
984 ("C-s" . isearch-forward
)
985 ("C-r" . isearch-backward
)
986 ("j" . pdf-view-next-line-or-next-page
)
987 ("k" . pdf-view-previous-line-or-previous-page
)
988 ("h" . image-backward-hscroll
)
989 ("l" . image-forward-hscroll
)))
997 :hook
(text-mode . typo-mode
))
1002 (global-hl-todo-mode))
1004 (use-package shrink-path
1007 (setq eshell-prompt-regexp
"\\(.*\n\\)*λ "
1008 eshell-prompt-function
#'+eshell
/prompt
)
1010 (defun +eshell
/prompt
()
1011 (let ((base/dir
(shrink-path-prompt default-directory
)))
1012 (concat (propertize (car base
/dir
)
1013 'face
'font-lock-comment-face
)
1014 (propertize (cdr base
/dir
)
1015 'face
'font-lock-constant-face
)
1016 (propertize (+eshell--current-git-branch
)
1017 'face
'font-lock-function-name-face
)
1019 (propertize "λ" 'face
'eshell-prompt-face
)
1020 ;; needed for the input text to not have prompt face
1021 (propertize " " 'face
'default
))))
1023 (defun +eshell--current-git-branch
()
1024 (let ((branch (car (loop for match in
(split-string (shell-command-to-string "git branch") "\n")
1025 when
(string-match "^\*" match
)
1027 (if (not (eq branch nil
))
1028 (concat " " (substring branch
2))
1033 :commands
(slack-start)
1035 (eval-when-compile ; silence the byte-compiler
1036 (defvar url-http-data nil
)
1037 (defvar url-http-extra-headers nil
)
1038 (defvar url-http-method nil
)
1039 (defvar url-callback-function nil
)
1040 (defvar url-callback-arguments nil
)
1041 (defvar oauth--token-data nil
))
1042 (setq slack-buffer-emojify t
1043 slack-prefer-current-team t
)
1045 (slack-register-team
1048 :client-id uw-apv-client-id
1049 :client-secret uw-apv-client-secret
1051 :subscribed-channels
'(general)
1052 :full-and-display-names t
)
1053 (slack-register-team
1056 :client-id watform-client-id
1057 :client-secret watform-client-secret
1058 :token watform-token
1059 :subscribed-channels
'(general)
1060 :full-and-display-names t
)
1061 (add-to-list 'swiper-font-lock-exclude
'slack-message-buffer-mode t
)
1062 (setq lui-time-stamp-format
"[%Y-%m-%d %H:%M:%S]"
1063 lui-time-stamp-only-when-changed-p t
1064 lui-time-stamp-position
'right
)
1066 (("C-c s s" . slack-start
)
1067 ("C-c s u" . slack-select-unread-rooms
)
1068 ("C-c s b" . slack-select-rooms
)
1069 ("C-c s t" . slack-change-current-team
)
1070 ("C-c s c" . slack-ws-close
)
1072 ("M-p" . slack-buffer-goto-prev-message
)
1073 ("M-n" . slack-buffer-goto-next-message
)
1074 ("C-c e" . slack-message-edit
)
1075 ("C-c k" . slack-message-delete
)
1076 ("C-c C-k" . slack-channel-leave
)
1077 ("C-c r a" . slack-message-add-reaction
)
1078 ("C-c r r" . slack-message-remove-reaction
)
1079 ("C-c r s" . slack-message-show-reaction-users
)
1080 ("C-c p l" . slack-room-pins-list
)
1081 ("C-c p a" . slack-message-pins-add
)
1082 ("C-c p r" . slack-message-pins-remove
)
1083 ("@" . slack-message-embed-mention
)
1084 ("#" . slack-message-embed-channel
)))
1089 (setq alert-default-style
'notifier
))
1091 (use-package eshell-up
1094 (use-package multi-term
1096 :bind
(("C-c C-j" . term-line-mode
)
1097 ("C-c a s m m" . multi-term
)
1098 ("C-c a s m p" . multi-term-dedicated-toggle
))
1100 (setq multi-term-program
"/bin/screen"
1101 ;; TODO: add separate bindings for connecting to existing
1102 ;; session vs. always creating a new one
1103 multi-term-dedicated-select-after-open-p t
1104 multi-term-dedicated-window-height
20
1105 multi-term-dedicated-max-window-height
30
1107 '(("C-c C-c" . term-interrupt-subjob
)
1108 ("C-c C-e" . term-send-esc
)
1110 ("C-y" . term-paste
)
1111 ("M-f" . term-send-forward-word
)
1112 ("M-b" . term-send-backward-word
)
1113 ("M-p" . term-send-up
)
1114 ("M-n" . term-send-down
)
1115 ("<C-backspace>" . term-send-backward-kill-word
)
1116 ("<M-DEL>" . term-send-backward-kill-word
)
1117 ("M-d" . term-send-delete-word
)
1118 ("M-," . term-send-raw
)
1119 ("M-." . comint-dynamic-complete
))
1120 term-unbind-key-alist
1121 '("C-z" "C-x" "C-c" "C-h" "C-y" "<ESC>")))
1123 (use-package page-break-lines
1125 (global-page-break-lines-mode))
1130 (defvar amin-maildir
(expand-file-name "~/mail/"))
1132 (add-to-list 'recentf-exclude amin-maildir
))
1135 amin-gnus-init-file
(no-littering-expand-etc-file-name "gnus")
1136 mail-user-agent
'gnus-user-agent
1137 read-mail-command
'gnus
)
1140 :bind
(("s-m" . gnus
)
1141 ("s-M" . gnus-unplugged
))
1144 gnus-select-method
'(nnnil "")
1145 gnus-secondary-select-methods
1147 (nnimap-stream plain
)
1148 (nnimap-address "127.0.0.1")
1149 (nnimap-server-port 143)
1150 (nnimap-authenticator plain
)
1151 (nnimap-user "amin@aminb.org"))
1153 (nnimap-stream plain
)
1154 (nnimap-address "127.0.0.1")
1155 (nnimap-server-port 143)
1156 (nnimap-authenticator plain
)
1157 (nnimap-user "abandali@uwaterloo.ca")))
1158 gnus-message-archive-group
"nnimap+amin:Sent"
1162 gnus-large-newsgroup
50
1163 gnus-home-directory
(no-littering-expand-var-file-name "gnus/")
1164 gnus-directory
(concat gnus-home-directory
"news/")
1165 message-directory
(concat gnus-home-directory
"mail/")
1166 nndraft-directory
(concat gnus-home-directory
"drafts/")
1167 gnus-save-newsrc-file nil
1168 gnus-read-newsrc-file nil
1169 gnus-interactive-exit nil
1170 gnus-gcc-mark-as-read t
))
1172 (use-package gnus-art
1175 gnus-visible-headers
1176 (concat gnus-visible-headers
"\\|^List-Id:\\|^X-RT-Originator:\\|^User-Agent:")
1177 gnus-sorted-header-list
1178 '("^From:" "^Subject:" "^Summary:" "^Keywords:"
1179 "^Followup-To:" "^To:" "^Cc:" "X-RT-Originator"
1180 "^Newsgroups:" "List-Id:" "^Organization:"
1181 "^User-Agent:" "^Date:")
1182 ;; local-lapsed article dates
1183 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
1184 gnus-article-date-headers
'(user-defined)
1185 gnus-article-time-format
1187 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time
))
1188 (local (article-make-date-line date
'local
))
1189 (combined-lapsed (article-make-date-line date
1192 (string-match " (.+" combined-lapsed
)
1193 (match-string 0 combined-lapsed
))))
1194 (concat local lapsed
))))
1196 :map gnus-article-mode-map
1197 ("r" . gnus-article-reply-with-original
)
1198 ("R" . gnus-article-wide-reply-with-original
)
1199 ("M-L" . org-store-link
)))
1201 (use-package gnus-sum
1202 :bind
(:map gnus-summary-mode-map
1203 :prefix-map amin--gnus-summary-prefix-map
1205 ("r" . gnus-summary-reply
)
1206 ("w" . gnus-summary-wide-reply
)
1207 ("v" . gnus-summary-show-raw-article
))
1210 :map gnus-summary-mode-map
1211 ("r" . gnus-summary-reply-with-original
)
1212 ("R" . gnus-summary-wide-reply-with-original
)
1213 ("M-L" . org-store-link
))
1214 :hook
(gnus-summary-mode . amin--no-mouse-autoselect-window
))
1216 (use-package gnus-msg
1218 (setq gnus-posting-styles
1220 (address "amin@aminb.org")
1221 (body "\nBest,\namin\n")
1222 (eval (setq amin--message-cite-say-hi t
)))
1224 (address "bandali@gnu.org"))
1225 ((header "subject" "ThankCRM")
1226 (to "webmasters-comment@gnu.org")
1227 (body "\nAdded to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
1228 (eval (setq amin--message-cite-say-hi nil
)))
1229 ("nnimap\\+uwaterloo:.*"
1230 (address "abandali@uwaterloo.ca")
1231 (gcc "\"nnimap+uwaterloo:Sent Items\"")))))
1233 (use-package gnus-topic
1234 :hook
(gnus-group-mode . gnus-topic-mode
))
1236 (use-package gnus-agent
1238 (setq gnus-agent-synchronize-flags
'ask
)
1239 :hook
(gnus-group-mode . gnus-agent-mode
))
1241 (use-package gnus-group
1243 (setq gnus-permanently-visible-groups
"\\((INBOX\\|gnu$\\)"))
1245 (use-package mm-decode
1247 (setq mm-discouraged-alternatives
'("text/html" "text/richtext")))
1249 (use-package sendmail
1251 (setq sendmail-program
"/usr/bin/msmtp"
1252 ;; message-sendmail-extra-arguments '("-v" "-d")
1253 mail-specify-envelope-from t
1254 mail-envelope-from
'header
))
1256 (use-package message
1258 (defconst amin--message-cite-style-format
"On %Y-%m-%d %l:%M %p, %N wrote:")
1259 (defconst message-cite-style-bandali
1260 '((message-cite-function 'message-cite-original
)
1261 (message-citation-line-function 'message-insert-formatted-citation-line
)
1262 (message-cite-reply-position 'traditional
)
1263 (message-yank-prefix "> ")
1264 (message-yank-cited-prefix ">")
1265 (message-yank-empty-prefix ">")
1266 (message-citation-line-format
1267 (if amin--message-cite-say-hi
1268 (concat "Hi %F,\n\n" amin--message-cite-style-format
)
1269 amin--message-cite-style-format
)))
1270 "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.")
1271 (setq message-cite-style
'message-cite-style-bandali
1272 message-kill-buffer-on-exit t
1273 message-send-mail-function
'message-send-mail-with-sendmail
1274 message-sendmail-envelope-from
'header
1275 message-dont-reply-to-names
1276 "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)"
1277 message-user-fqdn
"aminb.org")
1278 :hook
(;; (message-setup . mml-secure-message-sign-pgpmime)
1279 (message-mode . flyspell-mode
)
1280 (message-mode .
(lambda ()
1281 ;; (setq fill-column 65
1282 ;; message-fill-column 65)
1283 (make-local-variable 'company-idle-delay
)
1284 (setq company-idle-delay
0.2))))
1286 ;; (message-header-subject ((t (:foreground "#111" :weight semi-bold))))
1287 ;; (message-header-to ((t (:foreground "#111" :weight normal))))
1288 ;; (message-header-cc ((t (:foreground "#333" :weight normal))))
1292 (setq mml-secure-openpgp-encrypt-to-self t
1293 mml-secure-openpgp-sign-with-sender t
))
1295 (use-package footnote
1298 (:map message-mode-map
1299 :prefix-map amin--footnote-prefix-map
1301 ("a" . footnote-add-footnote
)
1302 ("b" . footnote-back-to-message
)
1303 ("c" . footnote-cycle-style
)
1304 ("d" . footnote-delete-footnote
)
1305 ("g" . footnote-goto-footnote
)
1306 ("r" . footnote-renumber-footnotes
)
1307 ("s" . footnote-set-style
))
1309 (setq footnote-start-tag
""
1311 footnote-style
'unicode
))
1314 :load-path
"lisp/bbdb"
1316 (load (expand-file-name "lisp/bbdb/bbdb-autoloads.el" user-emacs-directory
))
1317 ;; (bbdb-mua-auto-update-init 'message)
1318 (setq bbdb-mua-auto-update-p
'query
1319 bbdb-complete-mail nil
)
1320 (bbdb-initialize 'gnus
'message
))
1322 (use-package message-x
1325 (message-x-completion-alist
1327 (("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" . gnus-harvest-find-address
)
1330 (quote message-newgroups-header-regexp
))
1331 message-newgroups-header-regexp message-newsgroups-header-regexp
)
1332 . message-expand-group
)))))
1334 (use-package gnus-harvest
1336 :commands gnus-harvest-install
1339 (if (featurep 'message-x
)
1340 (gnus-harvest-install 'message-x
)
1341 (gnus-harvest-install)))
1346 (use-package ox-hugo
1349 (use-package ox-hugo-auto-export
1350 :load-path
"lib/ox-hugo")
1353 ;; * Post initialization
1355 (message "Loading %s...done (%.3fs)" user-init-file
1356 (float-time (time-subtract (current-time)
1357 amin--before-user-init-time
)))
1359 ;;; init.el ends here