diff options
author | 2020-10-05 23:38:06 -0400 | |
---|---|---|
committer | 2020-10-05 23:38:06 -0400 | |
commit | d7dee82420a04e5c92e5b5ad316e14a49bd4d689 (patch) | |
tree | 9dceac59e3b0d40b0357e8854e191ac5559d41ab /.emacs.d/lisp | |
parent | 927b50b7aec2da105bd5125dec272a89e38663c3 (diff) | |
download | configs-d7dee82420a04e5c92e5b5ad316e14a49bd4d689.tar.gz configs-d7dee82420a04e5c92e5b5ad316e14a49bd4d689.tar.xz configs-d7dee82420a04e5c92e5b5ad316e14a49bd4d689.zip |
Move GNU Emacs configs from ./ into .emacs.d/
I will be using the repository to store my configurations for other
non-Emacs pieces of software. The repository itself will be located
at ~/ rather than ~/.emacs.d/.
Diffstat (limited to '.emacs.d/lisp')
m--------- | .emacs.d/lisp/alloy-mode | 0 | ||||
m--------- | .emacs.d/lisp/amx | 0 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-dired.el | 93 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-ebdb.el | 52 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-erc.el | 178 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-eshell.el | 86 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-exwm.el | 239 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-gnus.el | 478 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-ibuffer.el | 110 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-ivy.el | 74 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-magit.el | 70 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-message.el | 138 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-org.el | 119 | ||||
-rw-r--r-- | .emacs.d/lisp/bandali-theme.el | 87 | ||||
m--------- | .emacs.d/lisp/boxquote | 0 | ||||
-rw-r--r-- | .emacs.d/lisp/gnus-article-treat-patch.el | 465 | ||||
m--------- | .emacs.d/lisp/hl-todo | 0 | ||||
m--------- | .emacs.d/lisp/page-break-lines | 0 | ||||
m--------- | .emacs.d/lisp/s | 0 | ||||
m--------- | .emacs.d/lisp/scpaste | 0 |
20 files changed, 2189 insertions, 0 deletions
diff --git a/.emacs.d/lisp/alloy-mode b/.emacs.d/lisp/alloy-mode new file mode 160000 +Subproject 0d05bdd10c77ec04c3d61eccf67e68c08284951 diff --git a/.emacs.d/lisp/amx b/.emacs.d/lisp/amx new file mode 160000 +Subproject ccfc92c600df681df5e8b5fecec328c462ceb71 diff --git a/.emacs.d/lisp/bandali-dired.el b/.emacs.d/lisp/bandali-dired.el new file mode 100644 index 0000000..9ed1030 --- /dev/null +++ b/.emacs.d/lisp/bandali-dired.el @@ -0,0 +1,93 @@ +;;; bandali-dired.el --- bandali's dired setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: files + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My dired setup and customizations. + +;;; Code: + +(with-eval-after-load 'dired + (csetq + dired-dwim-target t + dired-listing-switches "-alh" + dired-recent-directories-file (b/var "dired-recent-directories.el") + ls-lisp-dirs-first t + ls-lisp-use-insert-directory-program nil) + + (declare-function dired-dwim-target-directory "dired-aux") + ;; easily diff 2 marked files + ;; https://oremacs.com/2017/03/18/dired-ediff/ + (defun dired-ediff-files () + (interactive) + (require 'dired-aux) + (defvar ediff-after-quit-hook-internal) + (let ((files (dired-get-marked-files)) + (wnd (current-window-configuration))) + (if (<= (length files) 2) + (let ((file1 (car files)) + (file2 (if (cdr files) + (cadr files) + (read-file-name + "file: " + (dired-dwim-target-directory))))) + (if (file-newer-than-file-p file1 file2) + (ediff-files file2 file1) + (ediff-files file1 file2)) + (add-hook 'ediff-after-quit-hook-internal + (lambda () + (setq ediff-after-quit-hook-internal nil) + (set-window-configuration wnd)))) + (error "no more than 2 files should be marked")))) + + (defun b/dired-start-process (program &optional args) + "Open current file with a PROGRAM." + ;; Shell command looks like this: "program [ARGS]... FILE" (ARGS + ;; can be nil, so remove it). + (declare-function dired-get-file-for-visit "dired") + (apply #'b/start-process + program + (remove nil (list args (dired-get-file-for-visit))))) + + ;; local key bindings + (define-key dired-mode-map (kbd "b") #'dired-up-directory) + (define-key dired-mode-map (kbd "E") #'dired-ediff-files) + (define-key dired-mode-map (kbd "e") #'dired-toggle-read-only) + (define-key dired-mode-map (kbd "\\") #'dired-hide-details-mode) + (define-key dired-mode-map (kbd "z") + (lambda () + (interactive) + (b/dired-start-process "zathura"))) + + (require 'dired-x) + (csetq dired-guess-shell-alist-user + '(("\\.pdf\\'" "evince" "zathura" "okular") + ("\\.doc\\'" "libreoffice") + ("\\.docx\\'" "libreoffice") + ("\\.ppt\\'" "libreoffice") + ("\\.pptx\\'" "libreoffice") + ("\\.xls\\'" "libreoffice") + ("\\.xlsx\\'" "libreoffice") + ("\\.flac\\'" "mpv")))) +;; hooks +(add-hook 'dired-mode-hook #'dired-hide-details-mode) + +(provide 'bandali-dired) +;;; bandali-dired.el ends here diff --git a/.emacs.d/lisp/bandali-ebdb.el b/.emacs.d/lisp/bandali-ebdb.el new file mode 100644 index 0000000..4d21978 --- /dev/null +++ b/.emacs.d/lisp/bandali-ebdb.el @@ -0,0 +1,52 @@ +;;; bandali-ebdb.el --- bandali's EBDB configuration -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My EBDB setup. + +;;; Code: + +(with-eval-after-load 'gnus + (require 'ebdb) + (csetq ebdb-sources (b/var "ebdb")) + (with-eval-after-load 'swiper + (add-to-list 'swiper-font-lock-exclude #'ebdb-mode t)) + ;; local key bindings + (define-key gnus-group-mode-map (kbd "e") #'ebdb)) + +(with-eval-after-load 'ebdb + (with-eval-after-load 'ebdb-complete + ;; (csetq ebdb-complete-mail 'capf) + (ebdb-complete-enable)) + + (require 'ebdb-message) + + (require 'ebdb-gnus) + (csetq ebdb-gnus-window-size 0.3) + + (require 'ebdb-mua) + (csetq ebdb-mua-pop-up t)) + +;; (with-eval-after-load 'company-ebdb +;; (defun company-ebdb--post-complete (_) nil)) + +(provide 'bandali-ebdb) +;;; bandali-ebdb.el ends here diff --git a/.emacs.d/lisp/bandali-erc.el b/.emacs.d/lisp/bandali-erc.el new file mode 100644 index 0000000..41a152c --- /dev/null +++ b/.emacs.d/lisp/bandali-erc.el @@ -0,0 +1,178 @@ +;;; bandali-erc.el --- bandali's ERC setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My ERC setup for IRC. It uses my fork of ZNC.el. + +;;; Code: + +(defvar b/erc-detach-on-kill t + "Whether killing a channel should send a DETACH command (for ZNC).") + +(with-eval-after-load 'erc + (make-directory (b/var "erc/dcc/") t) + (csetq + erc-auto-query 'bury + erc-autojoin-domain-only nil + erc-dcc-get-default-directory (b/var "erc/dcc/") + erc-format-nick-function 'erc-format-@nick + erc-join-buffer 'bury + erc-log-channels-directory (b/var "erc/log-channels/") + erc-lurker-hide-list '("JOIN" "PART" "QUIT") + erc-nick "bandali" + erc-prompt "erc>" + erc-prompt-for-password nil + erc-rename-buffers t + erc-server-reconnect-attempts 5 + erc-server-reconnect-timeout 3) + + (declare-function erc-message "erc-backend" + (message-command line &optional force)) + (declare-function erc-default-target "erc") + (declare-function erc-current-nick "erc") + (defun erc-cmd-OPME () + "Request chanserv to op me." + (erc-message "PRIVMSG" + (format "chanserv op %s %s" + (erc-default-target) + (erc-current-nick)) nil)) + (declare-function erc-cmd-DEOP "erc" (&rest people)) + (defun erc-cmd-DEOPME () + "Deop myself from current channel." + (erc-cmd-DEOP (format "%s" (erc-current-nick)))) + (add-to-list 'erc-modules 'keep-place) + (add-to-list 'erc-modules 'notifications) + (add-to-list 'erc-modules 'smiley) + (add-to-list 'erc-modules 'spelling) + (declare-function erc-update-modules "erc") + (erc-update-modules) + + (set-face-attribute + 'erc-nick-default-face nil + ;; :weight 'semibold + ;; :background "#f2f2f2" + ;; :foreground "#222222" + :weight 'bold + :background "#f8f8f8" + :foreground "#6a6a6a") + + ;; (set-face-attribute + ;; 'erc-notice-face nil + ;; ;; :background "#fffadf" + ;; ;; :background "#f9f9f9" + ;; :background 'unspecified + ;; ;; :foreground "#809de5" + ;; :foreground "steel blue") + + ;; erc-fill + ;; (csetq + ;; erc-fill-column 77 + ;; erc-fill-function 'erc-fill-variable + ;; erc-fill-static-center 18) + ;; to disable: + ;; (erc-fill-mode -1) + + ;; erc-match + (csetq + erc-pal-highlight-type 'nick + erc-pals + '("aindilis" "blackbeard" "bremner" "brettgilio" "civodul" + "dto" "ggoes" "jrasata" "mplsCorwin" "rwp" "technomancy")) + (with-eval-after-load 'erc-match + (set-face-attribute + 'erc-pal-face nil + :foreground 'unspecified + :weight 'unspecified + :inherit 'erc-nick-default-face + :background (face-attribute 'font-lock-string-face :background))) + + ;; erc-pcomplete + (csetq erc-pcomplete-nick-postfix ", ") + + ;; erc-stamp + (csetq erc-timestamp-only-if-changed-flag nil + erc-timestamp-format "%T " + erc-insert-timestamp-function 'erc-insert-timestamp-left) + (with-eval-after-load 'erc-match + (set-face-attribute + 'erc-timestamp-face nil + :foreground "#aaaaaa" + :weight 'unspecified + :background 'unspecified)) + + ;; erc-track + (csetq + erc-track-enable-keybindings nil + erc-track-exclude-types '("JOIN" "MODE" "NICK" "PART" "QUIT" + "324" "329" "332" "333" "353" "477") + erc-track-position-in-mode-line t + erc-track-priority-faces-only 'all + erc-track-shorten-function nil + erc-track-showcount t) + + ;; key bindings + (global-set-key (kbd "C-c w e") #'erc-switch-to-buffer-other-window) + (define-key erc-mode-map (kbd "M-a") #'erc-track-switch-buffer) + + ;; hooks + (defun b/erc-detach-or-kill-channel () + (if b/erc-detach-on-kill + (when (erc-server-process-alive) + (let ((tgt (erc-default-target))) + (erc-server-send (format "DETACH %s" tgt) nil tgt))) + (erc-kill-channel))) + (add-hook 'erc-kill-channel-hook #'b/erc-detach-or-kill-channel) + (remove-hook 'erc-kill-channel-hook #'erc-kill-channel)) + +;; global key bindings +(global-set-key + (kbd "C-c a e f") + (lambda () + (interactive) + (let* ((auth (auth-source-search :host "znca")) + (p (if (null auth) + (error "Couldn't find znca's authinfo") + (funcall (plist-get (car auth) :secret))))) + (erc-tls :server "znc.emacsconf.org" :port 6697 + :password (concat "bandali/freenode:" p))))) +(global-set-key + (kbd "C-c a e o") + (lambda () + (interactive) + (let* ((auth (auth-source-search :host "znca")) + (p (if (null auth) + (error "Couldn't find znca's authinfo") + (funcall (plist-get (car auth) :secret))))) + (erc-tls :server "znc.emacsconf.org" :port 6697 + :password (concat "bandali/oftc:" p))))) +(global-set-key + (kbd "C-c a e t") + (lambda () + (interactive) + (let* ((auth (auth-source-search :host "znca")) + (p (if (null auth) + (error "Couldn't find znca's authinfo") + (funcall (plist-get (car auth) :secret))))) + (erc-tls :server "znc.emacsconf.org" :port 6697 + :password (concat "bandali/tildechat:" p))))) + +(provide 'bandali-erc) +;;; bandali-erc.el ends here diff --git a/.emacs.d/lisp/bandali-eshell.el b/.emacs.d/lisp/bandali-eshell.el new file mode 100644 index 0000000..820dc05 --- /dev/null +++ b/.emacs.d/lisp/bandali-eshell.el @@ -0,0 +1,86 @@ +;;; bandali-eshell.el --- bandali's Eshell setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: processes + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My awesome Eshell setup. + +;;; Code: + +(with-eval-after-load 'eshell + (make-directory (b/etc "eshell/") t) + (csetq + eshell-aliases-file (b/etc "eshell/aliases") + eshell-directory-name (b/var "eshell/") + eshell-hist-ignoredups t + eshell-input-filter #'eshell-input-filter-initial-space + eshell-prompt-regexp "\\(.*\n\\)*[$#] " + eshell-prompt-function + (lambda () + (concat + (propertize (format "%s@%s:" (user-login-name) (system-name)) + 'face 'default) + (propertize (abbreviate-file-name default-directory) + 'face 'font-lock-comment-face) + (propertize "\n" 'face 'default) + (if (= (user-uid) 0) + (propertize "#" 'face 'red) + (propertize "$" 'face 'default)) + (propertize " " 'face 'default)))) + (eval-when-compile + (defvar eshell-prompt-regexp) + (declare-function eshell-life-is-too-much "esh-mode") + (declare-function eshell-send-input "esh-mode" + (&optional use-region queue-p no-newline))) + (defun b/eshell-quit-or-delete-char (arg) + (interactive "p") + (if (and (eolp) (looking-back eshell-prompt-regexp nil)) + (eshell-life-is-too-much) + (delete-char arg))) + (defun b/eshell-clear () + (interactive) + (let ((inhibit-read-only t)) + (erase-buffer)) + (eshell-send-input)) + (defun b/eshell-setup () + (make-local-variable 'company-idle-delay) + (defvar company-idle-delay) + (eval-when-compile + (defvar eshell-mode-map) + (defvar eshell-hist-mode-map)) + (setq company-idle-delay nil) + ;; local key bindings + (define-key eshell-mode-map (kbd "C-d") + #'b/eshell-quit-or-delete-char) + (define-key eshell-mode-map (kbd "C-S-l") + #'b/eshell-clear) + (define-key eshell-mode-map (kbd "M-r") + #'counsel-esh-history) + ;; (define-key eshell-mode-map [tab] + ;; #'company-complete) + (define-key eshell-hist-mode-map (kbd "M-r") + #'counsel-esh-history))) +;; global key bindings +(global-set-key (kbd "C-c a s e") #'eshell) +;; hooks +(add-hook 'eshell-mode-hook #'b/eshell-setup) + +(provide 'bandali-eshell) +;;; bandali-eshell.el ends here diff --git a/.emacs.d/lisp/bandali-exwm.el b/.emacs.d/lisp/bandali-exwm.el new file mode 100644 index 0000000..6b57898 --- /dev/null +++ b/.emacs.d/lisp/bandali-exwm.el @@ -0,0 +1,239 @@ +;;; bandali-exwm.el --- bandali's EXWM configuration -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My EXWM setup. Makes good use of its simulation keys. + +;;; Code: + +(use-package exwm + :if b/exwm-p + :demand + :config + ;; make class name the buffer name, truncating beyond 60 characters + (defun b/exwm-rename-buffer () + (interactive) + (exwm-workspace-rename-buffer + (concat exwm-class-name ":" + (if (<= (length exwm-title) 60) exwm-title + (concat (substring exwm-title 0 59) "..."))))) + ;; Enable EXWM + (exwm-enable) + :hook ((exwm-update-class . b/exwm-rename-buffer) + (exwm-update-title . b/exwm-rename-buffer))) + +(use-package exwm-config + :demand + :after exwm + :hook (exwm-init . exwm-config--fix/ido-buffer-window-other-frame)) + +(use-package exwm-input + :demand + :after exwm + :config + (defun b/exwm-ws-prev-index () + "Return the index for the previous EXWM workspace, wrapping +around if needed." + (if (= exwm-workspace-current-index 0) + (1- exwm-workspace-number) + (1- exwm-workspace-current-index))) + + (defun b/exwm-ws-next-index () + "Return the index for the next EXWM workspace, wrapping +around if needed." + (if (= exwm-workspace-current-index + (1- exwm-workspace-number)) + 0 + (1+ exwm-workspace-current-index))) + + ;; shorten 'C-c C-q' to 'C-q' + (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key) + + (setq exwm-workspace-number 4 + exwm-input-global-keys + `(([?\s-R] . exwm-reset) + ([?\s-\\] . exwm-workspace-switch) + ([?\s-\s] . dmenu) + ([?\S-\s-\s] . (lambda (command) + (interactive + (list (read-shell-command "➜ "))) + (start-process-shell-command + command nil command))) + ([s-return] . (lambda () + (interactive) + (start-process "" nil "urxvt"))) + ([?\C-\s-\s] . counsel-linux-app) + ([?\M-\s-\s] . (lambda () + (interactive) + (start-process-shell-command + "rofi-pass" nil "rofi-pass"))) + ([?\s-h] . windmove-left) + ([?\s-j] . windmove-down) + ([?\s-k] . windmove-up) + ([?\s-l] . windmove-right) + ([?\s-H] . windmove-swap-states-left) + ([?\s-J] . windmove-swap-states-down) + ([?\s-K] . windmove-swap-states-up) + ([?\s-L] . windmove-swap-states-right) + ([?\M-\s-h] . shrink-window-horizontally) + ([?\M-\s-l] . enlarge-window-horizontally) + ([?\M-\s-k] . shrink-window) + ([?\M-\s-j] . enlarge-window) + ([?\s-\[] . (lambda () + (interactive) + (exwm-workspace-switch-create + (b/exwm-ws-prev-index)))) + ([?\s-\]] . (lambda () + (interactive) + (exwm-workspace-switch-create + (b/exwm-ws-next-index)))) + ([?\s-{] . (lambda () + (interactive) + (exwm-workspace-move-window + (b/exwm-ws-prev-index)))) + ([?\s-}] . (lambda () + (interactive) + (exwm-workspace-move-window + (b/exwm-ws-next-index)))) + ,@(mapcar (lambda (i) + `(,(kbd (format "s-%d" i)) . + (lambda () + (interactive) + (exwm-workspace-switch-create ,i)))) + (number-sequence 0 (1- exwm-workspace-number))) + ([?\s-t] . exwm-floating-toggle-floating) + ([?\s-f] . exwm-layout-toggle-fullscreen) + ([?\s-W] . (lambda () + (interactive) + (kill-buffer (current-buffer)))) + ([?\s-Q] . (lambda () + (interactive) + (exwm-manage--kill-client))) + ([?\s-\'] . (lambda () + (interactive) + (start-process-shell-command + "rofi-light" nil "rofi-light"))) + ([XF86AudioMute] . + (lambda () + (interactive) + (start-process "" nil "amixer" "set" "'Master',0" "toggle"))) + ([XF86AudioLowerVolume] . + (lambda () + (interactive) + (start-process + "" nil "amixer" "set" "'Master',0" "5%-"))) + ([XF86AudioRaiseVolume] . + (lambda () + (interactive) + (start-process + "" nil "amixer" "set" "'Master',0" "5%+"))) + ([XF86AudioPlay] . + (lambda () + (interactive) + (start-process "" nil "mpc" "toggle"))) + ([XF86AudioPrev] . + (lambda () + (interactive) + (start-process "" nil "mpc" "prev"))) + ([XF86AudioNext] . + (lambda () + (interactive) + (start-process "" nil "mpc" "next"))) + ([XF86ScreenSaver] . + (lambda () + (interactive) + (start-process "" nil "dm-tool" "lock"))) + ([\s-XF86Back] . previous-buffer) + ([\s-XF86Forward] . next-buffer))) + + ;; Line-editing shortcuts + (setq exwm-input-simulation-keys + '(;; movement + ([?\C-b] . [left]) + ([?\M-b] . [C-left]) + ([?\C-f] . [right]) + ([?\M-f] . [C-right]) + ([?\C-p] . [up]) + ([?\C-n] . [down]) + ([?\C-a] . [home]) + ([?\C-e] . [end]) + ([?\M-v] . [prior]) + ([?\C-v] . [next]) + ([?\C-d] . [delete]) + ([?\C-k] . [S-end ?\C-x]) + ([?\M-<] . C-home) + ([?\M->] . C-end) + ;; cut/copy/paste + ([?\C-w] . [?\C-x]) + ([?\M-w] . [?\C-c]) + ([?\C-y] . [?\C-v]) + ([?\M-d] . [C-S-right ?\C-x]) + ([?\M-\d] . [C-S-left ?\C-x]) + ;; window + ([?\s-w] . [?\C-w]) + ([?\s-q] . [?\C-q]) + ;; misc + ([?\C-s] . [?\C-f]) + ([?\s-s] . [?\C-s]) + ([?\C-g] . [escape])))) + +(use-package exwm-manage + :demand + :after exwm + :hook + (exwm-manage-finish . (lambda () + (when exwm-class-name + (cond + ((string= exwm-class-name "IceCat") + (exwm-input-set-local-simulation-keys + `(,@exwm-input-simulation-keys + ([?\C-\S-d] . [?\C-d])))) + ((string= exwm-class-name "URxvt") + (exwm-input-set-local-simulation-keys + '(([?\C-c ?\C-c] . [?\C-c]) + ([?\C-c ?\C-u] . [?\C-u])))) + ((string= exwm-class-name "Zathura") + (exwm-input-set-local-simulation-keys + '(([?\C-p] . [C-up]) + ([?\C-n] . [C-down]))))))))) + +(use-package exwm-randr + :demand + :after exwm + :config + (exwm-randr-enable) + :custom + (exwm-randr-workspace-monitor-plist '(1 "VGA-1"))) + +(use-package exwm-systemtray + :demand + :after exwm + :config + (exwm-systemtray-enable)) + +(use-package exwm-workspace) + +(use-package exwm-edit + :demand + :after exwm) + +(provide 'bandali-exwm) +;;; bandali-exwm.el ends here diff --git a/.emacs.d/lisp/bandali-gnus.el b/.emacs.d/lisp/bandali-gnus.el new file mode 100644 index 0000000..1958793 --- /dev/null +++ b/.emacs.d/lisp/bandali-gnus.el @@ -0,0 +1,478 @@ +;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: mail, news + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My trusty super awesome Gnus setup. + +;;; Code: + +(defvar b/maildir (expand-file-name "~/mail/")) +(with-eval-after-load 'recentf + (add-to-list 'recentf-exclude b/maildir)) + +(defvar b/gnus-init-file (b/etc "gnus")) + +(eval-when-compile + (progn + (defvar nndraft-directory) + (defvar gnus-read-newsrc-file) + (defvar gnus-save-newsrc-file) + (defvar gnus-gcc-mark-as-read) + (defvar nnmail-split-abbrev-alist))) + +(declare-function article-make-date-line "gnus-art" (date type)) + +(csetq + mail-user-agent 'gnus-user-agent + read-mail-command 'gnus + + gnus-select-method '(nnnil "") + gnus-secondary-select-methods + '((nnimap "shemshak" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "bandali@shemshak.local")) + (nnimap "gnu" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "bandali@gnu.local") + (nnimap-inbox "INBOX") + (nnimap-split-methods 'nnimap-split-fancy) + (nnimap-split-fancy (| + ;; (: gnus-registry-split-fancy-with-parent) + ;; (: gnus-group-split-fancy "INBOX" t "INBOX") + ;; keep debbugs emails in INBOX + (list ".*<\\(.*\\)\\.debbugs\\.gnu\\.org>.*" "INBOX") + ;; gnu + (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1") + ;; gnus + (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1") + ;; libreplanet + (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1") + ;; iana (e.g. tz-announce) + (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1") + ;; orbitalfox (e.g. gemini) + (list ".*<\\(.*\\)\\.lists\\.orbitalfox\\.eu>.*" "l.\\1") + ;; *.lists.sr.ht, omitting one dot if present + ;; add more \\.?\\([^.]*\\) if needed + (list ".*<~\\(.*\\)/\\([^.]*\\)\\.?\\([^.]*\\)\\.lists\\.sr\\.ht>.*" "l.~\\1.\\2\\3") + ;; webmasters + (from "webmasters\\(-comment\\)?@gnu\\.org" "webmasters") + ;; other + (list ".*atreus.freelists.org" "l.atreus") + (list ".*deepspec.lists.cs.princeton.edu" "l.deepspec") + ;; (list ".*haskell-art.we.lurk.org" "l.haskell.art") ;d + (list ".*haskell-cafe.haskell.org" "l.haskell-cafe") + ;; (list ".*notmuch.notmuchmail.org" "l.notmuch") ;u + (list ".*dev.lists.parabola.nu" "l.parabola-dev") + ;; ---------------------------------- + ;; legend: (u)nsubscribed | (d)ead + ;; ---------------------------------- + ;; spam + ("X-Spam_action" "reject" "Junk") + ;; otherwise, leave mail in INBOX + "INBOX"))) + (nnimap "uwaterloo" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "abandali@uwaterloo.local") + (nnimap-inbox "INBOX") + (nnimap-split-methods 'nnimap-split-fancy) + (nnimap-split-fancy (| + ;; (: gnus-registry-split-fancy-with-parent) + ;; se212-f19 + ("subject" "SE\\s-?212" "course.se212-f19") + (from "SE\\s-?212" "course.se212-f19") + ;; catch-all + "INBOX"))) + (nnimap "csc" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "abandali@csclub.uwaterloo.local") + (nnimap-inbox "INBOX") + (nnimap-split-methods 'nnimap-split-fancy) + (nnimap-split-fancy (| + ;; cron reports and other messages from root + (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX") + ;; spam + ("X-Spam-Flag" "YES" "Junk") + ;; catch-all + "INBOX"))) + (nnimap "sfl" + (nnimap-stream tls) + (nnimap-address "mail.savoirfairelinux.com") + (nnimap-user "amin.bandali"))) + gnus-message-archive-group "nnimap+gnu:INBOX" + gnus-parameters + '(("l\\.atreus" + (to-address . "atreus@freelists.org") + (to-list . "atreus@freelists.org")) + ("l\\.deepspec" + (to-address . "deepspec@lists.cs.princeton.edu") + (to-list . "deepspec@lists.cs.princeton.edu") + (list-identifier . "\\[deepspec\\]")) + ("l\\.emacs-devel" + (to-address . "emacs-devel@gnu.org") + (to-list . "emacs-devel@gnu.org")) + ("l\\.help-gnu-emacs" + (to-address . "help-gnu-emacs@gnu.org") + (to-list . "help-gnu-emacs@gnu.org")) + ("l\\.info-gnu-emacs" + (to-address . "info-gnu-emacs@gnu.org") + (to-list . "info-gnu-emacs@gnu.org")) + ("l\\.emacs-orgmode" + (to-address . "emacs-orgmode@gnu.org") + (to-list . "emacs-orgmode@gnu.org") + (list-identifier . "\\[O\\]")) + ("l\\.emacs-tangents" + (to-address . "emacs-tangents@gnu.org") + (to-list . "emacs-tangents@gnu.org")) + ("l\\.emacsconf-committee" + (to-address . "emacsconf-committee@gnu.org") + (to-list . "emacsconf-committee@gnu.org")) + ("l\\.emacsconf-discuss" + (to-address . "emacsconf-discuss@gnu.org") + (to-list . "emacsconf-discuss@gnu.org")) + ("l\\.emacsconf-org" + (to-address . "emacsconf-org@gnu.org") + (to-list . "emacsconf-org@gnu.org")) + ("l\\.emacsconf-org-private" + (to-address . "emacsconf-org-private@gnu.org") + (to-list . "emacsconf-org-private@gnu.org")) + ("l\\.emacsconf-register" + (to-address . "emacsconf-register@gnu.org") + (to-list . "emacsconf-register@gnu.org")) + ("l\\.emacsconf-submit" + (to-address . "emacsconf-submit@gnu.org") + (to-list . "emacsconf-submit@gnu.org")) + ("l\\.fencepost-users" + (to-address . "fencepost-users@gnu.org") + (to-list . "fencepost-users@gnu.org") + (list-identifier . "\\[Fencepost-users\\]")) + ("l\\.gnewsense-art" + (to-address . "gnewsense-art@nongnu.org") + (to-list . "gnewsense-art@nongnu.org") + (list-identifier . "\\[gNewSense-art\\]")) + ("l\\.gnewsense-dev" + (to-address . "gnewsense-dev@nongnu.org") + (to-list . "gnewsense-dev@nongnu.org") + (list-identifier . "\\[Gnewsense-dev\\]")) + ("l\\.gnewsense-users" + (to-address . "gnewsense-users@nongnu.org") + (to-list . "gnewsense-users@nongnu.org") + (list-identifier . "\\[gNewSense-users\\]")) + ("l\\.gnunet-developers" + (to-address . "gnunet-developers@gnu.org") + (to-list . "gnunet-developers@gnu.org") + (list-identifier . "\\[GNUnet-developers\\]")) + ("l\\.help-gnunet" + (to-address . "help-gnunet@gnu.org") + (to-list . "help-gnunet@gnu.org") + (list-identifier . "\\[Help-gnunet\\]")) + ("l\\.bug-gnuzilla" + (to-address . "bug-gnuzilla@gnu.org") + (to-list . "bug-gnuzilla@gnu.org") + (list-identifier . "\\[Bug-gnuzilla\\]")) + ("l\\.gnuzilla-dev" + (to-address . "gnuzilla-dev@gnu.org") + (to-list . "gnuzilla-dev@gnu.org") + (list-identifier . "\\[Gnuzilla-dev\\]")) + ("l\\.guile-devel" + (to-address . "guile-devel@gnu.org") + (to-list . "guile-devel@gnu.org")) + ("l\\.guile-user" + (to-address . "guile-user@gnu.org") + (to-list . "guile-user@gnu.org")) + ("l\\.guix-devel" + (to-address . "guix-devel@gnu.org") + (to-list . "guix-devel@gnu.org")) + ("l\\.help-guix" + (to-address . "help-guix@gnu.org") + (to-list . "help-guix@gnu.org")) + ("l\\.info-guix" + (to-address . "info-guix@gnu.org") + (to-list . "info-guix@gnu.org")) + ("l\\.savannah-hackers-public" + (to-address . "savannah-hackers-public@gnu.org") + (to-list . "savannah-hackers-public@gnu.org")) + ("l\\.savannah-users" + (to-address . "savannah-users@gnu.org") + (to-list . "savannah-users@gnu.org")) + ("l\\.www-commits" + (to-address . "www-commits@gnu.org") + (to-list . "www-commits@gnu.org")) + ("l\\.www-discuss" + (to-address . "www-discuss@gnu.org") + (to-list . "www-discuss@gnu.org")) + ("l\\.haskell-art" + (to-address . "haskell-art@we.lurk.org") + (to-list . "haskell-art@we.lurk.org") + (list-identifier . "\\[haskell-art\\]")) + ("l\\.haskell-cafe" + (to-address . "haskell-cafe@haskell.org") + (to-list . "haskell-cafe@haskell.org") + (list-identifier . "\\[Haskell-cafe\\]")) + ("l\\.notmuch" + (to-address . "notmuch@notmuchmail.org") + (to-list . "notmuch@notmuchmail.org")) + ("l\\.parabola-dev" + (to-address . "dev@lists.parabola.nu") + (to-list . "dev@lists.parabola.nu") + (list-identifier . "\\[Dev\\]")) + ("l\\.~bandali\\.public-inbox" + (to-address . "~bandali/public-inbox@lists.sr.ht") + (to-list . "~bandali/public-inbox@lists.sr.ht")) + ("l\\.~sircmpwn\\.free-writers-club" + (to-address . "~sircmpwn/free-writers-club@lists.sr.ht") + (to-list . "~sircmpwn/free-writers-club@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-admins" + (to-address . "~sircmpwn/sr.ht-admins@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-admins@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-announce" + (to-address . "~sircmpwn/sr.ht-announce@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-announce@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-dev" + (to-address . "~sircmpwn/sr.ht-dev@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-dev@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-discuss" + (to-address . "~sircmpwn/sr.ht-discuss@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-discuss@lists.sr.ht")) + ("webmasters" + (to-address . "webmasters@gnu.org") + (to-list . "webmasters@gnu.org")) + ("gnu.*" + (gcc-self . t)) + ("l\\." + (subscribed . t)) + ("nnimap\\+uwaterloo:.*" + (gcc-self . t))) + ;; nnimap-record-commands t + gnus-large-newsgroup 50 + gnus-home-directory (b/var "gnus/") + gnus-directory (concat gnus-home-directory "news/") + message-directory (concat gnus-home-directory "mail/") + nndraft-directory (concat gnus-home-directory "drafts/") + gnus-save-newsrc-file nil + gnus-read-newsrc-file nil + gnus-interactive-exit nil + gnus-gcc-mark-as-read t) + +(with-eval-after-load 'gnus + (when (version< emacs-version "27") + (with-eval-after-load 'nnmail + (add-to-list + 'nnmail-split-abbrev-alist + '(list . "list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop") + t))) + + ;; (require 'gnus-registry) + ;; (setq gnus-registry-max-entries 2500) + ;; (setq gnus-registry-ignored-groups + ;; (append gnus-registry-ignored-groups + ;; '(("^nnimap:gnu\\.l" t) + ;; ("webmasters$" t)))) + ;; (gnus-registry-initialize) + + (with-eval-after-load 'recentf + (add-to-list 'recentf-exclude gnus-home-directory)) + + ;; hooks + (add-hook 'gnus-group-mode-hook #'gnus-topic-mode) + (add-hook 'gnus-group-mode-hook #'gnus-agent-mode)) +;; global key bindings +(global-set-key (kbd "s-m") #'gnus-plugged) +(global-set-key (kbd "s-M") #'gnus-unplugged) +(global-set-key (kbd "C-c a m") #'gnus-plugged) +(global-set-key (kbd "C-c a M") #'gnus-unplugged) + +(with-eval-after-load 'gnus-art + (csetq + gnus-buttonized-mime-types '("multipart/\\(signed\\|encrypted\\)") + gnus-sorted-header-list '("^From:" + "^X-RT-Originator" + "^Newsgroups:" + "^Subject:" + "^Date:" + "^Envelope-To:" + "^Followup-To:" + "^Reply-To:" + "^Organization:" + "^Summary:" + "^Abstract:" + "^Keywords:" + "^To:" + "^[BGF]?Cc:" + "^Posted-To:" + "^Mail-Copies-To:" + "^Mail-Followup-To:" + "^Apparently-To:" + "^Resent-From:" + "^User-Agent:" + "^X-detected-operating-system:" + "^X-Spam_action:" + "^X-Spam_bar:" + "^Message-ID:" + ;; "^References:" + "^List-Id:" + "^Gnus-Warning:") + gnus-visible-headers (mapconcat 'identity + gnus-sorted-header-list + "\\|") + ;; local-lapsed article dates + ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11 + gnus-article-date-headers '(user-defined) + gnus-article-time-format + (lambda (time) + (let* ((date (format-time-string "%a, %d %b %Y %T %z" time)) + (local (article-make-date-line date 'local)) + (combined-lapsed (article-make-date-line date + 'combined-lapsed)) + (lapsed (progn + (string-match " (.+" combined-lapsed) + (match-string 0 combined-lapsed)))) + (concat local lapsed)))) + ;; local key bindings + (define-key gnus-article-mode-map (kbd "M-L") #'org-store-link)) + +(with-eval-after-load 'gnus-sum + (csetq gnus-thread-sort-functions '(gnus-thread-sort-by-number + gnus-thread-sort-by-subject + gnus-thread-sort-by-date)) + ;; local key bindings + (define-key gnus-summary-mode-map (kbd "M-L") #'org-store-link) + (defvar b/gnus-summary-prefix-map) + (define-prefix-command 'b/gnus-summary-prefix-map) + (define-key gnus-summary-mode-map (kbd "v") + 'b/gnus-summary-prefix-map) + (define-key b/gnus-summary-prefix-map (kbd "r") + #'gnus-summary-reply) + (define-key b/gnus-summary-prefix-map (kbd "w") + #'gnus-summary-wide-reply) + (define-key b/gnus-summary-prefix-map (kbd "v") + #'gnus-summary-show-raw-article)) +;; hooks +(add-hook 'gnus-summary-mode-hook #'b/no-mouse-autoselect-window) + +(defvar b/sfl-p nil) +(with-eval-after-load 'gnus-msg + (defvar b/shemshak-signature "Amin Bandali +https://shemshak.org/~bandali") + (defvar b/uwaterloo-signature "Amin Bandali, MMath +https://bndl.org") + (defvar b/csc-signature "Amin Bandali (https://bndl.org) +Systems Committee <syscom@csclub.uwaterloo.ca> +Computer Science Club of the University of Waterloo") + (defvar b/sfl-signature "Amin Bandali +Free Software Consultant +Savoir-faire Linux +GNU Jami: bandali") + (csetq + gnus-message-replysign t + gnus-posting-styles + '((".*" + (address "bandali@gnu.org")) + ("nnimap\\+gnu:l\\..*" + (signature nil)) + ("nnimap\\+gnu:.*" + (organization "GNU")) + ((header "subject" "ThankCRM") + (to "webmasters-comment@gnu.org") + (body "") + (eval (setq b/message-cite-say-hi nil))) + ("nnimap\\+shemshak:.*" + (address "amin@shemshak.org") + (body "\nBest,\n") + (signature b/shemshak-signature) + (gcc "nnimap+shemshak:Sent") + (eval (setq b/message-cite-say-hi t))) + ("nnimap\\+uwaterloo:.*" + (address "bandali@uwaterloo.ca") + (body "\nBest,\n") + (signature b/uwaterloo-signature)) + ("nnimap\\+uwaterloo:INBOX" + (gcc "\"nnimap+uwaterloo:Sent Items\"")) + ("nnimap\\+csc:.*" + (address "bandali@csclub.uwaterloo.ca") + (signature b/csc-signature) + (gcc "nnimap+csc:Sent")) + ("nnimap\\+sfl:.*" + (address "amin.bandali@savoirfairelinux.com") + (signature b/sfl-signature) + (gcc "nnimap+sfl:Sent") + (eval (setq-local b/sfl-p t)))))) +;; hooks +(with-eval-after-load 'gnus + (add-hook 'gnus-message-setup-hook + (lambda () + (unless (or (mml-secure-is-encrypted-p) + b/sfl-p) + (mml-secure-message-sign))))) + +(with-eval-after-load 'gnus-topic + (csetq gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n")) + +(with-eval-after-load 'gnus-agent + (csetq gnus-agent-synchronize-flags 'ask)) + +(with-eval-after-load 'gnus-group + (csetq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)")) + +;; problematic with ebdb's popup, *EBDB-Gnus* +;; (with-eval-after-load 'gnus-win +;; (csetq gnus-use-full-window nil)) + +(with-eval-after-load 'gnus-dired + (add-hook 'dired-mode-hook 'gnus-dired-mode)) + +;; (with-eval-after-load 'gnus-utils +;; (csetq gnus-completing-read-function 'gnus-ido-completing-read)) + +(with-eval-after-load 'mm-decode + (csetq mm-discouraged-alternatives '("text/html" "text/richtext") + mm-decrypt-option 'known + mm-verify-option 'known)) + +(with-eval-after-load 'mm-uu + (when (version< "27" emacs-version) + (set-face-attribute 'mm-uu-extract nil :extend t)) + (when (version< emacs-version "27") + (csetq mm-uu-diff-groups-regexp "."))) + +(with-eval-after-load 'mml-sec + (csetq mml-secure-openpgp-encrypt-to-self t + mml-secure-openpgp-sign-with-sender t)) + +;; (require 'gnus-article-treat-patch) +;; ;; note: be sure to customize faces with `:foreground "white"' when +;; ;; using a theme with a white/light background :) +;; (setq ft/gnus-article-patch-conditions +;; '("^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@")) + +(provide 'bandali-gnus) +;;; bandali-gnus.el ends here diff --git a/.emacs.d/lisp/bandali-ibuffer.el b/.emacs.d/lisp/bandali-ibuffer.el new file mode 100644 index 0000000..7cd4331 --- /dev/null +++ b/.emacs.d/lisp/bandali-ibuffer.el @@ -0,0 +1,110 @@ +;;; bandali-ibuffer.el --- bandali's Ibuffer setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My Ibuffer setup. + +;;; Code: + +(csetq + ibuffer-saved-filter-groups + '(("default" + ("dired" (mode . dired-mode)) + ("org" (mode . org-mode)) + ("gnus" + (or + (mode . gnus-group-mode) + (mode . gnus-summary-mode) + (mode . gnus-article-mode) + (mode . message-mode))) + ("web" + (or + (mode . mhtml-mode) + (mode . css-mode) + (mode . scss-mode) + (mode . js2-mode))) + ("shell" + (or + (mode . eshell-mode) + (mode . shell-mode) + (mode . term-mode))) + ("programming" + (or + (mode . python-mode) + (mode . c-mode) + (mode . c++-mode) + (mode . java-mode) + (mode . emacs-lisp-mode) + (mode . scheme-mode) + (mode . haskell-mode) + (mode . lean-mode) + ;; (mode . go-mode) + (mode . alloy-mode))) + ("tex" + (or + (mode . bibtex-mode) + (mode . latex-mode))) + ("emacs" + (or + (name . "^\\*scratch\\*$") + (name . "^\\*Messages\\*$"))) + ("exwm" (mode . exwm-mode)) + ("erc" (mode . erc-mode)))) + ibuffer-formats + '((mark modified read-only locked " " + (name 72 72 :left :elide) + " " + (size-h 9 -1 :right) + " " + (mode 16 16 :left :elide) + " " filename-and-process) + (mark " " + (name 16 -1) + " " filename))) +(with-eval-after-load 'ibuffer + ;; Use human readable Size column instead of original one + (define-ibuffer-column size-h + (:name "Size" :inline t) + (cond + ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0))) + ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0))) + ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0))) + (t (format "%8d" (buffer-size))))) + + ;; local key bindings + (define-key ibuffer-mode-map (kbd "P") + #'ibuffer-backward-filter-group) + (define-key ibuffer-mode-map (kbd "N") + #'ibuffer-forward-filter-group) + (define-key ibuffer-mode-map (kbd "M-p") + #'ibuffer-do-print) + (define-key ibuffer-mode-map (kbd "M-n") + #'ibuffer-do-shell-command-pipe-replace)) +;; global key bindings +(global-set-key (kbd "C-x C-b") #'ibuffer) +;; hooks +(declare-function ibuffer-switch-to-saved-filter-groups "ibuf-ext" + (name)) +(add-hook 'ibuffer-hook + (lambda () (ibuffer-switch-to-saved-filter-groups "default"))) + +(provide 'bandali-ibuffer) +;;; bandali-ibuffer.el ends here diff --git a/.emacs.d/lisp/bandali-ivy.el b/.emacs.d/lisp/bandali-ivy.el new file mode 100644 index 0000000..973323a --- /dev/null +++ b/.emacs.d/lisp/bandali-ivy.el @@ -0,0 +1,74 @@ +;;; bandali-ivy.el --- bandali's Ivy setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: matching + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My configuration for Ivy and family. + +;;; Code: + +(run-with-idle-timer 0.3 nil #'require 'ivy) +(with-eval-after-load 'ivy + ;; ivy + (csetq ivy-wrap t + ;; ivy-height 14 + ivy-use-virtual-buffers t + ivy-virtual-abbreviate 'abbreviate + ivy-count-format "%d/%d ") + + (defvar b/ivy-ignore-buffer-modes + '(;; dired-mode + ;; magit-mode + erc-mode)) + (defun b/ivy-ignore-buffer-p (str) + "Return non-nil if str names a buffer with a major mode +derived from one of `b/ivy-ignore-buffer-modes'. + +This function is intended for use with `ivy-ignore-buffers'." + (let* ((buf (get-buffer str)) + (mode (and buf (buffer-local-value 'major-mode buf)))) + (and mode + (apply #'provided-mode-derived-p mode b/ivy-ignore-buffer-modes)))) + (add-to-list 'ivy-ignore-buffers #'b/ivy-ignore-buffer-p) + + (define-key ivy-minibuffer-map [escape] #'keyboard-escape-quit) + (define-key ivy-minibuffer-map [S-up] + #'ivy-previous-history-element) + (define-key ivy-minibuffer-map [S-down] + #'ivy-next-history-element) + (define-key ivy-minibuffer-map (kbd "DEL") + #'ivy-backward-delete-char) + + (ivy-mode 1) + + ;; swiper + (require 'swiper) + (global-set-key (kbd "C-S-s") #'swiper-isearch) + + ;; counsel + (require 'counsel) + (counsel-mode 1) + (defalias 'locate #'counsel-locate) + (global-set-key (kbd "C-c f r") #'counsel-recentf) + (define-key minibuffer-local-map + (kbd "C-r") #'counsel-minibuffer-history)) + +(provide 'bandali-ivy) +;;; bandali-ivy.el ends here diff --git a/.emacs.d/lisp/bandali-magit.el b/.emacs.d/lisp/bandali-magit.el new file mode 100644 index 0000000..7432a11 --- /dev/null +++ b/.emacs.d/lisp/bandali-magit.el @@ -0,0 +1,70 @@ +;;; bandali-magit.el --- bandali's magit configuration -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: vc + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; It's Magit! + +;;; Code: + +(csetq transient-history-file (b/var "transient/history.el") + transient-levels-file (b/etc "transient/levels.el") + transient-values-file (b/etc "transient/values.el")) +(with-eval-after-load 'magit + (declare-function magit-add-section-hook "magit-section" + (hook function &optional at append local)) + (magit-add-section-hook 'magit-status-sections-hook + 'magit-insert-modules + 'magit-insert-stashes + 'append) + ;; (magit-add-section-hook 'magit-status-sections-hook + ;; 'magit-insert-ignored-files + ;; 'magit-insert-untracked-files + ;; 'append) + (declare-function magit-display-buffer-fullframe-status-v1 + "magit-mode" (buffer)) + (csetq + magit-diff-refine-hunk t + magit-repository-directories '(("~/.emacs.d/" . 0) + ("~/src/git/" . 2)) + ;; magit-completing-read-function 'magit-ido-completing-read + magit-display-buffer-function + #'magit-display-buffer-fullframe-status-v1) + (nconc magit-section-initial-visibility-alist + '(([unpulled status] . show) + ([unpushed status] . show))) + (custom-set-faces '(magit-diff-file-heading ((t (:weight normal))))) + + (with-eval-after-load 'magit-extras + (csetq + magit-pop-revision-stack-format + (pcase-let ((`(,pt ,_eob ,index-regexp) + (default-value 'magit-pop-revision-stack-format))) + `(,pt "[%N: %h]: %ci\n %s + https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=%H" + ,index-regexp))))) +;; global key bindings +(global-set-key (kbd "C-x g") #'magit-status) +(global-set-key (kbd "C-c g b") #'magit-blame-addition) +(global-set-key (kbd "C-c g l") #'magit-log-buffer-file) +(global-set-key (kbd "C-c g y") #'magit-pop-revision-stack) + +(provide 'bandali-magit) +;;; bandali-magit.el ends here diff --git a/.emacs.d/lisp/bandali-message.el b/.emacs.d/lisp/bandali-message.el new file mode 100644 index 0000000..c13bffc --- /dev/null +++ b/.emacs.d/lisp/bandali-message.el @@ -0,0 +1,138 @@ +;;; bandali-message.el --- bandali's message.el setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: mail, news + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My setup for message.el. + +;;; Code: + +(with-eval-after-load 'message + ;; :bind (:map message-mode-map ("<C-return>" . b/insert-asterism)) + ;; redefine for a simplified In-Reply-To header + ;; (see https://todo.sr.ht/~sircmpwn/lists.sr.ht/67) + (defun message-make-in-reply-to () + "Return the In-Reply-To header for this message." + (when message-reply-headers + (let ((from (mail-header-from message-reply-headers)) + (msg-id (mail-header-id message-reply-headers))) + (when from + msg-id)))) + + (defconst b/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 b/message-cite-say-hi + (concat "Hi %F,\n\n" b/message-cite-style-format) + b/message-cite-style-format))) + "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.") + (csetq + message-elide-ellipsis "[...]\n" + ;; message-cite-style 'message-cite-style-bandali + message-citation-line-format "%N writes:\n" + message-citation-line-function 'message-insert-formatted-citation-line + message-kill-buffer-on-exit t + message-send-mail-function 'message-send-mail-with-sendmail + message-sendmail-envelope-from 'header + message-subscribed-address-functions + '(gnus-find-subscribed-addresses) + message-dont-reply-to-names + "\\(\\(amin@shemshak\\.org\\)\\|\\(.*@aminb\\.org\\)\\|\\(\\(bandali\\|mab\\|aminb?\\)@gnu\\.org\\)\\|bandali@fsf\\.org\\|\\(a?bandali@\\(csclub\\.\\)?uwaterloo\\.ca\\)\\|amin\\.bandali@savoirfairelinux\\.com\\)") + ;; (require 'company-ebdb) + ;; (custom-set-faces + ;; '(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)))) + + ;; footnote + (with-eval-after-load 'footnote + ;; (csetq footnote-start-tag "" + ;; footnote-end-tag "" + ;; footnote-style 'unicode) + (when (featurep 'which-key) + (which-key-add-major-mode-key-based-replacements 'message-mode + "C-c f n" "footnote"))) + + ;; orgalist + (add-hook 'message-mode-hook + (lambda () + ;; work around incompatibility between + ;; orgalist and yasnippet + (yas-minor-mode -1) + (orgalist-mode 1) + (yas-minor-mode 1))) + + ;; local key bindings + (defvar b/footnote-prefix-map) + (define-prefix-command 'b/footnote-prefix-map) + (define-key message-mode-map (kbd "C-c f n") + 'b/footnote-prefix-map) + (define-key b/footnote-prefix-map (kbd "a") + #'footnote-add-footnote) + (define-key b/footnote-prefix-map (kbd "b") + #'footnote-back-to-message) + (define-key b/footnote-prefix-map (kbd "c") + #'footnote-cycle-style) + (define-key b/footnote-prefix-map (kbd "d") + #'footnote-delete-footnote) + (define-key b/footnote-prefix-map (kbd "g") + #'footnote-goto-footnote) + (define-key b/footnote-prefix-map (kbd "r") + #'footnote-renumber-footnotes) + (define-key b/footnote-prefix-map (kbd "s") + #'footnote-set-style)) +;; hooks +;; (add-hook 'message-setup-hook #'mml-secure-message-sign-pgpmime) +(add-hook 'message-mode-hook #'flyspell-mode) +(add-hook 'message-mode-hook + (lambda () + ;; (setq-local fill-column b/fill-column + ;; message-fill-column b/fill-column) + (eval-when-compile (defvar company-idle-delay)) + (make-local-variable 'company-idle-delay) + (setq company-idle-delay 0.2))) + +;; (with-eval-after-load 'message-x +;; (csetq +;; message-x-completion-alist +;; '(("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" +;; . gnus-harvest-find-address) +;; ((if +;; (boundp +;; (quote message-newgroups-header-regexp)) +;; message-newgroups-header-regexp message-newsgroups-header-regexp) +;; . message-expand-group)))) + +;; (require 'gnus-harvest) +;; (if (featurep 'message-x) +;; (gnus-harvest-install 'message-x) +;; (gnus-harvest-install)) + +(provide 'bandali-message) +;;; bandali-message.el ends here diff --git a/.emacs.d/lisp/bandali-org.el b/.emacs.d/lisp/bandali-org.el new file mode 100644 index 0000000..38a4a5a --- /dev/null +++ b/.emacs.d/lisp/bandali-org.el @@ -0,0 +1,119 @@ +;;; bandali-org.el --- bandali's Org setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: calendar, data, docs, hypermedia, outlines + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My set up for Org (org-mode) and all things Org. + +;;; Code: + +(with-eval-after-load 'org + (csetq org-src-tab-acts-natively t + org-src-preserve-indentation nil + org-edit-src-content-indentation 0 + org-id-locations-file (b/var "org/id-locations.el") + org-link-email-description-format "Email %c: %s" ; %.30s + org-highlight-latex-and-related '(entities) + org-use-speed-commands t + org-startup-folded 'content + org-catch-invisible-edits 'show-and-error + org-log-done 'time + org-pretty-entities t + org-agenda-files '("~/usr/org/todos/personal.org" + "~/usr/org/todos/habits.org" + "~/src/git/masters-thesis/todo.org") + org-agenda-start-on-weekday 0 + org-agenda-time-leading-zero t + org-habit-graph-column 44 + org-latex-packages-alist '(("" "listings") ("" "color"))) + (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t) + (add-to-list 'org-modules 'org-habit) + (custom-set-faces + '(org-block-begin-line + ((t (:foreground "#5a5b5a" :background "#1d1f21")))) + '(org-block ((t (:background "#1d1f21")))) + '(org-latex-and-related ((t (:foreground "#b294bb"))))) + ;; local key bindings + (define-key org-mode-map (kbd "M-L") #'org-insert-last-stored-link) + (define-key org-mode-map (kbd "M-O") #'org-toggle-link-display) + ;; hooks + (add-hook 'org-mode-hook #'org-indent-mode) + (add-hook 'org-mode-hook #'auto-fill-mode) + (add-hook 'org-mode-hook #'flyspell-mode) + + ;; asynchronous tangle, using emacs-async to asynchronously tangle an + ;; org file. closely inspired by + ;; https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles + (defvar b/show-async-tangle-results nil + "Keep *emacs* async buffers around for later inspection.") + + (defvar b/show-async-tangle-time nil + "Show the time spent tangling the file.") + + (defun b/async-babel-tangle () + "Tangle org file asynchronously." + (interactive) + (let* ((file-tangle-start-time (current-time)) + (file (buffer-file-name)) + (file-nodir (file-name-nondirectory file)) + ;; (async-quiet-switch "-q") + ;; (file-noext (file-name-sans-extension file)) + ) + (async-start + `(lambda () + (require 'org) + (org-babel-tangle-file ,file)) + (unless b/show-async-tangle-results + `(lambda (result) + (if result + (message "Tangled %s%s" + ,file-nodir + (if b/show-async-tangle-time + (format " (%.3fs)" + (float-time (time-subtract (current-time) + ',file-tangle-start-time))) + "")) + (message "Tangling %s failed" ,file-nodir))))))) + (add-to-list + 'safe-local-variable-values + '(eval add-hook 'after-save-hook #'b/async-babel-tangle 'append 'local))) +;; global key bindings +(global-set-key (kbd "C-c a o a") #'org-agenda) + +(with-eval-after-load 'ox-latex + (csetq org-latex-listings 'listings + ;; org-latex-prefer-user-labels t + ) + (add-to-list 'org-latex-classes + '("IEEEtran" "\\documentclass[11pt]{IEEEtran}" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) + t) + (require 'ox-beamer)) + +(with-eval-after-load 'ox-extra + (declare-function ox-extras-activate "ox-extra" (extras)) + (ox-extras-activate '(latex-header-blocks ignore-headlines))) + +(provide 'bandali-org) +;;; bandali-org.el ends here diff --git a/.emacs.d/lisp/bandali-theme.el b/.emacs.d/lisp/bandali-theme.el new file mode 100644 index 0000000..13929cb --- /dev/null +++ b/.emacs.d/lisp/bandali-theme.el @@ -0,0 +1,87 @@ +;;; bandali-theme.el --- bandali's custom theme setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: faces + +;; 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 +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My custom theme setup. + +;;; Code: + +(with-eval-after-load 'package + (require 'refinery-theme) + (load-theme 'refinery t)) + +;; (require 'smart-mode-line) +;; ;; thanks, but no thanks; don't make fixed-width fills. +;; (defun sml/fill-for-buffer-identification nil "") +;; (setq sml/theme 'respectful) +;; (let ((sml/no-confirm-load-theme t)) +;; (sml/setup) +;; (smart-mode-line-enable)) + +;; (require 'minions) +;; (minions-mode) + +(defvar b/org-mode-font-lock-keywords + '(("[ \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 + "For use with the `doom-tomorrow-night' theme.") + +(eval-when-compile + (declare-function exwm-systemtray--refresh "exwm-systemtray") + (declare-function erc-hl-nicks-reset-face-table "erc-hl-nicks")) + +(defun b/lights-on () + "Enable my favourite light theme." + (interactive) + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'refinery t) + (when (featurep 'smart-mode-line) + (let ((sml/no-confirm-load-theme t)) + (sml/apply-theme 'respectful))) + (font-lock-remove-keywords + 'org-mode b/org-mode-font-lock-keywords) + (when (featurep 'erc-hl-nicks) + (erc-hl-nicks-reset-face-table)) + (when (featurep 'exwm-systemtray) + (exwm-systemtray--refresh))) + +(defun b/lights-off () + "Go dark." + (interactive) + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'refinery-dark t) + (when (featurep 'smart-mode-line) + (let ((sml/no-confirm-load-theme t)) + (sml/apply-theme 'dark))) + (font-lock-add-keywords + 'org-mode b/org-mode-font-lock-keywords t) + (when (featurep 'erc-hl-nicks) + (erc-hl-nicks-reset-face-table)) + (when (featurep 'exwm-systemtray) + (exwm-systemtray--refresh))) + +(global-set-key (kbd "C-c t d") #'b/lights-off) +(global-set-key (kbd "C-c t l") #'b/lights-on) + +(provide 'bandali-theme) +;;; bandali-theme.el ends here diff --git a/.emacs.d/lisp/boxquote b/.emacs.d/lisp/boxquote new file mode 160000 +Subproject 7e47e0e2853bc1215739b2e28f260e9eed93b2c diff --git a/.emacs.d/lisp/gnus-article-treat-patch.el b/.emacs.d/lisp/gnus-article-treat-patch.el new file mode 100644 index 0000000..f2f5c21 --- /dev/null +++ b/.emacs.d/lisp/gnus-article-treat-patch.el @@ -0,0 +1,465 @@ +;;; gnus-article-treat-patch.el --- Highlight inline patches in articles +;; +;; Copyright © 2011-2019 Frank Terbeck <ft@bewatermyfriend.org> +;; +;; This file is not part of GNU Emacs. +;; +;; This file is free software; you can redistribute it and/or modify it under +;; the terms of the GNU General Public License as published by the Free Soft- +;; ware Foundation; either version 3, or (at your option) any later version. +;; +;; This file is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS FOR +;; A PARTICULAR PURPOSE. See the GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License along with +;; this file. If not, see <http://www.gnu.org/licenses/>. +;; +;; +;;; Commentary: +;; +;; Gnus addon to beautify patch-like emails. This uses a "ft/" prefix for +;; everything to avoid clashing with anything upstream. That prefix can be +;; savely s,ft/,,'d - if this is to be submitted to the gnus developers. + +(require 'diff-mode) + +(add-hook 'gnus-part-display-hook 'ft/gnus-article-treat-patch) + +;; Colour handling and faces +(defun ft/gnus-colour-line (use-face) + "Set text overlay to `use-face' for the current line." + (overlay-put (make-overlay (point-at-bol) (point-at-eol)) 'face use-face)) + +(make-face 'ft/gnus-three-dashes) +(set-face-attribute 'ft/gnus-three-dashes nil :foreground "brightblue") +(make-face 'ft/gnus-scissors) +(set-face-attribute 'ft/gnus-scissors nil :foreground "brown") +(make-face 'ft/gnus-diff-index) +(set-face-attribute 'ft/gnus-diff-index nil :foreground "brightmagenta") +(make-face 'ft/gnus-diff-hunk) +(set-face-attribute 'ft/gnus-diff-hunk nil :foreground "brightblue") +(make-face 'ft/gnus-diff-equals) +(set-face-attribute 'ft/gnus-diff-equals nil :foreground "brightmagenta") +(make-face 'ft/gnus-commit-message) +(set-face-attribute 'ft/gnus-commit-message nil :foreground "white") +(make-face 'ft/gnus-diff-stat-file) +(set-face-attribute 'ft/gnus-diff-stat-file nil :foreground "yellow") +(make-face 'ft/gnus-diff-stat-bar) +(set-face-attribute 'ft/gnus-diff-stat-bar nil :foreground "magenta") +(make-face 'ft/gnus-diff-stat-num) +(set-face-attribute 'ft/gnus-diff-stat-num nil :foreground "white") +(make-face 'ft/gnus-diff-misc) +(set-face-attribute 'ft/gnus-diff-misc nil :foreground "magenta") +(make-face 'ft/gnus-commit-comment) +(set-face-attribute 'ft/gnus-commit-comment nil :inherit 'default) +(make-face 'ft/gnus-diff-header) +(set-face-attribute 'ft/gnus-diff-header nil :inherit 'diff-header) +(make-face 'ft/gnus-diff-add) +(set-face-attribute 'ft/gnus-diff-add nil :inherit 'diff-added) +(make-face 'ft/gnus-diff-remove) +(set-face-attribute 'ft/gnus-diff-remove nil :inherit 'diff-removed) + +;; Pseudo-headers +(defvar ft/gnus-article-patch-pseudo-headers + '(("^Acked-by: " 'gnus-header-name 'gnus-header-from) + ("^C\\(c\\|C\\): " 'gnus-header-name 'gnus-header-from) + ("^From: " 'gnus-header-name 'gnus-header-from) + ("^Link: " 'gnus-header-name 'gnus-header-from) + ("^Reported-by: " 'gnus-header-name 'gnus-header-from) + ("^Reviewed-by: " 'gnus-header-name 'gnus-header-from) + ("^Signed-off-by: " 'gnus-header-name 'gnus-header-from) + ("^Subject: " 'gnus-header-name 'gnus-header-from) + ("^Suggested-by: " 'gnus-header-name 'gnus-header-from)) + "List of lists of regular expressions (with two face names) +which are used to determine the highlighting of pseudo headers in +the commit message (such as \"Signed-off-by:\"). + +The first face if used to highlight the header's name; the second +highlights the header's value.") + +(defun ft/gnus-pseudo-header-get (line) + "Check if `line' is a pseudo header, and if so return its enty in +`ft/gnus-article-patch-pseudo-headers'." + (catch 'done + (dolist (entry ft/gnus-article-patch-pseudo-headers) + (let ((regex (car entry))) + (if (string-match regex line) + (throw 'done entry)))) + (throw 'done '()))) + +(defun ft/gnus-pseudo-header-p (line) + "Returns `t' if `line' looks like a pseudo-header; `nil' otherwise. + +`ft/gnus-article-patch-pseudo-headers' is used to determine what a pseudo-header +is." + (if (eq (ft/gnus-pseudo-header-get line) '()) nil t)) + +(defun ft/gnus-pseudo-header-colour (line) + "Colourise a pseudo-header line." + (let ((data (ft/gnus-pseudo-header-get line))) + (if (eq data '()) + nil + (let* ((s (point-at-bol)) + (e (point-at-eol)) + (colon (re-search-forward ":")) + (value (+ colon 1))) + (overlay-put (make-overlay s colon) 'face (nth 1 data)) + (overlay-put (make-overlay value e) 'face (nth 2 data)))))) + +;; diff-stat +(defun ft/gnus-diff-stat-colour (line) + "Colourise a diff-stat line." + (let ((s (point-at-bol)) + (e (point-at-eol)) + (bar (- (re-search-forward "|") 1)) + (num (- (re-search-forward "[0-9]") 1)) + (pm (- (re-search-forward "\\([+-]\\|$\\)") 1))) + + (overlay-put (make-overlay s (- bar 1)) 'face 'ft/gnus-diff-stat-file) + (overlay-put (make-overlay bar (+ bar 1)) 'face 'ft/gnus-diff-stat-bar) + (overlay-put (make-overlay num pm) 'face 'ft/gnus-diff-stat-num) + + (goto-char pm) + (let* ((plus (looking-at "\\+")) + (regex (if plus "-+" "\\++")) + (brk (if plus + (re-search-forward "-" e t) + (re-search-forward "\\+" e t))) + (first-face (if plus 'ft/gnus-diff-add 'ft/gnus-diff-remove)) + (second-face (if plus 'ft/gnus-diff-remove 'ft/gnus-diff-add))) + + (if (eq brk nil) + (overlay-put (make-overlay pm e) 'face first-face) + (progn + (setq brk (- brk 1)) + (overlay-put (make-overlay pm brk) 'face first-face) + (overlay-put (make-overlay brk e) 'face second-face)))))) + +(defun ft/gnus-diff-stat-summary-colour (line) + "Colourise a diff-stat summary-line." + (let* ((e (point-at-eol)) + (plus (- (re-search-forward "(\\+)" e t) 2)) + (minus (- (re-search-forward "(-)" e t) 2))) + (overlay-put (make-overlay plus (+ plus 1)) 'face 'ft/gnus-diff-add) + (overlay-put (make-overlay minus (+ minus 1)) 'face 'ft/gnus-diff-remove))) + +(defun ft/gnus-diff-stat-line-p (line) + "Return `t' if `line' is a diff-stat line; `nil' otherwise." + (string-match "^ *[^ ]+[^|]+| +[0-9]+\\( *\\| +[+-]+\\)$" line)) + +(defun ft/gnus-diff-stat-summary-p (line) + "Return `t' if `line' is a diff-stat summary-line; `nil' otherwise." + (string-match "^ *[0-9]+ file\\(s\\|\\) changed,.*insertion.*deletion" line)) + +;; unified-diffs +(defun ft/gnus-diff-header-p (line) + "Returns `t' if `line' looks like a diff-header; `nil' otherwise." + (cond + ((string-match "^\\(\\+\\+\\+\\|---\\) " line) t) + ((string-match "^diff -" line) t) + (t nil))) + +(defun ft/gnus-index-line-p (line) + "Returns `t' if `line' looks like an index-line; `nil' otherwise." + (cond + ((string-match "^Index: " line) t) + ((string-match "^index [0-9a-f]+\\.\\.[0-9a-f]+" line) t) + (t nil))) + +(defun ft/gnus-hunk-line-p (line) + "Returns `t' if `line' looks like a hunk-line; `nil' otherwise." + (string-match "^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@" line)) + +(defun ft/gnus-atp-misc-diff-p (line) + "Return `t' if `line' is a \"misc line\" with respect to patch +treatment; `nil' otherwise." + (let ((patterns '("^new file" + "^RCS file:" + "^retrieving revision "))) + (catch 'done + (dolist (regex patterns) + (if (string-match regex line) + (throw 'done t))) + (throw 'done nil)))) + +(defun ft/gnus-atp-looks-like-diff (line) + "Return `t' if `line' looks remotely like a line from a unified +diff; `nil' otherwise." + (or (ft/gnus-index-line-p line) + (ft/gnus-diff-header-p line) + (ft/gnus-hunk-line-p line))) + +;; miscellaneous line handlers +(defun ft/gnus-scissors-line-p (line) + "Returns `t' if `line' looks like a scissors-line; `nil' otherwise." + (cond + ((string-match "^\\( *--* *\\(8<\\|>8\\)\\)+ *-* *$" line) t) + (t nil))) + +;; Patch mail detection +(defvar ft/gnus-article-patch-conditions nil + "List of conditions that will enable patch treatment. String +values will be matched as regular expressions within the currently +processed part. Non-string value are supposed to be code fragments, +which determine whether or not to do treatment: The code needs to +return `t' if treatment is wanted.") + +(defun ft/gnus-part-want-patch-treatment () + "Run through `ft/gnus-article-patch-conditions' to determine whether +patch treatment is wanted or not. Return `t' or `nil' accordingly." + (catch 'done + (dolist (entry ft/gnus-article-patch-conditions) + (cond + ((stringp entry) + (if (re-search-forward entry nil t) + (throw 'done t))) + (t + (if (eval entry) + (throw 'done t))))) + (throw 'done nil))) + + +;; The actual article treatment code +(defun ft/gnus-article-treat-patch-state-machine () + "Implement the state machine which colourises a part of an article +if it looks patch-like. + +The state machine works like this: + + 0a. The machinery starts at the first line of the article's body. Not + the header lines. We don't care about header lines at all. + + 0b. The whole thing works line by line. It doesn't do any forward or + backward looks. + + 1. Initially, we assume, that what we'll see first is part of the + patch's commit-message. Hence this first initial state is + \"commit-message\". There are several ways out of this state: + + a) a scissors line is found (see 2.) + b) a pseudo-header line is found (see 3.) + c) a three-dashes line is found (see 4.) + d) something that looks like the start of a unified diff is + found (see 7.) + + 2. A scissors line is something that looks like a pair of scissors running + through a piece of paper. Like this: + + ------ 8< ----- 8< ------ + + or this: + + ------------>8----------- + + The function `ft/gnus-scissors-line-p' decides whether a line is a + scissors line or not. After a scissors line was treated, the machine + will switch back to the \"commit-mesage\" state. + + 3. This is very similar to a scissors line. It'll just return to the old + state after its being done. The `ft/gnus-pseudo-header-p' function + decides if a line is a pseudo header. The line will be appropriately + coloured. + + 4. A three-dashes line is a line that looks like this: \"---\". It's the + definite end of the \"commit-message\" state. The three dashes line is + coloured and the state switches to \"commit-comment\". (See 5.) + + 5. Nothing in \"commit-comment\" will appear in the generated commit (this + is git-am specific semantics, but it's useful, so...). It may contain + things like random comments or - promimently - a diff stat. (See 6.) + + 6. A diff stat provides statistics about how much changed in a given commit + by files and by whole commit (in a summary line). Two functions + `ft/gnus-diff-stat-line-p' and `ft/gnus-diff-stat-summary-p' decide if a + line belongs to a diff stat. It's coloured appropriately and the state + switches back to \"commit-comment\". + + 7. There is a function `ft/gnus-unified-diff-line-p' which will cause the + state to switch to \"unified-diff\" state from either \"commit-message\" + or \"commit-comment\". In this mode there can be a set of lines types: + + a) diff-header lines (`ft/gnus-diff-header-p') + b) index lines (`ft/gnus-index-line-p') + c) hunk lines (`ft/gnus-hunk-line-p') + d) equals line (\"^==*$\") + e) context lines (\"^ \") + f) add lines (\"^\\+\") + g) remove lines (\"^-\") + h) empty lines (\"^$\") + + This state runs until the end of the part." + (catch 'ft/gnus-atp-done + (let ((state 'commit-message) + line do-not-move) + + (while t + ;; Put the current line into an easy-to-handle string variable. + (setq line + (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (setq do-not-move nil) + + ;; Switched state machine. The "real" states are `commit-message', + ;; `commit-comment' and `unified-diff'. The other "states" are only + ;; single-line colourisations that return to their respective parent- + ;; state. Each state may (throw 'ft/gnus-atp-done) to leave the state- + ;; machine immediately. + (setq state + (cond + + ((eq state 'commit-message) + (cond + ((ft/gnus-scissors-line-p line) + (ft/gnus-colour-line 'ft/gnus-scissors) + 'commit-message) + ((ft/gnus-pseudo-header-p line) + (ft/gnus-pseudo-header-colour line) + 'commit-message) + ((string= line "---") + (ft/gnus-colour-line 'ft/gnus-three-dashes) + 'commit-comment) + ((ft/gnus-atp-looks-like-diff line) + (setq do-not-move t) + 'unified-diff) + (t + (ft/gnus-colour-line 'ft/gnus-commit-message) + 'commit-message))) + + ((eq state 'commit-comment) + (cond + ((ft/gnus-diff-stat-line-p line) + (ft/gnus-diff-stat-colour line) + 'commit-comment) + ((ft/gnus-diff-stat-summary-p line) + (ft/gnus-diff-stat-summary-colour line) + 'commit-comment) + ((ft/gnus-atp-looks-like-diff line) + (setq do-not-move t) + 'unified-diff) + (t + (ft/gnus-colour-line 'ft/gnus-commit-comment) + 'commit-comment))) + + ((eq state 'unified-diff) + (cond + ((ft/gnus-diff-header-p line) + (ft/gnus-colour-line 'ft/gnus-diff-header) + 'unified-diff) + ((ft/gnus-index-line-p line) + (ft/gnus-colour-line 'ft/gnus-diff-index) + 'unified-diff) + ((ft/gnus-hunk-line-p line) + (ft/gnus-colour-line 'ft/gnus-diff-hunk) + 'unified-diff) + ((string-match "^==*$" line) + (ft/gnus-colour-line 'ft/gnus-diff-equals) + 'unified-diff) + ((string-match "^$" line) + 'unified-diff) + ((string-match "^ " line) + (ft/gnus-colour-line 'ft/gnus-diff-context) + 'unified-diff) + ((ft/gnus-atp-misc-diff-p line) + (ft/gnus-colour-line 'ft/gnus-diff-misc) + 'unified-diff) + ((string-match "^\\+" line) + (ft/gnus-colour-line 'ft/gnus-diff-add) + 'unified-diff) + ((string-match "^-" line) + (ft/gnus-colour-line 'ft/gnus-diff-remove) + 'unified-diff) + (t 'unified-diff))))) + + (if (not do-not-move) + (if (> (forward-line) 0) + (throw 'ft/gnus-atp-done t))))))) + +(defun ft/gnus-article-treat-patch () + "Highlight mail parts, that look like patches (well, usually +they *are* patches - or possibly, when you take git's format-patch output, +entire commit exports - including comments). This treatment assumes the +use of unified diffs. Here is how it works: + +The most fancy type of patch mails look like this: + + From: ... + Subject: ... + Other-Headers: ... + + Body text, which can be reflecting the commit message but may + optionally be followed by a so called scissors line, which + looks like this (in case of a scissors line, the text above is + not part of the commit message): + + -------8<---------- + + If there really was a scissors line, then it's usually + followed by repeated mail-headers. Which do not *have* to + be the same as the one from the sender. + + From: ... + Subject: ... + + More text. Usually part of the commit message. Likely + multiline. What follows may be an optional diffstat. If + there is one, it's usually preceded by a line that contains + only three dashes and nothing more. Before the diffstat, + however, there may be a set of pseudo headers again, like + these: + + Acked-by: Mike Dev <md@other.tld> + Signed-off-by: Joe D. User <jdu@example.com> + + --- + ChangeLog | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletions(-) + + Now, there is again room for optional text, which is not + part of the actual commit message. May be multiline. Actually, + anything between the three-dashes line and the diff content + is ignored as far as the commit message goes. + + Now for the actual diff part. I want this to work for as + many unified diff formats as possible. What comes to mind + is the format used by git and the format used by cvs and + quilt. + + CVS style looks like this: + + Index: foo/bar.c + ============================================================ + --- boo.orig/foo/bar.c 2010-02-24 .... + +++ boo/foo/bar.c 2010-02-28 .... + @@ -1823,7 +1823,7 @@ + <hunk> + + There may be multiple hunks. Each file gets an \"Index:\" and + equals line. Now the git format looks like this: + + diff --git a/ChangeLog b/ChangeLog + index 6ffbc8c..36e5c17 100644 + --- a/ChangeLog + +++ b/ChangeLog + @@ -3,6 +3,9 @@ + <hunk> + + Again, there may be multiple hunks. + + When all hunks and all files are done, there may be additional + text below the actual text. + +And that's it. + +You may define the look of several things: pseudo headers, scissor +lines, three-dashes-line, equals lines, diffstat lines, diffstat +summary. Then there is added lines, removed lines, context lines, +diff-header lines and diff-file-header lines, for which we are +borrowing the highlighting faces for from `diff-mode'." + (if (ft/gnus-part-want-patch-treatment) + (save-excursion + (progn + (let ((inhibit-read-only t)) + (goto-char (point-min)) + (ft/gnus-article-treat-patch-state-machine)))))) + +(provide 'gnus-article-treat-patch) diff --git a/.emacs.d/lisp/hl-todo b/.emacs.d/lisp/hl-todo new file mode 160000 +Subproject 0598b98f63b623c1778cbd2e2f60b774b7a311b diff --git a/.emacs.d/lisp/page-break-lines b/.emacs.d/lisp/page-break-lines new file mode 160000 +Subproject f8c4cd7fc67638ae4113551dcffdf87fcd252d9 diff --git a/.emacs.d/lisp/s b/.emacs.d/lisp/s new file mode 160000 +Subproject 43ba8b563bee3426cead0e6d4ddc09398e1a349 diff --git a/.emacs.d/lisp/scpaste b/.emacs.d/lisp/scpaste new file mode 160000 +Subproject cd4fa0aafecd839736e0b6cba68b4fc4d704547 |