From 90f051d46a1d9cfbae5d9c2984a96a621ae4a82a Mon Sep 17 00:00:00 2001 From: Amin Bandali Date: Sun, 31 Mar 2024 21:40:41 -0400 Subject: Merge .emacs.d/lisp/bandali-*.el into .emacs.d/init.el Somewhat major overhaul. Worth mentioning are the b/keymap-* wrappers added around the newly introduced keymap-* functions in GNU Emacs 29. Also dropped some mostly unused configs like exwm and org. --- .emacs.d/eshell/alias | 21 + .emacs.d/etc/.dir-locals.el | 4 - .emacs.d/etc/eshell/aliases | 21 - .emacs.d/etc/secrets.el | 5 - .emacs.d/init.el | 1434 +++++++++++++++++++++++++++----------- .emacs.d/lisp/bandali-dired.el | 95 --- .emacs.d/lisp/bandali-erc.el | 200 ------ .emacs.d/lisp/bandali-eshell.el | 97 --- .emacs.d/lisp/bandali-exwm.el | 352 ---------- .emacs.d/lisp/bandali-gnus.el | 430 ------------ .emacs.d/lisp/bandali-ibuffer.el | 110 --- .emacs.d/lisp/bandali-message.el | 110 --- .emacs.d/lisp/bandali-org.el | 125 ---- .emacs.d/lisp/bandali-po.el | 61 -- .emacs.d/lisp/bandali-theme.el | 79 --- 15 files changed, 1052 insertions(+), 2092 deletions(-) create mode 100644 .emacs.d/eshell/alias delete mode 100644 .emacs.d/etc/.dir-locals.el delete mode 100644 .emacs.d/etc/eshell/aliases delete mode 100644 .emacs.d/etc/secrets.el delete mode 100644 .emacs.d/lisp/bandali-dired.el delete mode 100644 .emacs.d/lisp/bandali-erc.el delete mode 100644 .emacs.d/lisp/bandali-eshell.el delete mode 100644 .emacs.d/lisp/bandali-exwm.el delete mode 100644 .emacs.d/lisp/bandali-gnus.el delete mode 100644 .emacs.d/lisp/bandali-ibuffer.el delete mode 100644 .emacs.d/lisp/bandali-message.el delete mode 100644 .emacs.d/lisp/bandali-org.el delete mode 100644 .emacs.d/lisp/bandali-po.el delete mode 100644 .emacs.d/lisp/bandali-theme.el diff --git a/.emacs.d/eshell/alias b/.emacs.d/eshell/alias new file mode 100644 index 0000000..113ef31 --- /dev/null +++ b/.emacs.d/eshell/alias @@ -0,0 +1,21 @@ +alias .. cd .. +alias ... cd ../.. +alias d dired $* +alias e find-file-other-window $1 +alias ee find-file $1 +alias emacs find-file $1 +alias gd magit-diff-unstaged +alias gds magit-diff-staged +alias git git --no-pager $* +alias l ls -l $* +alias la ls -al $* +alias ll ls -al $* +alias man woman $1 +alias up eshell-up $1 +alias pk eshell-up-peek $1 +alias vi find-file $1 +alias vim find-file $1 +alias mbsync mbsync -c $XDG_CONFIG_HOME/isync/mbsyncrc $* +alias getmail getmail --getmaildir $XDG_CONFIG_HOME/getmail --rcfile getmailrc $* +alias m mbsync csclub; mbsync kelar; mbsync shemshak; mbsync gnub; mbsync sfl; mbsync sflro; getmail +alias mc mbsync canonical; mbsync csclub; mbsync kelar; mbsync shemshak; mbsync gnub; mbsync sfl; mbsync sflro; getmail diff --git a/.emacs.d/etc/.dir-locals.el b/.emacs.d/etc/.dir-locals.el deleted file mode 100644 index e007adb..0000000 --- a/.emacs.d/etc/.dir-locals.el +++ /dev/null @@ -1,4 +0,0 @@ -;;; Directory Local Variables -;;; For more information see (info "(emacs) Directory Variables") - -((emacs-lisp-mode . ((flycheck-disabled-checkers . (emacs-lisp-checkdoc))))) diff --git a/.emacs.d/etc/eshell/aliases b/.emacs.d/etc/eshell/aliases deleted file mode 100644 index 113ef31..0000000 --- a/.emacs.d/etc/eshell/aliases +++ /dev/null @@ -1,21 +0,0 @@ -alias .. cd .. -alias ... cd ../.. -alias d dired $* -alias e find-file-other-window $1 -alias ee find-file $1 -alias emacs find-file $1 -alias gd magit-diff-unstaged -alias gds magit-diff-staged -alias git git --no-pager $* -alias l ls -l $* -alias la ls -al $* -alias ll ls -al $* -alias man woman $1 -alias up eshell-up $1 -alias pk eshell-up-peek $1 -alias vi find-file $1 -alias vim find-file $1 -alias mbsync mbsync -c $XDG_CONFIG_HOME/isync/mbsyncrc $* -alias getmail getmail --getmaildir $XDG_CONFIG_HOME/getmail --rcfile getmailrc $* -alias m mbsync csclub; mbsync kelar; mbsync shemshak; mbsync gnub; mbsync sfl; mbsync sflro; getmail -alias mc mbsync canonical; mbsync csclub; mbsync kelar; mbsync shemshak; mbsync gnub; mbsync sfl; mbsync sflro; getmail diff --git a/.emacs.d/etc/secrets.el b/.emacs.d/etc/secrets.el deleted file mode 100644 index edfa1a6..0000000 --- a/.emacs.d/etc/secrets.el +++ /dev/null @@ -1,5 +0,0 @@ -(eval-when-compile (require 'auth-source)) -(defvar nday-students-token (eval-when-compile (plist-get (car (auth-source-search :host "nday-students.slack.com" :max 1)) :token))) - -(defvar canlock-password (eval-when-compile (funcall (plist-get (car (auth-source-search :host "gnus-canlock-password" :max 1)) :secret)))) - diff --git a/.emacs.d/init.el b/.emacs.d/init.el index 6e038d4..c9e5c8e 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -17,17 +17,20 @@ ;;; Commentary: -;; GNU Emacs configuration of bandali, free software activist, -;; computing scientist, and GNU maintainer and volunteer. - -;; Over the years, I've taken inspiration from configurations of many -;; great people. Some that I can remember off the top of my head are: +;; bandali's opinionated GNU Emacs configs. I tend to use the latest +;; development trunk of emacs.git, but I try to maintain backward +;; compatibility with a few of the recent older GNU Emacs releases +;; so I could easily reuse it on machines stuck with older Emacsen. + +;; When initially putting this together, I took inspiration from +;; configurations of many great people. Some that I could remember +;; off the top of my head are: ;; ;; - https://github.com/dieggsy/dotfiles ;; - https://github.com/dakra/dmacs -;; - http://pages.sachachua.com/.emacs.d/Sacha.html +;; - https://pages.sachachua.com/.emacs.d/Sacha.html ;; - https://github.com/dakrone/eos -;; - http://doc.rix.si/cce/cce.html +;; - https://cce.whatthefuck.computer/ ;; - https://github.com/jwiegley/dot-emacs ;; - https://github.com/wasamasa/dotemacs ;; - https://github.com/hlissner/doom-emacs @@ -42,11 +45,10 @@ (defconst b/gc-cons-threshold gc-cons-threshold) (defconst b/gc-cons-percentage gc-cons-percentage) (defvar b/file-name-handler-alist file-name-handler-alist) -(setq gc-cons-threshold (* 30 1024 1024) ; 30 MiB - gc-cons-percentage 0.6 - file-name-handler-alist nil - ;; sidesteps a bug when profiling with esup - esup-child-profile-require-level 0) +(setq + gc-cons-threshold (* 30 1024 1024) ; 30 MiB + gc-cons-percentage 0.6 + file-name-handler-alist nil) ;; Set them back to their defaults once we're done initializing. (defun b/post-init () @@ -55,92 +57,107 @@ b/emacs-initialized t gc-cons-threshold b/gc-cons-threshold gc-cons-percentage b/gc-cons-percentage - file-name-handler-alist b/file-name-handler-alist)) + file-name-handler-alist b/file-name-handler-alist) + + (require 'package) + (package-initialize)) (add-hook 'after-init-hook #'b/post-init) ;; whoami -(setq user-full-name "Amin Bandali" - user-mail-address "bandali@kelar.org") - - -;;; Package management - -;; variables of interest: -;; package-archive-priorities -;; package-load-list -;; package-pinned-packages - -;; (let* ((b (find-file-noselect "refinery-theme.el")) -;; (d (with-current-buffer b (package-buffer-info)))) -;; (package-generate-description-file d "refinery-theme-pkg.el")) -(run-with-idle-timer 0.01 nil #'require 'package) -(with-eval-after-load 'package - ;; (setq - ;; ;; package-archives - ;; ;; `(,@package-archives - ;; ;; ("bndl" . "https://p.bndl.org/elpa/")) - ;; package-load-list - ;; '(;; GNU ELPA - ;; (debbugs "0.29") - ;; (delight "1.7") - ;; (emms "7.7") - ;; (rt-liberation "2.4"))) - (package-initialize)) +(setq + user-full-name "Amin Bandali" + user-mail-address "bandali@kelar.org") ;;; Initial setup -;; Keep ~/.emacs.d clean. -(defvar b/etc-dir - (expand-file-name - (convert-standard-filename "etc/") user-emacs-directory) - "The directory where packages place their configuration files.") -(defvar b/var-dir - (expand-file-name - (convert-standard-filename "var/") user-emacs-directory) - "The directory where packages place their persistent data files.") -(defvar b/lisp-dir - (expand-file-name - (convert-standard-filename "lisp/") user-emacs-directory) - "The directory where packages place their persistent data files.") -(defun b/etc (file) - "Expand filename FILE relative to `b/etc-dir'." - (expand-file-name (convert-standard-filename file) b/etc-dir)) -(defun b/var (file) - "Expand filename FILE relative to `b/var-dir'." - (expand-file-name (convert-standard-filename file) b/var-dir)) -(defun b/lisp (file) - "Expand filename FILE relative to `b/lisp-dir'." - (expand-file-name (convert-standard-filename file) b/lisp-dir)) +(eval-and-compile + (defsubst b/emacs.d (path) + "Expand path PATH relative to `user-emacs-directory'." + (expand-file-name + (convert-standard-filename path) user-emacs-directory)) + + ;; Wrappers around the new keybinding functions, with fallback to + ;; the corresponding older lower level function on older Emacsen. + (defsubst b/keymap-set (keymap key definition) + (if (version< emacs-version "29") + (define-key keymap (kbd key) definition) + (keymap-set keymap key definition))) + (defsubst b/keymap-global-set (key command) + (if (version< emacs-version "29") + (global-set-key (kbd key) command) + (keymap-global-set key command))) + (defsubst b/keymap-local-set (key command) + (if (version< emacs-version "29") + (local-set-key (kbd key) command) + (keymap-local-set key command))) + (defsubst b/keymap-global-unset (key) + (if (version< emacs-version "29") + (global-unset-key (kbd key)) + (keymap-global-unset key 'remove))) + (defsubst b/keymap-local-unset (key) + (if (version< emacs-version "29") + (local-unset-key (kbd key)) + (keymap-local-unset key 'remove))) + + (when (version< emacs-version "29") + ;; Emacs 29 introduced the handy `setopt' macro for setting user + ;; options (defined with `defcustom') with a syntax similar to + ;; `setq'. So, we define it on older Emacsen that don't have it. + (defmacro setopt (&rest pairs) + "Set VARIABLE/VALUE pairs, and return the final VALUE. +This is like `setq', but is meant for user options instead of +plain variables. This means that `setopt' will execute any +`custom-set' form associated with VARIABLE. + +\(fn [VARIABLE VALUE]...)" + (declare (debug setq)) + (unless (zerop (mod (length pairs) 2)) + (error "PAIRS must have an even number of variable/value members")) + (let ((expr nil)) + (while pairs + (unless (symbolp (car pairs)) + (error "Attempting to set a non-symbol: %s" (car pairs))) + (push `(setopt--set ',(car pairs) ,(cadr pairs)) + expr) + (setq pairs (cddr pairs))) + (macroexp-progn (nreverse expr)))) + + (defun setopt--set (variable value) + (custom-load-symbol variable) + ;; Check that the type is correct. + (when-let ((type (get variable 'custom-type))) + (unless (widget-apply (widget-convert type) :match value) + (warn "Value `%S' does not match type %s" value type))) + (put variable 'custom-check-value (list value)) + (funcall (or (get variable 'custom-set) #'set-default) variable value)))) ;; Separate custom file (don't want it mixing with init.el). +(setopt custom-file (b/emacs.d "custom.el")) (with-eval-after-load 'custom - (setq custom-file (b/etc "custom.el")) (when (file-exists-p custom-file) - (load custom-file)) - ;; Only one custom theme at a time. - ;; (defadvice load-theme (before clear-previous-themes activate) - ;; "Clear existing theme settings instead of layering them" - ;; (mapc #'disable-theme custom-enabled-themes)) - ) - -;; Load the secrets file if it exists, otherwise show a warning. -;; (with-demoted-errors -;; (load (b/etc "secrets"))) - -;; Start up emacs server: -;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html + (load custom-file))) + +;; Start Emacs server +;; (https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html) (run-with-idle-timer 0.5 nil #'require 'server) (with-eval-after-load 'server (declare-function server-edit "server") - (global-set-key (kbd "C-c F D") #'server-edit) + (b/keymap-global-set "C-c F D" #'server-edit) (declare-function server-running-p "server") (or (server-running-p) (server-mode))) ;;; Defaults -;;;; C-level customizations +;;;; C source code + +(setq-default + ;; Case-sensitive search (and `dabbrev-expand'). + ;; case-fold-search nil + indent-tabs-mode nil ; always use space for indentation + ;; tab-width 4 + indicate-buffer-boundaries 'left) (setq ;; line-spacing 3 @@ -153,83 +170,53 @@ ;; mouse-autoselect-window t scroll-conservatively 15 scroll-preserve-screen-position 1 - ;; I don't feel like jumping out of my chair every now and again; - ;; so...don't *BEEP* at me, Emacs. =) + ;; I don't feel like randomly jumping out of my chair. ring-bell-function 'ignore) -(setq-default - ;; Case-sensitive search (and `dabbrev-expand'). - ;; case-fold-search nil - indent-tabs-mode nil ; always use space for indentation - tab-width 4 - indicate-buffer-boundaries 'left) - -;; Lazy-person-friendly yes/no prompts. -(defalias 'yes-or-no-p #'y-or-n-p) - -(when (display-graphic-p) - ;; (set-frame-font "Source Code Pro-10.5:weight=medium" nil t) - ;; (set-frame-font "FreeSans" nil t) - (set-fontset-font t 'arabic "Sahel WOL")) - -;;;; Elisp-level customizations +;;;; elisp source code (with-eval-after-load 'minibuffer - (setq read-file-name-completion-ignore-case t)) - -;; `startup' -(setq auto-save-list-file-prefix (b/var "auto-save/sessions/")) + (setopt read-file-name-completion-ignore-case t)) (with-eval-after-load 'files - (setq - ;; backups (C-h v make-backup-files RET) - backup-by-copying t - backup-directory-alist (list (cons "." (b/var "backup/"))) - version-control t - delete-old-versions t - ;; auto-save - auto-save-file-name-transforms `((".*" ,(b/var "auto-save/") t)) - ;; insert newline at the end of files + (setopt + make-backup-files nil + ;; Insert newline at the end of files ;; require-final-newline t - ;; open read-only file buffers in view-mode - ;; (enables niceties like `q' for quit) - view-read-only t)) + ;; Open read-only file buffers in view-mode; + ;; it enables niceties like `q' for quit. + view-read-only t) + (add-to-list 'auto-mode-alist '("\\.*rc$" . conf-mode)) + (add-to-list 'auto-mode-alist '("\\.bashrc$" . sh-mode))) -;; `novice' (setq disabled-command-function nil) -;; `subr' -;; (keyboard-translate ?\( ?\[) -;; (keyboard-translate ?\) ?\]) -;; (keyboard-translate ?\[ ?\() -;; (keyboard-translate ?\] ?\)) - (run-with-idle-timer 0.1 nil #'require 'autorevert) (with-eval-after-load 'autorevert - (setq + (setopt ;; auto-revert-verbose nil global-auto-revert-non-file-buffers nil) (global-auto-revert-mode 1)) (run-with-idle-timer 0.1 nil #'require 'time) (with-eval-after-load 'time - (setq + (setopt display-time-default-load-average nil display-time-format " %a %Y-%m-%d %-l:%M%P" - display-time-mail-icon '(image :type xpm - :file "gnus/gnus-pointer.xpm" - :ascent center) + display-time-mail-icon + '(image :type xpm :file "gnus/gnus-pointer.xpm" :ascent center) display-time-use-mail-icon t zoneinfo-style-world-list `(,@zoneinfo-style-world-list ("Etc/UTC" "UTC") ("Asia/Tehran" "Tehran") ("Australia/Melbourne" "Melbourne"))) - (display-time-mode)) + (unless (display-graphic-p) + (display-time-mode))) (run-with-idle-timer 0.1 nil #'require 'battery) (with-eval-after-load 'battery - (setq battery-mode-line-format " [%p%% %t]") + (setopt battery-mode-line-format " [%b%p%% %t]") (display-battery-mode)) (progn ; display system volume in mode-line @@ -299,30 +286,18 @@ microphone) instead of the default sink." (run-with-idle-timer 0.5 nil #'require 'winner) (with-eval-after-load 'winner - (winner-mode 1) - (when (featurep 'exwm) - ;; prevent a bad interaction between EXWM and winner-mode, where - ;; sometimes closing a window (like closing a terminal after - ;; entering a GPG password via pinentry-gnome3's floating window) - ;; results in a dead frame somewhere and effectively freezes EXWM. - (advice-add - 'winner-insert-if-new - :around - (lambda (orig-fun &rest args) - ;; only add the frame if it's live - (when (frame-live-p (car args)) - (apply orig-fun args)))))) + (winner-mode 1)) (run-with-idle-timer 0.5 nil #'require 'windmove) (with-eval-after-load 'windmove - (setq windmove-wrap-around t) - (global-set-key (kbd "M-H") #'windmove-left) - (global-set-key (kbd "M-L") #'windmove-right) - (global-set-key (kbd "M-K") #'windmove-up) - (global-set-key (kbd "M-J") #'windmove-down)) + (setopt windmove-wrap-around t) + (b/keymap-global-set "M-H" #'windmove-left) + (b/keymap-global-set "M-L" #'windmove-right) + (b/keymap-global-set "M-K" #'windmove-up) + (b/keymap-global-set "M-J" #'windmove-down)) (with-eval-after-load 'isearch - (setq + (setopt ;; Allow scrolling in Isearch. isearch-allow-scroll t isearch-lazy-count t @@ -334,27 +309,28 @@ microphone) instead of the default sink." ;; (with-eval-after-load 'replace ;; ;; Uncomment to extend the above behaviour to query-replace. -;; (setq replace-char-fold t)) +;; (setopt replace-char-fold t)) -;; `vc' -(global-set-key (kbd "C-x v C-=") #'vc-ediff) +(b/keymap-global-set "C-x v C-=" #'vc-ediff) (with-eval-after-load 'vc-git - (setq vc-git-print-log-follow t - vc-git-show-stash 0)) + (setopt + ;; vc-git-show-stash 0 + vc-git-print-log-follow t)) (with-eval-after-load 'ediff - (setq ediff-window-setup-function 'ediff-setup-windows-plain - ediff-split-window-function 'split-window-horizontally)) + (setopt + ediff-window-setup-function #'ediff-setup-windows-plain + ediff-split-window-function #'split-window-horizontally)) -(with-eval-after-load 'face-remap - (setq - ;; Gentler font resizing. - text-scale-mode-step 1.05)) +;; (with-eval-after-load 'face-remap +;; (setopt +;; ;; Gentler font resizing. +;; text-scale-mode-step 1.05)) (run-with-idle-timer 0.4 nil #'require 'mwheel) (with-eval-after-load 'mwheel - (setq + (setopt mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; one line at a time mouse-wheel-progressive-speed nil ; don't accelerate scrolling mouse-wheel-follow-mouse t)) ; scroll window under mouse @@ -364,17 +340,17 @@ microphone) instead of the default sink." (pixel-scroll-mode 1)) (with-eval-after-load 'epg-config - (setq + (setopt epg-gpg-program (executable-find "gpg") ;; Ask for GPG passphrase in minibuffer. ;; Will fail if gpg >= 2.1 is not available. epg-pinentry-mode 'loopback)) -(with-eval-after-load 'auth-source - (setq - auth-sources '("~/.authinfo.gpg") - authinfo-hidden - (regexp-opt '("password" "client-secret" "token")))) +;; (with-eval-after-load 'auth-source +;; (setopt +;; auth-sources '("~/.authinfo.gpg") +;; authinfo-hidden +;; (regexp-opt '("password" "client-secret" "token")))) (with-eval-after-load 'info (setq @@ -385,6 +361,7 @@ microphone) instead of the default sink." "/usr/share/info/"))) (when (display-graphic-p) + (set-fontset-font t 'arabic "Sahel WOL") (with-eval-after-load 'faces (let ((grey "#e7e7e7")) (set-face-attribute 'fixed-pitch nil @@ -394,10 +371,10 @@ microphone) instead of the default sink." :background grey :inherit 'fixed-pitch)))) -(when (version< emacs-version "28") - ;; Manually make some `mode-line' spaces smaller. Emacs 28 (and - ;; above) does a terrific job at this out of the box when - ;; `mode-line-compact' is set to t (see above)." +(when (and (version< emacs-version "28") mode-line-compact) + ;; Manually make some `mode-line' spaces smaller. + ;; Emacs 28 and above do a terrific job at this out of the box + ;; when `mode-line-compact' is set to t (see above)." (setq-default mode-line-format (mapcar @@ -414,12 +391,6 @@ microphone) instead of the default sink." ;;; Useful utilities -(defun b/add-elisp-section () - (interactive) - (insert "\n") - (forward-line -1) - (insert "\n \n;;; ")) - (defun b/insert-asterism () "Insert a centred asterism." (interactive) @@ -433,39 +404,13 @@ microphone) instead of the default sink." asterism "\n")))) -(defun b/start-process (program &rest args) - "Same as `start-process', but doesn't bother about name and buffer." - (let ((process-name (concat program "_process")) - (buffer-name (generate-new-buffer-name - (concat program "_output")))) - (apply #'start-process - process-name buffer-name program args))) - -(defun b/no-mouse-autoselect-window () - "Conveniently disable `focus-follows-mouse'. -For disabling the behaviour for certain buffers and/or modes." - (make-local-variable 'mouse-autoselect-window) - (setq mouse-autoselect-window nil)) - -;; (defun b/move-indentation-or-beginning-of-line (arg) -;; "Move to the indentation or to the beginning of line." -;; (interactive "^p") -;; ;; (if (bolp) -;; ;; (back-to-indentation) -;; ;; (move-beginning-of-line arg)) -;; (if (= (point) -;; (progn (back-to-indentation) -;; (point))) -;; (move-beginning-of-line arg))) - (defun b/join-line-top () "Like `join-line', but join next line to the current line." (interactive) (join-line 1)) (defun b/*scratch* () - "Switch to `*scratch*' buffer, creating it if it does not - exist." + "Switch to `*scratch*' buffer, creating it if it does not exist." (interactive) (let ((fun (if (functionp #'get-scratch-buffer-create) #'get-scratch-buffer-create ; (version<= "29" emacs-version) @@ -500,88 +445,54 @@ for all frames." (let ((frame (unless arg (selected-frame)))) (invert-face 'default frame) - (invert-face 'mode-line frame)) - (when (fboundp #'exwm-systemtray--refresh-background-color) - (exwm-systemtray--refresh-background-color 'remap))) - -(defun b/export-frame () - (interactive) - ;; TODO: ask for fn and/or take as arg - (let* ((fn (make-temp-file "emacs" nil ".pdf")) - (data (x-export-frames nil 'pdf))) - (with-temp-file fn - (insert data)) - (kill-new fn) - (message fn))) + (invert-face 'mode-line frame))) ;;; General key bindings -;; (global-set-key (kbd "C-a") #'b/move-indentation-or-beginning-of-line) -(global-set-key (kbd "C-c i") #'ielm) -(global-set-key (kbd "C-c d") #'b/duplicate-line-or-region) -(global-set-key (kbd "C-c j") #'b/join-line-top) -(global-set-key (kbd "C-S-j") #'b/join-line-top) -(global-set-key (kbd "C-c s c") #'b/*scratch*) -(global-set-key (kbd "C-c v") #'b/invert-default-face) +(b/keymap-global-set "C-c i" #'ielm) +(b/keymap-global-set "C-c d" #'b/duplicate-line-or-region) +(b/keymap-global-set "C-c j" #'b/join-line-top) +(b/keymap-global-set "C-S-j" #'b/join-line-top) +(b/keymap-global-set "C-c s c" #'b/*scratch*) +(b/keymap-global-set "C-c v" #'b/invert-default-face) ;; evaling and macro-expanding -(global-set-key (kbd "C-c e b") #'eval-buffer) -(global-set-key (kbd "C-c e e") #'eval-last-sexp) -(global-set-key (kbd "C-c e m") #'pp-macroexpand-last-sexp) -(global-set-key (kbd "C-c e r") #'eval-region) +(b/keymap-global-set "C-c e b" #'eval-buffer) +(b/keymap-global-set "C-c e e" #'eval-last-sexp) +(b/keymap-global-set "C-c e m" #'pp-macroexpand-last-sexp) +(b/keymap-global-set "C-c e r" #'eval-region) ;; emacs things -(global-set-key (kbd "C-c e i") #'emacs-init-time) -(global-set-key (kbd "C-c e u") #'emacs-uptime) -(global-set-key (kbd "C-c e v") #'emacs-version) +(b/keymap-global-set "C-c e i" #'emacs-init-time) +(b/keymap-global-set "C-c e u" #'emacs-uptime) +(b/keymap-global-set "C-c e v" #'emacs-version) ;; finding -(global-set-key (kbd "C-c f .") #'find-file) -(global-set-key (kbd "C-c f d") #'find-name-dired) -(global-set-key (kbd "C-c f l") #'find-library) -(global-set-key (kbd "C-c f p") #'find-file-at-point) +(b/keymap-global-set "C-c f ." #'find-file) +(b/keymap-global-set "C-c f l" #'find-library) +(b/keymap-global-set "C-c f p" #'find-file-at-point) ;; frames -(global-set-key (kbd "C-c F m") #'make-frame-command) -(global-set-key (kbd "C-c F d") #'delete-frame) +(b/keymap-global-set "C-c F m" #'make-frame-command) +(b/keymap-global-set "C-c F d" #'delete-frame) ;; help/describe -(global-set-key (kbd "C-S-h F") #'describe-face) +(b/keymap-global-set "C-c h F" #'describe-face) -(define-key emacs-lisp-mode-map (kbd "C-") #'b/add-elisp-section) - -(when (display-graphic-p) - (global-unset-key (kbd "C-z"))) +;; (when (display-graphic-p) +;; ;; Too easy to accidentally suspend (freeze) Emacs GUI. +;; (b/keymap-global-unset "C-z")) ;;; Essential packages -(add-to-list - 'load-path - (expand-file-name - (convert-standard-filename "lisp") user-emacs-directory)) - -(when - (and - (display-graphic-p) - ;; we're not running in another WM/DE - (not (getenv "XDG_CURRENT_DESKTOP")) - (member (system-name) '("chaman" "langa"))) - (require 'bandali-exwm) - (global-set-key (kbd "C-x b") #'exwm-workspace-switch-to-buffer)) - -(require 'bandali-org) - -;; (require 'bandali-theme) +(add-to-list 'load-path (b/emacs.d "lisp")) ;; recently opened files (run-with-idle-timer 0.2 nil #'require 'recentf) (with-eval-after-load 'recentf - (setq - recentf-max-saved-items 2000 - recentf-save-file (b/var "recentf-save.el")) - ;; (add-to-list 'recentf-keep #'file-remote-p) + (setopt recentf-max-saved-items 2000) (recentf-mode) (defun b/recentf-open () @@ -589,7 +500,7 @@ for all frames." (interactive) (find-file (completing-read "Find recent file: " recentf-list))) - (global-set-key (kbd "C-c f r") #'b/recentf-open)) + (b/keymap-global-set "C-c f r" #'b/recentf-open)) ;; (define-key minibuffer-local-completion-map ;; "\t" #'minibuffer-force-complete) @@ -627,69 +538,812 @@ for all frames." ;; completion-styles '(basic substring partial-completion flex)))) ;; (add-hook 'minibuffer-setup-hook #'b/icomplete--fido-mode-setup 1) -(require 'bandali-eshell) - -(require 'bandali-ibuffer) - -(require 'bandali-dired) - -(with-eval-after-load 'help - (temp-buffer-resize-mode) - (setq help-window-select t)) +(with-eval-after-load 'eshell + (setopt + eshell-hist-ignoredups t + eshell-input-filter #'eshell-input-filter-initial-space + eshell-prompt-regexp "^[^#$\n]* [#$] ; " + eshell-prompt-function + (lambda () + (let ((uid (if (functionp #'file-user-uid) + #'file-user-uid ; (version<= "30" emacs-version) + #'user-uid))) ; (version< emacs-version "30") + (concat ": " + (system-name) + ":" + (abbreviate-file-name (eshell/pwd)) + (unless (eshell-exit-success-p) + (format " [%d]" eshell-last-command-status)) + (if (= (funcall uid) 0) " # " " $ ") + "; ")))) + (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-history () + (interactive) + (completing-read "Eshell history: " + (ring-elements eshell-history-ring))) + (with-eval-after-load 'esh-mode + (let ((m eshell-mode-map)) + (b/keymap-set m "C-d" #'b/eshell-quit-or-delete-char) + (b/keymap-set m "C-S-l" #'b/eshell-clear))) + (with-eval-after-load 'esh-hist + (let ((m eshell-hist-mode-map)) + (b/keymap-set m "M-r" #'b/eshell-history)))) +(b/keymap-global-set "C-c s e" #'eshell) + +(with-eval-after-load 'ibuffer + (setopt + ibuffer-saved-filter-groups + '(("default" + ("dired" (mode . dired-mode)) + ("erc" (mode . erc-mode)) + ("gnus" + (or + (mode . gnus-group-mode) + (mode . gnus-server-mode) + (mode . gnus-summary-mode) + (mode . gnus-article-mode) + (mode . message-mode))) + ("shell" + (or + (mode . eshell-mode) + (mode . shell-mode) + (mode . term-mode))) + ("tex" + (or + (mode . tex-mode) + (mode . bibtex-mode) + (mode . latex-mode))))) + ibuffer-formats + `((mark modified read-only locked + " " (name 18 18 :left :elide) + " " (size-h 9 -1 :right) + " " (mode 16 16 :left :elide) " " filename-and-process) + ,@ibuffer-formats)) + ;; Use human readable Size column instead of original one + (define-ibuffer-column size-h + (:name "Size" :inline t) + (cond + ((> (buffer-size) (* 1024 1024)) + (format "%7.1fM" (/ (buffer-size) (* 1024.0 1024.0)))) + ((> (buffer-size) (* 100 1024)) + (format "%7.0fK" (/ (buffer-size) 1024.0))) + ((> (buffer-size) 1024) + (format "%7.1fK" (/ (buffer-size) 1024.0))) + (t (format "%8d" (buffer-size))))) + + (let ((m ibuffer-mode-map)) + (b/keymap-set m "P" #'ibuffer-backward-filter-group) + (b/keymap-set m "N" #'ibuffer-forward-filter-group) + (b/keymap-set m "M-p" #'ibuffer-do-print) + (b/keymap-set m "M-n" #'ibuffer-do-shell-command-pipe-replace))) +(b/keymap-global-set "C-x C-b" #'ibuffer) +(declare-function + ibuffer-switch-to-saved-filter-groups "ibuf-ext" (name)) +(add-hook + 'ibuffer-hook + (lambda () (ibuffer-switch-to-saved-filter-groups "default"))) + +(with-eval-after-load 'dired + ;; (require 'ls-lisp) + (setopt + dired-dwim-target t + ;; dired-listing-switches "-alh --group-directories-first" + dired-listing-switches "-alh" + ;; 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")))) + + ;; local key bindings + (let ((m dired-mode-map)) + (b/keymap-set m "b" #'dired-up-directory) + (b/keymap-set m "E" #'dired-ediff-files) + (b/keymap-set m "e" #'dired-toggle-read-only) + (b/keymap-set m "\\" #'dired-hide-details-mode)) + + (require 'dired-x) + (setopt + dired-guess-shell-alist-user + '(("\\.pdf\\'" "atril" "evince" "zathura" "okular") + ("\\.doc\\'" "libreoffice") + ("\\.docx\\'" "libreoffice") + ("\\.ppt\\'" "libreoffice") + ("\\.pptx\\'" "libreoffice") + ("\\.xls\\'" "libreoffice") + ("\\.xlsx\\'" "libreoffice") + ("\\.flac\\'" "mpv")))) +(add-hook 'dired-mode-hook #'dired-hide-details-mode) + +;; (with-eval-after-load 'help +;; (temp-buffer-resize-mode) +;; (setopt help-window-select t)) (with-eval-after-load 'help-mode - (define-key help-mode-map (kbd "p") #'backward-button) - (define-key help-mode-map (kbd "n") #'forward-button)) + (let ((m help-mode-map)) + (b/keymap-set m "p" #'backward-button) + (b/keymap-set m "n" #'forward-button) + (b/keymap-set m "b" #'help-go-back) + (b/keymap-set m "f" #'help-go-forward))) (with-eval-after-load 'tramp - (setq tramp-auto-save-directory (b/var "tramp/auto-save/") - tramp-persistency-file-name (b/var "tramp/persistency.el")) + (setopt tramp-auto-save-directory (b/emacs.d "tramp-auto-save/")) (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:")) (add-to-list 'tramp-default-proxies-alist '("localhost" nil nil)) (add-to-list 'tramp-default-proxies-alist (list (regexp-quote (system-name)) nil nil))) (with-eval-after-load 'doc-view - (define-key doc-view-mode-map (kbd "M-RET") #'image-previous-line)) + (b/keymap-set doc-view-mode-map "M-RET" #'image-previous-line)) + +(with-eval-after-load 'shr + (setopt shr-max-width 80)) -(setq shr-max-width 80) + +;;; Email + +(defvar b/maildir + (expand-file-name (convert-standard-filename "~/mail/"))) +(with-eval-after-load 'recentf + (add-to-list 'recentf-exclude b/maildir)) + +(setopt + mail-user-agent 'gnus-user-agent + read-mail-command #'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)) + +(with-eval-after-load 'gnus + (with-eval-after-load 'nnimap + (setq nnimap-record-commands init-file-debug)) + + (setopt + gnus-select-method '(nnnil "") + gnus-secondary-select-methods + `(,@(when (member (system-name) '("darya" "nostalgia")) + '((nnimap + "canonical" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "bandali@canonical.local")))) + (nnimap + "kelar" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "bandali@kelar.local") + ;; (nnmail-expiry-wait immediate) + (nnmail-expiry-target nnmail-fancy-expiry-target) + (nnmail-fancy-expiry-targets + (("from" ".*" "nnimap+kelar:Archive.%Y")))) + (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") + ;; spam + ("X-Spam_action" "reject" "Junk") + ;; keep debbugs emails in INBOX + (list ".*<\\(.*\\)\\.debbugs\\.gnu\\.org>.*" "INBOX") + ;; list moderation emails + (from ".+-\\(owner\\|bounces\\)@\\(non\\)?gnu\\.org" "listmod") + ;; gnu + (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1") + ("Envelope-To" "emacsconf-donations@gnu.org" "l.emacsconf-donations") + ;; board-eval + (| + (list ".*<.*\\.board-eval\\.fsf\\.org>.*" "l.board-eval") + (from ".*@board-eval\\.fsf\\.org" "l.board-eval")) + ;; fsf + (list ".*<\\(.*\\)\\.fsf\\.org>.*" "l.\\1") + ;; cfarm + (from "cfarm-.*@lists\\.tetaneutral\\.net" "l.cfarm") + ;; debian + (list ".*<\\(.*\\)\\.\\(lists\\|other\\)\\.debian\\.org>.*" "l.\\1") + (list ".*<\\(.*\\)\\.alioth-lists\\.debian\\.net>.*" "l.\\1") + ;; gnus + (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1") + ;; libreplanet + (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1") + ;; iana (e.g. tz-announce) + (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1") + ;; mailop + (list ".*<\\(.*\\)\\.mailop\\.org>.*" "l.\\1") + ;; sdlu + (list ".*<\\(.*\\)\\.spammers\\.dontlike\\.us>.*" "l.sdlu") + ;; bitfolk + (from ".*@\\(.+\\)?bitfolk\\.com>.*" "bitfolk") + ;; haskell + (list ".*<\\(.*\\)\\.haskell\\.org>.*" "l.\\1") + ;; 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 ".*notmuch.notmuchmail.org" "l.notmuch") ;u + (list ".*dev.lists.parabola.nu" "l.parabola-dev") + ;; ---------------------------------- + ;; legend: (u)nsubscribed | (d)ead + ;; ---------------------------------- + ;; otherwise, leave mail in INBOX + "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 plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "amin.bandali@savoirfairelinux.local"))) + gnus-message-archive-group "nnimap+kelar:INBOX" + gnus-parameters + '(("l\\.fencepost-users" + (to-address . "fencepost-users@gnu.org") + (to-list . "fencepost-users@gnu.org") + (list-identifier . "\\[Fencepost-users\\]")) + ("l\\.haskell-cafe" + (to-address . "haskell-cafe@haskell.org") + (to-list . "haskell-cafe@haskell.org") + (list-identifier . "\\[Haskell-cafe\\]"))) + ;; gnus-large-newsgroup 50 + gnus-process-mark-toggle t + gnus-home-directory (b/emacs.d "gnus/") + gnus-directory + (expand-file-name + (convert-standard-filename "news/") gnus-home-directory) + gnus-interactive-exit nil + gnus-user-agent '(emacs gnus type)) + + (with-eval-after-load 'message + (setopt + message-directory + (expand-file-name + (convert-standard-filename "mail/") gnus-home-directory))) + + (with-eval-after-load 'nndraft + (setopt + nndraft-directory + (expand-file-name + (convert-standard-filename "drafts/") gnus-home-directory))) + + (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") + 'append))) + + (with-eval-after-load 'gnus-agent + (setopt gnus-agent-synchronize-flags 'ask)) + + (with-eval-after-load 'gnus-art ; article + (setopt + 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 "\\|"))) + + (with-eval-after-load 'gnus-dired + (with-eval-after-load 'dired + (add-hook 'dired-mode-hook #'gnus-dired-mode))) + + (with-eval-after-load 'gnus-group + (setopt + gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)") + (add-hook 'gnus-group-mode-hook #'gnus-topic-mode) + (add-hook 'gnus-group-mode-hook #'gnus-agent-mode)) + + (with-eval-after-load 'gnus-msg + (let ((bandali "Amin Bandali%s - https://kelar.org/~bandali")) + (defvar b/csc-signature + (mapconcat + #'identity + `(,(format bandali ", MMath") + "Systems Committee " + "Computer Science Club of the University of Waterloo") + "\n")) + (defvar b/sfl-signature + (mapconcat + #'identity + `(,(format bandali "") + "Volunteer, Savoir-faire Linux" + "jami:bandali") + "\n"))) + (setopt + gnus-gcc-mark-as-read t + gnus-message-replysign t + gnus-posting-styles + '(("nnimap\\+kelar:.*" + (address "bandali@kelar.org") + ("X-Message-SMTP-Method" "smtp mail.kelar.org 587") + (gcc "nnimap+kelar:INBOX")) + ("nnimap\\+shemshak:.*" + (address "amin@shemshak.org") + ("X-Message-SMTP-Method" "smtp mail.shemshak.org 587") + (gcc "nnimap+shemshak:Sent")) + ("nnimap\\+gnu:.*" + (address "bandali@gnu.org") + ("X-Message-SMTP-Method" "smtp fencepost.gnu.org 587") + (gcc "nnimap+gnu:INBOX")) + ("nnimap\\+canonical:.*" + (address "bandali@canonical.com") + ("X-Message-SMTP-Method" "smtp smtp.canonical.com 587") + (signature nil) + (gcc "nnimap+canonical:Sent")) + ((header "to" "amin\\.bandali@canonical\\.com") + (address "amin.bandali@canonical.com")) + ((header "cc" "amin\\.bandali@canonical\\.com") + (address "amin.bandali@canonical.com")) + ;; ("nnimap\\+.*:l\\.ubuntu-.*" + ;; (address "bandali@ubuntu.com") + ;; ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")) + ;; ((header "list-id" ".*\\.lists.ubuntu.com") + ;; (address "bandali@ubuntu.com") + ;; ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")) + ("nnimap\\+csc:.*" + (address "bandali@csclub.uwaterloo.ca") + ("X-Message-SMTP-Method" "smtp mail.csclub.uwaterloo.ca 587") + (signature b/csc-signature) + (gcc "nnimap+csc:Sent")) + ("nnimap\\+sfl:.*" + (address "amin.bandali@savoirfairelinux.com") + ("X-Message-SMTP-Method" "smtp mail.savoirfairelinux.com 587") + (signature b/sfl-signature) + (gcc "nnimap+sfl:Sent"))))) + + ;; (require 'gnus-registry) + ;; (with-eval-after-load 'gnus-registry + ;; (setopt + ;; gnus-registry-max-entries 2500 + ;; gnus-registry-ignored-groups + ;; (append gnus-registry-ignored-groups + ;; '(("^nnimap:gnu\\.l" t) ("webmasters$" t)))) + ;; (gnus-registry-initialize)) + + (with-eval-after-load 'gnus-search + (setopt + gnus-search-use-parsed-queries t)) + + (with-eval-after-load 'gnus-start + (setopt + gnus-save-newsrc-file nil + gnus-read-newsrc-file nil) + (add-hook 'gnus-after-getting-new-news-hook #'gnus-notifications)) + + (with-eval-after-load 'gnus-sum ; summary + (setopt + gnus-thread-sort-functions + '(gnus-thread-sort-by-number + gnus-thread-sort-by-subject + gnus-thread-sort-by-date)) + (with-eval-after-load 'message + (setopt + gnus-ignored-from-addresses message-dont-reply-to-names)) + + (defun b/gnus-junk-article (&optional n) + (interactive "P" gnus-summary-mode) + (gnus-summary-move-article + n + (gnus-group-prefixed-name + "Junk" + (gnus-find-method-for-group gnus-newsgroup-name)))) + + (defvar b/gnus-summary-prefix-map) + (define-prefix-command 'b/gnus-summary-prefix-map) + (b/keymap-set + gnus-summary-mode-map "v" 'b/gnus-summary-prefix-map) + (let ((m b/gnus-summary-prefix-map)) + (b/keymap-set m "r r" #'gnus-summary-very-wide-reply) + (b/keymap-set m "r q" #'gnus-summary-very-wide-reply-with-original) + (b/keymap-set m "R r" #'gnus-summary-reply) + (b/keymap-set m "R q" #'gnus-summary-reply-with-original) + (b/keymap-set m "r a w" #'gnus-summary-show-raw-article) + (b/keymap-set m "s" #'b/gnus-junk-article))) + + (with-eval-after-load 'gnus-topic + ;; (setopt gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n") + (setopt gnus-topic-line-format "%i[ %(%{%n%}%) (%A) ]%v\n") + (setq gnus-topic-topology + `(("Gnus" visible nil nil) + (("misc" visible nil nil)) + ,@(when (member (system-name) '("darya" "nostalgia")) + '((("canonical" visible nil nil)))) + (("csc" visible nil nil)) + (("kelar" visible nil nil)) + (("shemshak" visible nil nil)) + (("gnu" visible nil nil)) + ;; (("old-gnu" visible nil nil)) + (("sfl" visible nil nil))))) + + (with-eval-after-load 'gnus-win + (setopt gnus-use-full-window nil)) + + (with-eval-after-load 'mm-archive + (add-to-list + 'mm-archive-decoders + '("application/gzip" nil "gunzip" "-S" ".zip" "-kd" "%f" "-r"))) + + (with-eval-after-load 'mm-decode + (setopt + ;; mm-attachment-override-types `("text/x-diff" "text/x-patch" + ;; ,@mm-attachment-override-types) + mm-discouraged-alternatives '("text/html" "text/richtext") + mm-decrypt-option 'known + mm-verify-option 'known) + (add-to-list + 'mm-inline-media-tests + `("application/gzip" mm-archive-dissect-and-inline identity)) + (add-to-list 'mm-inlined-types "application/gzip" 'append)) + + (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") + (setopt mm-uu-diff-groups-regexp "."))) + + (with-eval-after-load 'mml + (setopt + mml-attach-file-at-the-end t + mml-content-disposition-alist + '((text + (markdown . "attachment") + (rtf . "attachment") + (t . "inline")) + (t . "attachment")))) + + (with-eval-after-load 'mml-sec + (setopt + mml-secure-openpgp-encrypt-to-self t + mml-secure-openpgp-sign-with-sender t)) + + (with-eval-after-load 'recentf + (add-to-list 'recentf-exclude gnus-home-directory))) +(b/keymap-global-set "C-c g" #'gnus-plugged) +(b/keymap-global-set "C-c G" #'gnus-unplugged) + +(with-eval-after-load 'message + ;; Redefine for a simplified In-Reply-To header + ;; (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)))) + + (setopt + message-elide-ellipsis "[...]\n" + message-citation-line-format "%N writes:\n" + message-citation-line-function + #'message-insert-formatted-citation-line + message-confirm-send t + message-fill-column 70 + message-forward-as-mime t + ;; message-kill-buffer-on-exit t + message-send-mail-function #'smtpmail-send-it + message-subscribed-address-functions + '(gnus-find-subscribed-addresses) + message-dont-reply-to-names + (mapconcat + #'identity + '("bandali@kelar\\.org" + "amin@shemshak\\.org" + "\\(bandali\\|mab\\|aminb?\\)@gnu\\.org" + "a?bandali@\\(csclub\\.\\)?uwaterloo\\.ca" + "amin\\.bandali@savoirfairelinux\\.com" + "\\(amin\\.\\)?bandali@canonical\\.com" + "bandali@ubuntu\\.com" + "bandali@debian\\.org") + "\\|")) + + (defun b/newlines-or-asterism (arg) + "Create newlines per my liking, or insert asterism if ARG is +non-nil." + (interactive "P") + (if arg + (b/insert-asterism) + (progn + (beginning-of-line) + (delete-region (point) (line-end-position)) + (newline) + (open-line 1)))) + (b/keymap-set message-mode-map "M-RET" #'b/newlines-or-asterism) + + (add-hook 'message-mode-hook #'flyspell-mode) + (add-hook + 'message-mode-hook (lambda () (b/keymap-local-unset "C-c C-s")))) -;; Email (with Gnus, message, and smtpmail) ;; (with-eval-after-load 'sendmail -;; (setq mail-header-separator "")) -(require 'bandali-gnus) -(require 'bandali-message) +;; (setopt mail-header-separator "")) + ;; (with-eval-after-load 'smtpmail -;; (setq smtpmail-queue-mail t -;; smtpmail-queue-dir (concat b/maildir "queue/"))) +;; (setopt smtpmail-queue-mail t +;; smtpmail-queue-dir (concat b/maildir "queue/"))) -;; IRC (with ERC) -(require 'bandali-erc) + +;;; IRC +(with-eval-after-load 'erc + (setopt + erc-auto-query 'bury + erc-autojoin-domain-only nil + erc-dcc-get-default-directory (b/emacs.d "erc-dcc") + erc-email-userid "bandali" + ;; erc-join-buffer 'bury + ;; erc-lurker-hide-list '("JOIN" "PART" "QUIT") + erc-nick "bandali" + erc-prompt "erc>" + erc-prompt-for-password nil + erc-query-display 'buffer + ;; erc-server-reconnect-attempts 5 + erc-server-reconnect-timeout 3) + + (if (version< erc-version "5.6-git") + (setopt erc-format-nick-function #'erc-format-@nick) + (setopt erc-show-speaker-membership-status t)) + + (unless (version< erc-version "5.5") + (setopt erc-rename-buffers t)) + + (unless (version< erc-version "5.4") + (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 () + "Ask chanserv to op me in the current channel." + (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 in the current channel." + (erc-cmd-DEOP (format "%s" (erc-current-nick))))) + + (add-to-list 'erc-modules 'keep-place) + (add-to-list 'erc-modules 'log) + (when (display-graphic-p) + (add-to-list 'erc-modules 'notifications) + (add-to-list 'erc-modules 'smiley)) + (add-to-list 'erc-modules 'spelling) + + ;; (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") + + (setopt + ;; erc-enable-logging 'erc-log-all-but-server-buffers + erc-log-file-coding-system 'utf-8 + erc-log-write-after-insert t + erc-log-write-after-send t + erc-save-buffer-on-part nil + erc-save-queries-on-quit nil) + + (with-eval-after-load 'erc-match + (setopt + erc-pal-highlight-type 'nick + erc-pals + '("corwin" "^gopar" "^iank" "^rwp" "technomancy" "thomzane")) + (set-face-attribute + 'erc-pal-face nil + :foreground 'unspecified + :weight 'unspecified + :inherit 'erc-nick-default-face + ;; :background (face-attribute 'font-lock-string-face :background) + :background "#ffffdf")) + + (with-eval-after-load 'erc-pcomplete + (setopt erc-pcomplete-nick-postfix ",") + ;; for matterircd nick (username) completions + ;; (advice-add + ;; #'pcomplete-erc-nicks + ;; :around + ;; (lambda (orig-fun &rest args) + ;; (let ((nicks (apply orig-fun args))) + ;; (if (string-match-p "matterircd" (symbol-name (erc-network))) + ;; (mapcar (lambda (nick) (concat "@" nick)) nicks) + ;; nicks)))) + ) + + (with-eval-after-load 'erc-stamp + (setopt + erc-timestamp-only-if-changed-flag nil + erc-timestamp-format "%T " + erc-insert-timestamp-function #'erc-insert-timestamp-left) + (set-face-attribute + 'erc-timestamp-face nil + :foreground "#aaaaaa" + :weight 'unspecified + :background 'unspecified)) + + (with-eval-after-load 'erc-track + (setopt + 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)) + + (declare-function erc-update-modules "erc") + (erc-update-modules) + + (b/keymap-global-set "C-c w e" #'erc-switch-to-buffer-other-window) + (b/keymap-set erc-mode-map "M-a" #'erc-track-switch-buffer)) +(b/keymap-global-set + "C-c e l" + (lambda () + (interactive) + (erc-tls :server "irc.libera.chat" :port 6697 + :client-certificate t))) +(b/keymap-global-set + "C-c e o" + (lambda () + (interactive) + (erc-tls :server "irc.oftc.net" :port 6697 + :client-certificate t))) +(b/keymap-global-set + "C-c e t" + (lambda () + (interactive) + (erc-tls :server "na.tilde.chat" :port 6697 + :client-certificate t))) + +;; (b/keymap-global-set +;; "C-c e c" +;; (lambda () +;; (interactive) +;; (erc :server "localhost" :port 6667 +;; :id 'matterircd-canonical))) ;;; Editing -(when (featurep 'eldoc) - ;; Display Lisp objects at point in the echo area. - (with-eval-after-load 'eldoc - (setq eldoc-minor-mode-string " eldoc") - (global-eldoc-mode))) +;; Display Lisp objects at point in the echo area. +(with-eval-after-load 'eldoc + (setopt eldoc-minor-mode-string " eldoc") + (global-eldoc-mode 1)) ;; highlight matching parens (run-with-idle-timer 0.2 nil #'require 'paren) (with-eval-after-load 'paren - (show-paren-mode)) + (show-paren-mode 1)) ;; (run-with-idle-timer 0.2 nil #'require 'elec-pair) ;; (with-eval-after-load 'elec-pair ;; (electric-pair-mode)) (with-eval-after-load 'simple - (setq - ;; Save what I copy into clipboard from other applications into Emacs' - ;; kill-ring, which would allow me to still be able to easily access - ;; it in case I kill (cut or copy) something else inside Emacs before - ;; yanking (pasting) what I'd originally intended to. + (setopt + ;; Save what I copy into clipboard from other applications into + ;; Emacs' kill-ring, which would allow me to still be able to + ;; easily access it in case I kill (cut or copy) something else + ;; inside Emacs before yanking (pasting) what I'd originally + ;; intended to. save-interprogram-paste-before-kill t) (column-number-mode 1) (line-number-mode 1)) @@ -697,82 +1351,50 @@ for all frames." (run-with-idle-timer 0.2 nil #'require 'savehist) (with-eval-after-load 'savehist ;; Save minibuffer history. - (setq savehist-file (b/var "savehist.el")) - (savehist-mode) + (savehist-mode 1) (add-to-list 'savehist-additional-variables 'kill-ring)) ;; Automatically save place in files. -(setq save-place-file (b/var "save-place.el")) (run-with-idle-timer 0.2 nil #'require 'saveplace nil 'noerror) (with-eval-after-load 'saveplace - ;; (setq save-place-file (b/var "save-place.el")) - (save-place-mode)) - -(add-to-list 'auto-mode-alist '("\\.*rc$" . conf-mode)) -(add-to-list 'auto-mode-alist '("\\.bashrc$" . sh-mode)) + (save-place-mode 1)) (with-eval-after-load 'flyspell - (setq flyspell-mode-line-string " fly")) + (setopt flyspell-mode-line-string " fly")) (with-eval-after-load 'text-mode (add-hook 'text-mode-hook #'flyspell-mode) - (define-key text-mode-map (kbd "C-") #'b/insert-asterism)) - -;; ;; http://endlessparentheses.com/ispell-and-apostrophes.html -;; (run-with-idle-timer 0.6 nil #'require 'ispell) -;; (with-eval-after-load 'ispell -;; ;; ’ can be part of a word. -;; (setq ispell-local-dictionary-alist -;; `((nil "[[:alpha:]]" "[^[:alpha:]]" -;; "['\x2019]" nil ("-B") nil utf-8)) -;; ispell-program-name (executable-find "hunspell")) -;; ;; Don't send ’ to the subprocess. -;; (defun endless/replace-apostrophe (args) -;; (cons (replace-regexp-in-string -;; "’" "'" (car args)) -;; (cdr args))) -;; (advice-add #'ispell-send-string :filter-args -;; #'endless/replace-apostrophe) -;; ;; Convert ' back to ’ from the subprocess. -;; (defun endless/replace-quote (args) -;; (if (not (derived-mode-p 'org-mode)) -;; args -;; (cons (replace-regexp-in-string -;; "'" "’" (car args)) -;; (cdr args)))) -;; (advice-add #'ispell-parse-output :filter-args -;; #'endless/replace-quote)) + (b/keymap-set text-mode-map "M-RET" #'b/insert-asterism)) (with-eval-after-load 'abbrev - (setq abbrev-file-name (b/etc "abbrev.el"))) -(add-hook 'text-mode-hook #'abbrev-mode) + (add-hook 'text-mode-hook #'abbrev-mode)) ;;; Programming modes -(with-eval-after-load 'lisp-mode - (defun indent-spaces-mode () - (setq indent-tabs-mode nil)) - (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode)) - -(add-to-list 'load-path (b/lisp "alloy-mode")) -(autoload 'alloy-mode "alloy-mode" nil t) -(with-eval-after-load 'alloy-mode - (setq alloy-basic-offset 2) - ;; (defun b/alloy-simple-indent (start end) - ;; (interactive "r") - ;; ;; (if (region-active-p) - ;; ;; (indent-rigidly start end alloy-basic-offset) - ;; ;; (if (bolp) - ;; ;; (indent-rigidly (line-beginning-position) - ;; ;; (line-end-position) - ;; ;; alloy-basic-offset))) - ;; (indent-to (+ (current-column) alloy-basic-offset))) - (define-key alloy-mode-map (kbd "RET") #'electric-newline-and-maybe-indent) - ;; (define-key alloy-mode-map (kbd "TAB") #'b/alloy-simple-indent) - (define-key alloy-mode-map (kbd "TAB") #'indent-for-tab-command)) -(add-to-list 'auto-mode-alist '("\\.\\(als\\|dsh\\)\\'" . alloy-mode)) -(add-hook 'alloy-mode-hook (lambda nil (setq-local indent-tabs-mode nil))) +;; (with-eval-after-load 'lisp-mode +;; (defun indent-spaces-mode () +;; (setq indent-tabs-mode nil)) +;; (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode)) + +;; (add-to-list 'load-path (b/lisp "alloy-mode")) +;; (autoload 'alloy-mode "alloy-mode" nil t) +;; (with-eval-after-load 'alloy-mode +;; (setq alloy-basic-offset 2) +;; ;; (defun b/alloy-simple-indent (start end) +;; ;; (interactive "r") +;; ;; ;; (if (region-active-p) +;; ;; ;; (indent-rigidly start end alloy-basic-offset) +;; ;; ;; (if (bolp) +;; ;; ;; (indent-rigidly (line-beginning-position) +;; ;; ;; (line-end-position) +;; ;; ;; alloy-basic-offset))) +;; ;; (indent-to (+ (current-column) alloy-basic-offset))) +;; (define-key alloy-mode-map (kbd "RET") #'electric-newline-and-maybe-indent) +;; ;; (define-key alloy-mode-map (kbd "TAB") #'b/alloy-simple-indent) +;; (define-key alloy-mode-map (kbd "TAB") #'indent-for-tab-command)) +;; (add-to-list 'auto-mode-alist '("\\.\\(als\\|dsh\\)\\'" . alloy-mode)) +;; (add-hook 'alloy-mode-hook (lambda nil (setq-local indent-tabs-mode nil))) ;; (eval-when-compile (defvar lean-mode-map)) ;; (run-with-idle-timer 0.4 nil #'require 'lean-mode) @@ -788,63 +1410,48 @@ for all frames." ;; (define-key lean-mode-map (kbd "S-SPC") #'company-complete)) (with-eval-after-load 'sgml-mode - (setq sgml-basic-offset 0)) + (setopt sgml-basic-offset 0)) (with-eval-after-load 'css-mode - (setq css-indent-offset 2)) - -;; (with-eval-after-load 'auctex -;; (setq font-latex-fontify-sectioning 'color)) + (setopt css-indent-offset 2)) -(with-eval-after-load 'tex-mode - (cl-delete-if - (lambda (p) (string-match "^---?" (car p))) - tex--prettify-symbols-alist)) (add-hook 'tex-mode-hook #'auto-fill-mode) (add-hook 'tex-mode-hook #'flyspell-mode) -(run-with-idle-timer 0.5 nil #'require 'cmake-mode) +(autoload 'cmake-mode "cmake-mode" nil t) +(add-to-list 'auto-mode-alist '("CMakeLists\\.txt\\'" . cmake-mode)) +(add-to-list 'auto-mode-alist '("\\.cmake\\'" . cmake-mode)) (with-eval-after-load 'cmake-mode - ;; (setq cmake-tab-width 4) - (add-to-list 'load-path (b/lisp "cmake-font-lock")) - (run-with-idle-timer 0.5 nil #'require 'cmake-font-lock)) + ;; (setopt cmake-tab-width 4) + (add-to-list 'load-path (b/emacs.d "lisp/cmake-font-lock")) + (require 'cmake-font-lock)) ;;; Emacs enhancements & auxiliary packages - -(with-eval-after-load 'nsm - (setq nsm-settings-file (b/var "nsm-settings.el"))) - (with-eval-after-load 'man - (setq Man-width 80)) + (setopt Man-width 80)) ;; `debbugs' -(global-set-key (kbd "C-c D d") #'debbugs-gnu) -(global-set-key (kbd "C-c D b") #'debbugs-gnu-bugs) -(global-set-key (kbd "C-c D e") ; bug-gnu-emacs +(b/keymap-global-set "C-c D d" #'debbugs-gnu) +(b/keymap-global-set "C-c D b" #'debbugs-gnu-bugs) +(b/keymap-global-set "C-c D e" ; bug-gnu-emacs (lambda () (interactive) (setq debbugs-gnu-current-suppress t) (debbugs-gnu debbugs-gnu-default-severities '("emacs")))) -(global-set-key (kbd "C-c D g") ; bug-gnuzilla +(b/keymap-global-set "C-c D g" ; bug-gnuzilla (lambda () (interactive) (setq debbugs-gnu-current-suppress t) (debbugs-gnu debbugs-gnu-default-severities '("gnuzilla")))) -(with-eval-after-load 'url - (setq url-configuration-directory (b/var "url/configuration/"))) - -(with-eval-after-load 'url-cache - (setq url-cache-directory (b/var "url/cache/"))) - (with-eval-after-load 'eww - (setq + (setopt eww-download-directory (file-name-as-directory (getenv "XDG_DOWNLOAD_DIR")))) -(global-set-key (kbd "C-c e w") #'eww) +(b/keymap-global-set "C-c e w" #'eww) (run-with-idle-timer 0.2 nil #'require 'display-fill-column-indicator nil 'noerror) @@ -852,19 +1459,8 @@ for all frames." (global-display-fill-column-indicator-mode 1)) (with-eval-after-load 'window - (setq split-width-threshold 150)) - -;; Uncomment to disable reftex-cite's default choice of previous word. -;; (with-eval-after-load 'reftex -;; (require 'reftex-cite) -;; (defun reftex-get-bibkey-default () -;; "If the cursor is in a citation macro, return the word before -;; the macro." -;; (let* ((macro (reftex-what-macro 1))) -;; (save-excursion -;; (when (and macro (string-match "cite" (car macro))) -;; (goto-char (cdr macro))) -;; (reftex-this-word))))) + (setopt split-width-threshold 150)) + (add-hook 'latex-mode-hook #'reftex-mode) (run-with-idle-timer 0.5 nil #'require 'delight) @@ -873,12 +1469,44 @@ for all frames." (delight 'abbrev-mode "" "abbrev") (delight 'mml-mode " mml" "mml")) -(require 'bandali-po) - -(add-to-list 'load-path (b/lisp "ffs")) +(with-eval-after-load 'po-mode + ;; Based on the `po-wrap' function from the GNUN manual: + ;; https://www.gnu.org/s/trans-coord/manual/gnun/html_node/Wrapping-Long-Lines.html + (defun b/po-wrap () + "Run the current `po-mode' buffer through `msgcat' to wrap all +lines." + (interactive) + (when (eq major-mode 'po-mode) + (let ((tmp-file (make-temp-file "po-wrap.")) + (tmp-buffer (generate-new-buffer "*temp*"))) + (unwind-protect + (progn + (write-region (point-min) (point-max) tmp-file nil 1) + (if (zerop + (call-process "msgcat" nil tmp-buffer t + (shell-quote-argument tmp-file))) + (let ((saved (point)) + (inhibit-read-only t)) + (delete-region (point-min) (point-max)) + (insert-buffer-substring tmp-buffer) + (goto-char (min saved (point-max)))) + (with-current-buffer tmp-buffer + (error (buffer-string))))) + (kill-buffer tmp-buffer) + (delete-file tmp-file))))) + + (add-hook + 'po-mode-hook (lambda () (run-with-timer 0.1 nil #'View-exit))) + (b/keymap-set po-mode-map "M-q" #'b/po-wrap)) + +(autoload #'po-mode "po-mode" + "Major mode for editing PO translation files" t) +(add-to-list 'auto-mode-alist '("\\.po\\'\\|\\.po\\." . po-mode)) + +(add-to-list 'load-path (b/emacs.d "lisp/ffs")) (run-with-idle-timer 0.5 nil #'require 'ffs) (with-eval-after-load 'ffs - (setq ffs-default-face-height 250) + (setopt ffs-default-face-height 250) (global-set-key (kbd "C-c f s") #'ffs)) (add-hook 'ffs-start-hook (lambda () @@ -913,7 +1541,7 @@ for all frames." scroll-bar-mode)) (fringe-mode nil))) -(add-to-list 'load-path (b/lisp "debian-el")) +(add-to-list 'load-path (b/emacs.d "lisp/debian-el")) (run-with-idle-timer 0.5 nil #'require 'debian-el) (with-eval-after-load 'debian-el (require 'apt-sources) @@ -923,7 +1551,7 @@ for all frames." (require 'gnus-BTS) (require 'preseed)) -(add-to-list 'load-path (b/lisp "dpkg-dev-el")) +(add-to-list 'load-path (b/emacs.d "lisp/dpkg-dev-el")) (run-with-idle-timer 0.5 nil #'require 'dpkg-dev-el) (with-eval-after-load 'dpkg-dev-el (require 'debian-changelog-mode) diff --git a/.emacs.d/lisp/bandali-dired.el b/.emacs.d/lisp/bandali-dired.el deleted file mode 100644 index 0cbd7ed..0000000 --- a/.emacs.d/lisp/bandali-dired.el +++ /dev/null @@ -1,95 +0,0 @@ -;;; bandali-dired.el --- bandali's dired setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2022 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My dired setup and customizations. - -;;; Code: - -(with-eval-after-load 'dired - ;; (require 'ls-lisp) - (setq - dired-dwim-target t - dired-listing-switches "-alh --group-directories-first" - 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) - (setq - 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-erc.el b/.emacs.d/lisp/bandali-erc.el deleted file mode 100644 index 8cd1457..0000000 --- a/.emacs.d/lisp/bandali-erc.el +++ /dev/null @@ -1,200 +0,0 @@ -;;; bandali-erc.el --- bandali's ERC setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2022 Amin Bandali - -;; Author: Amin Bandali -;; Keywords: IRC, chat, client, Internet - -;; 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 . - -;;; Commentary: - -;; My ERC setup for IRC in GNU Emacs. - -;;; Code: - -(with-eval-after-load 'erc - (make-directory (b/var "erc/dcc") t) - (setq - erc-auto-query 'bury - erc-autojoin-domain-only nil - erc-dcc-get-default-directory (b/var "erc/dcc") - erc-email-userid "bandali" - erc-format-nick-function 'erc-format-@nick - erc-join-buffer 'bury - ;; erc-lurker-hide-list '("JOIN" "PART" "QUIT") - erc-nick "bandali" - erc-prompt "erc>" - erc-prompt-for-password nil - erc-query-display 'buffer - 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 () - "Ask chanserv to op me in the current channel." - (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 in the current channel." - (erc-cmd-DEOP (format "%s" (erc-current-nick)))) - (add-to-list 'erc-modules 'keep-place) - (add-to-list 'erc-modules 'log) - (when (display-graphic-p) - (add-to-list 'erc-modules 'notifications) - (add-to-list 'erc-modules 'smiley)) - (add-to-list 'erc-modules 'spelling) - - ;; (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 - ;; (setq - ;; erc-fill-column 77 - ;; erc-fill-function 'erc-fill-variable - ;; erc-fill-static-center 18) - ;; to disable: - ;; (erc-fill-mode -1) - - ;; erc-log - (defun b/erc-log-directory (buffer target _nick server _port) - (let ((directory (concat (b/var "erc/logs/") - ;; (or (with-current-buffer buffer - ;; (symbol-name erc-network)) - ;; server) - server - (if (erc-server-buffer-p buffer) - (concat "/" server) - (and target (concat "/" target)))))) - (unless (file-exists-p directory) - (make-directory directory 'make-parents)) - directory)) - (defun b/erc-log-file-name (&rest _) - (concat (format-time-string "%Y-%m-%d") ".log")) - (setq - ;; erc-enable-logging 'erc-log-all-but-server-buffers - erc-generate-log-file-name-function #'b/erc-log-file-name - erc-log-channels-directory #'b/erc-log-directory - erc-log-file-coding-system 'utf-8 - erc-log-write-after-insert t - erc-log-write-after-send t - erc-save-buffer-on-part nil - erc-save-queries-on-quit nil) - - (with-eval-after-load 'erc-match - (setq - erc-pal-highlight-type 'nick - erc-pals - '("bremner" "^gopar" "^iank" "quidam" "^rwp" "sudoman" - "technomancy" "thomzane")) - (set-face-attribute - 'erc-pal-face nil - :foreground 'unspecified - :weight 'unspecified - :inherit 'erc-nick-default-face - ;; :background (face-attribute 'font-lock-string-face :background) - :background "#ffffdf")) - - (with-eval-after-load 'erc-pcomplete - (setq erc-pcomplete-nick-postfix ",") - ;; for matterircd nick (username) completions - ;; (advice-add - ;; #'pcomplete-erc-nicks - ;; :around - ;; (lambda (orig-fun &rest args) - ;; (let ((nicks (apply orig-fun args))) - ;; (if (string-match-p "matterircd" (symbol-name (erc-network))) - ;; (mapcar (lambda (nick) (concat "@" nick)) nicks) - ;; nicks)))) - ) - - (with-eval-after-load 'erc-stamp - (setq 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)) - - (with-eval-after-load 'erc-track - (setq - 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)) - - (declare-function erc-update-modules "erc") - (erc-update-modules) - - ;; 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)) - -;; global key bindings -(global-set-key - (kbd "C-c e l") - (lambda () - (interactive) - (erc-tls :server "irc.libera.chat" :port 6697 - :client-certificate t))) -(global-set-key - (kbd "C-c e o") - (lambda () - (interactive) - (erc-tls :server "irc.oftc.net" :port 6697 - :client-certificate t))) -(global-set-key - (kbd "C-c e t") - (lambda () - (interactive) - (erc-tls :server "na.tilde.chat" :port 6697 - :client-certificate t))) - -;; (global-set-key -;; (kbd "C-c e c") -;; (lambda () -;; (interactive) -;; (erc :server "localhost" :port 6667 -;; :id 'matterircd-canonical))) - -(provide 'bandali-erc) -;;; bandali-erc.el ends here diff --git a/.emacs.d/lisp/bandali-eshell.el b/.emacs.d/lisp/bandali-eshell.el deleted file mode 100644 index 7bf3b4f..0000000 --- a/.emacs.d/lisp/bandali-eshell.el +++ /dev/null @@ -1,97 +0,0 @@ -;;; bandali-eshell.el --- bandali's Eshell setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2022 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My awesome Eshell setup. - -;;; Code: - -(with-eval-after-load 'eshell - (make-directory (b/etc "eshell/") t) - (setq - 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))) - eshell-prompt-regexp "^[^#$\n]* [#$] ; " - eshell-prompt-function - (lambda () - (concat ": " - (system-name) - ":" - (abbreviate-file-name (eshell/pwd)) - (unless (eshell-exit-success-p) - (format " [%d]" eshell-last-command-status)) - (if (= (file-user-uid) 0) " # " " $ ") - "; "))) - (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-history () - (interactive) - (completing-read "Eshell history: " - (ring-elements eshell-history-ring))) - (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-hist-mode-map (kbd "M-r") - #'b/eshell-history))) -;; global key bindings -(global-set-key (kbd "C-c 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 deleted file mode 100644 index e7f83ce..0000000 --- a/.emacs.d/lisp/bandali-exwm.el +++ /dev/null @@ -1,352 +0,0 @@ -;;; bandali-exwm.el --- bandali's EXWM configuration -*- lexical-binding: t; -*- - -;; Copyright (c) 2018-2023 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My EXWM setup. Makes good use of its simulation keys. - -;;; Code: - -(add-to-list 'load-path (b/lisp "xelb")) -(add-to-list 'load-path (b/lisp "exwm")) -(require 'exwm) -;; (setq exwm-replace t) -;; 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) -(add-hook 'exwm-update-class-hook #'b/exwm-rename-buffer) -(add-hook 'exwm-update-title-hook #'b/exwm-rename-buffer) - -(require 'exwm-config) -(add-hook 'exwm-init-hook #'exwm-config--fix/ido-buffer-window-other-frame) - -(require 'exwm-input) -(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))) - -(defun b/exwm-ws-prev () - "Switch to previous EXWM workspace, wrapping around if needed." - (interactive) - (exwm-workspace-switch-create - (b/exwm-ws-prev-index))) - -(defun b/exwm-ws-next () - "Switch to next EXWM workspace, wrapping around if needed." - (interactive) - (exwm-workspace-switch-create - (b/exwm-ws-next-index))) - -;; shorten 'C-c C-q' to 'C-q' -(define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key) - -;; scroll up/down/left/right on the echo area -(define-key minibuffer-inactive-mode-map [mouse-4] #'b/exwm-ws-prev) -(define-key minibuffer-inactive-mode-map [mouse-5] #'b/exwm-ws-next) -(define-key minibuffer-inactive-mode-map [mouse-6] #'b/exwm-ws-prev) -(define-key minibuffer-inactive-mode-map [mouse-7] #'b/exwm-ws-next) - -(defvar b/shifted-ws-names - '(0 \) 1 \! 2 \@ 3 \# 4 \$ - 5 \% 6 \^ 7 \& 8 \* 9 \() - "Mapping of shifted numbers on my keyboard.") - -(setq - exwm-workspace-number 10 - exwm-input-global-keys - `(([?\s-R] . exwm-reset) - ;; ([?\s-b] . exwm-workspace-switch-to-buffer) - ([?\s-/] . exwm-workspace-switch) - ([?\s-\s] . dmenu) - ([?\s-\\] . (lambda () - (interactive) - (start-process-shell-command - "passmenu" nil "passmenu --type"))) - ([?\S-\s-\s] . (lambda (command) - (interactive - (list (read-shell-command "➜ "))) - (start-process-shell-command - command nil command))) - ([s-return] . (lambda () - (interactive) - (start-process "" nil "xterm"))) - ([S-s-return] . (lambda () - (interactive) - (start-process "" nil "xterm" - "-name" "floating"))) - ([?\C-\s-\s] . counsel-linux-app) - ([?\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) - ([?\s-N ?d] . (lambda () - (interactive) - (start-process - "" nil "dunstctl" "close"))) - ([?\s-N ?D] . (lambda () - (interactive) - (start-process - "" nil "dunstctl" "close-all"))) - ([?\s-N ?h] . (lambda () - (interactive) - (start-process - "" nil "dunstctl" "history-pop"))) - ([?\s-N return] . (lambda () - (interactive) - (start-process - "" nil "dunstctl" "context"))) - ([?\M-\s-h] . shrink-window-horizontally) - ([?\M-\s-l] . enlarge-window-horizontally) - ([?\M-\s-k] . shrink-window) - ([?\M-\s-j] . enlarge-window) - ([?\s-\[] . b/exwm-ws-prev) - ([?\s-\]] . b/exwm-ws-next) - ([mode-line mouse-4] . b/exwm-ws-prev) ; up - ([mode-line mouse-5] . b/exwm-ws-next) ; down - ([mode-line mouse-6] . b/exwm-ws-prev) ; left - ([mode-line mouse-7] . b/exwm-ws-next) ; right - ([?\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))) - ,@(mapcar - (lambda (i) - `(,(kbd (format "s-%s" - (plist-get b/shifted-ws-names i))) - . - (lambda () - (interactive) - (exwm-workspace-move-window ,i)))) - (number-sequence 0 (1- exwm-workspace-number))) - ([?\s-.] . 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 - "dmneu-light" nil "dmenu-light"))) - ([?\s-\;] . (lambda () - (interactive) - (start-process-shell-command - "dmneu-pamixer" nil "dmenu-pamixer") - (b/volume-update))) - ([XF86AudioMute] . ; borken on my X200 :-( - (lambda () - (interactive) - (start-process "" nil "pamixer" "--toggle-mute") - (b/volume-update))) - ([\s-XF86AudioMute] . ; toggle mic mute - (lambda () - (interactive) - (start-process - "" nil "pamixer" "--default-source" "--toggle-mute") - (b/volume-update))) - ([XF86Launch1] . - (lambda () - (interactive) - (start-process "" nil "pamixer" "--toggle-mute") - (b/volume-update))) - ([\s-XF86Launch1] . ; toggle mic mute - (lambda () - (interactive) - (start-process - "" nil "pamixer" "--default-source" "--toggle-mute") - (b/volume-update))) - ([XF86AudioLowerVolume] . - (lambda () - (interactive) - (start-process - "" nil "pamixer" "--allow-boost" "--decrease" "5") - (b/volume-update))) - ([XF86AudioRaiseVolume] . - (lambda () - (interactive) - (start-process - "" nil "pamixer" "--allow-boost" "--increase" "5") - (b/volume-update))) - ([\s-XF86AudioLowerVolume] . - (lambda () - (interactive) - (start-process - "" nil "pamixer" "--default-source" "--decrease" "5") - (b/volume-update))) - ([\s-XF86AudioRaiseVolume] . - (lambda () - (interactive) - (start-process - "" nil "pamixer" "--default-source" "--increase" "5") - (b/volume-update))) - ([XF86AudioPlay] . - (lambda () - (interactive) - (start-process "" nil "mpc" "toggle"))) - ([XF86AudioPrev] . - (lambda () - (interactive) - (start-process "" nil "mpc" "prev"))) - ([XF86AudioNext] . - (lambda () - (interactive) - (start-process "" nil "mpc" "next"))) - ([XF86MonBrightnessDown] . - (lambda () - (interactive) - (start-process "" nil "light" "-U" "5"))) - ([XF86MonBrightnessUp] . - (lambda () - (interactive) - (start-process "" nil "light" "-A" "5"))) - ([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-g] . [?\C-g]) - ([?\s-s] . [?\C-s]) - ([?\C-g] . [escape]) - ([?\C-/] . [?\C-z]))) - -(require 'exwm-manage) -(setq - exwm-manage-configurations - '(((equal exwm-instance-name "floating") - floating t - floating-mode-line nil))) -(add-hook 'exwm-manage-finish-hook - (lambda () - (when exwm-class-name - (cond - ((member exwm-class-name '("Abrowser" "IceCat" "Iceweasel")) - (exwm-input-set-local-simulation-keys - `(,@exwm-input-simulation-keys - ([?\C-\S-d] . [?\C-d])))) - ((member exwm-class-name '("XTerm" "Mate-terminal")) - (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])))))))) - -(require 'exwm-randr) -(setq - exwm-randr-workspace-monitor-plist - '(0 "eDP-1" - 1 "eDP-1" 2 "eDP-1" 3 "eDP-1" - 4 "eDP-1" 5 "eDP-1" 6 "eDP-1" - 7 "HDMI-1" 8 "HDMI-1" 9 "HDMI-1")) -;; (add-hook -;; 'exwm-randr-screen-change-hook -;; (lambda () -;; (start-process-shell-command -;; "xrandr" nil -;; "xrandr --output HDMI-1 --mode 1280x720 --above eDP-1 --auto"))) -(exwm-randr-enable) - -(require 'exwm-systemtray) -(exwm-systemtray-enable) - -(add-to-list 'load-path (b/lisp "exwm-edit")) -(require 'exwm-edit) - -(with-eval-after-load 'exwm-workspace - (setq exwm-workspace-show-all-buffers t) - (setq-default - mode-line-format - (append - mode-line-format - '((:eval - (format - " [%s]" (number-to-string - exwm-workspace-current-index))))))) - -(with-eval-after-load 'exwm-layout - (setq exwm-layout-show-all-buffers t)) - -(provide 'bandali-exwm) -;;; bandali-exwm.el ends here diff --git a/.emacs.d/lisp/bandali-gnus.el b/.emacs.d/lisp/bandali-gnus.el deleted file mode 100644 index 18c6b2e..0000000 --- a/.emacs.d/lisp/bandali-gnus.el +++ /dev/null @@ -1,430 +0,0 @@ -;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2024 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; 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)) - -(setq - mail-user-agent 'gnus-user-agent - read-mail-command 'gnus - - gnus-select-method '(nnnil "") - gnus-secondary-select-methods - `(,@(when (member (system-name) '("darya" "nostalgia")) - '((nnimap - "canonical" - (nnimap-stream plain) - (nnimap-address "127.0.0.1") - (nnimap-server-port 143) - (nnimap-authenticator plain) - (nnimap-user "bandali@canonical.local")))) - (nnimap - "kelar" - (nnimap-stream plain) - (nnimap-address "127.0.0.1") - (nnimap-server-port 143) - (nnimap-authenticator plain) - (nnimap-user "bandali@kelar.local") - ;; (nnmail-expiry-wait immediate) - (nnmail-expiry-target nnmail-fancy-expiry-target) - (nnmail-fancy-expiry-targets - (("from" ".*" "nnimap+kelar:Archive.%Y")))) - (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") - ;; spam - ("X-Spam_action" "reject" "Junk") - ;; keep debbugs emails in INBOX - (list ".*<\\(.*\\)\\.debbugs\\.gnu\\.org>.*" "INBOX") - ;; list moderation emails - (from ".+-\\(owner\\|bounces\\)@\\(non\\)?gnu\\.org" "listmod") - ;; gnu - (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1") - ("Envelope-To" "emacsconf-donations@gnu.org" "l.emacsconf-donations") - ;; board-eval - (| - (list ".*<.*\\.board-eval\\.fsf\\.org>.*" "l.board-eval") - (from ".*@board-eval\\.fsf\\.org" "l.board-eval")) - ;; fsf - (list ".*<\\(.*\\)\\.fsf\\.org>.*" "l.\\1") - ;; cfarm - (from "cfarm-.*@lists\\.tetaneutral\\.net" "l.cfarm") - ;; debian - (list ".*<\\(.*\\)\\.\\(lists\\|other\\)\\.debian\\.org>.*" "l.\\1") - (list ".*<\\(.*\\)\\.alioth-lists\\.debian\\.net>.*" "l.\\1") - ;; gnus - (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1") - ;; libreplanet - (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1") - ;; iana (e.g. tz-announce) - (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1") - ;; mailop - (list ".*<\\(.*\\)\\.mailop\\.org>.*" "l.\\1") - ;; sdlu - (list ".*<\\(.*\\)\\.spammers\\.dontlike\\.us>.*" "l.sdlu") - ;; bitfolk - (from ".*@\\(.+\\)?bitfolk\\.com>.*" "bitfolk") - ;; haskell - (list ".*<\\(.*\\)\\.haskell\\.org>.*" "l.\\1") - ;; 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 ".*notmuch.notmuchmail.org" "l.notmuch") ;u - (list ".*dev.lists.parabola.nu" "l.parabola-dev") - ;; ---------------------------------- - ;; legend: (u)nsubscribed | (d)ead - ;; ---------------------------------- - ;; otherwise, leave mail in INBOX - "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 plain) - (nnimap-address "127.0.0.1") - (nnimap-server-port 143) - (nnimap-authenticator plain) - (nnimap-user "amin.bandali@savoirfairelinux.local"))) - gnus-message-archive-group "nnimap+gnu:INBOX" - gnus-parameters - '(("l\\.fencepost-users" - (to-address . "fencepost-users@gnu.org") - (to-list . "fencepost-users@gnu.org") - (list-identifier . "\\[Fencepost-users\\]")) - ("l\\.haskell-cafe" - (to-address . "haskell-cafe@haskell.org") - (to-list . "haskell-cafe@haskell.org") - (list-identifier . "\\[Haskell-cafe\\]"))) - ;; nnimap-record-commands t - ;; gnus-large-newsgroup 50 - ;; gnus-process-mark-toggle t - 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-search-use-parsed-queries t - 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))) - - (setq gnus-user-agent '(emacs gnus type)) - - ;; (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 "C-c g") #'gnus-plugged) -(global-set-key (kbd "C-c G") #'gnus-unplugged) - -(with-eval-after-load 'gnus-art - (setq - 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 key bindings - (declare-function org-store-link "ol" (arg &optional interactive?)) - (define-key gnus-article-mode-map (kbd "M-L") #'org-store-link)) - -(with-eval-after-load 'gnus-sum - (setq gnus-thread-sort-functions '(gnus-thread-sort-by-number - gnus-thread-sort-by-subject - gnus-thread-sort-by-date)) - (with-eval-after-load 'message - (setq gnus-ignored-from-addresses message-dont-reply-to-names)) - - (defun b/gnus-junk-article (&optional n) - (interactive "P" gnus-summary-mode) - (gnus-summary-move-article - n - (gnus-group-prefixed-name - "Junk" - (gnus-find-method-for-group gnus-newsgroup-name)))) - ;; local key bindings - (define-key gnus-summary-mode-map (kbd "M-L") #'org-store-link) - ;; (define-key gnus-summary-mode-map (kbd "r") - ;; #'gnus-summary-reply-with-original) - ;; (define-key gnus-summary-mode-map (kbd "R") - ;; #'gnus-summary-wide-reply-with-original) - (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 r") - #'gnus-summary-very-wide-reply) - (define-key - b/gnus-summary-prefix-map (kbd "r q") - #'gnus-summary-very-wide-reply-with-original) - (define-key - b/gnus-summary-prefix-map (kbd "R r") - #'gnus-summary-reply) - (define-key - b/gnus-summary-prefix-map (kbd "R q") - #'gnus-summary-reply-with-original) - (define-key - b/gnus-summary-prefix-map (kbd "r a w") - #'gnus-summary-show-raw-article) - (define-key - b/gnus-summary-prefix-map (kbd "s") - #'b/gnus-junk-article)) -;; hooks -(add-hook 'gnus-summary-mode-hook #'b/no-mouse-autoselect-window) - -(defvar b/sfl-p nil) -(with-eval-after-load 'gnus-msg - (let ((bandali "Amin Bandali%s - https://www.gnu.ca/~bandali/")) - (defvar b/csc-signature - (mapconcat - #'identity - `(,(format bandali ", MMath") - "Systems Committee " - "Computer Science Club of the University of Waterloo") - "\n")) - (defvar b/sfl-signature - (mapconcat - #'identity - `(,bandali - "Volunteer, Savoir-faire Linux" - "jami:bandali") - "\n") - "")) ; the "" is for bandali's %s - (setq - gnus-message-replysign t - gnus-posting-styles - '((".*" - (address "bandali@gnu.org") - ("X-Message-SMTP-Method" "smtp fencepost.gnu.org 587")) - ((header "subject" "ThankCRM") - (to "webmasters-comment@gnu.org") - (body "")) - ("nnimap\\+kelar:.*" - (address "bandali@kelar.org") - ("X-Message-SMTP-Method" "smtp mail.kelar.org 587") - (gcc "nnimap+kelar:Sent")) - ("nnimap\\+shemshak:.*" - (address "amin@shemshak.org") - ("X-Message-SMTP-Method" "smtp mail.shemshak.org 587") - (gcc "nnimap+shemshak:Sent")) - ("nnimap\\+canonical:.*" - (address "bandali@canonical.com") - ("X-Message-SMTP-Method" "smtp smtp.canonical.com 587") - (signature nil) - (gcc "nnimap+canonical:Sent")) - ((header "to" "amin\\.bandali@canonical\\.com") - (address "amin.bandali@canonical.com")) - ((header "cc" "amin\\.bandali@canonical\\.com") - (address "amin.bandali@canonical.com")) - ("nnimap\\+.*:l\\.ubuntu-.*" - (address "bandali@ubuntu.com") - ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")) - ((header "list-id" ".*\\.lists.ubuntu.com") - (address "bandali@ubuntu.com") - ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")) - ("nnimap\\+csc:.*" - (address "bandali@csclub.uwaterloo.ca") - ("X-Message-SMTP-Method" "smtp mail.csclub.uwaterloo.ca 587") - (signature b/csc-signature) - (gcc "nnimap+csc:Sent")) - ("nnimap\\+sfl:.*" - (address "amin.bandali@savoirfairelinux.com") - ("X-Message-SMTP-Method" "smtp mail.savoirfairelinux.com 587") - (signature b/sfl-signature) - (eval (setq-local b/sfl-p t)) - (gcc "nnimap+sfl:Sent"))))) -;; 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 - (setq - gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n" - gnus-topic-topology - `(("Gnus" visible nil nil) - (("misc" visible nil nil)) - ,@(when (member (system-name) '("darya" "nostalgia")) - '((("canonical" visible nil nil)))) - (("csc" visible nil nil)) - (("kelar" visible nil nil)) - (("shemshak" visible nil nil)) - (("gnu" visible nil nil)) - ;(("old-gnu" visible nil nil)) - (("sfl" visible nil nil))))) - -(with-eval-after-load 'gnus-agent - (setq gnus-agent-synchronize-flags 'ask)) - -(with-eval-after-load 'gnus-group - (setq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)")) - -(with-eval-after-load 'gnus-win - (setq gnus-use-full-window nil)) - -(with-eval-after-load 'gnus-dired - (add-hook 'dired-mode-hook 'gnus-dired-mode)) - -(with-eval-after-load 'mm-archive - (add-to-list - 'mm-archive-decoders - '("application/gzip" nil "gunzip" "-S" ".zip" "-kd" "%f" "-r"))) - -(with-eval-after-load 'gnus-start - (add-hook 'gnus-after-getting-new-news-hook #'gnus-notifications)) - -(with-eval-after-load 'mm-decode - (setq - ;; mm-attachment-override-types `("text/x-diff" "text/x-patch" - ;; ,@mm-attachment-override-types) - mm-discouraged-alternatives '("text/html" "text/richtext") - mm-decrypt-option 'known - mm-verify-option 'known) - (add-to-list - 'mm-inline-media-tests - `("application/gzip" mm-archive-dissect-and-inline identity)) - (add-to-list 'mm-inlined-types "application/gzip" 'append)) - -(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") - (setq mm-uu-diff-groups-regexp "."))) - -(with-eval-after-load 'mml - (setq - mml-attach-file-at-the-end t - mml-content-disposition-alist - '((text - (markdown . "attachment") - (rtf . "attachment") - (t . "inline")) - (t. "attachment")))) - -(with-eval-after-load 'mml-sec - (setq mml-secure-openpgp-encrypt-to-self t - mml-secure-openpgp-sign-with-sender t)) - -(provide 'bandali-gnus) -;;; bandali-gnus.el ends here diff --git a/.emacs.d/lisp/bandali-ibuffer.el b/.emacs.d/lisp/bandali-ibuffer.el deleted file mode 100644 index a706dc6..0000000 --- a/.emacs.d/lisp/bandali-ibuffer.el +++ /dev/null @@ -1,110 +0,0 @@ -;;; bandali-ibuffer.el --- bandali's Ibuffer setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2022 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My Ibuffer setup. - -;;; Code: - -(setq - 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-message.el b/.emacs.d/lisp/bandali-message.el deleted file mode 100644 index f9f0873..0000000 --- a/.emacs.d/lisp/bandali-message.el +++ /dev/null @@ -1,110 +0,0 @@ -;;; bandali-message.el --- bandali's message.el setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2022 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My setup for message.el. - -;;; Code: - -(with-eval-after-load 'message - ;; :bind (:map message-mode-map ("" . 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 b/message-cite-style-format)) - "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.") - (setq - message-elide-ellipsis "[...]\n" - ;; message-cite-style 'message-cite-style-bandali - message-citation-line-format "%N writes:\n" - ;; message-citation-line-format "On %a, %d %b %Y, %N wrote:\n" - message-citation-line-function 'message-insert-formatted-citation-line - message-confirm-send t - message-fill-column 70 - message-forward-as-mime t - message-kill-buffer-on-exit t - message-send-mail-function #'smtpmail-send-it - message-subscribed-address-functions - '(gnus-find-subscribed-addresses) - message-dont-reply-to-names - (mapconcat - #'identity - '("\\(bandali\\|mab\\|aminb?\\)@gnu\\.org" - "bandali@kelar\\.org" - "amin@shemshak\\.org" - "a?bandali@\\(csclub\\.\\)?uwaterloo\\.ca" - "amin\\.bandali@savoirfairelinux\\.com" - "\\(amin\\.\\)?bandali@canonical\\.com" - "bandali@ubuntu\\.com") - "\\|")) - ;; (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)))) - - ;; custom newline & reformat function - (defun b/message-newline-or-asterism (arg) - "Create newlines per my liking or insert asterism if ARG is -non-nil." - (interactive "P") - (if arg - (b/insert-asterism) - (progn - (beginning-of-line) - (delete-region (point) (line-end-position)) - (newline) - (open-line 1)))) - (define-key message-mode-map - (kbd "M-RET") #'b/message-newline-or-asterism) - - ;; local key bindings - ;; (define-key message-mode-map - ;; [remap next-line] #'mail-abbrev-next-line) - ;; (define-key message-mode-map - ;; [remap end-of-buffer] #'mail-abbrev-end-of-buffer) - ) -;; hooks -;; (add-hook 'message-setup-hook #'mml-secure-message-sign-pgpmime) -(add-hook 'message-mode-hook #'flyspell-mode) -(add-hook 'message-mode-hook - (lambda () - (local-unset-key (kbd "C-c C-s")))) - -(provide 'bandali-message) -;;; bandali-message.el ends here diff --git a/.emacs.d/lisp/bandali-org.el b/.emacs.d/lisp/bandali-org.el deleted file mode 100644 index bdaff4e..0000000 --- a/.emacs.d/lisp/bandali-org.el +++ /dev/null @@ -1,125 +0,0 @@ -;;; bandali-org.el --- bandali's Org setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2022 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My set up for Org (org-mode) and all things Org. - -;;; Code: - -;; (setq org--inhibit-version-check t) - -(with-eval-after-load 'org - (setq - 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-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 - ;; `org-indent-mode' doesn't seem to play nice with - ;; `display-fill-column-indicator'. - ;; (add-hook 'org-mode-hook #'org-indent-mode) - (add-hook 'org-mode-hook #'auto-fill-mode) - (add-hook 'org-mode-hook #'flyspell-mode) - - ;; additional export backends - (require 'ox-md) - - ;; 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 - (setq - 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-po.el b/.emacs.d/lisp/bandali-po.el deleted file mode 100644 index a31fee2..0000000 --- a/.emacs.d/lisp/bandali-po.el +++ /dev/null @@ -1,61 +0,0 @@ -;;; bandali-po.el --- bandali's po-mode setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2021 Amin Bandali - -;; Author: Amin Bandali -;; Keywords: i18n gettext - -;; 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 . - -;;; Commentary: - -;; My po-mode setup for editing PO translation files in GNU Emacs. - -;;; Code: - -(with-eval-after-load 'po-mode - ;; based on the `po-wrap' function from the GNUN manual: - ;; https://www.gnu.org/s/trans-coord/manual/gnun/html_node/Wrapping-Long-Lines.html - (defun b/po-wrap () - "Run the current `po-mode' buffer through `msgcat' to wrap all -lines." - (interactive) - (when (eq major-mode 'po-mode) - (let ((tmp-file (make-temp-file "po-wrap.")) - (tmp-buffer (generate-new-buffer "*temp*"))) - (unwind-protect - (progn - (write-region (point-min) (point-max) tmp-file nil 1) - (if (zerop - (call-process "msgcat" nil tmp-buffer t - (shell-quote-argument tmp-file))) - (let ((saved (point)) - (inhibit-read-only t)) - (delete-region (point-min) (point-max)) - (insert-buffer-substring tmp-buffer) - (goto-char (min saved (point-max)))) - (with-current-buffer tmp-buffer - (error (buffer-string))))) - (kill-buffer tmp-buffer) - (delete-file tmp-file))))) - - (add-hook 'po-mode-hook (lambda nil (run-with-timer 0.1 nil 'View-exit))) - (define-key po-mode-map (kbd "M-q") #'b/po-wrap)) - -(autoload #'po-mode "po-mode" - "Major mode for editing PO translation files" t) -(add-to-list 'auto-mode-alist '("\\.po\\'\\|\\.po\\." . po-mode)) - -(provide 'bandali-po) -;;; bandali-po.el ends here diff --git a/.emacs.d/lisp/bandali-theme.el b/.emacs.d/lisp/bandali-theme.el deleted file mode 100644 index fa5911c..0000000 --- a/.emacs.d/lisp/bandali-theme.el +++ /dev/null @@ -1,79 +0,0 @@ -;;; bandali-theme.el --- bandali's custom theme setup -*- lexical-binding: t; -*- - -;; Copyright (C) 2018-2020 Amin Bandali - -;; Author: Amin Bandali -;; 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 . - -;;; Commentary: - -;; My custom theme setup. - -;;; Code: - -(when (display-graphic-p) - (add-to-list 'load-path (b/lisp "refinery-theme")) - (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) - (font-lock-remove-keywords - 'org-mode b/org-mode-font-lock-keywords) - (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) - (font-lock-add-keywords - 'org-mode b/org-mode-font-lock-keywords t) - (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 -- cgit v1.2.3-60-g2f50