X-Git-Url: https://git.shemshak.org/~bandali/configs/blobdiff_plain/05f602d9cfaf567dd0d21bd5c15e9261eb08465c..a5f4a7d98c7b935a523c993c80d28df4e525db73:/init.org?ds=inline diff --git a/init.org b/init.org index b6fe1b8..7c12ad5 100644 --- a/init.org +++ b/init.org @@ -76,7 +76,7 @@ file. ** License #+begin_src emacs-lisp :comments none -;; Copyright (C) 2018 Amin Bandali +;; Copyright (C) 2018 Amin Bandali ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -327,8 +327,11 @@ it it's own file. While at it, treat themes as safe. ** Secrets file +Load the secrets file if it exists, otherwise show a warning. + #+begin_src emacs-lisp -(load (no-littering-expand-etc-file-name "secrets")) +(with-demoted-errors + (load (no-littering-expand-etc-file-name "secrets"))) #+end_src ** Better =$PATH= handling @@ -348,7 +351,7 @@ in my shell. (exec-path-from-shell-copy-env "SSH_AUTH_SOCK")) #+end_src -** Only one custom theme at a time +** COMMENT Only one custom theme at a time #+begin_src emacs-lisp (defadvice load-theme (before clear-previous-themes activate) @@ -645,6 +648,19 @@ Enable =winner-mode=. (cons msg code))) #+end_src +*** Search for non-ASCII characters + +I’d like non-ASCII characters such as ‘’“”«»‹›áⓐ𝒶 to be selected when +I search for their ASCII counterpart. Shoutout to [[http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html][endlessparentheses]] +for this. + +#+begin_src emacs-lisp +(setq search-default-mode #'char-fold-to-regexp) + +;; uncomment to extend this behaviour to query-replace +;; (setq replace-char-fold t) +#+end_src + ** Bindings #+begin_src emacs-lisp @@ -703,23 +719,20 @@ customizing it. (use-package evil :demand t ;; :hook (org-src-mode . evil-motion-state) - :init - (setq evil-want-integration nil) :config (evil-mode 1) (general-swap-key nil '(normal motion) ";" ":") - (setq - evil-want-visual-char-semi-exclusive t - evil-move-beyond-eol t - ;; evil-move-cursor-back nil - ) + (setq evil-want-visual-char-semi-exclusive t + evil-cross-lines t) - ;; motion state modes - (dolist (mode '(ebdb-mode - helpful-mode - view-mode)) - (evil-set-initial-state mode 'motion)) + ;; custom mode state mappings + (dolist (mspair '((ebdb-mode . emacs) + (term-mode . emacs) + (helpful-mode . motion) + (magit-blame-mode . motion) + (view-mode . motion))) + (evil-set-initial-state (car mspair) (cdr mspair))) ;; fix tab and indentation in src blocks inside org-mode buffer ;; also see https://git.sr.ht/~bandali/dotfiles/commit/0e2ffd584aafdd4cf256bcdf2473f01c3aaaed55 @@ -731,7 +744,14 @@ customizing it. (unbind-key "C-a" evil-insert-state-map) (unbind-key "C-e" evil-insert-state-map) (unbind-key "C-p" evil-insert-state-map) - (unbind-key "C-n" evil-insert-state-map)) + (unbind-key "C-n" evil-insert-state-map) + (unbind-key "C-k" evil-insert-state-map) + (bind-keys + :map evil-insert-state-map + ("C-k" . kill-line) + ("C-S-k" . evil-insert-digraph) + :map evil-motion-state-map + ([down-mouse-1] . nil))) #+end_src #+begin_src emacs-lisp @@ -751,10 +771,36 @@ customizing it. (push #'minibufferp evil-escape-inhibit-functions)) #+end_src +#+begin_src emacs-lisp +(use-package evil-nerd-commenter + :after evil + :general + (nmap + "gc" 'evilnc-comment-operator + "gy" 'evilnc-copy-and-comment-lines)) +#+end_src + +#+begin_src emacs-lisp +(use-package evil-surround + :after evil + :general + (omap + "s" 'evil-surround-edit + "S" 'evil-Surround-edit) + (vmap + "S" 'evil-surround-region + "gS" 'evil-Surround-region)) +#+end_src + #+begin_src emacs-lisp (amin--leader-keys "/" '(:ignore t :wk "search") + "a" '(:ignore t :wk "apps") + "a i" 'ielm + + "a s" '(:ignore t :wk "shells/terms") + "b" '(:ignore t :wk "buffers") "b k" 'kill-this-buffer "b s" 'save-buffer @@ -763,8 +809,6 @@ customizing it. "e b" 'eval-buffer "e r" 'eval-region - "e e" 'shell-pop - "f" '(:ignore t :wk "files") "F" '(:ignore t :wk "frames") @@ -786,6 +830,12 @@ customizing it. "w" '(:ignore t :wk "window") "w o" 'other-window + "w 0" 'delete-window + "w 1" 'delete-other-windows + "w 2" 'split-window-below + "w 3" 'split-window-right + "w u" 'winner-undo + "w r" 'winner-redo "q" '(:ignore t :wk "quit") "q q" 'save-buffers-kill-terminal) @@ -803,7 +853,7 @@ In short, my favourite way of life. #+begin_src emacs-lisp (use-package org - :defer 3 + :defer 1 :general (amin--leader-keys :states 'normal @@ -825,6 +875,7 @@ In short, my favourite way of life. org-src-preserve-indentation nil org-edit-src-content-indentation 0 org-email-link-description-format "Email %c: %s" ; %.30s + org-highlight-latex-and-related '(entities) org-log-done 'time) (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t) (after! org-src @@ -838,12 +889,23 @@ In short, my favourite way of life. (org-edit-src-save) (org-edit-src-exit))) (define-key org-src-mode-map [remap evil-quit] 'org-edit-src-abort)) + (font-lock-add-keywords + 'org-mode + '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)" + (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive + (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind + (4 '(:foreground "#c5c8c6") t))) ; title + t) :bind (:map org-mode-map ("M-L" . org-insert-last-stored-link)) :hook ((org-mode . org-indent-mode) (org-mode . auto-fill-mode) (org-mode . flyspell-mode)) :custom - (org-latex-packages-alist '(("" "listings") ("" "color")))) + (org-latex-packages-alist '(("" "listings") ("" "color"))) + :custom-face + '(org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21")))) + '(org-block ((t (:background "#1d1f21")))) + '(org-latex-and-related ((t (:foreground "#b294bb"))))) (use-package ox-latex :after ox @@ -935,7 +997,7 @@ Not just how I do git, but /the/ way to do git. #+begin_src emacs-lisp (use-package magit - :defer 2 + :defer 1 :general (amin--leader-keys "g s" 'magit-status) :bind ("s-g" . magit-status) :config @@ -946,6 +1008,9 @@ Not just how I do git, but /the/ way to do git. (setq magit-repository-directories '(("~/.emacs.d/" . 0) ("~/src/git/" . 1))) + (nconc magit-section-initial-visibility-alist + '(([unpulled status] . show) + ([unpushed status] . show))) :custom-face (magit-diff-file-heading ((t (:weight normal))))) #+end_src @@ -973,10 +1038,11 @@ There's no way I could top that, so I won't attempt to. :config (setq ivy-wrap t) (ivy-mode 1) - :custom-face - (ivy-minibuffer-match-face-2 ((t (:background "#e99ce8" :weight semi-bold)))) - (ivy-minibuffer-match-face-3 ((t (:background "#bbbbff" :weight semi-bold)))) - (ivy-minibuffer-match-face-4 ((t (:background "#ffbbff" :weight semi-bold))))) + ;; :custom-face + ;; (ivy-minibuffer-match-face-2 ((t (:background "#e99ce8" :weight semi-bold)))) + ;; (ivy-minibuffer-match-face-3 ((t (:background "#bbbbff" :weight semi-bold)))) + ;; (ivy-minibuffer-match-face-4 ((t (:background "#ffbbff" :weight semi-bold)))) +) #+end_src **** Swiper @@ -1014,7 +1080,7 @@ There's no way I could top that, so I won't attempt to. #+begin_src emacs-lisp (use-package eshell - :defer t + :defer 1 :commands eshell :config (eval-when-compile (defvar eshell-prompt-regexp)) @@ -1031,11 +1097,18 @@ There's no way I could top that, so I won't attempt to. (eshell-send-input)) (defun amin|eshell-setup () + (make-local-variable 'company-idle-delay) + (setq company-idle-delay nil) (bind-keys :map eshell-mode-map - ("C-d" . amin/eshell-quit-or-delete-char) - ("C-l" . amin/eshell-clear))) + ("C-d" . amin/eshell-quit-or-delete-char) + ("C-S-l" . amin/eshell-clear) + ("M-r" . counsel-esh-history) + ([tab] . company-complete))) - :hook (eshell-mode . amin|eshell-setup)) + :hook (eshell-mode . amin|eshell-setup) + :custom + (eshell-hist-ignoredups t) + (eshell-input-filter 'eshell-input-filter-initial-space)) #+end_src *** Ibuffer @@ -1193,7 +1266,8 @@ TODO: break this giant source block down into individual org sections. :config (column-number-mode)) (progn ; `text-mode' - (add-hook 'text-mode-hook #'indicate-buffer-boundaries-left)) + (add-hook 'text-mode-hook #'indicate-buffer-boundaries-left) + (add-hook 'text-mode-hook #'abbrev-mode)) (use-package tramp :defer t @@ -1204,12 +1278,14 @@ TODO: break this giant source block down into individual org sections. (list (regexp-quote (system-name)) nil nil))) (use-package undo-tree - :bind (("C-?" . undo-tree-undo) - ("M-_" . undo-tree-redo)) :config - (global-undo-tree-mode) - (setq undo-tree-mode-lighter "" - undo-tree-auto-save-history t)) + (global-undo-tree-mode -1)) + ;; :bind (("C-?" . undo-tree-undo) + ;; ("M-_" . undo-tree-redo)) + ;; :config + ;; (global-undo-tree-mode) + ;; (setq undo-tree-mode-lighter "" + ;; undo-tree-auto-save-history t)) #+end_src * Editing @@ -1218,13 +1294,12 @@ TODO: break this giant source block down into individual org sections. #+begin_src emacs-lisp (use-package company - :defer 2 + :defer 1 :bind (:map company-active-map ([tab] . company-complete-common-or-cycle) ([escape] . company-abort)) :custom - (company-idle-delay 0.3) (company-minimum-prefix-length 1) (company-selection-wrap-around t) (company-dabbrev-char-regexp "\\sw\\|\\s_\\|[-_]") @@ -1650,14 +1725,49 @@ Emacs package that displays available keybindings in popup :config (which-key-mode)) #+end_src -** [[https://github.com/Malabarba/smart-mode-line][smart-mode-line]] +** theme #+begin_src emacs-lisp -(use-package smart-mode-line - :config - (sml/setup) - ;; (sml/apply-theme 'light) - (remove-hook 'display-time-hook 'sml/propertize-time-string)) +(add-to-list 'custom-theme-load-path "~/.emacs.d/lisp") +(load-theme 'tangomod t) +#+end_src + +** doom-modeline + +#+begin_src emacs-lisp +(use-package doom-modeline + :demand t + :config (setq doom-modeline-height 32) + :hook (after-init . doom-modeline-init)) +#+end_src + +** doom-themes + +#+begin_src emacs-lisp +(use-package doom-themes) +#+end_src + +** theme helper functions + +#+begin_src emacs-lisp +(defun amin/lights-on () + "Enable my favourite light theme." + (interactive) + (progn + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'tangomod t))) + +(defun amin/lights-off () + "Go dark." + (interactive) + (progn + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'doom-tomorrow-night t))) + +(amin--leader-keys + "t" '(:ignore t :wk "theme") + "t d" 'amin/lights-off + "t l" 'amin/lights-on) #+end_src ** [[https://github.com/bbatsov/crux][crux]] @@ -1697,7 +1807,7 @@ Emacs package that displays available keybindings in popup #+begin_src emacs-lisp (use-package projectile - :defer 2 + :defer t :bind-keymap ("C-c p" . projectile-command-map) :config (projectile-mode) @@ -1729,14 +1839,52 @@ Emacs package that displays available keybindings in popup "h h p" 'helpful-at-point)) #+end_src -** [[https://github.com/kyagi/shell-pop-el][shell-pop]] +** [[https://github.com/knu/shell-toggle.el][shell-toggle]] #+begin_src emacs-lisp -(use-package shell-pop - :defer 1 - :init - (setq shell-pop-universal-key "C-c e" - shell-pop-shell-type '("eshell" "*eshell*" (lambda nil (eshell))))) +(use-package shell-toggle + :after eshell + :general (amin--leader-keys "a s e" 'amin/shell-toggle) + :bind ("C-c e" . amin/shell-toggle) + :config + (defun amin/shell-toggle (make-cd) + "Toggle between the shell buffer and whatever buffer you are editing. +With a prefix argument MAKE-CD also insert a \"cd DIR\" command +into the shell, where DIR is the directory of the current buffer. + +When called in the shell buffer returns you to the buffer you were editing +before calling this the first time. + +Options: `shell-toggle-goto-eob'" + (interactive "P") + ;; Try to decide on one of three possibilities: + ;; If not in shell-buffer, switch to it. + ;; If in shell-buffer, return to state before going to the shell-buffer + (if (eq (current-buffer) shell-toggle-shell-buffer) + (shell-toggle-buffer-return-from-shell) + (progn + (shell-toggle-buffer-goto-shell make-cd) + (if shell-toggle-full-screen-window-only (delete-other-windows))))) + + ;; override to split horizontally instead + (defun shell-toggle-buffer-switch-to-other-window () + "Switch to other window. +If the current window is the only window in the current frame, +create a new window and switch to it. + +\(This is less intrusive to the current window configuration than +`switch-buffer-other-window')" + (let ((this-window (selected-window))) + (other-window 1) + ;; If we did not switch window then we only have one window and need to + ;; create a new one. + (if (eq this-window (selected-window)) + (progn + (split-window-horizontally) + (other-window 1))))) + + :custom + (shell-toggle-launch-shell 'shell-toggle-eshell)) #+end_src ** [[https://github.com/EricCrosson/unkillable-scratch][unkillable-scratch]] @@ -1749,6 +1897,7 @@ Make =*scratch*= and =*Messages*= unkillable. :config (unkillable-scratch 1) :custom + (unkillable-scratch-behavior 'do-nothing) (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$"))) #+end_src @@ -1877,6 +2026,9 @@ Hopefully temporary. :subscribed-channels '(general) :full-and-display-names t) (add-to-list 'swiper-font-lock-exclude 'slack-message-buffer-mode t) + (setq lui-time-stamp-format "[%Y-%m-%d %H:%M:%S]" + lui-time-stamp-only-when-changed-p t + lui-time-stamp-position 'right) :bind (("C-c s s" . slack-start) ("C-c s u" . slack-select-unread-rooms) @@ -1956,6 +2108,47 @@ For when I /have to/ use GH. (setq magithub-clone-default-directory "~/src/git")) #+end_src +** [[https://github.com/peterwvj/eshell-up][eshell-up]] + +#+begin_src emacs-lisp +(use-package eshell-up + :after eshell) +#+end_src + +** multi-term + +#+begin_src emacs-lisp +(use-package multi-term + :defer 1 + :general (amin--leader-keys + "a s m" 'multi-term + "a s p" 'multi-term-dedicated-toggle) + :bind ("C-c C-j" . term-line-mode) + :config + (setq multi-term-program "/bin/screen" + ;; TODO: add separate bindings for connecting to existing + ;; session vs. always creating a new one + multi-term-dedicated-select-after-open-p t + multi-term-dedicated-window-height 20 + multi-term-dedicated-max-window-height 30 + term-bind-key-alist + '(("C-c C-c" . term-interrupt-subjob) + ("C-c C-e" . term-send-esc) + ("C-k" . kill-line) + ("C-y" . term-paste) + ("M-f" . term-send-forward-word) + ("M-b" . term-send-backward-word) + ("M-p" . term-send-up) + ("M-n" . term-send-down) + ("" . term-send-backward-kill-word) + ("" . term-send-backward-kill-word) + ("M-d" . term-send-delete-word) + ("M-," . term-send-raw) + ("M-." . comint-dynamic-complete)) + term-unbind-key-alist + '("C-z" "C-x" "C-c" "C-h" "C-y" ""))) +#+end_src + * Email #+begin_src emacs-lisp @@ -1995,7 +2188,7 @@ For when I /have to/ use GH. (nnimap-server-port 143) (nnimap-authenticator plain) (nnimap-user "abandali@uwaterloo.ca"))) - gnus-message-archive-group "nnimap:Sent" + gnus-message-archive-group "nnimap+amin:Sent" gnus-parameters '(("gnu.*" (gcc-self . t))) @@ -2057,9 +2250,14 @@ For when I /have to/ use GH. (setq gnus-posting-styles '((".*" (address "amin@aminb.org") - (body "\nBest,\namin\n")) + (body "\nBest,\namin\n") + (eval (setq amin--message-cite-say-hi t))) ("gnu.*" (address "bandali@gnu.org")) + ((header "subject" "ThankCRM") + (to "webmasters-comment@gnu.org") + (body "\nAdded to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n") + (eval (setq amin--message-cite-say-hi nil))) ("nnimap\\+uwaterloo:.*" (address "abandali@uwaterloo.ca") (gcc "\"nnimap+uwaterloo:Sent Items\""))))) @@ -2097,20 +2295,38 @@ For when I /have to/ use GH. #+begin_src emacs-lisp (use-package message :config - (setq message-kill-buffer-on-exit t + (defconst amin--message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:") + (defconst message-cite-style-bandali + '((message-cite-function 'message-cite-original) + (message-citation-line-function 'message-insert-formatted-citation-line) + (message-cite-reply-position 'traditional) + (message-yank-prefix "> ") + (message-yank-cited-prefix ">") + (message-yank-empty-prefix ">") + (message-citation-line-format + (if amin--message-cite-say-hi + (concat "Hi %F,\n\n" amin--message-cite-style-format) + amin--message-cite-style-format))) + "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.") + (setq message-cite-style 'message-cite-style-bandali + message-kill-buffer-on-exit t message-send-mail-function 'message-send-mail-with-sendmail message-sendmail-envelope-from 'header message-dont-reply-to-names - "\\(\\(.*@aminb\\.org\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)" + "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)" message-user-fqdn "aminb.org") :hook (;; (message-setup . mml-secure-message-sign-pgpmime) (message-mode . flyspell-mode) - (message-mode . (lambda () (setq fill-column 65 - message-fill-column 65)))) - :custom-face - (message-header-subject ((t (:foreground "#111" :weight semi-bold)))) - (message-header-to ((t (:foreground "#111" :weight normal)))) - (message-header-cc ((t (:foreground "#333" :weight normal))))) + (message-mode . (lambda () + ;; (setq fill-column 65 + ;; message-fill-column 65) + (make-local-variable 'company-idle-delay) + (setq company-idle-delay 0.2)))) + ;; :custom-face + ;; (message-header-subject ((t (:foreground "#111" :weight semi-bold)))) + ;; (message-header-to ((t (:foreground "#111" :weight normal)))) + ;; (message-header-cc ((t (:foreground "#333" :weight normal)))) + ) (after! mml-sec (setq mml-secure-openpgp-encrypt-to-self t @@ -2141,80 +2357,37 @@ Convenient footnotes in =message-mode=. footnote-style 'unicode)) #+end_src -** supercite +** bbdb -#+begin_src emacs-lisp -(use-package supercite - :after message - :init - (setq sc-nested-citation-p t - ;; sc-cite-blank-lines-p t - sc-citation-leader "" - sc-reference-tag-string "" - sc-auto-fill-region-p nil - sc-confirm-always-p nil) - :config - (defun amin--sc-header () - "Hi ,\n\n writes:" - (let ((sc-mumble "") - (whofrom (sc-whofrom))) - (if whofrom - (insert (sc-hdr "Hi " (sc-mail-field "sc-firstname") ",\n\n") - sc-reference-tag-string - whofrom - " writes:\n")))) - (add-to-list 'sc-rewrite-header-list '(amin--sc-header) t) - (setq sc-preferred-header-style (1- (length sc-rewrite-header-list))) - (add-hook 'mail-citation-hook 'sc-cite-original)) -#+end_src +Manually install bbdb (=lisp/bbdb= copied from an ELPA-based setup), +because installing it from source on Emacs 27 using the following +submodule configuration for some reason doesn’t work and results in +very strange errors when using any of the functions. -** ebdb - -#+begin_src emacs-lisp -(use-package ebdb - :defer 1 - :bind (:map gnus-group-mode-map ("e" . ebdb)) - :config - (setq ebdb-sources (no-littering-expand-var-file-name "ebdb"))) - -(use-package ebdb-com - :after ebdb) - -(use-package ebdb-complete - :after ebdb - :config - (ebdb-complete-enable)) - -(use-package ebdb-gnus - :after ebdb) - -(use-package ebdb-message - :after ebdb) - -;; (use-package ebdb-vcard -;; :after ebdb) -#+end_src - -** COMMENT bbdb - -#+begin_comment +#+begin_src conf :tangle no [submodule "bbdb"] path = lib/bbdb url = https://git.savannah.nongnu.org/git/bbdb.git - load-path = lisp/elisp + load-path = lisp info-path = doc build-step = ./autogen.sh - build-step = ./configure --with-lispdir=elisp + build-step = ./configure build-step = make build-step = make install -#+end_comment +#+end_src + +I tried using =borg-elpa= instead of doing it like this, but it added +2 seconds to my startup time, which is unacceptable to me. #+begin_src emacs-lisp (use-package bbdb + :load-path "lisp/bbdb" :init - (bbdb-mua-auto-update-init 'message) - (setq bbdb-mua-auto-update-p 'query) - (add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)) + (load (expand-file-name "lisp/bbdb/bbdb-autoloads.el" user-emacs-directory)) + ;; (bbdb-mua-auto-update-init 'message) + (setq bbdb-mua-auto-update-p 'query + bbdb-complete-mail nil) + (bbdb-initialize 'gnus 'message)) #+end_src ** COMMENT message-x @@ -2244,181 +2417,6 @@ Convenient footnotes in =message-mode=. (gnus-harvest-install))) #+end_src -** COMMENT gnus-alias :ARCHIVE: - -#+begin_src emacs-lisp -(use-package gnus-alias - :commands (gnus-alias-determine-identity - gnus-alias-select-identity) - :bind (:map message-mode-map - ("s-i" . gnus-alias-select-identity)) - :config - (setq - gnus-alias-default-identity "amin" - gnus-alias-identity-alist - '(("amin" - nil ;; Does not refer to any other identity - "Amin Bandali " - nil ;; Organization - nil ;; extra headers - nil ;; extra body text - nil) ;; signature file - ("gnu" - nil - "Amin Bandali " - nil - nil - nil - nil) - ("uw" - nil - "Amin Bandali " - nil - (("Gcc" . "\"nnimap+uwaterloo:Sent Items\"")) - nil - nil)) - gnus-alias-identity-rules - '(("amin" ("Delivered-To" "