X-Git-Url: https://git.shemshak.org/~bandali/configs/blobdiff_plain/620ed6895854c0b82e72a9acedd481e5e14cf80a..fda74f52b706447243a113efa4c768c80ead09de:/init.org diff --git a/init.org b/init.org index d90812e..cd210db 100644 --- a/init.org +++ b/init.org @@ -65,7 +65,7 @@ make build ** First line #+begin_src emacs-lisp :comments none -;;; init.el --- Amin Bandali's Emacs config -*- lexical-binding: t ; eval: (view-mode 1)-*- +;;; init.el --- Amin Bandali's Emacs config -*- lexical-binding: t; eval: (view-mode 1) -*- #+end_src Enable =view-mode=, which both makes the file read-only (as a reminder @@ -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 @@ -113,7 +113,6 @@ The conventions below were inspired by [[https://github.com/hlissner/doom-emacs] ;; amin-... public variables or non-interactive functions ;; amin--... private anything (non-interactive), not safe for direct use ;; amin/... an interactive function; safe for M-x or keybinding -;; amin:... an evil operator, motion, or command ;; amin|... a hook function ;; amin*... an advising function ;; amin@... a hydra command @@ -125,10 +124,6 @@ The conventions below were inspired by [[https://github.com/hlissner/doom-emacs] :CUSTOM_ID: initial-setup :END: -#+begin_src emacs-lisp :comments none -;;; Code: -#+end_src - ** Emacs initialization I'd like to do a couple of measurements of Emacs' startup time. First, @@ -240,10 +235,11 @@ can then be managed with the help of Magit or other tools. (with-eval-after-load 'bind-key (bind-keys :package borg - ("C-c B A" . borg-activate) - ("C-c B a" . borg-assimilate) - ("C-c B b" . borg-build) - ("C-c B c" . borg-clone))) + ("C-c b A" . borg-activate) + ("C-c b a" . borg-assimilate) + ("C-c b b" . borg-build) + ("C-c b c" . borg-clone) + ("C-c b r" . borg-remove))) #+end_src *** =use-package= @@ -281,10 +277,9 @@ database, low-level functions for querying the database, and a (use-package epkg :defer t :bind - (("C-c B d" . epkg-describe-package) - ("C-c B p" . epkg-list-packages) - ("C-c B r" . borg-remove) - ("C-c B u" . epkg-update))) + (("C-c b d" . epkg-describe-package) + ("C-c b p" . epkg-list-packages) + ("C-c b u" . epkg-update))) #+end_src ** No littering in =~/.emacs.d= @@ -326,8 +321,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 @@ -347,7 +345,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) @@ -355,7 +353,7 @@ in my shell. (mapc #'disable-theme custom-enabled-themes)) #+end_src -** COMMENT Server +** Server Start server if not already running. Alternatively, can be done by issuing =emacs --daemon= in the terminal, which can be automated with @@ -376,7 +374,7 @@ See [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.htm Font stack with better unicode support, around =Ubuntu Mono= and =Hack=. -#+begin_src emacs-lisp :tangle no +#+begin_src emacs-lisp (dolist (ft (fontset-list)) (set-fontset-font ft @@ -415,6 +413,24 @@ Font stack with better unicode support, around =Ubuntu Mono= and (setq text-scale-mode-step 1.05) #+end_src +** Focus follows mouse + +I’d like focus to follow the mouse when I move the cursor from one +window to the next. + +#+begin_src emacs-lisp +(setq mouse-autoselect-window t) +#+end_src + +Let’s define a function to conveniently disable this for certain +buffers and/or modes. + +#+begin_src emacs-lisp +(defun amin--no-mouse-autoselect-window () + (make-local-variable 'mouse-autoselect-window) + (setq mouse-autoselect-window nil)) +#+end_src + ** Libraries #+begin_src emacs-lisp @@ -610,7 +626,7 @@ Enable automatic reloading of changed buffers and files. #+begin_src emacs-lisp (global-auto-revert-mode 1) (setq auto-revert-verbose nil - global-auto-revert-non-file-buffers t) + global-auto-revert-non-file-buffers nil) #+end_src *** Always use space for indentation @@ -630,7 +646,7 @@ Enable =winner-mode=. (winner-mode 1) #+end_src -*** Close =*compilation*= on success +*** COMMENT Close =*compilation*= on success #+begin_src emacs-lisp (setq compilation-exit-message-function @@ -644,22 +660,40 @@ 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 (bind-keys - ("C-c b k" . kill-this-buffer) - ("C-c b s" . save-buffer) - ("C-c S" . save-buffer) - ("C-c o" . other-window) - ("C-c q q" . save-buffers-kill-terminal) + ("C-c a i" . ielm) + + ("C-c e b" . eval-buffer) + ("C-c e r" . eval-region) ("C-c F m" . make-frame-command) ("C-c F d" . delete-frame) ("C-c F D" . delete-other-frames) - ("s-c e b" . eval-buffer) - ("s-c e r" . eval-region) + ("C-c o" . other-window) + + ("C-c Q" . save-buffers-kill-terminal) + + ("C-S-h C" . describe-char) + ("C-S-h F" . describe-face) + + ("C-x K" . kill-this-buffer) ("s-p" . beginning-of-buffer) ("s-n" . end-of-buffer)) @@ -701,20 +735,32 @@ In short, my favourite way of life. #+begin_src emacs-lisp (use-package org - :defer 3 + :defer 1 :config (setq org-src-tab-acts-natively t 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) + (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 @@ -781,7 +827,8 @@ file. ',file-tangle-start-time))) "")) (when amin-async-tangle-post-compile - (compile amin-async-tangle-post-compile))) + (save-window-excursion + (compile amin-async-tangle-post-compile)))) (message "Tangling %s failed" ,file-nodir)))))))) (add-to-list @@ -799,29 +846,21 @@ Not just how I do git, but /the/ way to do git. #+begin_src emacs-lisp (use-package magit - :defer 2 - :bind - (("s-g" . magit-status) - :prefix-map amin--magit-prefix-map - :prefix "C-c g" - ("SPC" . magit-status) - ("s" . magit-status) - ("S" . magit-status-prefix) - ("B" . magit-blame-addition) - ("C" . magit-clone) - ("f" . magit-fetch-other) - ("F" . magit-pull-branch) - ("P" . magit-push-other) - ("p" . magit-dispatch-popup) - ("c c" . magit-commit-create) - ("c a" . magit-commit-amend) - ("b b" . magit-checkout) - ("b c" . magit-branch-create)) + :defer 1 + :bind (("C-x g" . magit-status) + ("s-g s" . magit-status) + ("s-g l" . magit-log-buffer-file)) :config (magit-add-section-hook 'magit-status-sections-hook 'magit-insert-modules 'magit-insert-stashes 'append) + (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 @@ -840,8 +879,7 @@ There's no way I could top that, so I won't attempt to. (use-package ivy :defer 1 :bind - (("C-c b b" . ivy-switch-buffer) - :map ivy-minibuffer-map + (:map ivy-minibuffer-map ([escape] . keyboard-escape-quit) ([S-up] . ivy-previous-history-element) ([S-down] . ivy-next-history-element) @@ -849,10 +887,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 @@ -884,7 +923,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)) @@ -901,11 +940,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 @@ -915,7 +961,6 @@ There's no way I could top that, so I won't attempt to. :defer t :bind (("C-x C-b" . ibuffer-other-window) - ("C-c b B" . ibuffer-other-window) :map ibuffer-mode-map ("P" . ibuffer-backward-filter-group) ("N" . ibuffer-forward-filter-group) @@ -1018,7 +1063,9 @@ TODO: break this giant source block down into individual org sections. (use-package help :defer t - :config (temp-buffer-resize-mode)) + :config + (temp-buffer-resize-mode) + (setq help-window-select t)) (progn ; `isearch' (setq isearch-allow-scroll t)) @@ -1061,7 +1108,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 @@ -1071,13 +1119,6 @@ TODO: break this giant source block down into individual org sections. (add-to-list 'tramp-default-proxies-alist (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)) #+end_src * Editing @@ -1086,13 +1127,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_\\|[-_]") @@ -1103,6 +1143,7 @@ TODO: break this giant source block down into individual org sections. #+end_src * Syntax and spell checking + #+begin_src emacs-lisp (use-package flycheck :defer 3 @@ -1415,19 +1456,11 @@ instead. :hook (web-mode css-mode html-mode sgml-mode)) #+end_src -** Nix - -#+begin_src emacs-lisp -(use-package nix-mode - :defer t - :mode "\\.nix\\'") -#+end_src - -** Java +** COMMENT Java *** meghanada -#+begin_src emacs-lisp :tangle no +#+begin_src emacs-lisp (use-package meghanada :bind (:map meghanada-mode-map @@ -1454,7 +1487,7 @@ tree-mode treemacs #+end_comment -#+begin_src emacs-lisp :tangle no +#+begin_src emacs-lisp (use-package treemacs :config (setq treemacs-never-persist t)) @@ -1504,6 +1537,23 @@ treemacs :after (treemacs)) #+end_src +** geiser + +#+begin_src emacs-lisp +(use-package geiser) + +(use-package geiser-guile + :config + (setq geiser-guile-load-path "~/src/git/guix")) +#+end_src + +** guix + +#+begin_src emacs-lisp +(use-package guix + :load-path "lib/guix/elisp") +#+end_src + * Emacs Enhancements ** [[https://github.com/justbur/emacs-which-key][which-key]] @@ -1518,14 +1568,47 @@ 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 +(add-to-list 'custom-theme-load-path "~/.emacs.d/lisp") +(load-theme 'tangomod t) +#+end_src + +** smart-mode-line #+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)) + (sml/setup)) +#+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) + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'tangomod t) + (sml/apply-theme 'automatic)) + +(defun amin/lights-off () + "Go dark." + (interactive) + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'doom-tomorrow-night t) + (sml/apply-theme 'automatic)) + +(bind-keys + ("s-t d" . amin/lights-off) + ("s-t l" . amin/lights-on)) #+end_src ** [[https://github.com/bbatsov/crux][crux]] @@ -1533,14 +1616,14 @@ Emacs package that displays available keybindings in popup #+begin_src emacs-lisp (use-package crux :defer 1 - :bind (("C-c d" . crux-duplicate-current-line-or-region) - ("C-c M-d" . crux-duplicate-and-comment-current-line-or-region) - ("C-c b K" . crux-kill-other-buffers) - ("C-c f C" . crux-copy-file-preserve-attributes) - ("C-c f D" . crux-delete-file-and-buffer) - ("C-c f R" . crux-rename-file-and-buffer) - ("C-S-j" . crux-top-join-line) - ("C-c j" . crux-top-join-line))) + :bind (("C-c b k" . crux-kill-other-buffers) + ("C-c d" . crux-duplicate-current-line-or-region) + ("C-c D" . crux-duplicate-and-comment-current-line-or-region) + ("C-c f c" . crux-copy-file-preserve-attributes) + ("C-c f d" . crux-delete-file-and-buffer) + ("C-c f r" . crux-rename-file-and-buffer) + ("C-c j" . crux-top-join-line) + ("C-S-j" . crux-top-join-line))) #+end_src ** [[https://github.com/alezost/mwim.el][mwim]] @@ -1557,7 +1640,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) @@ -1580,33 +1663,58 @@ Emacs package that displays available keybindings in popup (use-package helpful :defer 1 :bind - (;; ("C-h F" . helpful-function) - ("C-h f" . helpful-callable) - ("C-h v" . helpful-variable) - ("C-h k" . helpful-key) - ("C-c C-d" . helpful-at-point) - ("C-h C" . helpful-command) - ("C-h c" . describe-char) - ("C-h F" . describe-face))) - -(use-package help - :bind - (("C-S-h f" . describe-function) - ("C-S-h v" . describe-variable) - ("C-S-h k" . describe-key) - ("C-S-h C" . describe-coding-system) - ("C-S-h c" . describe-key-briefly)) - :config (setq help-window-select t)) + (("C-S-h c" . helpful-command) + ("C-S-h f" . helpful-callable) ; helpful-function + ("C-S-h v" . helpful-variable) + ("C-S-h k" . helpful-key) + ("C-S-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 + :bind ("C-c a s 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]] @@ -1619,6 +1727,7 @@ Make =*scratch*= and =*Messages*= unkillable. :config (unkillable-scratch 1) :custom + (unkillable-scratch-behavior 'do-nothing) (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$"))) #+end_src @@ -1660,7 +1769,7 @@ Make =*scratch*= and =*Messages*= unkillable. Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. -** [[https://github.com/DarthFennec/highlight-indent-guides][highlight-indent-guides]] +** COMMENT [[https://github.com/DarthFennec/highlight-indent-guides][highlight-indent-guides]] #+begin_src emacs-lisp (use-package highlight-indent-guides @@ -1696,12 +1805,6 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. ("l" . image-forward-hscroll))) #+end_src -** anzu - -#+begin_src emacs-lisp -(use-package anzu) -#+end_src - ** typo.el #+begin_src emacs-lisp @@ -1712,7 +1815,47 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. :hook (text-mode . typo-mode)) #+end_src -** slack +** hl-todo + +#+begin_src emacs-lisp +(use-package hl-todo + :defer 4 + :config + (global-hl-todo-mode)) +#+end_src + +** shrink-path + +#+begin_src emacs-lisp +(use-package shrink-path + :after eshell + :config + (setq eshell-prompt-regexp "\\(.*\n\\)*λ " + eshell-prompt-function #'+eshell/prompt) + + (defun +eshell/prompt () + (let ((base/dir (shrink-path-prompt default-directory))) + (concat (propertize (car base/dir) + 'face 'font-lock-comment-face) + (propertize (cdr base/dir) + 'face 'font-lock-constant-face) + (propertize (+eshell--current-git-branch) + 'face 'font-lock-function-name-face) + "\n" + (propertize "λ" 'face 'eshell-prompt-face) + ;; needed for the input text to not have prompt face + (propertize " " 'face 'default)))) + + (defun +eshell--current-git-branch () + (let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n") + when (string-match "^\*" match) + collect match)))) + (if (not (eq branch nil)) + (concat " " (substring branch 2)) + "")))) +#+end_src + +** COMMENT slack Hopefully temporary. @@ -1747,6 +1890,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) @@ -1774,56 +1920,52 @@ Hopefully temporary. (setq alert-default-style 'notifier)) #+end_src -** hl-todo +** [[https://github.com/peterwvj/eshell-up][eshell-up]] #+begin_src emacs-lisp -(use-package hl-todo - :defer 4 - :config - (global-hl-todo-mode)) +(use-package eshell-up + :after eshell) #+end_src -** shrink-path +** multi-term #+begin_src emacs-lisp -(use-package shrink-path - :after eshell +(use-package multi-term + :defer 1 + :bind (("C-c C-j" . term-line-mode) + ("C-c a s m m" . multi-term) + ("C-c a s m p" . multi-term-dedicated-toggle)) :config - (setq eshell-prompt-regexp "\\(.*\n\\)*λ " - eshell-prompt-function #'+eshell/prompt) - - (defun +eshell/prompt () - (let ((base/dir (shrink-path-prompt default-directory))) - (concat (propertize (car base/dir) - 'face 'font-lock-comment-face) - (propertize (cdr base/dir) - 'face 'font-lock-constant-face) - (propertize (+eshell--current-git-branch) - 'face 'font-lock-function-name-face) - "\n" - (propertize "λ" 'face 'eshell-prompt-face) - ;; needed for the input text to not have prompt face - (propertize " " 'face 'default)))) - - (defun +eshell--current-git-branch () - (let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n") - when (string-match "^\*" match) - collect match)))) - (if (not (eq branch nil)) - (concat " " (substring branch 2)) - "")))) -#+end_src - -** magithub - -For when I /have to/ use GH. - -#+begin_src emacs-lisp -(use-package magithub - :after magit + (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 + +** page-break-lines + +#+begin_src emacs-lisp +(use-package page-break-lines :config - (magithub-feature-autoinject t) - (setq magithub-clone-default-directory "~/src/git")) + (global-page-break-lines-mode)) #+end_src * Email @@ -1843,8 +1985,10 @@ For when I /have to/ use GH. read-mail-command 'gnus) (use-package gnus - :bind (("s-m" . gnus) - ("s-M" . gnus-unplugged)) + :bind (("C-c m" . gnus) + ("C-c M" . gnus-unplugged) + ("s-m" . gnus) + ("s-M" . gnus-unplugged)) :init (setq gnus-select-method '(nnnil "") @@ -1861,7 +2005,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))) @@ -1916,15 +2060,22 @@ For when I /have to/ use GH. :map gnus-summary-mode-map ("r" . gnus-summary-reply-with-original) ("R" . gnus-summary-wide-reply-with-original) - ("M-L" . org-store-link))) + ("M-L" . org-store-link)) + :hook (gnus-summary-mode . amin--no-mouse-autoselect-window)) (use-package gnus-msg :config (setq gnus-posting-styles '((".*" - (address "amin@aminb.org")) + (address "amin@aminb.org") + (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\""))))) @@ -1962,20 +2113,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 @@ -2006,233 +2175,68 @@ Convenient footnotes in =message-mode=. footnote-style 'unicode)) #+end_src -** supercite - -#+begin_src emacs-lisp :tangle no -(use-package supercite - :commands sc-cite-original - :init - (add-hook 'mail-citation-hook 'sc-cite-original) +** bbdb - (defun sc-remove-existing-signature () - (save-excursion - (goto-char (region-beginning)) - (when (re-search-forward message-signature-separator (region-end) t) - (delete-region (match-beginning 0) (region-end))))) +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. - (add-hook 'mail-citation-hook 'sc-remove-existing-signature) +#+begin_src conf :tangle no +[submodule "bbdb"] + path = lib/bbdb + url = https://git.savannah.nongnu.org/git/bbdb.git + load-path = lisp + info-path = doc + build-step = ./autogen.sh + build-step = ./configure + build-step = make + build-step = make install +#+end_src - (defun sc-remove-if-not-mailing-list () - (unless (assoc "list-id" sc-mail-info) - (setq attribution sc-default-attribution - citation (concat sc-citation-delimiter - sc-citation-separator)))) +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. - (add-hook 'sc-attribs-postselect-hook 'sc-remove-if-not-mailing-list) +#+begin_src emacs-lisp +(use-package bbdb + :load-path "lisp/bbdb" + :init + (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 - :config - (defun sc-fill-if-different (&optional prefix) - "Fill the region bounded by `sc-fill-begin' and point. -Only fill if optional PREFIX is different than -`sc-fill-line-prefix'. If `sc-auto-fill-region-p' is nil, do not -fill region. If PREFIX is not supplied, initialize fill -variables. This is useful for a regi `begin' frame-entry." - (if (not prefix) - (setq sc-fill-line-prefix "" - sc-fill-begin (line-beginning-position)) - (if (and sc-auto-fill-region-p - (not (string= prefix sc-fill-line-prefix))) - (let ((fill-prefix sc-fill-line-prefix)) - (unless (or (string= fill-prefix "") - (save-excursion - (goto-char sc-fill-begin) - (or (looking-at ">+ +") - (< (length - (buffer-substring (point) - (line-end-position))) - 65)))) - (fill-region sc-fill-begin (line-beginning-position))) - (setq sc-fill-line-prefix prefix - sc-fill-begin (line-beginning-position))))) -nil)) -#+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" "