1 ;;; init.el --- Amin Bandali's Emacs config -*- lexical-binding: t ; eval: (view-mode 1)-*-
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:... an evil operator, motion, or command
31 ;; amin|... a hook function
32 ;; amin*... an advising function
33 ;; amin@... a hydra command
38 (defvar amin--before-user-init-time
(current-time)
39 "Value of `current-time' when Emacs begins loading `user-init-file'.")
40 (message "Loading Emacs...done (%.3fs)"
41 (float-time (time-subtract amin--before-user-init-time
44 (defvar amin--gc-cons-threshold gc-cons-threshold
)
45 (defvar amin--gc-cons-percentage gc-cons-percentage
)
46 (defvar amin--file-name-handler-alist file-name-handler-alist
)
47 (setq gc-cons-threshold
(* 400 1024 1024) ; 400 MiB
48 gc-cons-percentage
0.6
49 file-name-handler-alist nil
50 ;; sidesteps a bug when profiling with esup
51 esup-child-profile-require-level
0)
56 (setq gc-cons-threshold amin--gc-cons-threshold
57 gc-cons-percentage amin--gc-cons-percentage
58 file-name-handler-alist amin--file-name-handler-alist
)))
60 (setq message-log-max
20000)
62 ;; (setq byte-compile-warnings
63 ;; '(not free-vars unresolved noruntime lexical make-local))
65 (setq user-full-name
"Amin Bandali"
66 user-mail-address
"amin@aminb.org")
68 (setq package-enable-at-startup nil
)
69 ;; (package-initialize)
71 (setq user-init-file
(or load-file-name buffer-file-name
)
72 user-emacs-directory
(file-name-directory user-init-file
))
73 (add-to-list 'load-path
74 (expand-file-name "lib/borg" user-emacs-directory
))
78 ;; (require 'borg-nix-shell)
79 ;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
81 (with-eval-after-load 'bind-key
84 ("C-c b A" . borg-activate
)
85 ("C-c b a" . borg-assimilate
)
86 ("C-c b b" . borg-build
)
87 ("C-c b c" . borg-clone
)
88 ("C-c b r" . borg-remove
)))
90 (require 'use-package
)
91 (if nil
; set to t when need to debug init
92 (setq use-package-verbose t
93 use-package-expand-minimally nil
94 use-package-compute-statistics t
96 (setq use-package-verbose nil
97 use-package-expand-minimally t
))
102 (("C-c b d" . epkg-describe-package
)
103 ("C-c b p" . epkg-list-packages
)
104 ("C-c b u" . epkg-update
)))
106 (use-package no-littering
110 (add-to-list 'savehist-additional-variables
'kill-ring
)
112 (setq auto-save-file-name-transforms
113 `((".*" ,(no-littering-expand-var-file-name "auto-save/") t
))))
118 (setq custom-file
(no-littering-expand-etc-file-name "custom.el"))
119 (when (file-exists-p custom-file
)
121 (setf custom-safe-themes t
))
124 (load (no-littering-expand-etc-file-name "secrets")))
126 (use-package exec-path-from-shell
129 (setq exec-path-from-shell-check-startup-files nil
)
131 (exec-path-from-shell-initialize)
132 ;; while we're at it, let's fix access to our running ssh-agent
133 (exec-path-from-shell-copy-env "SSH_AGENT_PID")
134 (exec-path-from-shell-copy-env "SSH_AUTH_SOCK"))
136 ;; only one custom theme at a time
138 ;; (defadvice load-theme (before clear-previous-themes activate)
139 ;; "Clear existing theme settings instead of layering them"
140 ;; (mapc #'disable-theme custom-enabled-themes))
144 :config
(or (server-running-p) (server-mode)))
148 ;; (dolist (ft (fontset-list))
152 ;; (font-spec :name "Source Code Pro" :size 14))
156 ;; (font-spec :name "DejaVu Sans Mono")
159 ;; ;; (set-fontset-font
163 ;; ;; :name "Symbola monospacified for DejaVu Sans Mono")
166 ;; ;; (set-fontset-font
169 ;; ;; (font-spec :name "DejaVu Sans Mono")
175 ;; (font-spec :name "DejaVu Sans Mono" :size 14)
179 (setq text-scale-mode-step
1.05)
181 (setq mouse-autoselect-window t
)
183 (defun amin--no-mouse-autoselect-window ()
184 (make-local-variable 'mouse-autoselect-window
)
185 (setq mouse-autoselect-window nil
))
190 (defun amin-enlist (exp)
191 "Return EXP wrapped in a list, or as-is if already a list."
192 (if (listp exp
) exp
(list exp
)))
194 ; from https://github.com/hlissner/doom-emacs/commit/589108fdb270f24a98ba6209f6955fe41530b3ef
195 (defmacro after
! (features &rest body
)
196 "A smart wrapper around `with-eval-after-load'. Supresses warnings during
198 (declare (indent defun
) (debug t
))
199 (list (if (or (not (bound-and-true-p byte-compile-current-file
))
200 (dolist (next (amin-enlist features
))
202 (require next nil
:no-error
)
203 (load next
:no-message
:no-error
))))
206 (cond ((symbolp features
)
207 `(eval-after-load ',features
'(progn ,@body
)))
208 ((and (consp features
)
209 (memq (car features
) '(:or
:any
)))
211 ,@(cl-loop for next in
(cdr features
)
212 collect
`(after! ,next
,@body
))))
213 ((and (consp features
)
214 (memq (car features
) '(:and
:all
)))
215 (dolist (next (cdr features
))
216 (setq body
`(after! ,next
,@body
)))
219 `(after! (:all
,@features
) ,@body
)))))
221 (defmacro setq-every
! (value &rest vars
)
222 "Set all the variables from VARS to value VALUE."
223 (declare (indent defun
) (debug t
))
224 `(progn ,@(mapcar (lambda (x) (list 'setq x value
)) vars
)))
226 ;; (fringe-mode '(3 . 1))
229 (setq disabled-command-function nil
)
231 (setq save-interprogram-paste-before-kill t
)
233 (setq enable-recursive-minibuffers t
234 resize-mini-windows t
)
236 (defalias 'yes-or-no-p
#'y-or-n-p
)
238 (setq initial-buffer-choice t
)
240 (setq initial-scratch-message nil
)
242 (setq initial-major-mode
'text-mode
)
244 (setq inhibit-startup-buffer-menu t
)
246 (advice-add #'display-startup-echo-area-message
:override
#'ignore
)
247 (setq inhibit-startup-screen t
248 inhibit-startup-echo-area-message user-login-name
)
250 (setq frame-title-format
251 '("" invocation-name
" - "
252 (:eval
(if (buffer-file-name)
253 (abbreviate-file-name (buffer-file-name))
256 (setq backup-by-copying t
258 delete-old-versions t
)
260 (global-auto-revert-mode 1)
261 (setq auto-revert-verbose nil
262 global-auto-revert-non-file-buffers nil
)
266 require-final-newline t
271 (setq compilation-exit-message-function
272 (lambda (status code msg
)
273 "Close the compilation window if successful."
274 ;; if M-x compile exits with 0
275 (when (and (eq status
'exit
) (zerop code
))
277 (delete-window (get-buffer-window (get-buffer "*compilation*"))))
278 ;; return the result of compilation-exit-message-function
281 (setq search-default-mode
#'char-fold-to-regexp
)
283 ;; uncomment to extend this behaviour to query-replace
284 ;; (setq replace-char-fold t)
289 ("C-c e b" . eval-buffer
)
290 ("C-c e r" . eval-region
)
292 ("C-c F m" . make-frame-command
)
293 ("C-c F d" . delete-frame
)
294 ("C-c F D" . delete-other-frames
)
296 ("C-c o" . other-window
)
298 ("C-c Q" . save-buffers-kill-terminal
)
300 ("C-S-h C" . describe-char
)
301 ("C-S-h F" . describe-face
)
303 ("C-x K" . kill-this-buffer
)
305 ("s-p" . beginning-of-buffer
)
306 ("s-n" . end-of-buffer
))
308 (use-package auto-compile
311 (auto-compile-on-load-mode)
312 (auto-compile-on-save-mode)
313 (setq auto-compile-display-buffer nil
314 auto-compile-mode-line-counter t
315 auto-compile-source-recreate-deletes-dest t
316 auto-compile-toggle-deletes-nonlib-dest t
317 auto-compile-update-autoloads t
)
318 (add-hook 'auto-compile-inhibit-compile-hook
319 'auto-compile-inhibit-compile-detached-git-head
))
324 (setq org-src-tab-acts-natively t
325 org-src-preserve-indentation nil
326 org-edit-src-content-indentation
0
327 org-email-link-description-format
"Email %c: %s" ; %.30s
328 org-highlight-latex-and-related
'(entities)
330 (add-to-list 'org-structure-template-alist
'("L" .
"src emacs-lisp") t
)
331 (font-lock-add-keywords
333 '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
334 (1 '(:foreground
"#5a5b5a" :background
"#292b2b") t
) ; directive
335 (3 '(:foreground
"#81a2be" :background
"#292b2b") t
) ; kind
336 (4 '(:foreground
"#c5c8c6") t
))) ; title
338 :bind
(:map org-mode-map
("M-L" . org-insert-last-stored-link
))
339 :hook
((org-mode . org-indent-mode
)
340 (org-mode . auto-fill-mode
)
341 (org-mode . flyspell-mode
))
343 (org-latex-packages-alist '(("" "listings") ("" "color")))
345 '(org-block-begin-line ((t (:foreground
"#5a5b5a" :background
"#1d1f21"))))
346 '(org-block ((t (:background
"#1d1f21"))))
347 '(org-latex-and-related ((t (:foreground
"#b294bb")))))
349 (use-package ox-latex
352 (setq org-latex-listings
'listings
353 ;; org-latex-prefer-user-labels t
355 (add-to-list 'org-latex-packages-alist
'("" "listings"))
356 (add-to-list 'org-latex-packages-alist
'("" "color"))
357 (add-to-list 'org-latex-classes
358 '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
359 ("\\section{%s}" .
"\\section*{%s}")
360 ("\\subsection{%s}" .
"\\subsection*{%s}")
361 ("\\subsubsection{%s}" .
"\\subsubsection*{%s}")
362 ("\\paragraph{%s}" .
"\\paragraph*{%s}")
363 ("\\subparagraph{%s}" .
"\\subparagraph*{%s}"))
366 (use-package ox-beamer
369 (use-package orgalist
371 :hook
(message-mode . orgalist-mode
))
374 (defvar amin-show-async-tangle-results nil
375 "Keep *emacs* async buffers around for later inspection.")
377 (defvar amin-show-async-tangle-time nil
378 "Show the time spent tangling the file.")
380 (defvar amin-async-tangle-post-compile
"make ti"
381 "If non-nil, pass to `compile' after successful tangle.")
383 (defun amin/async-babel-tangle
()
384 "Tangle org file asynchronously."
386 (let* ((file-tangle-start-time (current-time))
387 (file (buffer-file-name))
388 (file-nodir (file-name-nondirectory file
))
389 (async-quiet-switch "-q"))
393 (org-babel-tangle-file ,file
))
394 (unless amin-show-async-tangle-results
398 (message "Tangled %s%s"
400 (if amin-show-async-tangle-time
402 (float-time (time-subtract (current-time)
403 ',file-tangle-start-time
)))
405 (when amin-async-tangle-post-compile
406 (compile amin-async-tangle-post-compile
)))
407 (message "Tangling %s failed" ,file-nodir
))))))))
410 'safe-local-variable-values
411 '(eval add-hook
'after-save-hook
#'amin
/async-babel-tangle
'append
'local
))
415 :bind
(("C-x g" . magit-status
)
416 ("s-g s" . magit-status
)
417 ("s-g l" . magit-log-buffer-file
))
419 (magit-add-section-hook 'magit-status-sections-hook
420 'magit-insert-modules
421 'magit-insert-stashes
424 magit-repository-directories
'(("~/.emacs.d/" .
0)
426 (nconc magit-section-initial-visibility-alist
427 '(([unpulled status
] . show
)
428 ([unpushed status
] . show
)))
429 :custom-face
(magit-diff-file-heading ((t (:weight normal
)))))
434 (:map ivy-minibuffer-map
435 ([escape] . keyboard-escape-quit)
436 ([S-up] . ivy-previous-history-element)
437 ([S-down] . ivy-next-history-element)
438 ("DEL" . ivy-backward-delete-char))
443 ;; (ivy-minibuffer-match-face-2 ((t (:background "#e99ce8" :weight semi-bold))))
444 ;; (ivy-minibuffer-match-face-3 ((t (:background "#bbbbff" :weight semi-bold))))
445 ;; (ivy-minibuffer-match-face-4 ((t (:background "#ffbbff" :weight semi-bold))))
449 :bind (("C-s" . swiper)
454 :bind (([remap execute-extended-command] . counsel-M-x)
455 ([remap find-file] . counsel-find-file)
456 ("s-r" . counsel-recentf)
457 ("C-c x" . counsel-M-x)
458 ("C-c f ." . counsel-find-file)
459 :map minibuffer-local-map
460 ("C-r" . counsel-minibuffer-history))
463 (defalias 'locate #'counsel-locate))
469 (eval-when-compile (defvar eshell-prompt-regexp))
470 (defun amin/eshell-quit-or-delete-char (arg)
472 (if (and (eolp) (looking-back eshell-prompt-regexp nil))
473 (eshell-life-is-too-much)
476 (defun amin/eshell-clear ()
478 (let ((inhibit-read-only t))
482 (defun amin|eshell-setup ()
483 (make-local-variable 'company-idle-delay)
484 (setq company-idle-delay nil)
485 (bind-keys :map eshell-mode-map
486 ("C-d" . amin/eshell-quit-or-delete-char)
487 ("C-S-l" . amin/eshell-clear)
488 ("M-r" . counsel-esh-history)
489 ([tab] . company-complete)))
491 :hook (eshell-mode . amin|eshell-setup)
493 (eshell-hist-ignoredups t)
494 (eshell-input-filter 'eshell-input-filter-initial-space))
499 (("C-x C-b" . ibuffer-other-window)
500 :map ibuffer-mode-map
501 ("P" . ibuffer-backward-filter-group)
502 ("N" . ibuffer-forward-filter-group)
503 ("M-p" . ibuffer-do-print)
504 ("M-n" . ibuffer-do-shell-command-pipe-replace))
506 ;; Use human readable Size column instead of original one
507 (define-ibuffer-column size-h
508 (:name "Size" :inline t)
510 ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
511 ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
512 ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
513 (t (format "%8d" (buffer-size)))))
515 (ibuffer-saved-filter-groups
517 ("dired" (mode . dired-mode))
518 ("org" (mode . org-mode))
528 (mode . shell-mode)))
529 ("notmuch" (name . "\*notmuch\*"))
534 (mode . emacs-lisp-mode)))
537 (name . "^\\*scratch\\*$")
538 (name . "^\\*Messages\\*$")))
541 (name . "^\\*Slack*"))))))
543 '((mark modified read-only locked " "
544 (name 18 18 :left :elide)
548 (mode 16 16 :left :elide)
549 " " filename-and-process)
553 :hook (ibuffer . (lambda () (ibuffer-switch-to-saved-filter-groups "default"))))
557 :hook (prog-mode . outline-minor-mode)
560 outline-minor-mode-map
561 ("<s-tab>" . outline-toggle-children)
562 ("M-p" . outline-previous-visible-heading)
563 ("M-n" . outline-next-visible-heading)
564 :prefix-map amin--outline-prefix-map
566 ("TAB" . outline-toggle-children)
567 ("a" . outline-hide-body)
568 ("H" . outline-hide-body)
569 ("S" . outline-show-all)
570 ("h" . outline-hide-subtree)
571 ("s" . outline-show-subtree)))
574 :config (dash-enable-font-lock))
578 (setq diff-hl-draw-borders nil)
579 (global-diff-hl-mode)
580 (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh t))
584 :config (setq dired-listing-switches "-alh"))
587 :when (version< "25" emacs-version)
588 :config (global-eldoc-mode))
593 (temp-buffer-resize-mode)
594 (setq help-window-select t))
597 (setq isearch-allow-scroll t))
599 (use-package lisp-mode
601 (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
602 (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
603 (defun indent-spaces-mode ()
604 (setq indent-tabs-mode nil))
605 (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
609 :config (setq Man-width 80))
612 :config (show-paren-mode))
614 (use-package prog-mode
615 :config (global-prettify-symbols-mode)
616 (defun indicate-buffer-boundaries-left ()
617 (setq indicate-buffer-boundaries 'left))
618 (add-hook 'prog-mode-hook #'indicate-buffer-boundaries-left))
623 (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
624 (setq recentf-max-saved-items 40))
626 (use-package savehist
627 :config (savehist-mode))
629 (use-package saveplace
630 :when (version< "25" emacs-version)
631 :config (save-place-mode))
634 :config (column-number-mode))
637 (add-hook 'text-mode-hook #'indicate-buffer-boundaries-left)
638 (add-hook 'text-mode-hook #'abbrev-mode))
643 (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
644 (add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
645 (add-to-list 'tramp-default-proxies-alist
646 (list (regexp-quote (system-name)) nil nil)))
648 (use-package undo-tree
650 (global-undo-tree-mode -1))
651 ;; :bind (("C-?" . undo-tree-undo)
652 ;; ("M-_" . undo-tree-redo))
654 ;; (global-undo-tree-mode)
655 ;; (setq undo-tree-mode-lighter ""
656 ;; undo-tree-auto-save-history t))
661 (:map company-active-map
662 ([tab] . company-complete-common-or-cycle)
663 ([escape] . company-abort
))
665 (company-minimum-prefix-length 1)
666 (company-selection-wrap-around t
)
667 (company-dabbrev-char-regexp "\\sw\\|\\s_\\|[-_]")
668 (company-dabbrev-downcase nil
)
669 (company-dabbrev-ignore-case nil
)
671 (global-company-mode t
))
673 (use-package flycheck
675 :hook
(prog-mode . flycheck-mode
)
677 (:map flycheck-mode-map
678 ("M-P" . flycheck-previous-error
)
679 ("M-N" . flycheck-next-error
))
681 ;; Use the load-path from running Emacs when checking elisp files
682 (setq flycheck-emacs-lisp-load-path
'inherit
)
684 ;; Only flycheck when I actually save the buffer
685 (setq flycheck-check-syntax-automatically
'(mode-enabled save
)))
687 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
691 ;; ’ can be part of a word
692 (setq ispell-local-dictionary-alist
693 `((nil "[[:alpha:]]" "[^[:alpha:]]"
694 "['\x2019]" nil
("-B") nil utf-8
)))
695 ;; don't send ’ to the subprocess
696 (defun endless/replace-apostrophe
(args)
697 (cons (replace-regexp-in-string
700 (advice-add #'ispell-send-string
:filter-args
701 #'endless
/replace-apostrophe
)
703 ;; convert ' back to ’ from the subprocess
704 (defun endless/replace-quote
(args)
705 (if (not (derived-mode-p 'org-mode
))
707 (cons (replace-regexp-in-string
710 (advice-add #'ispell-parse-output
:filter-args
711 #'endless
/replace-quote
))
713 (use-package alloy-mode
715 :config
(setq alloy-basic-offset
2))
717 (use-package proof-site
; Proof General
719 :load-path
"lib/proof-site/generic/")
721 (eval-when-compile (defvar lean-mode-map
))
722 (use-package lean-mode
724 :bind
(:map lean-mode-map
725 ("S-SPC" . company-complete
))
727 (require 'lean-input
)
728 (setq default-input-method
"Lean"
729 lean-input-tweak-all
'(lean-input-compose
730 (lean-input-prepend "/")
731 (lean-input-nonempty))
732 lean-input-user-translations
'(("/" "/")))
735 (use-package haskell-mode
738 (setq haskell-indentation-layout-offset
4
739 haskell-indentation-left-offset
4
740 flycheck-checker
'haskell-hlint
741 flycheck-disabled-checkers
'(haskell-stack-ghc haskell-ghc
)))
746 :hook
(haskell-mode . dante-mode
))
748 (use-package hlint-refactor
750 :bind
(:map hlint-refactor-mode-map
751 ("C-c l b" . hlint-refactor-refactor-buffer
)
752 ("C-c l r" . hlint-refactor-refactor-at-point
))
753 :hook
(haskell-mode . hlint-refactor-mode
))
755 (use-package flycheck-haskell
758 (use-package sgml-mode
761 (setq sgml-basic-offset
2))
763 (use-package css-mode
766 (setq css-indent-offset
2))
768 (use-package web-mode
773 web-mode-code-indent-offset
774 web-mode-css-indent-offset
775 web-mode-markup-indent-offset
))
777 (use-package emmet-mode
778 :after
(:any web-mode css-mode sgml-mode
)
779 :bind
* (("C-)" . emmet-next-edit-point
)
780 ("C-(" . emmet-prev-edit-point
))
782 (unbind-key "C-j" emmet-mode-keymap
)
783 (setq emmet-move-cursor-between-quotes t
)
784 :hook
(web-mode css-mode html-mode sgml-mode
))
786 (use-package nix-mode
790 (use-package which-key
792 :config
(which-key-mode))
794 (add-to-list 'custom-theme-load-path
"~/.emacs.d/lisp")
795 (load-theme 'tangomod t
)
797 (use-package doom-modeline
799 :config
(setq doom-modeline-height
32)
800 :hook
(after-init . doom-modeline-init
))
802 (use-package doom-themes
)
804 (defun amin/lights-on
()
805 "Enable my favourite light theme."
808 (mapc #'disable-theme custom-enabled-themes
)
809 (load-theme 'tangomod t
)))
811 (defun amin/lights-off
()
815 (mapc #'disable-theme custom-enabled-themes
)
816 (load-theme 'doom-tomorrow-night t
)))
819 ("s-t d" . amin
/lights-off
)
820 ("s-t l" . amin
/lights-on
))
824 :bind
(("C-c b k" . crux-kill-other-buffers
)
825 ("C-c d" . crux-duplicate-current-line-or-region
)
826 ("C-c D" . crux-duplicate-and-comment-current-line-or-region
)
827 ("C-c f c" . crux-copy-file-preserve-attributes
)
828 ("C-c f d" . crux-delete-file-and-buffer
)
829 ("C-c f r" . crux-rename-file-and-buffer
)
830 ("C-c j" . crux-top-join-line
)
831 ("C-S-j" . crux-top-join-line
)))
834 :bind
(("C-a" . mwim-beginning-of-code-or-line
)
835 ("C-e" . mwim-end-of-code-or-line
)
836 ("<home>" . mwim-beginning-of-line-or-code
)
837 ("<end>" . mwim-end-of-line-or-code
)))
839 (use-package projectile
841 :bind-keymap
("C-c p" . projectile-command-map
)
845 (defun my-projectile-invalidate-cache (&rest _args
)
846 ;; ignore the args to `magit-checkout'
847 (projectile-invalidate-cache nil
))
849 (eval-after-load 'magit-branch
851 (advice-add 'magit-checkout
852 :after
#'my-projectile-invalidate-cache
)
853 (advice-add 'magit-branch-and-checkout
854 :after
#'my-projectile-invalidate-cache
))))
859 (("C-S-h c" . helpful-command
)
860 ("C-S-h f" . helpful-callable
) ; helpful-function
861 ("C-S-h v" . helpful-variable
)
862 ("C-S-h k" . helpful-key
)
863 ("C-S-h p" . helpful-at-point
)))
865 (use-package shell-toggle
867 :bind
("C-c a s e" . amin
/shell-toggle
)
869 (defun amin/shell-toggle
(make-cd)
870 "Toggle between the shell buffer and whatever buffer you are editing.
871 With a prefix argument MAKE-CD also insert a \"cd DIR\" command
872 into the shell, where DIR is the directory of the current buffer.
874 When called in the shell buffer returns you to the buffer you were editing
875 before calling this the first time.
877 Options: `shell-toggle-goto-eob'"
879 ;; Try to decide on one of three possibilities:
880 ;; If not in shell-buffer, switch to it.
881 ;; If in shell-buffer, return to state before going to the shell-buffer
882 (if (eq (current-buffer) shell-toggle-shell-buffer
)
883 (shell-toggle-buffer-return-from-shell)
885 (shell-toggle-buffer-goto-shell make-cd
)
886 (if shell-toggle-full-screen-window-only
(delete-other-windows)))))
888 ;; override to split horizontally instead
889 (defun shell-toggle-buffer-switch-to-other-window ()
890 "Switch to other window.
891 If the current window is the only window in the current frame,
892 create a new window and switch to it.
894 \(This is less intrusive to the current window configuration than
895 `switch-buffer-other-window')"
896 (let ((this-window (selected-window)))
898 ;; If we did not switch window then we only have one window and need to
900 (if (eq this-window
(selected-window))
902 (split-window-horizontally)
906 (shell-toggle-launch-shell 'shell-toggle-eshell
))
908 (use-package unkillable-scratch
911 (unkillable-scratch 1)
913 (unkillable-scratch-behavior 'do-nothing
)
914 (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
916 (use-package boxquote
919 (:prefix-map amin--boxquote-prefix-map
921 ("b" . boxquote-buffer
)
922 ("B" . boxquote-insert-buffer
)
923 ("d" . boxquote-defun
)
924 ("F" . boxquote-insert-file
)
925 ("hf" . boxquote-describe-function
)
926 ("hk" . boxquote-describe-key
)
927 ("hv" . boxquote-describe-variable
)
928 ("hw" . boxquote-where-is
)
929 ("k" . boxquote-kill
)
930 ("p" . boxquote-paragraph
)
931 ("q" . boxquote-boxquote
)
932 ("r" . boxquote-region
)
933 ("s" . boxquote-shell-command
)
934 ("t" . boxquote-text
)
935 ("T" . boxquote-title
)
936 ("u" . boxquote-unbox
)
937 ("U" . boxquote-unbox-region
)
938 ("y" . boxquote-yank
)
939 ("M-q" . boxquote-fill-paragraph
)
940 ("M-w" . boxquote-kill-ring-save
)))
942 (use-package highlight-indent-guides
945 :hook
((prog-mode . highlight-indent-guides-mode
)
946 ;; (org-mode . highlight-indent-guides-mode)
949 (setq highlight-indent-guides-character ?\|
)
950 (setq highlight-indent-guides-auto-enabled nil
)
951 (setq highlight-indent-guides-method
'character
)
952 (setq highlight-indent-guides-responsive
'top
)
953 (set-face-foreground 'highlight-indent-guides-character-face
"gainsboro")
954 (set-face-foreground 'highlight-indent-guides-top-character-face
"grey40")) ; grey13 is nice too
956 (use-package pdf-tools
958 :magic
("%PDF" . pdf-view-mode
)
960 (setq pdf-view-resize-factor
1.05)
963 (:map pdf-view-mode-map
964 ("C-s" . isearch-forward
)
965 ("C-r" . isearch-backward
)
966 ("j" . pdf-view-next-line-or-next-page
)
967 ("k" . pdf-view-previous-line-or-previous-page
)
968 ("h" . image-backward-hscroll
)
969 ("l" . image-forward-hscroll
)))
977 :hook
(text-mode . typo-mode
))
982 (global-hl-todo-mode))
984 (use-package shrink-path
987 (setq eshell-prompt-regexp
"\\(.*\n\\)*λ "
988 eshell-prompt-function
#'+eshell
/prompt
)
990 (defun +eshell
/prompt
()
991 (let ((base/dir
(shrink-path-prompt default-directory
)))
992 (concat (propertize (car base
/dir
)
993 'face
'font-lock-comment-face
)
994 (propertize (cdr base
/dir
)
995 'face
'font-lock-constant-face
)
996 (propertize (+eshell--current-git-branch
)
997 'face
'font-lock-function-name-face
)
999 (propertize "λ" 'face
'eshell-prompt-face
)
1000 ;; needed for the input text to not have prompt face
1001 (propertize " " 'face
'default
))))
1003 (defun +eshell--current-git-branch
()
1004 (let ((branch (car (loop for match in
(split-string (shell-command-to-string "git branch") "\n")
1005 when
(string-match "^\*" match
)
1007 (if (not (eq branch nil
))
1008 (concat " " (substring branch
2))
1013 :commands
(slack-start)
1015 (eval-when-compile ; silence the byte-compiler
1016 (defvar url-http-data nil
)
1017 (defvar url-http-extra-headers nil
)
1018 (defvar url-http-method nil
)
1019 (defvar url-callback-function nil
)
1020 (defvar url-callback-arguments nil
)
1021 (defvar oauth--token-data nil
))
1022 (setq slack-buffer-emojify t
1023 slack-prefer-current-team t
)
1025 (slack-register-team
1028 :client-id uw-apv-client-id
1029 :client-secret uw-apv-client-secret
1031 :subscribed-channels
'(general)
1032 :full-and-display-names t
)
1033 (slack-register-team
1036 :client-id watform-client-id
1037 :client-secret watform-client-secret
1038 :token watform-token
1039 :subscribed-channels
'(general)
1040 :full-and-display-names t
)
1041 (add-to-list 'swiper-font-lock-exclude
'slack-message-buffer-mode t
)
1042 (setq lui-time-stamp-format
"[%Y-%m-%d %H:%M:%S]"
1043 lui-time-stamp-only-when-changed-p t
1044 lui-time-stamp-position
'right
)
1046 (("C-c s s" . slack-start
)
1047 ("C-c s u" . slack-select-unread-rooms
)
1048 ("C-c s b" . slack-select-rooms
)
1049 ("C-c s t" . slack-change-current-team
)
1050 ("C-c s c" . slack-ws-close
)
1052 ("M-p" . slack-buffer-goto-prev-message
)
1053 ("M-n" . slack-buffer-goto-next-message
)
1054 ("C-c e" . slack-message-edit
)
1055 ("C-c k" . slack-message-delete
)
1056 ("C-c C-k" . slack-channel-leave
)
1057 ("C-c r a" . slack-message-add-reaction
)
1058 ("C-c r r" . slack-message-remove-reaction
)
1059 ("C-c r s" . slack-message-show-reaction-users
)
1060 ("C-c p l" . slack-room-pins-list
)
1061 ("C-c p a" . slack-message-pins-add
)
1062 ("C-c p r" . slack-message-pins-remove
)
1063 ("@" . slack-message-embed-mention
)
1064 ("#" . slack-message-embed-channel
)))
1069 (setq alert-default-style
'notifier
))
1071 (use-package eshell-up
1074 (use-package multi-term
1076 :bind
(("C-c C-j" . term-line-mode
)
1077 ("C-c m m" . multi-term
)
1078 ("C-c m p" . multi-term-dedicated-toggle
))
1080 (setq multi-term-program
"/bin/screen"
1081 ;; TODO: add separate bindings for connecting to existing
1082 ;; session vs. always creating a new one
1083 multi-term-dedicated-select-after-open-p t
1084 multi-term-dedicated-window-height
20
1085 multi-term-dedicated-max-window-height
30
1087 '(("C-c C-c" . term-interrupt-subjob
)
1088 ("C-c C-e" . term-send-esc
)
1090 ("C-y" . term-paste
)
1091 ("M-f" . term-send-forward-word
)
1092 ("M-b" . term-send-backward-word
)
1093 ("M-p" . term-send-up
)
1094 ("M-n" . term-send-down
)
1095 ("<C-backspace>" . term-send-backward-kill-word
)
1096 ("<M-DEL>" . term-send-backward-kill-word
)
1097 ("M-d" . term-send-delete-word
)
1098 ("M-," . term-send-raw
)
1099 ("M-." . comint-dynamic-complete
))
1100 term-unbind-key-alist
1101 '("C-z" "C-x" "C-c" "C-h" "C-y" "<ESC>")))
1103 (defvar amin-maildir
(expand-file-name "~/mail/"))
1105 (add-to-list 'recentf-exclude amin-maildir
))
1108 amin-gnus-init-file
(no-littering-expand-etc-file-name "gnus")
1109 mail-user-agent
'gnus-user-agent
1110 read-mail-command
'gnus
)
1113 :bind
(("s-m" . gnus
)
1114 ("s-M" . gnus-unplugged
))
1117 gnus-select-method
'(nnnil "")
1118 gnus-secondary-select-methods
1120 (nnimap-stream plain
)
1121 (nnimap-address "127.0.0.1")
1122 (nnimap-server-port 143)
1123 (nnimap-authenticator plain
)
1124 (nnimap-user "amin@aminb.org"))
1126 (nnimap-stream plain
)
1127 (nnimap-address "127.0.0.1")
1128 (nnimap-server-port 143)
1129 (nnimap-authenticator plain
)
1130 (nnimap-user "abandali@uwaterloo.ca")))
1131 gnus-message-archive-group
"nnimap+amin:Sent"
1135 gnus-large-newsgroup
50
1136 gnus-home-directory
(no-littering-expand-var-file-name "gnus/")
1137 gnus-directory
(concat gnus-home-directory
"news/")
1138 message-directory
(concat gnus-home-directory
"mail/")
1139 nndraft-directory
(concat gnus-home-directory
"drafts/")
1140 gnus-save-newsrc-file nil
1141 gnus-read-newsrc-file nil
1142 gnus-interactive-exit nil
1143 gnus-gcc-mark-as-read t
))
1145 (use-package gnus-art
1148 gnus-visible-headers
1149 (concat gnus-visible-headers
"\\|^List-Id:\\|^X-RT-Originator:\\|^User-Agent:")
1150 gnus-sorted-header-list
1151 '("^From:" "^Subject:" "^Summary:" "^Keywords:"
1152 "^Followup-To:" "^To:" "^Cc:" "X-RT-Originator"
1153 "^Newsgroups:" "List-Id:" "^Organization:"
1154 "^User-Agent:" "^Date:")
1155 ;; local-lapsed article dates
1156 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
1157 gnus-article-date-headers
'(user-defined)
1158 gnus-article-time-format
1160 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time
))
1161 (local (article-make-date-line date
'local
))
1162 (combined-lapsed (article-make-date-line date
1165 (string-match " (.+" combined-lapsed
)
1166 (match-string 0 combined-lapsed
))))
1167 (concat local lapsed
))))
1169 :map gnus-article-mode-map
1170 ("r" . gnus-article-reply-with-original
)
1171 ("R" . gnus-article-wide-reply-with-original
)
1172 ("M-L" . org-store-link
)))
1174 (use-package gnus-sum
1175 :bind
(:map gnus-summary-mode-map
1176 :prefix-map amin--gnus-summary-prefix-map
1178 ("r" . gnus-summary-reply
)
1179 ("w" . gnus-summary-wide-reply
)
1180 ("v" . gnus-summary-show-raw-article
))
1183 :map gnus-summary-mode-map
1184 ("r" . gnus-summary-reply-with-original
)
1185 ("R" . gnus-summary-wide-reply-with-original
)
1186 ("M-L" . org-store-link
))
1187 :hook
(gnus-summary-mode . amin--no-mouse-autoselect-window
))
1189 (use-package gnus-msg
1191 (setq gnus-posting-styles
1193 (address "amin@aminb.org")
1194 (body "\nBest,\namin\n")
1195 (eval (setq amin--message-cite-say-hi t
)))
1197 (address "bandali@gnu.org"))
1198 ((header "subject" "ThankCRM")
1199 (to "webmasters-comment@gnu.org")
1200 (body "\nAdded to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
1201 (eval (setq amin--message-cite-say-hi nil
)))
1202 ("nnimap\\+uwaterloo:.*"
1203 (address "abandali@uwaterloo.ca")
1204 (gcc "\"nnimap+uwaterloo:Sent Items\"")))))
1206 (use-package gnus-topic
1207 :hook
(gnus-group-mode . gnus-topic-mode
))
1209 (use-package gnus-agent
1211 (setq gnus-agent-synchronize-flags
'ask
)
1212 :hook
(gnus-group-mode . gnus-agent-mode
))
1214 (use-package gnus-group
1216 (setq gnus-permanently-visible-groups
"\\((INBOX\\|gnu$\\)"))
1218 (use-package mm-decode
1220 (setq mm-discouraged-alternatives
'("text/html" "text/richtext")))
1222 (use-package sendmail
1224 (setq sendmail-program
"/usr/bin/msmtp"
1225 ;; message-sendmail-extra-arguments '("-v" "-d")
1226 mail-specify-envelope-from t
1227 mail-envelope-from
'header
))
1229 (use-package message
1231 (defconst amin--message-cite-style-format
"On %Y-%m-%d %l:%M %p, %N wrote:")
1232 (defconst message-cite-style-bandali
1233 '((message-cite-function 'message-cite-original
)
1234 (message-citation-line-function 'message-insert-formatted-citation-line
)
1235 (message-cite-reply-position 'traditional
)
1236 (message-yank-prefix "> ")
1237 (message-yank-cited-prefix ">")
1238 (message-yank-empty-prefix ">")
1239 (message-citation-line-format
1240 (if amin--message-cite-say-hi
1241 (concat "Hi %F,\n\n" amin--message-cite-style-format
)
1242 amin--message-cite-style-format
)))
1243 "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.")
1244 (setq message-cite-style
'message-cite-style-bandali
1245 message-kill-buffer-on-exit t
1246 message-send-mail-function
'message-send-mail-with-sendmail
1247 message-sendmail-envelope-from
'header
1248 message-dont-reply-to-names
1249 "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)"
1250 message-user-fqdn
"aminb.org")
1251 :hook
(;; (message-setup . mml-secure-message-sign-pgpmime)
1252 (message-mode . flyspell-mode
)
1253 (message-mode .
(lambda ()
1254 ;; (setq fill-column 65
1255 ;; message-fill-column 65)
1256 (make-local-variable 'company-idle-delay
)
1257 (setq company-idle-delay
0.2))))
1259 ;; (message-header-subject ((t (:foreground "#111" :weight semi-bold))))
1260 ;; (message-header-to ((t (:foreground "#111" :weight normal))))
1261 ;; (message-header-cc ((t (:foreground "#333" :weight normal))))
1265 (setq mml-secure-openpgp-encrypt-to-self t
1266 mml-secure-openpgp-sign-with-sender t
))
1268 (use-package footnote
1271 (:map message-mode-map
1272 :prefix-map amin--footnote-prefix-map
1274 ("a" . footnote-add-footnote
)
1275 ("b" . footnote-back-to-message
)
1276 ("c" . footnote-cycle-style
)
1277 ("d" . footnote-delete-footnote
)
1278 ("g" . footnote-goto-footnote
)
1279 ("r" . footnote-renumber-footnotes
)
1280 ("s" . footnote-set-style
))
1282 (setq footnote-start-tag
""
1284 footnote-style
'unicode
))
1287 :load-path
"lisp/bbdb"
1289 (load (expand-file-name "lisp/bbdb/bbdb-autoloads.el" user-emacs-directory
))
1290 ;; (bbdb-mua-auto-update-init 'message)
1291 (setq bbdb-mua-auto-update-p
'query
1292 bbdb-complete-mail nil
)
1293 (bbdb-initialize 'gnus
'message
))
1295 (use-package message-x
1298 (message-x-completion-alist
1300 (("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" . gnus-harvest-find-address
)
1303 (quote message-newgroups-header-regexp
))
1304 message-newgroups-header-regexp message-newsgroups-header-regexp
)
1305 . message-expand-group
)))))
1307 (use-package gnus-harvest
1309 :commands gnus-harvest-install
1312 (if (featurep 'message-x
)
1313 (gnus-harvest-install 'message-x
)
1314 (gnus-harvest-install)))
1316 (use-package ox-hugo
1319 (use-package ox-hugo-auto-export
1320 :load-path
"lib/ox-hugo")
1322 (message "Loading %s...done (%.3fs)" user-init-file
1323 (float-time (time-subtract (current-time)
1324 amin--before-user-init-time
)))
1326 ;;; init.el ends here