diff options
author | 2020-10-05 23:38:06 -0400 | |
---|---|---|
committer | 2020-10-05 23:38:06 -0400 | |
commit | d7dee82420a04e5c92e5b5ad316e14a49bd4d689 (patch) | |
tree | 9dceac59e3b0d40b0357e8854e191ac5559d41ab /.emacs.d | |
parent | 927b50b7aec2da105bd5125dec272a89e38663c3 (diff) | |
download | configs-d7dee82420a04e5c92e5b5ad316e14a49bd4d689.tar.gz configs-d7dee82420a04e5c92e5b5ad316e14a49bd4d689.tar.xz configs-d7dee82420a04e5c92e5b5ad316e14a49bd4d689.zip |
Move GNU Emacs configs from ./ into .emacs.d/
I will be using the repository to store my configurations for other
non-Emacs pieces of software. The repository itself will be located
at ~/ rather than ~/.emacs.d/.
Diffstat (limited to '.emacs.d')
50 files changed, 3509 insertions, 0 deletions
diff --git a/.emacs.d/early-init.el b/.emacs.d/early-init.el new file mode 100644 index 0000000..99646b0 --- /dev/null +++ b/.emacs.d/early-init.el @@ -0,0 +1,4 @@ +;; No package.el (for emacs 27 and later). See +;; https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b +(setq package-enable-at-startup nil) +(setq load-prefer-newer t) diff --git a/.emacs.d/etc/.dir-locals.el b/.emacs.d/etc/.dir-locals.el new file mode 100644 index 0000000..e007adb --- /dev/null +++ b/.emacs.d/etc/.dir-locals.el @@ -0,0 +1,4 @@ +;;; 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/abbrev.el b/.emacs.d/etc/abbrev.el new file mode 100644 index 0000000..76f19d8 --- /dev/null +++ b/.emacs.d/etc/abbrev.el @@ -0,0 +1,5 @@ +;;-*-coding: utf-8;-*- +(define-abbrev-table 'message-mode-abbrev-table + '( + ("linux" "GNU/Linux" nil :count 4) + )) diff --git a/.emacs.d/etc/custom.el b/.emacs.d/etc/custom.el new file mode 100644 index 0000000..ebb093b --- /dev/null +++ b/.emacs.d/etc/custom.el @@ -0,0 +1,124 @@ +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(fci-rule-color "#5B6268") + '(inhibit-startup-buffer-menu t) + '(inhibit-startup-echo-area-message "bandali") + '(inhibit-startup-screen t) + '(initial-buffer-choice t) + '(initial-scratch-message nil) + '(isearch-allow-scroll t) + '(jdee-db-active-breakpoint-face-colors (cons "#1B2229" "#51afef")) + '(jdee-db-requested-breakpoint-face-colors (cons "#1B2229" "#98be65")) + '(jdee-db-spec-breakpoint-face-colors (cons "#1B2229" "#3f444a")) + '(ls-lisp-dirs-first t) + '(magit-diff-refine-hunk t) + '(magit-display-buffer-function 'magit-display-buffer-fullframe-status-v1) + '(message-elide-ellipsis "[...] +") + '(minions-mode t) + '(mm-uu-diff-groups-regexp + "\\(gmane\\|gnu\\|l\\)\\..*\\(diff\\|commit\\|cvs\\|bug\\|dev\\)") + '(mml-secure-key-preferences + '((OpenPGP + (sign) + (encrypt + ("ineiev@gnu.org" "BD9D4DEE7B2FF1CBEF2EE0C4E0ACD3E0CBE7874A"))) + (CMS + (sign) + (encrypt)))) + '(mml-secure-openpgp-encrypt-to-self t) + '(mml-secure-openpgp-sign-with-sender t) + '(objed-cursor-color "#ff6c6b") + '(oddmuse-username "bandali" 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 t) + '(org-agenda-time-leading-zero t t) + '(org-habit-graph-column 44 t) + '(org-latex-packages-alist '(("" "listings") ("" "color"))) + '(org-pretty-entities t) + '(package-selected-packages + '(delight yasnippet ebdb rt-liberation refinery-theme counsel ivy org-plus-contrib orgalist debbugs)) + '(page-break-lines-max-width 70) + '(pdf-view-midnight-colors (cons "#bbc2cf" "#282c34")) + '(pdf-view-resize-factor 1.05) + '(projectile-completion-system 'ivy) + '(projectile-mode-line-prefix " proj") + '(recentf-max-saved-items 2000) + '(recentf-save-file "/home/bandali/.emacs.d/var/recentf-save.el") + '(require-final-newline t) + '(safe-local-variable-values + '((tex-main-file . "./bandali-mmath-thesis.tex") + (tex-main-file . "../bandali-mmath-thesis.tex") + (flycheck-disabled-checkers emacs-lisp-checkdoc) + (tex-main-file . "./thesis.tex") + (tex-main-file . "../thesis.tex") + (org-export-allow-bind-keywords . t) + (eval load-file "thesis.el") + (eval modify-syntax-entry 43 "'") + (eval modify-syntax-entry 36 "'") + (eval modify-syntax-entry 126 "'") + (eval require 'org-ref) + (eval when + (featurep 'typo + (typo-mode -1))) + (eval add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local) + (eval add-hook 'after-save-hook 'org-beamer-export-to-latex t t) + (eval setq org-latex-prefer-user-labels t) + (eval add-hook 'after-save-hook 'org-latex-export-to-latex t t))) + '(save-interprogram-paste-before-kill t) + '(save-place-file "/home/bandali/.emacs.d/var/save-place.el") + '(savehist-file "/home/bandali/.emacs.d/var/savehist.el") + '(search-default-mode 'char-fold-to-regexp) + '(split-width-threshold 150) + '(text-scale-mode-step 1.05 t) + '(unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")) + '(vc-annotate-background "#282c34") + '(vc-annotate-color-map + (list + (cons 20 "#98be65") + (cons 40 "#b4be6c") + (cons 60 "#d0be73") + (cons 80 "#ECBE7B") + (cons 100 "#e6ab6a") + (cons 120 "#e09859") + (cons 140 "#da8548") + (cons 160 "#d38079") + (cons 180 "#cc7cab") + (cons 200 "#c678dd") + (cons 220 "#d974b7") + (cons 240 "#ec7091") + (cons 260 "#ff6c6b") + (cons 280 "#cf6162") + (cons 300 "#9f585a") + (cons 320 "#6f4e52") + (cons 340 "#5B6268") + (cons 360 "#5B6268"))) + '(vc-annotate-very-old-color nil) + '(vc-git-print-log-follow t) + '(version-control t) + '(view-read-only t) + '(web-mode-enable-auto-indentation nil t) + '(which-key-add-column-padding 5) + '(which-key-max-description-length 32)) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(dired-directory ((t (:weight semi-bold)))) + '(ivy-current-match ((((class color) (background light)) :background "#d7d7d7" :foreground "black") (((class color) (background dark)) :background "#65a7e2" :foreground "black"))) + '(ivy-minibuffer-match-face-1 ((t (:background "#eeeeee")))) + '(ivy-minibuffer-match-face-2 ((t (:background "#e7e7e7" :weight bold)))) + '(ivy-minibuffer-match-face-3 ((t (:background "light goldenrod" :weight semi-bold)))) + '(ivy-minibuffer-match-face-4 ((t (:background "misty rose" :weight semi-bold)))) + '(ivy-virtual ((t (:inherit font-lock-builtin-face :foreground "dim gray")))) + '(magit-diff-file-heading ((t (:weight normal)))) + '(org-block ((t (:background "#1d1f21")))) + '(org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21")))) + '(org-latex-and-related ((t (:foreground "#b294bb")))) + '(quote (org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21"))))) + '(widget-button ((t (:weight semi-bold))))) diff --git a/.emacs.d/etc/eshell/aliases b/.emacs.d/etc/eshell/aliases new file mode 100644 index 0000000..203b616 --- /dev/null +++ b/.emacs.d/etc/eshell/aliases @@ -0,0 +1,20 @@ +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 uwaterloo; mbsync shemshak; mbsync gnub; getmail diff --git a/.emacs.d/etc/secrets.el b/.emacs.d/etc/secrets.el new file mode 100644 index 0000000..edfa1a6 --- /dev/null +++ b/.emacs.d/etc/secrets.el @@ -0,0 +1,5 @@ +(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/etc/yasnippet/snippets/java-mode/format b/.emacs.d/etc/yasnippet/snippets/java-mode/format new file mode 100644 index 0000000..7620366 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/java-mode/format @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: String.format +# key: f +# -- +String.format("$1${2:%n}");$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/java-mode/new b/.emacs.d/etc/yasnippet/snippets/java-mode/new new file mode 100644 index 0000000..1ffd2e5 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/java-mode/new @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: new +# key: new +# -- +${1:Type} ${2:obj} = new ${3:Constr}(${4:args});$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/java-mode/printf b/.emacs.d/etc/yasnippet/snippets/java-mode/printf new file mode 100644 index 0000000..1b8c277 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/java-mode/printf @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: printf +# key: pf +# -- +System.out.printf("$1${2:%n}"$3);$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/java-mode/println b/.emacs.d/etc/yasnippet/snippets/java-mode/println new file mode 100644 index 0000000..7bb944c --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/java-mode/println @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: println +# key: p +# -- +System.out.println($1);$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/java-mode/return b/.emacs.d/etc/yasnippet/snippets/java-mode/return new file mode 100644 index 0000000..977859e --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/java-mode/return @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: return +# key: r +# -- +return $1;$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/cite b/.emacs.d/etc/yasnippet/snippets/latex-mode/cite new file mode 100644 index 0000000..3b4d161 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/cite @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: cite +# key: c +# -- +$1${2:~}\cite{${3:$$(unless yas-modified-p (mapconcat 'identity (reftex-citation 'dont-insert) ","))}}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/eg b/.emacs.d/etc/yasnippet/snippets/latex-mode/eg new file mode 100644 index 0000000..7c025e3 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/eg @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: eg +# key: eg +# -- +\emph{e.g.}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/emph b/.emacs.d/etc/yasnippet/snippets/latex-mode/emph new file mode 100644 index 0000000..36b19d7 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/emph @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: emph +# key: e +# -- +\emph{$1}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/enumerate b/.emacs.d/etc/yasnippet/snippets/latex-mode/enumerate new file mode 100644 index 0000000..bcb1df1 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/enumerate @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: enumerate +# key: o +# -- +\begin{enumerate} +\item $0 +\end{enumerate}
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/etal b/.emacs.d/etc/yasnippet/snippets/latex-mode/etal new file mode 100644 index 0000000..96e1fb0 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/etal @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: etal +# key: etal +# -- +\emph{et~al.}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/etc b/.emacs.d/etc/yasnippet/snippets/latex-mode/etc new file mode 100644 index 0000000..86b698e --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/etc @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: etc +# key: etc +# -- +\emph{etc.}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/ie b/.emacs.d/etc/yasnippet/snippets/latex-mode/ie new file mode 100644 index 0000000..cb91c2a --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/ie @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: ie +# key: ie +# -- +\emph{i.e.}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/itemize b/.emacs.d/etc/yasnippet/snippets/latex-mode/itemize new file mode 100644 index 0000000..b7a6949 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/itemize @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: itemize +# key: u +# -- +\begin{itemize} +\item $0 +\end{itemize}
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/label b/.emacs.d/etc/yasnippet/snippets/latex-mode/label new file mode 100644 index 0000000..8a98d7e --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/label @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: label +# key: lbl +# -- +\label{$0}
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/newcommand b/.emacs.d/etc/yasnippet/snippets/latex-mode/newcommand new file mode 100644 index 0000000..e9e03ca --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/newcommand @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: newcommand +# key: cmd +# -- +\newcommand{\\${1:name}}${2:[${3:0}]}{$0}
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/ref b/.emacs.d/etc/yasnippet/snippets/latex-mode/ref new file mode 100644 index 0000000..7eef596 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/ref @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: ref +# key: r +# -- +$1${2:~}\ref{${3:$$(unless yas-modified-p (reftex-reference nil nil))}}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/section b/.emacs.d/etc/yasnippet/snippets/latex-mode/section new file mode 100644 index 0000000..e1a2710 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/section @@ -0,0 +1,8 @@ +# -*- mode: snippet -*- +# name: section +# key: s +# -- +\section{${1:name}} +\label{sec:${2:label}} + +$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/subsection b/.emacs.d/etc/yasnippet/snippets/latex-mode/subsection new file mode 100644 index 0000000..ddfa13d --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/subsection @@ -0,0 +1,8 @@ +# -*- mode: snippet -*- +# name: subsection +# key: ss +# -- +\subsection{${1:name}} +\label{sec:${2:label}} + +$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/textbf b/.emacs.d/etc/yasnippet/snippets/latex-mode/textbf new file mode 100644 index 0000000..84171d7 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/textbf @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: textbf +# key: b +# -- +\textbf{$1}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/texttt b/.emacs.d/etc/yasnippet/snippets/latex-mode/texttt new file mode 100644 index 0000000..43cd769 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/texttt @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: texttt +# key: tt +# -- +\texttt{$1}$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/latex-mode/usepackage b/.emacs.d/etc/yasnippet/snippets/latex-mode/usepackage new file mode 100644 index 0000000..3405077 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/latex-mode/usepackage @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: usepackage +# key: p +# -- +\usepackage{$0}
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/log-edit-mode/thankgnu b/.emacs.d/etc/yasnippet/snippets/log-edit-mode/thankgnu new file mode 100644 index 0000000..bf29b63 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/log-edit-mode/thankgnu @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: thankgnu +# key: th +# -- +[RT#$1] Add ${2:$$(yas-choose-value '("Contributor" "Sustaining Contributor" "Patron"))} $3 to the 20${4:20} ThankGNUs list$0
\ No newline at end of file diff --git a/.emacs.d/etc/yasnippet/snippets/message-mode/thankgnu b/.emacs.d/etc/yasnippet/snippets/message-mode/thankgnu new file mode 100644 index 0000000..0d10448 --- /dev/null +++ b/.emacs.d/etc/yasnippet/snippets/message-mode/thankgnu @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: thankgnu +# key: th +# -- +Added ${2:$$(yas-choose-value '("Contributor" "Sustaining Contributor" "Patron"))} $3 to 20${4:20}supporters.html. + +Moving to campaigns.$0 diff --git a/.emacs.d/init.el b/.emacs.d/init.el new file mode 100644 index 0000000..958f457 --- /dev/null +++ b/.emacs.d/init.el @@ -0,0 +1,1031 @@ +;;; init.el --- bandali's emacs configuration -*- lexical-binding: t -*- + +;; Copyright (C) 2018-2020 Amin Bandali <bandali@gnu.org> + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; GNU Emacs configuration of Amin Bandali, computer scientist, +;; Free Software activist, and GNU maintainer & webmaster. Packages +;; are installed through using Borg for a fully reproducible setup. + +;; 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: +;; +;; - https://github.com/dieggsy/dotfiles +;; - https://github.com/dakra/dmacs +;; - http://pages.sachachua.com/.emacs.d/Sacha.html +;; - https://github.com/dakrone/eos +;; - http://doc.rix.si/cce/cce.html +;; - https://github.com/jwiegley/dot-emacs +;; - https://github.com/wasamasa/dotemacs +;; - https://github.com/hlissner/doom-emacs + +;;; Code: + +;;; Emacs initialization + +(defvar b/before-user-init-time (current-time) + "Value of `current-time' when Emacs begins loading `user-init-file'.") +(defvar b/emacs-initialized nil + "Whether Emacs has been initialized.") + +(when (not (bound-and-true-p b/emacs-initialized)) + (message "Loading Emacs...done (%.3fs)" + (float-time (time-subtract b/before-user-init-time + before-init-time)))) + +;; temporarily increase `gc-cons-threshhold' and `gc-cons-percentage' +;; during startup to reduce garbage collection frequency. clearing +;; `file-name-handler-alist' seems to help reduce startup time too. +(defvar b/gc-cons-threshold gc-cons-threshold) +(defvar 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) + +;; set them back to their defaults once we're done initializing +(defun b/post-init () + "My post-initialize function, run after loading `user-init-file'." + (setq 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) + (when (featurep 'exwm-workspace) + (with-eval-after-load 'exwm-workspace + (setq-default + mode-line-format + (append + mode-line-format + '((:eval + (format + "[%s]" (number-to-string + exwm-workspace-current-index)))))))) + + ;; make some mode-line spaces smaller + (setq-default + mode-line-format + (mapcar + (lambda (x) + (if (and (stringp x) (or (string= x " ") (string= x " "))) + " " + x)) + mode-line-format) + mode-line-buffer-identification + (propertized-buffer-identification "%10b"))) +(add-hook 'after-init-hook #'b/post-init) + +;; increase number of lines kept in *Messages* log +(setq message-log-max 20000) + +;; optionally, uncomment to supress some byte-compiler warnings +;; (see C-h v byte-compile-warnings RET for more info) +;; (setq byte-compile-warnings +;; '(not free-vars unresolved noruntime lexical make-local)) + + +;;; whoami + +(setq user-full-name "Amin Bandali" + user-mail-address "bandali@gnu.org") + + +;;; csetq (`custom' setq) + +(require 'cl-lib) + +(defmacro csetq (&rest args) + "Set the value of user option VAR to VALUE. + +More generally, you can use multiple variables and values, as in + (csetq VAR VALUE VAR VALUE...) +This sets each user option VAR's value to the corresponding VALUE. + +\(fn [VAR VALUE]...)" + (declare (debug setq)) + `(progn + ,@(cl-loop for (var value) on args by 'cddr + collect + `(funcall (or (get ',var 'custom-set) #'set-default) + ',var ,value)))) + + +;;; 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 + (when (= (length package-archives) 1) + (csetq + package-archives + `(,@package-archives + ;; ("bndl" . "https://p.bndl.org/elpa/") + ("org" . "https://orgmode.org/elpa/")) + package-load-list + '(;; GNU ELPA + (ivy "0.13.1") + (counsel "0.13.1") + (swiper "0.13.1") + (debbugs "0.26") + (delight "1.7") + (ebdb "0.6.19") + (orgalist "1.13") + (rt-liberation "1.31") + (yasnippet "0.14.0") + ;; bndl + (refinery-theme "0.1.1") + ;; Org ELPA + (org-plus-contrib "20201005")))) + (package-initialize)) + +(csetq package-archive-upload-base "/ssh:caffeine:~/www/p/elpa") + + +;;; 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)) + +(csetq + auto-save-list-file-prefix (b/var "auto-save/sessions/") + nsm-settings-file (b/var "nsm-settings.el")) + +;; separate custom file (don't want it mixing with init.el) +(with-eval-after-load 'custom + (setq custom-file (b/etc "custom.el")) + (when (file-exists-p custom-file) + (load custom-file)) + ;; while at it, treat themes as safe + ;; (setf custom-safe-themes t) + ;; 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. see +;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server +(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) + (declare-function server-running-p "server") + (or (server-running-p) (server-mode))) + + +;;; Defaults + +;;;; C-level customizations + +(csetq + ;; minibuffer + enable-recursive-minibuffers t + resize-mini-windows t + ;; more useful frame titles + ;; frame-title-format '("" invocation-name " - " + ;; (:eval + ;; (if (buffer-file-name) + ;; (abbreviate-file-name (buffer-file-name)) + ;; "%b"))) + ;; i don't feel like jumping out of my chair every now and again; so + ;; don't BEEP! at me, emacs + ring-bell-function 'ignore + ;; better scrolling + ;; scroll-margin 1 + ;; scroll-conservatively 10000 + scroll-step 1 + scroll-conservatively 101 + scroll-preserve-screen-position 1 + ;; focus follows mouse + mouse-autoselect-window t) + +(setq-default + ;; always use space for indentation + indent-tabs-mode nil + tab-width 4 + ;; case-sensitive search (and `dabbrev-expand') + ;; case-fold-search nil + ;; cursor shape + cursor-type t) + +(set-fontset-font t 'arabic "Vazir") + +;; unicode support +;; (dolist (ft (fontset-list)) +;; (set-fontset-font +;; ft +;; 'unicode +;; (font-spec :name "Source Code Pro" :size 14)) +;; (set-fontset-font +;; ft +;; 'unicode +;; (font-spec :name "DejaVu Sans Mono") +;; nil +;; 'append) +;; ;; (set-fontset-font +;; ;; ft +;; ;; 'unicode +;; ;; (font-spec +;; ;; :name "Symbola monospacified for DejaVu Sans Mono") +;; ;; nil +;; ;; 'append) +;; ;; (set-fontset-font +;; ;; ft +;; ;; #x2115 ; ℕ +;; ;; (font-spec :name "DejaVu Sans Mono") +;; ;; nil +;; ;; 'append) +;; (set-fontset-font +;; ft +;; (cons ?Α ?ω) +;; (font-spec :name "DejaVu Sans Mono" :size 14) +;; nil +;; 'prepend)) + +;;;; Elisp-level customizations + +;; startup +;; don't need to see the startup echo area message +(advice-add #'display-startup-echo-area-message :override #'ignore) +(csetq + ;; i want *scratch* as my startup buffer + initial-buffer-choice t + ;; i don't need the default hint + initial-scratch-message nil + ;; use customizable text-mode as major mode for *scratch* + ;; (initial-major-mode 'text-mode) + ;; inhibit buffer list when more than 2 files are loaded + inhibit-startup-buffer-menu t + ;; don't need to see the startup screen or echo area message + inhibit-startup-screen t + inhibit-startup-echo-area-message user-login-name) + +;; files +(csetq + ;; 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 + require-final-newline t + ;; open read-only file buffers in view-mode + ;; (enables niceties like `q' for quit) + view-read-only t) + +;; novice +;; disable disabled commands +(csetq disabled-command-function nil) + +;; lazy-person-friendly yes/no prompts +(defalias 'yes-or-no-p #'y-or-n-p) + +;; autorevert: enable automatic reloading of changed buffers and files +(csetq auto-revert-verbose nil + global-auto-revert-non-file-buffers nil) +(require 'autorevert) +(global-auto-revert-mode 1) + +;; time and battery in mode-line +(csetq + display-time-default-load-average nil + display-time-format " %a %b %-e %-l:%M%P" + display-time-mail-icon '(image :type xpm + :file "gnus/gnus-pointer.xpm" + :ascent center) + display-time-use-mail-icon t) +(require 'time) +(display-time-mode) + +(csetq battery-mode-line-format " %p%% %t") +(require 'battery) +(display-battery-mode) + +(require 'fringe) +;; smaller fringe +;; (fringe-mode '(3 . 1)) +(fringe-mode nil) + +(require 'winner) +;; enable winner-mode (C-h f winner-mode RET) +(winner-mode 1) + +(with-eval-after-load 'compile + ;; don't display *compilation* buffer on success. based on + ;; https://stackoverflow.com/a/17788551, with changes to use `cl-letf' + ;; instead of the now obsolete `flet'. + (defun b/compilation-finish-function (buffer outstr) + (unless (string-match "finished" outstr) + (switch-to-buffer-other-window buffer)) + t) + + (setq compilation-finish-functions #'b/compilation-finish-function) + + (require 'cl-macs) + + (defadvice compilation-start + (around inhibit-display + (command &optional mode name-function highlight-regexp)) + (if (not (string-match "^\\(find\\|grep\\)" command)) + (cl-letf (((symbol-function 'display-buffer) #'ignore)) + (save-window-excursion ad-do-it)) + ad-do-it)) + (ad-activate 'compilation-start)) + +;; isearch +(csetq + ;; allow scrolling in Isearch + isearch-allow-scroll t + ;; search for non-ASCII characters: i’d like non-ASCII characters such + ;; as ‘’“”«»‹›áⓐ𝒶 to be selected when i search for their ASCII + ;; counterpart. shoutout to + ;; http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html + search-default-mode #'char-fold-to-regexp) + +;; replace +;; uncomment to extend the above behaviour to query-replace +;; (csetq replace-char-fold t) + +;; vc +(global-set-key (kbd "C-x v C-=") #'vc-ediff) + +(with-eval-after-load 'vc-git + (csetq vc-git-print-log-follow t + vc-git-show-stash 0)) + +(csetq ediff-window-setup-function 'ediff-setup-windows-plain + ediff-split-window-function 'split-window-horizontally) +(with-eval-after-load 'ediff + (add-hook 'ediff-after-quit-hook-internal #'winner-undo)) + +;; face-remap +(csetq + ;; gentler font resizing + text-scale-mode-step 1.05) + +(run-with-idle-timer 0.4 nil #'require 'mwheel) +(csetq 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 + +(run-with-idle-timer 0.4 nil #'require 'pixel-scroll) +(with-eval-after-load 'pixel-scroll + (pixel-scroll-mode 1)) + +;; epg-config +(csetq + epg-gpg-program (executable-find "gpg") + ;; ask for GPG passphrase in minibuffer + ;; this will fail if gpg>=2.1 is not available + epg-pinentry-mode 'loopback) + +;; (require 'pinentry) +;; workaround for systemd-based distros: +;; (setq pinentry--socket-dir server-socket-dir) +;; (pinentry-start) + +;; auth-source +(csetq + auth-sources '("~/.authinfo.gpg") + authinfo-hidden (regexp-opt '("password" "client-secret" "token"))) + + +;;; 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) + (let ((asterism "* * *")) + (insert + (concat + "\n" + (make-string + (floor (/ (- fill-column (length asterism)) 2)) + ?\s) + 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/kill-current-buffer () + "Kill the current buffer." + ;; also see https://redd.it/64xb3q + (interactive) + (kill-buffer (current-buffer))) + +(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/duplicate-line-or-region (&optional n) + "Duplicate the current line, or region (if active). +Make N (default: 1) copies of the current line or region." + (interactive "*p") + (let ((u-r-p (use-region-p)) ; if region is active + (n1 (or n 1))) + (save-excursion + (let ((text + (if u-r-p + (buffer-substring (region-beginning) (region-end)) + (prog1 (thing-at-point 'line) + (end-of-line) + (if (eobp) + (newline) + (forward-line 1)))))) + (dotimes (_ (abs n1)) + (insert text)))))) + + +;;; General key bindings + +(global-set-key (kbd "C-a") #'b/move-indentation-or-beginning-of-line) +(global-set-key (kbd "C-c a i") #'ielm) +(global-set-key (kbd "C-c d") #'b/duplicate-line-or-region) +(global-set-key (kbd "C-S-j") #'b/join-line-top) +(global-set-key (kbd "C-c x") #'execute-extended-command) + +;; 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 p") #'pp-macroexpand-last-sexp) +(global-set-key (kbd "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) + +;; 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) + +;; frames +(global-set-key (kbd "C-c F m") #'make-frame-command) +(global-set-key (kbd "C-c F d") #'delete-frame) + +;; help/describe +(global-set-key (kbd "C-S-h C") #'describe-char) +(global-set-key (kbd "C-S-h F") #'describe-face) + +;; (global-set-key (kbd "C-x k") #'b/kill-current-buffer) +;; (global-set-key (kbd "C-x K") #'kill-buffer) +;; (global-set-key (kbd "C-x s") #'save-buffer) +;; (global-set-key (kbd "C-x S") #'save-some-buffers) + +(define-key emacs-lisp-mode-map (kbd "<C-return>") #'b/add-elisp-section) + +(when (display-graphic-p) + (global-unset-key (kbd "C-z"))) + + +;;; Essential packages + +(add-to-list + 'load-path + (expand-file-name + (convert-standard-filename "lisp") user-emacs-directory)) + +;; (require 'bandali-exwm) + +(require 'bandali-org) + +(require 'bandali-theme) + +;; (require 'bandali-magit) + +;; recently opened files +(csetq recentf-max-saved-items 2000 + recentf-save-file (b/var "recentf-save.el")) +(run-with-idle-timer 0.2 nil #'require 'recentf) +(with-eval-after-load 'recentf + ;; (add-to-list 'recentf-keep #'file-remote-p) + (recentf-mode)) + +;; needed for history for counsel +(csetq amx-save-file (b/var "amx-save.el")) +(add-to-list 'load-path (b/lisp "s")) +(add-to-list 'load-path (b/lisp "amx")) +(run-with-idle-timer 0.3 nil #'require 'amx) +(with-eval-after-load 'amx + (amx-mode)) + +(require 'bandali-ivy) + +(require 'bandali-eshell) + +(require 'bandali-ibuffer) + +;; outline +;; (with-eval-after-load 'outline +;; (when (featurep 'which-key) +;; (which-key-add-key-based-replacements +;; "C-c @" "outline" +;; "s-O" "outline")) +;; (define-key outline-minor-mode-map (kbd "<s-tab>") +;; #'outline-toggle-children) +;; (define-key outline-minor-mode-map (kbd "M-p") +;; #'outline-previous-visible-heading) +;; (define-key outline-minor-mode-map (kbd "M-n") +;; #'outline-next-visible-heading) +;; (defvar b/outline-prefix-map) +;; (define-prefix-command 'b/outline-prefix-map) +;; (define-key outline-minor-mode-map (kbd "s-O") +;; 'b/outline-prefix-map) +;; (define-key b/outline-prefix-map (kbd "TAB") +;; #'outline-toggle-children) +;; (define-key b/outline-prefix-map (kbd "a") +;; #'outline-hide-body) +;; (define-key b/outline-prefix-map (kbd "H") +;; #'outline-hide-body) +;; (define-key b/outline-prefix-map (kbd "S") +;; #'outline-show-all) +;; (define-key b/outline-prefix-map (kbd "h") +;; #'outline-hide-subtree) +;; (define-key b/outline-prefix-map (kbd "s") +;; #'outline-show-subtree)) +;; (add-hook 'prog-mode-hook #'outline-minor-mode) + +(require 'bandali-dired) + +(with-eval-after-load 'help + (temp-buffer-resize-mode) + (csetq help-window-select t)) + +(with-eval-after-load 'help-mode + ;; local key bindings + (define-key help-mode-map (kbd "p") #'backward-button) + (define-key help-mode-map (kbd "n") #'forward-button)) + +(with-eval-after-load 'tramp + (csetq tramp-auto-save-directory (b/var "tramp/auto-save/") + tramp-persistency-file-name (b/var "tramp/persistency.el")) + (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)) + +(csetq shr-max-width 80) + +;; Email (with Gnus, message, and EBDB) +(require 'bandali-gnus) +(with-eval-after-load 'sendmail + (csetq sendmail-program (executable-find "msmtp") + ;; message-sendmail-extra-arguments '("-v" "-d") + mail-specify-envelope-from t + mail-envelope-from 'header)) +(require 'bandali-message) +(require 'bandali-ebdb) + +;; IRC (with ERC) +(require 'bandali-erc) + +;; 'paste' service (aka scp + web server) +(add-to-list 'load-path (b/lisp "scpaste")) +(with-eval-after-load 'scpaste + (csetq scpaste-http-destination "https://p.bndl.org" + scpaste-scp-destination "p:~")) +(autoload 'scpaste "scpaste" nil t) +(autoload 'scpaste-region "scpaste" nil t) +(global-set-key (kbd "C-c a p p") #'scpaste) +(global-set-key (kbd "C-c a p r") #'scpaste-region) + + +;;; Editing + +;; display Lisp objects at point in the echo area +(when (version< "25" emacs-version) + (with-eval-after-load 'eldoc + (csetq eldoc-minor-mode-string " eldoc") + (global-eldoc-mode))) + +;; highlight matching parens +(require 'paren) +(show-paren-mode) + +;; (require 'elec-pair) +;; (electric-pair-mode) + +(csetq + ;; 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) +(with-eval-after-load 'simple + (column-number-mode 1)) + +;; save minibuffer history +(require 'savehist) +(csetq savehist-file (b/var "savehist.el")) +(savehist-mode) +(add-to-list 'savehist-additional-variables 'kill-ring) + +;; automatically save place in files +(when (version< "25" emacs-version) + (csetq save-place-file (b/var "save-place.el")) + (save-place-mode)) + +(defun indicate-buffer-boundaries-left () + (csetq indicate-buffer-boundaries 'left)) +(with-eval-after-load 'prog-mode + (global-prettify-symbols-mode)) +(add-hook 'prog-mode-hook #'indicate-buffer-boundaries-left) + +(define-key text-mode-map (kbd "C-<return>") #'b/insert-asterism) +(add-hook 'text-mode-hook #'indicate-buffer-boundaries-left) +(add-hook 'text-mode-hook #'flyspell-mode) + +(add-to-list 'auto-mode-alist '("\\.*rc$" . conf-mode)) + +(add-to-list 'auto-mode-alist '("\\.bashrc$" . sh-mode)) + +(with-eval-after-load 'flyspell + (csetq flyspell-mode-line-string " fly")) + +;; flycheck +;; (run-with-idle-timer 0.6 nil #'require 'flycheck) +;; (with-eval-after-load 'flycheck +;; (csetq +;; ;; Use the load-path from running Emacs when checking elisp files +;; flycheck-emacs-lisp-load-path 'inherit +;; ;; Only flycheck when I actually save the buffer +;; flycheck-check-syntax-automatically '(mode-enabled save) +;; flycheck-mode-line-prefix "flyc")) +;; (define-key flycheck-mode-map (kbd "M-P") #'flycheck-previous-error) +;; (define-key flycheck-mode-map (kbd "M-N") #'flycheck-next-error) +;; (add-hook 'prog-mode-hook #'flycheck-mode) + +;; ispell +;; 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 +;; (csetq 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)) + +;; abbrev +(csetq abbrev-file-name (b/etc "abbrev.el")) +(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)) + +;; alloy +(add-to-list 'load-path (b/lisp "alloy-mode")) +(autoload 'alloy-mode "alloy-mode" nil t) +(with-eval-after-load 'alloy-mode + (csetq 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))) + ;; local key bindings + (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))) + +;; lean +;; (eval-when-compile (defvar lean-mode-map)) +;; (run-with-idle-timer 0.4 nil #'require 'lean-mode) +;; (with-eval-after-load 'lean-mode +;; (require 'lean-input) +;; (csetq default-input-method "Lean" +;; lean-input-tweak-all '(lean-input-compose +;; (lean-input-prepend "/") +;; (lean-input-nonempty)) +;; lean-input-user-translations '(("/" "/"))) +;; (lean-input-setup) +;; ;; local key bindings +;; (define-key lean-mode-map (kbd "S-SPC") #'company-complete)) + +(with-eval-after-load 'sgml-mode + (csetq sgml-basic-offset 0)) + +(with-eval-after-load 'css-mode + (csetq css-indent-offset 2)) + +;; po-mode +;; (add-hook 'po-mode-hook (lambda nil (run-with-timer 0.1 nil 'View-exit))) + +;; auctex +;; (csetq font-latex-fontify-sectioning 'color) + +(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) + + +;;; Emacs enhancements & auxiliary packages + +(with-eval-after-load 'man + (csetq Man-width 80)) + +(defun b/*scratch* () + "Switch to `*scratch*' buffer, creating it if it does not exist." + (interactive) + (switch-to-buffer + (or (get-buffer "*scratch*") + (with-current-buffer (get-buffer-create "*scratch*") + (set-buffer-major-mode (current-buffer)) + (current-buffer))))) +(global-set-key (kbd "C-c s") #'b/*scratch*) + +;; ,---- +;; | make pretty boxed quotes like this +;; `---- +(add-to-list 'load-path (b/lisp "boxquote")) +(run-with-idle-timer 0.6 nil #'require 'boxquote) +(with-eval-after-load 'boxquote + (defvar b/boxquote-prefix-map) + (define-prefix-command 'b/boxquote-prefix-map) + (global-set-key (kbd "C-c q") 'b/boxquote-prefix-map) + (define-key b/boxquote-prefix-map (kbd "b") #'boxquote-buffer) + (define-key b/boxquote-prefix-map (kbd "B") #'boxquote-insert-buffer) + (define-key b/boxquote-prefix-map (kbd "d") #'boxquote-defun) + (define-key b/boxquote-prefix-map (kbd "F") #'boxquote-insert-file) + (define-key b/boxquote-prefix-map (kbd "hf") #'boxquote-describe-function) + (define-key b/boxquote-prefix-map (kbd "hk") #'boxquote-describe-key) + (define-key b/boxquote-prefix-map (kbd "hv") #'boxquote-describe-variable) + (define-key b/boxquote-prefix-map (kbd "hw") #'boxquote-where-is) + (define-key b/boxquote-prefix-map (kbd "k") #'boxquote-kill) + (define-key b/boxquote-prefix-map (kbd "p") #'boxquote-paragraph) + (define-key b/boxquote-prefix-map (kbd "q") #'boxquote-boxquote) + (define-key b/boxquote-prefix-map (kbd "r") #'boxquote-region) + (define-key b/boxquote-prefix-map (kbd "s") #'boxquote-shell-command) + (define-key b/boxquote-prefix-map (kbd "t") #'boxquote-text) + (define-key b/boxquote-prefix-map (kbd "T") #'boxquote-title) + (define-key b/boxquote-prefix-map (kbd "u") #'boxquote-unbox) + (define-key b/boxquote-prefix-map (kbd "U") #'boxquote-unbox-region) + (define-key b/boxquote-prefix-map (kbd "y") #'boxquote-yank) + (define-key b/boxquote-prefix-map (kbd "M-q") #'boxquote-fill-paragraph) + (define-key b/boxquote-prefix-map (kbd "M-w") #'boxquote-kill-ring-save)) + +(add-to-list 'load-path (b/lisp "hl-todo")) +(run-with-idle-timer 0.5 nil #'require 'hl-todo) +(with-eval-after-load 'hl-todo + ;; highlight TODOs in buffers + (global-hl-todo-mode)) + +(add-to-list 'load-path (b/lisp "page-break-lines")) +(run-with-idle-timer 0.5 nil #'require 'page-break-lines) +(with-eval-after-load 'page-break-lines + (csetq page-break-lines-max-width fill-column) + (global-page-break-lines-mode)) + +;; expand-region +(global-set-key (kbd "C-=") #'er/expand-region) + +(run-with-idle-timer 0.6 nil #'require 'yasnippet) +(with-eval-after-load 'yasnippet + (declare-function yas-reload-all + "yasnippet" (&optional no-jit interactive)) + (declare-function yas-maybe-expand-abbrev-key-filter + "yasnippet" (cmd)) + + (defconst yas-verbosity-cur yas-verbosity) + (setq yas-verbosity 2) + (csetq yas-snippet-dirs `(,(b/etc "yasnippet/snippets"))) + (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets" t) + (yas-reload-all) + (setq yas-verbosity yas-verbosity-cur) + + (defun b/yas-maybe-expand-abbrev-key-filter (cmd) + (when (and (yas-maybe-expand-abbrev-key-filter cmd) + (not (bound-and-true-p git-commit-mode))) + cmd)) + (defconst b/yas-maybe-expand + '(menu-item "" yas-expand + :filter b/yas-maybe-expand-abbrev-key-filter)) + (define-key yas-minor-mode-map (kbd "SPC") b/yas-maybe-expand) + + (yas-global-mode)) + +;; 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 + (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 + (lambda () + (interactive) + (setq debbugs-gnu-current-suppress t) + (debbugs-gnu debbugs-gnu-default-severities + '("gnuzilla")))) +(global-set-key (kbd "C-c D G b") ; bug-guix + (lambda () + (interactive) + (setq debbugs-gnu-current-suppress t) + (debbugs-gnu debbugs-gnu-default-severities + '("guix")))) +(global-set-key (kbd "C-c D G p") ; guix-patches + (lambda () + (interactive) + (setq debbugs-gnu-current-suppress t) + (debbugs-gnu debbugs-gnu-default-severities + '("guix-patches")))) + +;; url and url-cache +(csetq + url-configuration-directory (b/var "url/configuration/") + url-cache-directory (b/var "url/cache/")) + +;; eww +(csetq eww-download-directory (file-name-as-directory + (getenv "XDG_DOWNLOAD_DIR"))) +(global-set-key (kbd "C-c a e w") #'eww) + +;; ;; org-ref +;; (csetq +;; reftex-default-bibliography '("~/usr/org/references.bib") +;; org-ref-default-bibliography '("~/usr/org/references.bib") +;; org-ref-bibliography-notes "~/usr/org/notes.org" +;; org-ref-pdf-directory "~/usr/org/bibtex-pdfs/") + +;; fill-column-indicator ? + +;; window +(csetq split-width-threshold 150) +(global-set-key (kbd "C-c w s l") + (lambda () + (interactive) + (split-window-right) + (other-window 1))) +(global-set-key (kbd "C-c w s j") + (lambda () + (interactive) + (split-window-below) + (other-window 1))) +(global-set-key (kbd "C-c w q") #'quit-window) + +(run-with-idle-timer 0.6 nil #'require 'windmove) +(global-set-key (kbd "C-c w h") #'windmove-left) +(global-set-key (kbd "C-c w j") #'windmove-down) +(global-set-key (kbd "C-c w k") #'windmove-up) +(global-set-key (kbd "C-c w l") #'windmove-right) +(global-set-key (kbd "C-c w H") #'windmove-swap-states-left) +(global-set-key (kbd "C-c w J") #'windmove-swap-states-down) +(global-set-key (kbd "C-c w K") #'windmove-swap-states-up) +(global-set-key (kbd "C-c w L") #'windmove-swap-states-right) + +;; pass +;; (global-set-key (kbd "C-c a p") #'pass) +;; (add-hook 'pass-mode-hook #'View-exit) + +;; reftex +;; 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))))) +(add-hook 'latex-mode-hook #'reftex-mode) + +;; dmenu +;; (csetq +;; dmenu-prompt-string "run: " +;; dmenu-save-file (b/var "dmenu-items")) + +;; eosd ? + +;; delight +(run-with-idle-timer 0.5 nil #'require 'delight) +(with-eval-after-load 'delight + (delight 'auto-fill-function " f" "simple") + (delight 'abbrev-mode "" "abbrev") + (delight 'page-break-lines-mode "" "page-break-lines") + (delight 'ivy-mode "" "ivy") + (delight 'counsel-mode "" "counsel") + (delight 'mml-mode " mml" "mml") + (delight 'yas-minor-mode "" "yasnippet")) + + +;;; Post initialization + +(message "Loading %s...done (%.3fs)" user-init-file + (float-time (time-subtract (current-time) + b/before-user-init-time))) + +;;; init.el ends here diff --git a/.emacs.d/lisp/alloy-mode b/.emacs.d/lisp/alloy-mode new file mode 160000 +Subproject 0d05bdd10c77ec04c3d61eccf67e68c08284951 diff --git a/.emacs.d/lisp/amx b/.emacs.d/lisp/amx new file mode 160000 +Subproject ccfc92c600df681df5e8b5fecec328c462ceb71 diff --git a/.emacs.d/lisp/bandali-dired.el b/.emacs.d/lisp/bandali-dired.el new file mode 100644 index 0000000..9ed1030 --- /dev/null +++ b/.emacs.d/lisp/bandali-dired.el @@ -0,0 +1,93 @@ +;;; bandali-dired.el --- bandali's dired setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: files + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My dired setup and customizations. + +;;; Code: + +(with-eval-after-load 'dired + (csetq + dired-dwim-target t + dired-listing-switches "-alh" + dired-recent-directories-file (b/var "dired-recent-directories.el") + ls-lisp-dirs-first t + ls-lisp-use-insert-directory-program nil) + + (declare-function dired-dwim-target-directory "dired-aux") + ;; easily diff 2 marked files + ;; https://oremacs.com/2017/03/18/dired-ediff/ + (defun dired-ediff-files () + (interactive) + (require 'dired-aux) + (defvar ediff-after-quit-hook-internal) + (let ((files (dired-get-marked-files)) + (wnd (current-window-configuration))) + (if (<= (length files) 2) + (let ((file1 (car files)) + (file2 (if (cdr files) + (cadr files) + (read-file-name + "file: " + (dired-dwim-target-directory))))) + (if (file-newer-than-file-p file1 file2) + (ediff-files file2 file1) + (ediff-files file1 file2)) + (add-hook 'ediff-after-quit-hook-internal + (lambda () + (setq ediff-after-quit-hook-internal nil) + (set-window-configuration wnd)))) + (error "no more than 2 files should be marked")))) + + (defun b/dired-start-process (program &optional args) + "Open current file with a PROGRAM." + ;; Shell command looks like this: "program [ARGS]... FILE" (ARGS + ;; can be nil, so remove it). + (declare-function dired-get-file-for-visit "dired") + (apply #'b/start-process + program + (remove nil (list args (dired-get-file-for-visit))))) + + ;; local key bindings + (define-key dired-mode-map (kbd "b") #'dired-up-directory) + (define-key dired-mode-map (kbd "E") #'dired-ediff-files) + (define-key dired-mode-map (kbd "e") #'dired-toggle-read-only) + (define-key dired-mode-map (kbd "\\") #'dired-hide-details-mode) + (define-key dired-mode-map (kbd "z") + (lambda () + (interactive) + (b/dired-start-process "zathura"))) + + (require 'dired-x) + (csetq dired-guess-shell-alist-user + '(("\\.pdf\\'" "evince" "zathura" "okular") + ("\\.doc\\'" "libreoffice") + ("\\.docx\\'" "libreoffice") + ("\\.ppt\\'" "libreoffice") + ("\\.pptx\\'" "libreoffice") + ("\\.xls\\'" "libreoffice") + ("\\.xlsx\\'" "libreoffice") + ("\\.flac\\'" "mpv")))) +;; hooks +(add-hook 'dired-mode-hook #'dired-hide-details-mode) + +(provide 'bandali-dired) +;;; bandali-dired.el ends here diff --git a/.emacs.d/lisp/bandali-ebdb.el b/.emacs.d/lisp/bandali-ebdb.el new file mode 100644 index 0000000..4d21978 --- /dev/null +++ b/.emacs.d/lisp/bandali-ebdb.el @@ -0,0 +1,52 @@ +;;; bandali-ebdb.el --- bandali's EBDB configuration -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My EBDB setup. + +;;; Code: + +(with-eval-after-load 'gnus + (require 'ebdb) + (csetq ebdb-sources (b/var "ebdb")) + (with-eval-after-load 'swiper + (add-to-list 'swiper-font-lock-exclude #'ebdb-mode t)) + ;; local key bindings + (define-key gnus-group-mode-map (kbd "e") #'ebdb)) + +(with-eval-after-load 'ebdb + (with-eval-after-load 'ebdb-complete + ;; (csetq ebdb-complete-mail 'capf) + (ebdb-complete-enable)) + + (require 'ebdb-message) + + (require 'ebdb-gnus) + (csetq ebdb-gnus-window-size 0.3) + + (require 'ebdb-mua) + (csetq ebdb-mua-pop-up t)) + +;; (with-eval-after-load 'company-ebdb +;; (defun company-ebdb--post-complete (_) nil)) + +(provide 'bandali-ebdb) +;;; bandali-ebdb.el ends here diff --git a/.emacs.d/lisp/bandali-erc.el b/.emacs.d/lisp/bandali-erc.el new file mode 100644 index 0000000..41a152c --- /dev/null +++ b/.emacs.d/lisp/bandali-erc.el @@ -0,0 +1,178 @@ +;;; bandali-erc.el --- bandali's ERC setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My ERC setup for IRC. It uses my fork of ZNC.el. + +;;; Code: + +(defvar b/erc-detach-on-kill t + "Whether killing a channel should send a DETACH command (for ZNC).") + +(with-eval-after-load 'erc + (make-directory (b/var "erc/dcc/") t) + (csetq + erc-auto-query 'bury + erc-autojoin-domain-only nil + erc-dcc-get-default-directory (b/var "erc/dcc/") + erc-format-nick-function 'erc-format-@nick + erc-join-buffer 'bury + erc-log-channels-directory (b/var "erc/log-channels/") + erc-lurker-hide-list '("JOIN" "PART" "QUIT") + erc-nick "bandali" + erc-prompt "erc>" + erc-prompt-for-password nil + erc-rename-buffers t + erc-server-reconnect-attempts 5 + erc-server-reconnect-timeout 3) + + (declare-function erc-message "erc-backend" + (message-command line &optional force)) + (declare-function erc-default-target "erc") + (declare-function erc-current-nick "erc") + (defun erc-cmd-OPME () + "Request chanserv to op me." + (erc-message "PRIVMSG" + (format "chanserv op %s %s" + (erc-default-target) + (erc-current-nick)) nil)) + (declare-function erc-cmd-DEOP "erc" (&rest people)) + (defun erc-cmd-DEOPME () + "Deop myself from current channel." + (erc-cmd-DEOP (format "%s" (erc-current-nick)))) + (add-to-list 'erc-modules 'keep-place) + (add-to-list 'erc-modules 'notifications) + (add-to-list 'erc-modules 'smiley) + (add-to-list 'erc-modules 'spelling) + (declare-function erc-update-modules "erc") + (erc-update-modules) + + (set-face-attribute + 'erc-nick-default-face nil + ;; :weight 'semibold + ;; :background "#f2f2f2" + ;; :foreground "#222222" + :weight 'bold + :background "#f8f8f8" + :foreground "#6a6a6a") + + ;; (set-face-attribute + ;; 'erc-notice-face nil + ;; ;; :background "#fffadf" + ;; ;; :background "#f9f9f9" + ;; :background 'unspecified + ;; ;; :foreground "#809de5" + ;; :foreground "steel blue") + + ;; erc-fill + ;; (csetq + ;; erc-fill-column 77 + ;; erc-fill-function 'erc-fill-variable + ;; erc-fill-static-center 18) + ;; to disable: + ;; (erc-fill-mode -1) + + ;; erc-match + (csetq + erc-pal-highlight-type 'nick + erc-pals + '("aindilis" "blackbeard" "bremner" "brettgilio" "civodul" + "dto" "ggoes" "jrasata" "mplsCorwin" "rwp" "technomancy")) + (with-eval-after-load 'erc-match + (set-face-attribute + 'erc-pal-face nil + :foreground 'unspecified + :weight 'unspecified + :inherit 'erc-nick-default-face + :background (face-attribute 'font-lock-string-face :background))) + + ;; erc-pcomplete + (csetq erc-pcomplete-nick-postfix ", ") + + ;; erc-stamp + (csetq erc-timestamp-only-if-changed-flag nil + erc-timestamp-format "%T " + erc-insert-timestamp-function 'erc-insert-timestamp-left) + (with-eval-after-load 'erc-match + (set-face-attribute + 'erc-timestamp-face nil + :foreground "#aaaaaa" + :weight 'unspecified + :background 'unspecified)) + + ;; erc-track + (csetq + erc-track-enable-keybindings nil + erc-track-exclude-types '("JOIN" "MODE" "NICK" "PART" "QUIT" + "324" "329" "332" "333" "353" "477") + erc-track-position-in-mode-line t + erc-track-priority-faces-only 'all + erc-track-shorten-function nil + erc-track-showcount t) + + ;; key bindings + (global-set-key (kbd "C-c w e") #'erc-switch-to-buffer-other-window) + (define-key erc-mode-map (kbd "M-a") #'erc-track-switch-buffer) + + ;; hooks + (defun b/erc-detach-or-kill-channel () + (if b/erc-detach-on-kill + (when (erc-server-process-alive) + (let ((tgt (erc-default-target))) + (erc-server-send (format "DETACH %s" tgt) nil tgt))) + (erc-kill-channel))) + (add-hook 'erc-kill-channel-hook #'b/erc-detach-or-kill-channel) + (remove-hook 'erc-kill-channel-hook #'erc-kill-channel)) + +;; global key bindings +(global-set-key + (kbd "C-c a e f") + (lambda () + (interactive) + (let* ((auth (auth-source-search :host "znca")) + (p (if (null auth) + (error "Couldn't find znca's authinfo") + (funcall (plist-get (car auth) :secret))))) + (erc-tls :server "znc.emacsconf.org" :port 6697 + :password (concat "bandali/freenode:" p))))) +(global-set-key + (kbd "C-c a e o") + (lambda () + (interactive) + (let* ((auth (auth-source-search :host "znca")) + (p (if (null auth) + (error "Couldn't find znca's authinfo") + (funcall (plist-get (car auth) :secret))))) + (erc-tls :server "znc.emacsconf.org" :port 6697 + :password (concat "bandali/oftc:" p))))) +(global-set-key + (kbd "C-c a e t") + (lambda () + (interactive) + (let* ((auth (auth-source-search :host "znca")) + (p (if (null auth) + (error "Couldn't find znca's authinfo") + (funcall (plist-get (car auth) :secret))))) + (erc-tls :server "znc.emacsconf.org" :port 6697 + :password (concat "bandali/tildechat:" p))))) + +(provide 'bandali-erc) +;;; bandali-erc.el ends here diff --git a/.emacs.d/lisp/bandali-eshell.el b/.emacs.d/lisp/bandali-eshell.el new file mode 100644 index 0000000..820dc05 --- /dev/null +++ b/.emacs.d/lisp/bandali-eshell.el @@ -0,0 +1,86 @@ +;;; bandali-eshell.el --- bandali's Eshell setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: processes + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My awesome Eshell setup. + +;;; Code: + +(with-eval-after-load 'eshell + (make-directory (b/etc "eshell/") t) + (csetq + eshell-aliases-file (b/etc "eshell/aliases") + eshell-directory-name (b/var "eshell/") + eshell-hist-ignoredups t + eshell-input-filter #'eshell-input-filter-initial-space + eshell-prompt-regexp "\\(.*\n\\)*[$#] " + eshell-prompt-function + (lambda () + (concat + (propertize (format "%s@%s:" (user-login-name) (system-name)) + 'face 'default) + (propertize (abbreviate-file-name default-directory) + 'face 'font-lock-comment-face) + (propertize "\n" 'face 'default) + (if (= (user-uid) 0) + (propertize "#" 'face 'red) + (propertize "$" 'face 'default)) + (propertize " " 'face 'default)))) + (eval-when-compile + (defvar eshell-prompt-regexp) + (declare-function eshell-life-is-too-much "esh-mode") + (declare-function eshell-send-input "esh-mode" + (&optional use-region queue-p no-newline))) + (defun b/eshell-quit-or-delete-char (arg) + (interactive "p") + (if (and (eolp) (looking-back eshell-prompt-regexp nil)) + (eshell-life-is-too-much) + (delete-char arg))) + (defun b/eshell-clear () + (interactive) + (let ((inhibit-read-only t)) + (erase-buffer)) + (eshell-send-input)) + (defun b/eshell-setup () + (make-local-variable 'company-idle-delay) + (defvar company-idle-delay) + (eval-when-compile + (defvar eshell-mode-map) + (defvar eshell-hist-mode-map)) + (setq company-idle-delay nil) + ;; local key bindings + (define-key eshell-mode-map (kbd "C-d") + #'b/eshell-quit-or-delete-char) + (define-key eshell-mode-map (kbd "C-S-l") + #'b/eshell-clear) + (define-key eshell-mode-map (kbd "M-r") + #'counsel-esh-history) + ;; (define-key eshell-mode-map [tab] + ;; #'company-complete) + (define-key eshell-hist-mode-map (kbd "M-r") + #'counsel-esh-history))) +;; global key bindings +(global-set-key (kbd "C-c a s e") #'eshell) +;; hooks +(add-hook 'eshell-mode-hook #'b/eshell-setup) + +(provide 'bandali-eshell) +;;; bandali-eshell.el ends here diff --git a/.emacs.d/lisp/bandali-exwm.el b/.emacs.d/lisp/bandali-exwm.el new file mode 100644 index 0000000..6b57898 --- /dev/null +++ b/.emacs.d/lisp/bandali-exwm.el @@ -0,0 +1,239 @@ +;;; bandali-exwm.el --- bandali's EXWM configuration -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My EXWM setup. Makes good use of its simulation keys. + +;;; Code: + +(use-package exwm + :if b/exwm-p + :demand + :config + ;; make class name the buffer name, truncating beyond 60 characters + (defun b/exwm-rename-buffer () + (interactive) + (exwm-workspace-rename-buffer + (concat exwm-class-name ":" + (if (<= (length exwm-title) 60) exwm-title + (concat (substring exwm-title 0 59) "..."))))) + ;; Enable EXWM + (exwm-enable) + :hook ((exwm-update-class . b/exwm-rename-buffer) + (exwm-update-title . b/exwm-rename-buffer))) + +(use-package exwm-config + :demand + :after exwm + :hook (exwm-init . exwm-config--fix/ido-buffer-window-other-frame)) + +(use-package exwm-input + :demand + :after exwm + :config + (defun b/exwm-ws-prev-index () + "Return the index for the previous EXWM workspace, wrapping +around if needed." + (if (= exwm-workspace-current-index 0) + (1- exwm-workspace-number) + (1- exwm-workspace-current-index))) + + (defun b/exwm-ws-next-index () + "Return the index for the next EXWM workspace, wrapping +around if needed." + (if (= exwm-workspace-current-index + (1- exwm-workspace-number)) + 0 + (1+ exwm-workspace-current-index))) + + ;; shorten 'C-c C-q' to 'C-q' + (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key) + + (setq exwm-workspace-number 4 + exwm-input-global-keys + `(([?\s-R] . exwm-reset) + ([?\s-\\] . exwm-workspace-switch) + ([?\s-\s] . dmenu) + ([?\S-\s-\s] . (lambda (command) + (interactive + (list (read-shell-command "➜ "))) + (start-process-shell-command + command nil command))) + ([s-return] . (lambda () + (interactive) + (start-process "" nil "urxvt"))) + ([?\C-\s-\s] . counsel-linux-app) + ([?\M-\s-\s] . (lambda () + (interactive) + (start-process-shell-command + "rofi-pass" nil "rofi-pass"))) + ([?\s-h] . windmove-left) + ([?\s-j] . windmove-down) + ([?\s-k] . windmove-up) + ([?\s-l] . windmove-right) + ([?\s-H] . windmove-swap-states-left) + ([?\s-J] . windmove-swap-states-down) + ([?\s-K] . windmove-swap-states-up) + ([?\s-L] . windmove-swap-states-right) + ([?\M-\s-h] . shrink-window-horizontally) + ([?\M-\s-l] . enlarge-window-horizontally) + ([?\M-\s-k] . shrink-window) + ([?\M-\s-j] . enlarge-window) + ([?\s-\[] . (lambda () + (interactive) + (exwm-workspace-switch-create + (b/exwm-ws-prev-index)))) + ([?\s-\]] . (lambda () + (interactive) + (exwm-workspace-switch-create + (b/exwm-ws-next-index)))) + ([?\s-{] . (lambda () + (interactive) + (exwm-workspace-move-window + (b/exwm-ws-prev-index)))) + ([?\s-}] . (lambda () + (interactive) + (exwm-workspace-move-window + (b/exwm-ws-next-index)))) + ,@(mapcar (lambda (i) + `(,(kbd (format "s-%d" i)) . + (lambda () + (interactive) + (exwm-workspace-switch-create ,i)))) + (number-sequence 0 (1- exwm-workspace-number))) + ([?\s-t] . exwm-floating-toggle-floating) + ([?\s-f] . exwm-layout-toggle-fullscreen) + ([?\s-W] . (lambda () + (interactive) + (kill-buffer (current-buffer)))) + ([?\s-Q] . (lambda () + (interactive) + (exwm-manage--kill-client))) + ([?\s-\'] . (lambda () + (interactive) + (start-process-shell-command + "rofi-light" nil "rofi-light"))) + ([XF86AudioMute] . + (lambda () + (interactive) + (start-process "" nil "amixer" "set" "'Master',0" "toggle"))) + ([XF86AudioLowerVolume] . + (lambda () + (interactive) + (start-process + "" nil "amixer" "set" "'Master',0" "5%-"))) + ([XF86AudioRaiseVolume] . + (lambda () + (interactive) + (start-process + "" nil "amixer" "set" "'Master',0" "5%+"))) + ([XF86AudioPlay] . + (lambda () + (interactive) + (start-process "" nil "mpc" "toggle"))) + ([XF86AudioPrev] . + (lambda () + (interactive) + (start-process "" nil "mpc" "prev"))) + ([XF86AudioNext] . + (lambda () + (interactive) + (start-process "" nil "mpc" "next"))) + ([XF86ScreenSaver] . + (lambda () + (interactive) + (start-process "" nil "dm-tool" "lock"))) + ([\s-XF86Back] . previous-buffer) + ([\s-XF86Forward] . next-buffer))) + + ;; Line-editing shortcuts + (setq exwm-input-simulation-keys + '(;; movement + ([?\C-b] . [left]) + ([?\M-b] . [C-left]) + ([?\C-f] . [right]) + ([?\M-f] . [C-right]) + ([?\C-p] . [up]) + ([?\C-n] . [down]) + ([?\C-a] . [home]) + ([?\C-e] . [end]) + ([?\M-v] . [prior]) + ([?\C-v] . [next]) + ([?\C-d] . [delete]) + ([?\C-k] . [S-end ?\C-x]) + ([?\M-<] . C-home) + ([?\M->] . C-end) + ;; cut/copy/paste + ([?\C-w] . [?\C-x]) + ([?\M-w] . [?\C-c]) + ([?\C-y] . [?\C-v]) + ([?\M-d] . [C-S-right ?\C-x]) + ([?\M-\d] . [C-S-left ?\C-x]) + ;; window + ([?\s-w] . [?\C-w]) + ([?\s-q] . [?\C-q]) + ;; misc + ([?\C-s] . [?\C-f]) + ([?\s-s] . [?\C-s]) + ([?\C-g] . [escape])))) + +(use-package exwm-manage + :demand + :after exwm + :hook + (exwm-manage-finish . (lambda () + (when exwm-class-name + (cond + ((string= exwm-class-name "IceCat") + (exwm-input-set-local-simulation-keys + `(,@exwm-input-simulation-keys + ([?\C-\S-d] . [?\C-d])))) + ((string= exwm-class-name "URxvt") + (exwm-input-set-local-simulation-keys + '(([?\C-c ?\C-c] . [?\C-c]) + ([?\C-c ?\C-u] . [?\C-u])))) + ((string= exwm-class-name "Zathura") + (exwm-input-set-local-simulation-keys + '(([?\C-p] . [C-up]) + ([?\C-n] . [C-down]))))))))) + +(use-package exwm-randr + :demand + :after exwm + :config + (exwm-randr-enable) + :custom + (exwm-randr-workspace-monitor-plist '(1 "VGA-1"))) + +(use-package exwm-systemtray + :demand + :after exwm + :config + (exwm-systemtray-enable)) + +(use-package exwm-workspace) + +(use-package exwm-edit + :demand + :after exwm) + +(provide 'bandali-exwm) +;;; bandali-exwm.el ends here diff --git a/.emacs.d/lisp/bandali-gnus.el b/.emacs.d/lisp/bandali-gnus.el new file mode 100644 index 0000000..1958793 --- /dev/null +++ b/.emacs.d/lisp/bandali-gnus.el @@ -0,0 +1,478 @@ +;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: mail, news + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My trusty super awesome Gnus setup. + +;;; Code: + +(defvar b/maildir (expand-file-name "~/mail/")) +(with-eval-after-load 'recentf + (add-to-list 'recentf-exclude b/maildir)) + +(defvar b/gnus-init-file (b/etc "gnus")) + +(eval-when-compile + (progn + (defvar nndraft-directory) + (defvar gnus-read-newsrc-file) + (defvar gnus-save-newsrc-file) + (defvar gnus-gcc-mark-as-read) + (defvar nnmail-split-abbrev-alist))) + +(declare-function article-make-date-line "gnus-art" (date type)) + +(csetq + mail-user-agent 'gnus-user-agent + read-mail-command 'gnus + + gnus-select-method '(nnnil "") + gnus-secondary-select-methods + '((nnimap "shemshak" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "bandali@shemshak.local")) + (nnimap "gnu" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "bandali@gnu.local") + (nnimap-inbox "INBOX") + (nnimap-split-methods 'nnimap-split-fancy) + (nnimap-split-fancy (| + ;; (: gnus-registry-split-fancy-with-parent) + ;; (: gnus-group-split-fancy "INBOX" t "INBOX") + ;; keep debbugs emails in INBOX + (list ".*<\\(.*\\)\\.debbugs\\.gnu\\.org>.*" "INBOX") + ;; gnu + (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1") + ;; gnus + (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1") + ;; libreplanet + (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1") + ;; iana (e.g. tz-announce) + (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1") + ;; orbitalfox (e.g. gemini) + (list ".*<\\(.*\\)\\.lists\\.orbitalfox\\.eu>.*" "l.\\1") + ;; *.lists.sr.ht, omitting one dot if present + ;; add more \\.?\\([^.]*\\) if needed + (list ".*<~\\(.*\\)/\\([^.]*\\)\\.?\\([^.]*\\)\\.lists\\.sr\\.ht>.*" "l.~\\1.\\2\\3") + ;; webmasters + (from "webmasters\\(-comment\\)?@gnu\\.org" "webmasters") + ;; other + (list ".*atreus.freelists.org" "l.atreus") + (list ".*deepspec.lists.cs.princeton.edu" "l.deepspec") + ;; (list ".*haskell-art.we.lurk.org" "l.haskell.art") ;d + (list ".*haskell-cafe.haskell.org" "l.haskell-cafe") + ;; (list ".*notmuch.notmuchmail.org" "l.notmuch") ;u + (list ".*dev.lists.parabola.nu" "l.parabola-dev") + ;; ---------------------------------- + ;; legend: (u)nsubscribed | (d)ead + ;; ---------------------------------- + ;; spam + ("X-Spam_action" "reject" "Junk") + ;; otherwise, leave mail in INBOX + "INBOX"))) + (nnimap "uwaterloo" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "abandali@uwaterloo.local") + (nnimap-inbox "INBOX") + (nnimap-split-methods 'nnimap-split-fancy) + (nnimap-split-fancy (| + ;; (: gnus-registry-split-fancy-with-parent) + ;; se212-f19 + ("subject" "SE\\s-?212" "course.se212-f19") + (from "SE\\s-?212" "course.se212-f19") + ;; catch-all + "INBOX"))) + (nnimap "csc" + (nnimap-stream plain) + (nnimap-address "127.0.0.1") + (nnimap-server-port 143) + (nnimap-authenticator plain) + (nnimap-user "abandali@csclub.uwaterloo.local") + (nnimap-inbox "INBOX") + (nnimap-split-methods 'nnimap-split-fancy) + (nnimap-split-fancy (| + ;; cron reports and other messages from root + (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX") + ;; spam + ("X-Spam-Flag" "YES" "Junk") + ;; catch-all + "INBOX"))) + (nnimap "sfl" + (nnimap-stream tls) + (nnimap-address "mail.savoirfairelinux.com") + (nnimap-user "amin.bandali"))) + gnus-message-archive-group "nnimap+gnu:INBOX" + gnus-parameters + '(("l\\.atreus" + (to-address . "atreus@freelists.org") + (to-list . "atreus@freelists.org")) + ("l\\.deepspec" + (to-address . "deepspec@lists.cs.princeton.edu") + (to-list . "deepspec@lists.cs.princeton.edu") + (list-identifier . "\\[deepspec\\]")) + ("l\\.emacs-devel" + (to-address . "emacs-devel@gnu.org") + (to-list . "emacs-devel@gnu.org")) + ("l\\.help-gnu-emacs" + (to-address . "help-gnu-emacs@gnu.org") + (to-list . "help-gnu-emacs@gnu.org")) + ("l\\.info-gnu-emacs" + (to-address . "info-gnu-emacs@gnu.org") + (to-list . "info-gnu-emacs@gnu.org")) + ("l\\.emacs-orgmode" + (to-address . "emacs-orgmode@gnu.org") + (to-list . "emacs-orgmode@gnu.org") + (list-identifier . "\\[O\\]")) + ("l\\.emacs-tangents" + (to-address . "emacs-tangents@gnu.org") + (to-list . "emacs-tangents@gnu.org")) + ("l\\.emacsconf-committee" + (to-address . "emacsconf-committee@gnu.org") + (to-list . "emacsconf-committee@gnu.org")) + ("l\\.emacsconf-discuss" + (to-address . "emacsconf-discuss@gnu.org") + (to-list . "emacsconf-discuss@gnu.org")) + ("l\\.emacsconf-org" + (to-address . "emacsconf-org@gnu.org") + (to-list . "emacsconf-org@gnu.org")) + ("l\\.emacsconf-org-private" + (to-address . "emacsconf-org-private@gnu.org") + (to-list . "emacsconf-org-private@gnu.org")) + ("l\\.emacsconf-register" + (to-address . "emacsconf-register@gnu.org") + (to-list . "emacsconf-register@gnu.org")) + ("l\\.emacsconf-submit" + (to-address . "emacsconf-submit@gnu.org") + (to-list . "emacsconf-submit@gnu.org")) + ("l\\.fencepost-users" + (to-address . "fencepost-users@gnu.org") + (to-list . "fencepost-users@gnu.org") + (list-identifier . "\\[Fencepost-users\\]")) + ("l\\.gnewsense-art" + (to-address . "gnewsense-art@nongnu.org") + (to-list . "gnewsense-art@nongnu.org") + (list-identifier . "\\[gNewSense-art\\]")) + ("l\\.gnewsense-dev" + (to-address . "gnewsense-dev@nongnu.org") + (to-list . "gnewsense-dev@nongnu.org") + (list-identifier . "\\[Gnewsense-dev\\]")) + ("l\\.gnewsense-users" + (to-address . "gnewsense-users@nongnu.org") + (to-list . "gnewsense-users@nongnu.org") + (list-identifier . "\\[gNewSense-users\\]")) + ("l\\.gnunet-developers" + (to-address . "gnunet-developers@gnu.org") + (to-list . "gnunet-developers@gnu.org") + (list-identifier . "\\[GNUnet-developers\\]")) + ("l\\.help-gnunet" + (to-address . "help-gnunet@gnu.org") + (to-list . "help-gnunet@gnu.org") + (list-identifier . "\\[Help-gnunet\\]")) + ("l\\.bug-gnuzilla" + (to-address . "bug-gnuzilla@gnu.org") + (to-list . "bug-gnuzilla@gnu.org") + (list-identifier . "\\[Bug-gnuzilla\\]")) + ("l\\.gnuzilla-dev" + (to-address . "gnuzilla-dev@gnu.org") + (to-list . "gnuzilla-dev@gnu.org") + (list-identifier . "\\[Gnuzilla-dev\\]")) + ("l\\.guile-devel" + (to-address . "guile-devel@gnu.org") + (to-list . "guile-devel@gnu.org")) + ("l\\.guile-user" + (to-address . "guile-user@gnu.org") + (to-list . "guile-user@gnu.org")) + ("l\\.guix-devel" + (to-address . "guix-devel@gnu.org") + (to-list . "guix-devel@gnu.org")) + ("l\\.help-guix" + (to-address . "help-guix@gnu.org") + (to-list . "help-guix@gnu.org")) + ("l\\.info-guix" + (to-address . "info-guix@gnu.org") + (to-list . "info-guix@gnu.org")) + ("l\\.savannah-hackers-public" + (to-address . "savannah-hackers-public@gnu.org") + (to-list . "savannah-hackers-public@gnu.org")) + ("l\\.savannah-users" + (to-address . "savannah-users@gnu.org") + (to-list . "savannah-users@gnu.org")) + ("l\\.www-commits" + (to-address . "www-commits@gnu.org") + (to-list . "www-commits@gnu.org")) + ("l\\.www-discuss" + (to-address . "www-discuss@gnu.org") + (to-list . "www-discuss@gnu.org")) + ("l\\.haskell-art" + (to-address . "haskell-art@we.lurk.org") + (to-list . "haskell-art@we.lurk.org") + (list-identifier . "\\[haskell-art\\]")) + ("l\\.haskell-cafe" + (to-address . "haskell-cafe@haskell.org") + (to-list . "haskell-cafe@haskell.org") + (list-identifier . "\\[Haskell-cafe\\]")) + ("l\\.notmuch" + (to-address . "notmuch@notmuchmail.org") + (to-list . "notmuch@notmuchmail.org")) + ("l\\.parabola-dev" + (to-address . "dev@lists.parabola.nu") + (to-list . "dev@lists.parabola.nu") + (list-identifier . "\\[Dev\\]")) + ("l\\.~bandali\\.public-inbox" + (to-address . "~bandali/public-inbox@lists.sr.ht") + (to-list . "~bandali/public-inbox@lists.sr.ht")) + ("l\\.~sircmpwn\\.free-writers-club" + (to-address . "~sircmpwn/free-writers-club@lists.sr.ht") + (to-list . "~sircmpwn/free-writers-club@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-admins" + (to-address . "~sircmpwn/sr.ht-admins@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-admins@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-announce" + (to-address . "~sircmpwn/sr.ht-announce@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-announce@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-dev" + (to-address . "~sircmpwn/sr.ht-dev@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-dev@lists.sr.ht")) + ("l\\.~sircmpwn\\.srht-discuss" + (to-address . "~sircmpwn/sr.ht-discuss@lists.sr.ht") + (to-list . "~sircmpwn/sr.ht-discuss@lists.sr.ht")) + ("webmasters" + (to-address . "webmasters@gnu.org") + (to-list . "webmasters@gnu.org")) + ("gnu.*" + (gcc-self . t)) + ("l\\." + (subscribed . t)) + ("nnimap\\+uwaterloo:.*" + (gcc-self . t))) + ;; nnimap-record-commands t + gnus-large-newsgroup 50 + gnus-home-directory (b/var "gnus/") + gnus-directory (concat gnus-home-directory "news/") + message-directory (concat gnus-home-directory "mail/") + nndraft-directory (concat gnus-home-directory "drafts/") + gnus-save-newsrc-file nil + gnus-read-newsrc-file nil + gnus-interactive-exit nil + gnus-gcc-mark-as-read t) + +(with-eval-after-load 'gnus + (when (version< emacs-version "27") + (with-eval-after-load 'nnmail + (add-to-list + 'nnmail-split-abbrev-alist + '(list . "list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop") + t))) + + ;; (require 'gnus-registry) + ;; (setq gnus-registry-max-entries 2500) + ;; (setq gnus-registry-ignored-groups + ;; (append gnus-registry-ignored-groups + ;; '(("^nnimap:gnu\\.l" t) + ;; ("webmasters$" t)))) + ;; (gnus-registry-initialize) + + (with-eval-after-load 'recentf + (add-to-list 'recentf-exclude gnus-home-directory)) + + ;; hooks + (add-hook 'gnus-group-mode-hook #'gnus-topic-mode) + (add-hook 'gnus-group-mode-hook #'gnus-agent-mode)) +;; global key bindings +(global-set-key (kbd "s-m") #'gnus-plugged) +(global-set-key (kbd "s-M") #'gnus-unplugged) +(global-set-key (kbd "C-c a m") #'gnus-plugged) +(global-set-key (kbd "C-c a M") #'gnus-unplugged) + +(with-eval-after-load 'gnus-art + (csetq + gnus-buttonized-mime-types '("multipart/\\(signed\\|encrypted\\)") + gnus-sorted-header-list '("^From:" + "^X-RT-Originator" + "^Newsgroups:" + "^Subject:" + "^Date:" + "^Envelope-To:" + "^Followup-To:" + "^Reply-To:" + "^Organization:" + "^Summary:" + "^Abstract:" + "^Keywords:" + "^To:" + "^[BGF]?Cc:" + "^Posted-To:" + "^Mail-Copies-To:" + "^Mail-Followup-To:" + "^Apparently-To:" + "^Resent-From:" + "^User-Agent:" + "^X-detected-operating-system:" + "^X-Spam_action:" + "^X-Spam_bar:" + "^Message-ID:" + ;; "^References:" + "^List-Id:" + "^Gnus-Warning:") + gnus-visible-headers (mapconcat 'identity + gnus-sorted-header-list + "\\|") + ;; local-lapsed article dates + ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11 + gnus-article-date-headers '(user-defined) + gnus-article-time-format + (lambda (time) + (let* ((date (format-time-string "%a, %d %b %Y %T %z" time)) + (local (article-make-date-line date 'local)) + (combined-lapsed (article-make-date-line date + 'combined-lapsed)) + (lapsed (progn + (string-match " (.+" combined-lapsed) + (match-string 0 combined-lapsed)))) + (concat local lapsed)))) + ;; local key bindings + (define-key gnus-article-mode-map (kbd "M-L") #'org-store-link)) + +(with-eval-after-load 'gnus-sum + (csetq gnus-thread-sort-functions '(gnus-thread-sort-by-number + gnus-thread-sort-by-subject + gnus-thread-sort-by-date)) + ;; local key bindings + (define-key gnus-summary-mode-map (kbd "M-L") #'org-store-link) + (defvar b/gnus-summary-prefix-map) + (define-prefix-command 'b/gnus-summary-prefix-map) + (define-key gnus-summary-mode-map (kbd "v") + 'b/gnus-summary-prefix-map) + (define-key b/gnus-summary-prefix-map (kbd "r") + #'gnus-summary-reply) + (define-key b/gnus-summary-prefix-map (kbd "w") + #'gnus-summary-wide-reply) + (define-key b/gnus-summary-prefix-map (kbd "v") + #'gnus-summary-show-raw-article)) +;; hooks +(add-hook 'gnus-summary-mode-hook #'b/no-mouse-autoselect-window) + +(defvar b/sfl-p nil) +(with-eval-after-load 'gnus-msg + (defvar b/shemshak-signature "Amin Bandali +https://shemshak.org/~bandali") + (defvar b/uwaterloo-signature "Amin Bandali, MMath +https://bndl.org") + (defvar b/csc-signature "Amin Bandali (https://bndl.org) +Systems Committee <syscom@csclub.uwaterloo.ca> +Computer Science Club of the University of Waterloo") + (defvar b/sfl-signature "Amin Bandali +Free Software Consultant +Savoir-faire Linux +GNU Jami: bandali") + (csetq + gnus-message-replysign t + gnus-posting-styles + '((".*" + (address "bandali@gnu.org")) + ("nnimap\\+gnu:l\\..*" + (signature nil)) + ("nnimap\\+gnu:.*" + (organization "GNU")) + ((header "subject" "ThankCRM") + (to "webmasters-comment@gnu.org") + (body "") + (eval (setq b/message-cite-say-hi nil))) + ("nnimap\\+shemshak:.*" + (address "amin@shemshak.org") + (body "\nBest,\n") + (signature b/shemshak-signature) + (gcc "nnimap+shemshak:Sent") + (eval (setq b/message-cite-say-hi t))) + ("nnimap\\+uwaterloo:.*" + (address "bandali@uwaterloo.ca") + (body "\nBest,\n") + (signature b/uwaterloo-signature)) + ("nnimap\\+uwaterloo:INBOX" + (gcc "\"nnimap+uwaterloo:Sent Items\"")) + ("nnimap\\+csc:.*" + (address "bandali@csclub.uwaterloo.ca") + (signature b/csc-signature) + (gcc "nnimap+csc:Sent")) + ("nnimap\\+sfl:.*" + (address "amin.bandali@savoirfairelinux.com") + (signature b/sfl-signature) + (gcc "nnimap+sfl:Sent") + (eval (setq-local b/sfl-p t)))))) +;; hooks +(with-eval-after-load 'gnus + (add-hook 'gnus-message-setup-hook + (lambda () + (unless (or (mml-secure-is-encrypted-p) + b/sfl-p) + (mml-secure-message-sign))))) + +(with-eval-after-load 'gnus-topic + (csetq gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n")) + +(with-eval-after-load 'gnus-agent + (csetq gnus-agent-synchronize-flags 'ask)) + +(with-eval-after-load 'gnus-group + (csetq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)")) + +;; problematic with ebdb's popup, *EBDB-Gnus* +;; (with-eval-after-load 'gnus-win +;; (csetq gnus-use-full-window nil)) + +(with-eval-after-load 'gnus-dired + (add-hook 'dired-mode-hook 'gnus-dired-mode)) + +;; (with-eval-after-load 'gnus-utils +;; (csetq gnus-completing-read-function 'gnus-ido-completing-read)) + +(with-eval-after-load 'mm-decode + (csetq mm-discouraged-alternatives '("text/html" "text/richtext") + mm-decrypt-option 'known + mm-verify-option 'known)) + +(with-eval-after-load 'mm-uu + (when (version< "27" emacs-version) + (set-face-attribute 'mm-uu-extract nil :extend t)) + (when (version< emacs-version "27") + (csetq mm-uu-diff-groups-regexp "."))) + +(with-eval-after-load 'mml-sec + (csetq mml-secure-openpgp-encrypt-to-self t + mml-secure-openpgp-sign-with-sender t)) + +;; (require 'gnus-article-treat-patch) +;; ;; note: be sure to customize faces with `:foreground "white"' when +;; ;; using a theme with a white/light background :) +;; (setq ft/gnus-article-patch-conditions +;; '("^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@")) + +(provide 'bandali-gnus) +;;; bandali-gnus.el ends here diff --git a/.emacs.d/lisp/bandali-ibuffer.el b/.emacs.d/lisp/bandali-ibuffer.el new file mode 100644 index 0000000..7cd4331 --- /dev/null +++ b/.emacs.d/lisp/bandali-ibuffer.el @@ -0,0 +1,110 @@ +;;; bandali-ibuffer.el --- bandali's Ibuffer setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: tools + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My Ibuffer setup. + +;;; Code: + +(csetq + ibuffer-saved-filter-groups + '(("default" + ("dired" (mode . dired-mode)) + ("org" (mode . org-mode)) + ("gnus" + (or + (mode . gnus-group-mode) + (mode . gnus-summary-mode) + (mode . gnus-article-mode) + (mode . message-mode))) + ("web" + (or + (mode . mhtml-mode) + (mode . css-mode) + (mode . scss-mode) + (mode . js2-mode))) + ("shell" + (or + (mode . eshell-mode) + (mode . shell-mode) + (mode . term-mode))) + ("programming" + (or + (mode . python-mode) + (mode . c-mode) + (mode . c++-mode) + (mode . java-mode) + (mode . emacs-lisp-mode) + (mode . scheme-mode) + (mode . haskell-mode) + (mode . lean-mode) + ;; (mode . go-mode) + (mode . alloy-mode))) + ("tex" + (or + (mode . bibtex-mode) + (mode . latex-mode))) + ("emacs" + (or + (name . "^\\*scratch\\*$") + (name . "^\\*Messages\\*$"))) + ("exwm" (mode . exwm-mode)) + ("erc" (mode . erc-mode)))) + ibuffer-formats + '((mark modified read-only locked " " + (name 72 72 :left :elide) + " " + (size-h 9 -1 :right) + " " + (mode 16 16 :left :elide) + " " filename-and-process) + (mark " " + (name 16 -1) + " " filename))) +(with-eval-after-load 'ibuffer + ;; Use human readable Size column instead of original one + (define-ibuffer-column size-h + (:name "Size" :inline t) + (cond + ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0))) + ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0))) + ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0))) + (t (format "%8d" (buffer-size))))) + + ;; local key bindings + (define-key ibuffer-mode-map (kbd "P") + #'ibuffer-backward-filter-group) + (define-key ibuffer-mode-map (kbd "N") + #'ibuffer-forward-filter-group) + (define-key ibuffer-mode-map (kbd "M-p") + #'ibuffer-do-print) + (define-key ibuffer-mode-map (kbd "M-n") + #'ibuffer-do-shell-command-pipe-replace)) +;; global key bindings +(global-set-key (kbd "C-x C-b") #'ibuffer) +;; hooks +(declare-function ibuffer-switch-to-saved-filter-groups "ibuf-ext" + (name)) +(add-hook 'ibuffer-hook + (lambda () (ibuffer-switch-to-saved-filter-groups "default"))) + +(provide 'bandali-ibuffer) +;;; bandali-ibuffer.el ends here diff --git a/.emacs.d/lisp/bandali-ivy.el b/.emacs.d/lisp/bandali-ivy.el new file mode 100644 index 0000000..973323a --- /dev/null +++ b/.emacs.d/lisp/bandali-ivy.el @@ -0,0 +1,74 @@ +;;; bandali-ivy.el --- bandali's Ivy setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: matching + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My configuration for Ivy and family. + +;;; Code: + +(run-with-idle-timer 0.3 nil #'require 'ivy) +(with-eval-after-load 'ivy + ;; ivy + (csetq ivy-wrap t + ;; ivy-height 14 + ivy-use-virtual-buffers t + ivy-virtual-abbreviate 'abbreviate + ivy-count-format "%d/%d ") + + (defvar b/ivy-ignore-buffer-modes + '(;; dired-mode + ;; magit-mode + erc-mode)) + (defun b/ivy-ignore-buffer-p (str) + "Return non-nil if str names a buffer with a major mode +derived from one of `b/ivy-ignore-buffer-modes'. + +This function is intended for use with `ivy-ignore-buffers'." + (let* ((buf (get-buffer str)) + (mode (and buf (buffer-local-value 'major-mode buf)))) + (and mode + (apply #'provided-mode-derived-p mode b/ivy-ignore-buffer-modes)))) + (add-to-list 'ivy-ignore-buffers #'b/ivy-ignore-buffer-p) + + (define-key ivy-minibuffer-map [escape] #'keyboard-escape-quit) + (define-key ivy-minibuffer-map [S-up] + #'ivy-previous-history-element) + (define-key ivy-minibuffer-map [S-down] + #'ivy-next-history-element) + (define-key ivy-minibuffer-map (kbd "DEL") + #'ivy-backward-delete-char) + + (ivy-mode 1) + + ;; swiper + (require 'swiper) + (global-set-key (kbd "C-S-s") #'swiper-isearch) + + ;; counsel + (require 'counsel) + (counsel-mode 1) + (defalias 'locate #'counsel-locate) + (global-set-key (kbd "C-c f r") #'counsel-recentf) + (define-key minibuffer-local-map + (kbd "C-r") #'counsel-minibuffer-history)) + +(provide 'bandali-ivy) +;;; bandali-ivy.el ends here diff --git a/.emacs.d/lisp/bandali-magit.el b/.emacs.d/lisp/bandali-magit.el new file mode 100644 index 0000000..7432a11 --- /dev/null +++ b/.emacs.d/lisp/bandali-magit.el @@ -0,0 +1,70 @@ +;;; bandali-magit.el --- bandali's magit configuration -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: vc + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; It's Magit! + +;;; Code: + +(csetq transient-history-file (b/var "transient/history.el") + transient-levels-file (b/etc "transient/levels.el") + transient-values-file (b/etc "transient/values.el")) +(with-eval-after-load 'magit + (declare-function magit-add-section-hook "magit-section" + (hook function &optional at append local)) + (magit-add-section-hook 'magit-status-sections-hook + 'magit-insert-modules + 'magit-insert-stashes + 'append) + ;; (magit-add-section-hook 'magit-status-sections-hook + ;; 'magit-insert-ignored-files + ;; 'magit-insert-untracked-files + ;; 'append) + (declare-function magit-display-buffer-fullframe-status-v1 + "magit-mode" (buffer)) + (csetq + magit-diff-refine-hunk t + magit-repository-directories '(("~/.emacs.d/" . 0) + ("~/src/git/" . 2)) + ;; magit-completing-read-function 'magit-ido-completing-read + magit-display-buffer-function + #'magit-display-buffer-fullframe-status-v1) + (nconc magit-section-initial-visibility-alist + '(([unpulled status] . show) + ([unpushed status] . show))) + (custom-set-faces '(magit-diff-file-heading ((t (:weight normal))))) + + (with-eval-after-load 'magit-extras + (csetq + magit-pop-revision-stack-format + (pcase-let ((`(,pt ,_eob ,index-regexp) + (default-value 'magit-pop-revision-stack-format))) + `(,pt "[%N: %h]: %ci\n %s + https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=%H" + ,index-regexp))))) +;; global key bindings +(global-set-key (kbd "C-x g") #'magit-status) +(global-set-key (kbd "C-c g b") #'magit-blame-addition) +(global-set-key (kbd "C-c g l") #'magit-log-buffer-file) +(global-set-key (kbd "C-c g y") #'magit-pop-revision-stack) + +(provide 'bandali-magit) +;;; bandali-magit.el ends here diff --git a/.emacs.d/lisp/bandali-message.el b/.emacs.d/lisp/bandali-message.el new file mode 100644 index 0000000..c13bffc --- /dev/null +++ b/.emacs.d/lisp/bandali-message.el @@ -0,0 +1,138 @@ +;;; bandali-message.el --- bandali's message.el setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: mail, news + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My setup for message.el. + +;;; Code: + +(with-eval-after-load 'message + ;; :bind (:map message-mode-map ("<C-return>" . b/insert-asterism)) + ;; redefine for a simplified In-Reply-To header + ;; (see https://todo.sr.ht/~sircmpwn/lists.sr.ht/67) + (defun message-make-in-reply-to () + "Return the In-Reply-To header for this message." + (when message-reply-headers + (let ((from (mail-header-from message-reply-headers)) + (msg-id (mail-header-id message-reply-headers))) + (when from + msg-id)))) + + (defconst b/message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:") + (defconst message-cite-style-bandali + '((message-cite-function 'message-cite-original) + (message-citation-line-function 'message-insert-formatted-citation-line) + (message-cite-reply-position 'traditional) + (message-yank-prefix "> ") + (message-yank-cited-prefix ">") + (message-yank-empty-prefix ">") + (message-citation-line-format + (if b/message-cite-say-hi + (concat "Hi %F,\n\n" b/message-cite-style-format) + b/message-cite-style-format))) + "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.") + (csetq + message-elide-ellipsis "[...]\n" + ;; message-cite-style 'message-cite-style-bandali + message-citation-line-format "%N writes:\n" + message-citation-line-function 'message-insert-formatted-citation-line + message-kill-buffer-on-exit t + message-send-mail-function 'message-send-mail-with-sendmail + message-sendmail-envelope-from 'header + message-subscribed-address-functions + '(gnus-find-subscribed-addresses) + message-dont-reply-to-names + "\\(\\(amin@shemshak\\.org\\)\\|\\(.*@aminb\\.org\\)\\|\\(\\(bandali\\|mab\\|aminb?\\)@gnu\\.org\\)\\|bandali@fsf\\.org\\|\\(a?bandali@\\(csclub\\.\\)?uwaterloo\\.ca\\)\\|amin\\.bandali@savoirfairelinux\\.com\\)") + ;; (require 'company-ebdb) + ;; (custom-set-faces + ;; '(message-header-subject + ;; ((t (:foreground "#111" :weight semi-bold)))) + ;; '(message-header-to + ;; ((t (:foreground "#111" :weight normal)))) + ;; '(message-header-cc + ;; ((t (:foreground "#333" :weight normal)))) + + ;; footnote + (with-eval-after-load 'footnote + ;; (csetq footnote-start-tag "" + ;; footnote-end-tag "" + ;; footnote-style 'unicode) + (when (featurep 'which-key) + (which-key-add-major-mode-key-based-replacements 'message-mode + "C-c f n" "footnote"))) + + ;; orgalist + (add-hook 'message-mode-hook + (lambda () + ;; work around incompatibility between + ;; orgalist and yasnippet + (yas-minor-mode -1) + (orgalist-mode 1) + (yas-minor-mode 1))) + + ;; local key bindings + (defvar b/footnote-prefix-map) + (define-prefix-command 'b/footnote-prefix-map) + (define-key message-mode-map (kbd "C-c f n") + 'b/footnote-prefix-map) + (define-key b/footnote-prefix-map (kbd "a") + #'footnote-add-footnote) + (define-key b/footnote-prefix-map (kbd "b") + #'footnote-back-to-message) + (define-key b/footnote-prefix-map (kbd "c") + #'footnote-cycle-style) + (define-key b/footnote-prefix-map (kbd "d") + #'footnote-delete-footnote) + (define-key b/footnote-prefix-map (kbd "g") + #'footnote-goto-footnote) + (define-key b/footnote-prefix-map (kbd "r") + #'footnote-renumber-footnotes) + (define-key b/footnote-prefix-map (kbd "s") + #'footnote-set-style)) +;; hooks +;; (add-hook 'message-setup-hook #'mml-secure-message-sign-pgpmime) +(add-hook 'message-mode-hook #'flyspell-mode) +(add-hook 'message-mode-hook + (lambda () + ;; (setq-local fill-column b/fill-column + ;; message-fill-column b/fill-column) + (eval-when-compile (defvar company-idle-delay)) + (make-local-variable 'company-idle-delay) + (setq company-idle-delay 0.2))) + +;; (with-eval-after-load 'message-x +;; (csetq +;; message-x-completion-alist +;; '(("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" +;; . gnus-harvest-find-address) +;; ((if +;; (boundp +;; (quote message-newgroups-header-regexp)) +;; message-newgroups-header-regexp message-newsgroups-header-regexp) +;; . message-expand-group)))) + +;; (require 'gnus-harvest) +;; (if (featurep 'message-x) +;; (gnus-harvest-install 'message-x) +;; (gnus-harvest-install)) + +(provide 'bandali-message) +;;; bandali-message.el ends here diff --git a/.emacs.d/lisp/bandali-org.el b/.emacs.d/lisp/bandali-org.el new file mode 100644 index 0000000..38a4a5a --- /dev/null +++ b/.emacs.d/lisp/bandali-org.el @@ -0,0 +1,119 @@ +;;; bandali-org.el --- bandali's Org setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: calendar, data, docs, hypermedia, outlines + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My set up for Org (org-mode) and all things Org. + +;;; Code: + +(with-eval-after-load 'org + (csetq org-src-tab-acts-natively t + org-src-preserve-indentation nil + org-edit-src-content-indentation 0 + org-id-locations-file (b/var "org/id-locations.el") + org-link-email-description-format "Email %c: %s" ; %.30s + org-highlight-latex-and-related '(entities) + org-use-speed-commands t + org-startup-folded 'content + org-catch-invisible-edits 'show-and-error + org-log-done 'time + org-pretty-entities t + org-agenda-files '("~/usr/org/todos/personal.org" + "~/usr/org/todos/habits.org" + "~/src/git/masters-thesis/todo.org") + org-agenda-start-on-weekday 0 + org-agenda-time-leading-zero t + org-habit-graph-column 44 + org-latex-packages-alist '(("" "listings") ("" "color"))) + (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t) + (add-to-list 'org-modules 'org-habit) + (custom-set-faces + '(org-block-begin-line + ((t (:foreground "#5a5b5a" :background "#1d1f21")))) + '(org-block ((t (:background "#1d1f21")))) + '(org-latex-and-related ((t (:foreground "#b294bb"))))) + ;; local key bindings + (define-key org-mode-map (kbd "M-L") #'org-insert-last-stored-link) + (define-key org-mode-map (kbd "M-O") #'org-toggle-link-display) + ;; hooks + (add-hook 'org-mode-hook #'org-indent-mode) + (add-hook 'org-mode-hook #'auto-fill-mode) + (add-hook 'org-mode-hook #'flyspell-mode) + + ;; asynchronous tangle, using emacs-async to asynchronously tangle an + ;; org file. closely inspired by + ;; https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles + (defvar b/show-async-tangle-results nil + "Keep *emacs* async buffers around for later inspection.") + + (defvar b/show-async-tangle-time nil + "Show the time spent tangling the file.") + + (defun b/async-babel-tangle () + "Tangle org file asynchronously." + (interactive) + (let* ((file-tangle-start-time (current-time)) + (file (buffer-file-name)) + (file-nodir (file-name-nondirectory file)) + ;; (async-quiet-switch "-q") + ;; (file-noext (file-name-sans-extension file)) + ) + (async-start + `(lambda () + (require 'org) + (org-babel-tangle-file ,file)) + (unless b/show-async-tangle-results + `(lambda (result) + (if result + (message "Tangled %s%s" + ,file-nodir + (if b/show-async-tangle-time + (format " (%.3fs)" + (float-time (time-subtract (current-time) + ',file-tangle-start-time))) + "")) + (message "Tangling %s failed" ,file-nodir))))))) + (add-to-list + 'safe-local-variable-values + '(eval add-hook 'after-save-hook #'b/async-babel-tangle 'append 'local))) +;; global key bindings +(global-set-key (kbd "C-c a o a") #'org-agenda) + +(with-eval-after-load 'ox-latex + (csetq org-latex-listings 'listings + ;; org-latex-prefer-user-labels t + ) + (add-to-list 'org-latex-classes + '("IEEEtran" "\\documentclass[11pt]{IEEEtran}" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) + t) + (require 'ox-beamer)) + +(with-eval-after-load 'ox-extra + (declare-function ox-extras-activate "ox-extra" (extras)) + (ox-extras-activate '(latex-header-blocks ignore-headlines))) + +(provide 'bandali-org) +;;; bandali-org.el ends here diff --git a/.emacs.d/lisp/bandali-theme.el b/.emacs.d/lisp/bandali-theme.el new file mode 100644 index 0000000..13929cb --- /dev/null +++ b/.emacs.d/lisp/bandali-theme.el @@ -0,0 +1,87 @@ +;;; bandali-theme.el --- bandali's custom theme setup -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Amin Bandali + +;; Author: Amin Bandali <bandali@gnu.org> +;; Keywords: faces + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; My custom theme setup. + +;;; Code: + +(with-eval-after-load 'package + (require 'refinery-theme) + (load-theme 'refinery t)) + +;; (require 'smart-mode-line) +;; ;; thanks, but no thanks; don't make fixed-width fills. +;; (defun sml/fill-for-buffer-identification nil "") +;; (setq sml/theme 'respectful) +;; (let ((sml/no-confirm-load-theme t)) +;; (sml/setup) +;; (smart-mode-line-enable)) + +;; (require 'minions) +;; (minions-mode) + +(defvar b/org-mode-font-lock-keywords + '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)" + (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive + (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind + (4 '(:foreground "#c5c8c6") t))) ; title + "For use with the `doom-tomorrow-night' theme.") + +(eval-when-compile + (declare-function exwm-systemtray--refresh "exwm-systemtray") + (declare-function erc-hl-nicks-reset-face-table "erc-hl-nicks")) + +(defun b/lights-on () + "Enable my favourite light theme." + (interactive) + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'refinery t) + (when (featurep 'smart-mode-line) + (let ((sml/no-confirm-load-theme t)) + (sml/apply-theme 'respectful))) + (font-lock-remove-keywords + 'org-mode b/org-mode-font-lock-keywords) + (when (featurep 'erc-hl-nicks) + (erc-hl-nicks-reset-face-table)) + (when (featurep 'exwm-systemtray) + (exwm-systemtray--refresh))) + +(defun b/lights-off () + "Go dark." + (interactive) + (mapc #'disable-theme custom-enabled-themes) + (load-theme 'refinery-dark t) + (when (featurep 'smart-mode-line) + (let ((sml/no-confirm-load-theme t)) + (sml/apply-theme 'dark))) + (font-lock-add-keywords + 'org-mode b/org-mode-font-lock-keywords t) + (when (featurep 'erc-hl-nicks) + (erc-hl-nicks-reset-face-table)) + (when (featurep 'exwm-systemtray) + (exwm-systemtray--refresh))) + +(global-set-key (kbd "C-c t d") #'b/lights-off) +(global-set-key (kbd "C-c t l") #'b/lights-on) + +(provide 'bandali-theme) +;;; bandali-theme.el ends here diff --git a/.emacs.d/lisp/boxquote b/.emacs.d/lisp/boxquote new file mode 160000 +Subproject 7e47e0e2853bc1215739b2e28f260e9eed93b2c diff --git a/.emacs.d/lisp/gnus-article-treat-patch.el b/.emacs.d/lisp/gnus-article-treat-patch.el new file mode 100644 index 0000000..f2f5c21 --- /dev/null +++ b/.emacs.d/lisp/gnus-article-treat-patch.el @@ -0,0 +1,465 @@ +;;; gnus-article-treat-patch.el --- Highlight inline patches in articles +;; +;; Copyright © 2011-2019 Frank Terbeck <ft@bewatermyfriend.org> +;; +;; This file is not part of GNU Emacs. +;; +;; This file is free software; you can redistribute it and/or modify it under +;; the terms of the GNU General Public License as published by the Free Soft- +;; ware Foundation; either version 3, or (at your option) any later version. +;; +;; This file is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS FOR +;; A PARTICULAR PURPOSE. See the GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License along with +;; this file. If not, see <http://www.gnu.org/licenses/>. +;; +;; +;;; Commentary: +;; +;; Gnus addon to beautify patch-like emails. This uses a "ft/" prefix for +;; everything to avoid clashing with anything upstream. That prefix can be +;; savely s,ft/,,'d - if this is to be submitted to the gnus developers. + +(require 'diff-mode) + +(add-hook 'gnus-part-display-hook 'ft/gnus-article-treat-patch) + +;; Colour handling and faces +(defun ft/gnus-colour-line (use-face) + "Set text overlay to `use-face' for the current line." + (overlay-put (make-overlay (point-at-bol) (point-at-eol)) 'face use-face)) + +(make-face 'ft/gnus-three-dashes) +(set-face-attribute 'ft/gnus-three-dashes nil :foreground "brightblue") +(make-face 'ft/gnus-scissors) +(set-face-attribute 'ft/gnus-scissors nil :foreground "brown") +(make-face 'ft/gnus-diff-index) +(set-face-attribute 'ft/gnus-diff-index nil :foreground "brightmagenta") +(make-face 'ft/gnus-diff-hunk) +(set-face-attribute 'ft/gnus-diff-hunk nil :foreground "brightblue") +(make-face 'ft/gnus-diff-equals) +(set-face-attribute 'ft/gnus-diff-equals nil :foreground "brightmagenta") +(make-face 'ft/gnus-commit-message) +(set-face-attribute 'ft/gnus-commit-message nil :foreground "white") +(make-face 'ft/gnus-diff-stat-file) +(set-face-attribute 'ft/gnus-diff-stat-file nil :foreground "yellow") +(make-face 'ft/gnus-diff-stat-bar) +(set-face-attribute 'ft/gnus-diff-stat-bar nil :foreground "magenta") +(make-face 'ft/gnus-diff-stat-num) +(set-face-attribute 'ft/gnus-diff-stat-num nil :foreground "white") +(make-face 'ft/gnus-diff-misc) +(set-face-attribute 'ft/gnus-diff-misc nil :foreground "magenta") +(make-face 'ft/gnus-commit-comment) +(set-face-attribute 'ft/gnus-commit-comment nil :inherit 'default) +(make-face 'ft/gnus-diff-header) +(set-face-attribute 'ft/gnus-diff-header nil :inherit 'diff-header) +(make-face 'ft/gnus-diff-add) +(set-face-attribute 'ft/gnus-diff-add nil :inherit 'diff-added) +(make-face 'ft/gnus-diff-remove) +(set-face-attribute 'ft/gnus-diff-remove nil :inherit 'diff-removed) + +;; Pseudo-headers +(defvar ft/gnus-article-patch-pseudo-headers + '(("^Acked-by: " 'gnus-header-name 'gnus-header-from) + ("^C\\(c\\|C\\): " 'gnus-header-name 'gnus-header-from) + ("^From: " 'gnus-header-name 'gnus-header-from) + ("^Link: " 'gnus-header-name 'gnus-header-from) + ("^Reported-by: " 'gnus-header-name 'gnus-header-from) + ("^Reviewed-by: " 'gnus-header-name 'gnus-header-from) + ("^Signed-off-by: " 'gnus-header-name 'gnus-header-from) + ("^Subject: " 'gnus-header-name 'gnus-header-from) + ("^Suggested-by: " 'gnus-header-name 'gnus-header-from)) + "List of lists of regular expressions (with two face names) +which are used to determine the highlighting of pseudo headers in +the commit message (such as \"Signed-off-by:\"). + +The first face if used to highlight the header's name; the second +highlights the header's value.") + +(defun ft/gnus-pseudo-header-get (line) + "Check if `line' is a pseudo header, and if so return its enty in +`ft/gnus-article-patch-pseudo-headers'." + (catch 'done + (dolist (entry ft/gnus-article-patch-pseudo-headers) + (let ((regex (car entry))) + (if (string-match regex line) + (throw 'done entry)))) + (throw 'done '()))) + +(defun ft/gnus-pseudo-header-p (line) + "Returns `t' if `line' looks like a pseudo-header; `nil' otherwise. + +`ft/gnus-article-patch-pseudo-headers' is used to determine what a pseudo-header +is." + (if (eq (ft/gnus-pseudo-header-get line) '()) nil t)) + +(defun ft/gnus-pseudo-header-colour (line) + "Colourise a pseudo-header line." + (let ((data (ft/gnus-pseudo-header-get line))) + (if (eq data '()) + nil + (let* ((s (point-at-bol)) + (e (point-at-eol)) + (colon (re-search-forward ":")) + (value (+ colon 1))) + (overlay-put (make-overlay s colon) 'face (nth 1 data)) + (overlay-put (make-overlay value e) 'face (nth 2 data)))))) + +;; diff-stat +(defun ft/gnus-diff-stat-colour (line) + "Colourise a diff-stat line." + (let ((s (point-at-bol)) + (e (point-at-eol)) + (bar (- (re-search-forward "|") 1)) + (num (- (re-search-forward "[0-9]") 1)) + (pm (- (re-search-forward "\\([+-]\\|$\\)") 1))) + + (overlay-put (make-overlay s (- bar 1)) 'face 'ft/gnus-diff-stat-file) + (overlay-put (make-overlay bar (+ bar 1)) 'face 'ft/gnus-diff-stat-bar) + (overlay-put (make-overlay num pm) 'face 'ft/gnus-diff-stat-num) + + (goto-char pm) + (let* ((plus (looking-at "\\+")) + (regex (if plus "-+" "\\++")) + (brk (if plus + (re-search-forward "-" e t) + (re-search-forward "\\+" e t))) + (first-face (if plus 'ft/gnus-diff-add 'ft/gnus-diff-remove)) + (second-face (if plus 'ft/gnus-diff-remove 'ft/gnus-diff-add))) + + (if (eq brk nil) + (overlay-put (make-overlay pm e) 'face first-face) + (progn + (setq brk (- brk 1)) + (overlay-put (make-overlay pm brk) 'face first-face) + (overlay-put (make-overlay brk e) 'face second-face)))))) + +(defun ft/gnus-diff-stat-summary-colour (line) + "Colourise a diff-stat summary-line." + (let* ((e (point-at-eol)) + (plus (- (re-search-forward "(\\+)" e t) 2)) + (minus (- (re-search-forward "(-)" e t) 2))) + (overlay-put (make-overlay plus (+ plus 1)) 'face 'ft/gnus-diff-add) + (overlay-put (make-overlay minus (+ minus 1)) 'face 'ft/gnus-diff-remove))) + +(defun ft/gnus-diff-stat-line-p (line) + "Return `t' if `line' is a diff-stat line; `nil' otherwise." + (string-match "^ *[^ ]+[^|]+| +[0-9]+\\( *\\| +[+-]+\\)$" line)) + +(defun ft/gnus-diff-stat-summary-p (line) + "Return `t' if `line' is a diff-stat summary-line; `nil' otherwise." + (string-match "^ *[0-9]+ file\\(s\\|\\) changed,.*insertion.*deletion" line)) + +;; unified-diffs +(defun ft/gnus-diff-header-p (line) + "Returns `t' if `line' looks like a diff-header; `nil' otherwise." + (cond + ((string-match "^\\(\\+\\+\\+\\|---\\) " line) t) + ((string-match "^diff -" line) t) + (t nil))) + +(defun ft/gnus-index-line-p (line) + "Returns `t' if `line' looks like an index-line; `nil' otherwise." + (cond + ((string-match "^Index: " line) t) + ((string-match "^index [0-9a-f]+\\.\\.[0-9a-f]+" line) t) + (t nil))) + +(defun ft/gnus-hunk-line-p (line) + "Returns `t' if `line' looks like a hunk-line; `nil' otherwise." + (string-match "^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@" line)) + +(defun ft/gnus-atp-misc-diff-p (line) + "Return `t' if `line' is a \"misc line\" with respect to patch +treatment; `nil' otherwise." + (let ((patterns '("^new file" + "^RCS file:" + "^retrieving revision "))) + (catch 'done + (dolist (regex patterns) + (if (string-match regex line) + (throw 'done t))) + (throw 'done nil)))) + +(defun ft/gnus-atp-looks-like-diff (line) + "Return `t' if `line' looks remotely like a line from a unified +diff; `nil' otherwise." + (or (ft/gnus-index-line-p line) + (ft/gnus-diff-header-p line) + (ft/gnus-hunk-line-p line))) + +;; miscellaneous line handlers +(defun ft/gnus-scissors-line-p (line) + "Returns `t' if `line' looks like a scissors-line; `nil' otherwise." + (cond + ((string-match "^\\( *--* *\\(8<\\|>8\\)\\)+ *-* *$" line) t) + (t nil))) + +;; Patch mail detection +(defvar ft/gnus-article-patch-conditions nil + "List of conditions that will enable patch treatment. String +values will be matched as regular expressions within the currently +processed part. Non-string value are supposed to be code fragments, +which determine whether or not to do treatment: The code needs to +return `t' if treatment is wanted.") + +(defun ft/gnus-part-want-patch-treatment () + "Run through `ft/gnus-article-patch-conditions' to determine whether +patch treatment is wanted or not. Return `t' or `nil' accordingly." + (catch 'done + (dolist (entry ft/gnus-article-patch-conditions) + (cond + ((stringp entry) + (if (re-search-forward entry nil t) + (throw 'done t))) + (t + (if (eval entry) + (throw 'done t))))) + (throw 'done nil))) + + +;; The actual article treatment code +(defun ft/gnus-article-treat-patch-state-machine () + "Implement the state machine which colourises a part of an article +if it looks patch-like. + +The state machine works like this: + + 0a. The machinery starts at the first line of the article's body. Not + the header lines. We don't care about header lines at all. + + 0b. The whole thing works line by line. It doesn't do any forward or + backward looks. + + 1. Initially, we assume, that what we'll see first is part of the + patch's commit-message. Hence this first initial state is + \"commit-message\". There are several ways out of this state: + + a) a scissors line is found (see 2.) + b) a pseudo-header line is found (see 3.) + c) a three-dashes line is found (see 4.) + d) something that looks like the start of a unified diff is + found (see 7.) + + 2. A scissors line is something that looks like a pair of scissors running + through a piece of paper. Like this: + + ------ 8< ----- 8< ------ + + or this: + + ------------>8----------- + + The function `ft/gnus-scissors-line-p' decides whether a line is a + scissors line or not. After a scissors line was treated, the machine + will switch back to the \"commit-mesage\" state. + + 3. This is very similar to a scissors line. It'll just return to the old + state after its being done. The `ft/gnus-pseudo-header-p' function + decides if a line is a pseudo header. The line will be appropriately + coloured. + + 4. A three-dashes line is a line that looks like this: \"---\". It's the + definite end of the \"commit-message\" state. The three dashes line is + coloured and the state switches to \"commit-comment\". (See 5.) + + 5. Nothing in \"commit-comment\" will appear in the generated commit (this + is git-am specific semantics, but it's useful, so...). It may contain + things like random comments or - promimently - a diff stat. (See 6.) + + 6. A diff stat provides statistics about how much changed in a given commit + by files and by whole commit (in a summary line). Two functions + `ft/gnus-diff-stat-line-p' and `ft/gnus-diff-stat-summary-p' decide if a + line belongs to a diff stat. It's coloured appropriately and the state + switches back to \"commit-comment\". + + 7. There is a function `ft/gnus-unified-diff-line-p' which will cause the + state to switch to \"unified-diff\" state from either \"commit-message\" + or \"commit-comment\". In this mode there can be a set of lines types: + + a) diff-header lines (`ft/gnus-diff-header-p') + b) index lines (`ft/gnus-index-line-p') + c) hunk lines (`ft/gnus-hunk-line-p') + d) equals line (\"^==*$\") + e) context lines (\"^ \") + f) add lines (\"^\\+\") + g) remove lines (\"^-\") + h) empty lines (\"^$\") + + This state runs until the end of the part." + (catch 'ft/gnus-atp-done + (let ((state 'commit-message) + line do-not-move) + + (while t + ;; Put the current line into an easy-to-handle string variable. + (setq line + (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (setq do-not-move nil) + + ;; Switched state machine. The "real" states are `commit-message', + ;; `commit-comment' and `unified-diff'. The other "states" are only + ;; single-line colourisations that return to their respective parent- + ;; state. Each state may (throw 'ft/gnus-atp-done) to leave the state- + ;; machine immediately. + (setq state + (cond + + ((eq state 'commit-message) + (cond + ((ft/gnus-scissors-line-p line) + (ft/gnus-colour-line 'ft/gnus-scissors) + 'commit-message) + ((ft/gnus-pseudo-header-p line) + (ft/gnus-pseudo-header-colour line) + 'commit-message) + ((string= line "---") + (ft/gnus-colour-line 'ft/gnus-three-dashes) + 'commit-comment) + ((ft/gnus-atp-looks-like-diff line) + (setq do-not-move t) + 'unified-diff) + (t + (ft/gnus-colour-line 'ft/gnus-commit-message) + 'commit-message))) + + ((eq state 'commit-comment) + (cond + ((ft/gnus-diff-stat-line-p line) + (ft/gnus-diff-stat-colour line) + 'commit-comment) + ((ft/gnus-diff-stat-summary-p line) + (ft/gnus-diff-stat-summary-colour line) + 'commit-comment) + ((ft/gnus-atp-looks-like-diff line) + (setq do-not-move t) + 'unified-diff) + (t + (ft/gnus-colour-line 'ft/gnus-commit-comment) + 'commit-comment))) + + ((eq state 'unified-diff) + (cond + ((ft/gnus-diff-header-p line) + (ft/gnus-colour-line 'ft/gnus-diff-header) + 'unified-diff) + ((ft/gnus-index-line-p line) + (ft/gnus-colour-line 'ft/gnus-diff-index) + 'unified-diff) + ((ft/gnus-hunk-line-p line) + (ft/gnus-colour-line 'ft/gnus-diff-hunk) + 'unified-diff) + ((string-match "^==*$" line) + (ft/gnus-colour-line 'ft/gnus-diff-equals) + 'unified-diff) + ((string-match "^$" line) + 'unified-diff) + ((string-match "^ " line) + (ft/gnus-colour-line 'ft/gnus-diff-context) + 'unified-diff) + ((ft/gnus-atp-misc-diff-p line) + (ft/gnus-colour-line 'ft/gnus-diff-misc) + 'unified-diff) + ((string-match "^\\+" line) + (ft/gnus-colour-line 'ft/gnus-diff-add) + 'unified-diff) + ((string-match "^-" line) + (ft/gnus-colour-line 'ft/gnus-diff-remove) + 'unified-diff) + (t 'unified-diff))))) + + (if (not do-not-move) + (if (> (forward-line) 0) + (throw 'ft/gnus-atp-done t))))))) + +(defun ft/gnus-article-treat-patch () + "Highlight mail parts, that look like patches (well, usually +they *are* patches - or possibly, when you take git's format-patch output, +entire commit exports - including comments). This treatment assumes the +use of unified diffs. Here is how it works: + +The most fancy type of patch mails look like this: + + From: ... + Subject: ... + Other-Headers: ... + + Body text, which can be reflecting the commit message but may + optionally be followed by a so called scissors line, which + looks like this (in case of a scissors line, the text above is + not part of the commit message): + + -------8<---------- + + If there really was a scissors line, then it's usually + followed by repeated mail-headers. Which do not *have* to + be the same as the one from the sender. + + From: ... + Subject: ... + + More text. Usually part of the commit message. Likely + multiline. What follows may be an optional diffstat. If + there is one, it's usually preceded by a line that contains + only three dashes and nothing more. Before the diffstat, + however, there may be a set of pseudo headers again, like + these: + + Acked-by: Mike Dev <md@other.tld> + Signed-off-by: Joe D. User <jdu@example.com> + + --- + ChangeLog | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletions(-) + + Now, there is again room for optional text, which is not + part of the actual commit message. May be multiline. Actually, + anything between the three-dashes line and the diff content + is ignored as far as the commit message goes. + + Now for the actual diff part. I want this to work for as + many unified diff formats as possible. What comes to mind + is the format used by git and the format used by cvs and + quilt. + + CVS style looks like this: + + Index: foo/bar.c + ============================================================ + --- boo.orig/foo/bar.c 2010-02-24 .... + +++ boo/foo/bar.c 2010-02-28 .... + @@ -1823,7 +1823,7 @@ + <hunk> + + There may be multiple hunks. Each file gets an \"Index:\" and + equals line. Now the git format looks like this: + + diff --git a/ChangeLog b/ChangeLog + index 6ffbc8c..36e5c17 100644 + --- a/ChangeLog + +++ b/ChangeLog + @@ -3,6 +3,9 @@ + <hunk> + + Again, there may be multiple hunks. + + When all hunks and all files are done, there may be additional + text below the actual text. + +And that's it. + +You may define the look of several things: pseudo headers, scissor +lines, three-dashes-line, equals lines, diffstat lines, diffstat +summary. Then there is added lines, removed lines, context lines, +diff-header lines and diff-file-header lines, for which we are +borrowing the highlighting faces for from `diff-mode'." + (if (ft/gnus-part-want-patch-treatment) + (save-excursion + (progn + (let ((inhibit-read-only t)) + (goto-char (point-min)) + (ft/gnus-article-treat-patch-state-machine)))))) + +(provide 'gnus-article-treat-patch) diff --git a/.emacs.d/lisp/hl-todo b/.emacs.d/lisp/hl-todo new file mode 160000 +Subproject 0598b98f63b623c1778cbd2e2f60b774b7a311b diff --git a/.emacs.d/lisp/page-break-lines b/.emacs.d/lisp/page-break-lines new file mode 160000 +Subproject f8c4cd7fc67638ae4113551dcffdf87fcd252d9 diff --git a/.emacs.d/lisp/s b/.emacs.d/lisp/s new file mode 160000 +Subproject 43ba8b563bee3426cead0e6d4ddc09398e1a349 diff --git a/.emacs.d/lisp/scpaste b/.emacs.d/lisp/scpaste new file mode 160000 +Subproject cd4fa0aafecd839736e0b6cba68b4fc4d704547 |