summaryrefslogtreecommitdiff
path: root/.emacs.d
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d')
-rw-r--r--.emacs.d/early-init.el2
-rw-r--r--.emacs.d/eshell/alias3
-rw-r--r--.emacs.d/init.el1298
3 files changed, 545 insertions, 758 deletions
diff --git a/.emacs.d/early-init.el b/.emacs.d/early-init.el
index a3793e15..08a4aa02 100644
--- a/.emacs.d/early-init.el
+++ b/.emacs.d/early-init.el
@@ -1,6 +1,6 @@
;;; early-init.el --- frames conf. -*- lexical-binding:t;no-byte-compile:t -*-
-;; Copyright (C) 2020-2022 Sean Whitton <spwhitton@spwhitton.name>
+;; Copyright (C) 2020-2023 Sean Whitton <spwhitton@spwhitton.name>
;;
;; 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
diff --git a/.emacs.d/eshell/alias b/.emacs.d/eshell/alias
index 5e66ab3b..29a43d2d 100644
--- a/.emacs.d/eshell/alias
+++ b/.emacs.d/eshell/alias
@@ -2,7 +2,7 @@ alias grep-queued { cd /ssh:ssh.upload.debian.org: && *grep $* /srv/upload.debia
alias grep-dak { cd /ssh:ftp-master.debian.org: && *grep $* /srv/ftp-master.debian.org/log/current }
alias push-develacc-dotfiles-branch git push -f origin develacc/develacc-"${hostname}":develacc-"${hostname}"
alias sbuild-prerelease sbuild --dpkg-source-opts='-Zgzip -z1 --format=1.0 -sn' $*
-alias sbuild-lts quilt pop -a; git is-clean ':!debian/patches/' && sbuild --no-clean-source --no-run-lintian $*
+alias sbuild-lts quilt pop -a; git is-clean ':!debian/patches/' && sbuild --no-clean-source $*
alias dpkg-bp-lts quilt pop -a; git is-clean && dpkg-buildpackage -S -nc --force-sign $*
alias dpkg-buildpackage-lts dpkg-bp-lts $*
alias d dired $1
@@ -18,6 +18,7 @@ alias afsid apt-file --filter-suites unstable $*
alias grepcopy grep -Eir '(copyright|©)' *
alias pdfwords pdftotext "$1" - | wc -w
alias dlp lp -o sides=two-sided-long-edge $*
+alias pdd dd bs=4M status=progress conv=fdatasync $*
alias tail-dak { cd /ssh:ftp-master.debian.org:/srv/ftp-master.debian.org/log && tail -f current }
alias tail-queued { cd /ssh:ssh.upload.debian.org:/srv/upload.debian.org/queued/run && tail -f log }
alias package-plan-unpack ~/src/dotfiles/scripts/debian/package-plan-unpack "$1"; cd "/tmp/$1"
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
index e220af96..f633c397 100644
--- a/.emacs.d/init.el
+++ b/.emacs.d/init.el
@@ -23,11 +23,6 @@
;; matching ~/.emacs.d/*.el, since the "spw-" and "spw--" prefixes would be
;; for a file called "spw.el" with a defined API, providing an `spw' feature.
;;
-;; Prefer using the customise interface for variables, faces and enabling and
-;; disabling global minor modes, except when we want to associate an extended
-;; comment to a number of settings (typically we use the customise interface's
-;; facility for adding comments for only short comments).
-;;
;; Aim for compatibility with the version of Emacs included in Debian stable.
;;
;; Bind only key sequences reserved for users or which are already bound to
@@ -82,40 +77,49 @@
;;;; Customisation & appearance
-(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.
+;; The customisation system is additionally used to save safe local variable
+;; values, SSL certificate overrides etc. (cf. `customize-push-and-save').
+;; Most of these should not be committed to git: they're often host-specific,
+;; usually only relevant for a short time, and sometimes private.
+;; So we use a disposable, local custom file, and `custom-theme-set-faces',
+;; `customize-set-variable' and `custom-theme-set-variables' in this file.
+;; (Re `setopt' vs. `customize-set-variable': former is for when we're making
+;; a dynamic change that is not just host-specific but session-specific.)
+(load (setq custom-file (expand-file-name "custom" user-emacs-directory))
+ 'noerror 'nomessage 'nosuffix)
+
+(custom-theme-set-faces
+ 'user
'(default ((t (:weight medium :height 105 :foundry "SRC" :family "Hack"))))
+ '(fixed-pitch ((t (:foundry "SRC" :family "Hack"))))
+ '(variable-pitch ((t (:weight regular :height 120
+ :foundry "bitstream" :family "Bitstream Charter"))))
+ ;; We want to handle the `variable-pitch'/`variable-pitch-text' distinction
+ ;; using `spw/maybe-scale-basic-faces' instead.
+ '(variable-pitch-text ((t (:inherit variable-pitch))))
+
'(comint-highlight-prompt ((t (:inherit minibuffer-prompt :weight bold))))
'(fill-column-indicator ((t (:background "light gray"))))
- '(fixed-pitch ((t (:foundry "SRC" :family "Hack"))))
- '(org-code ((t (:inherit (shadow fixed-pitch)))))
- '(org-date ((t (:inherit fixed-pitch :foreground "Purple" :underline t))))
- '(org-verbatim ((t (:inherit (shadow fixed-pitch)))))
- '(region ((t (:extend t :background "#EECD82"))) nil "Colour is from the Lucid build.")
- '(variable-pitch ((t (:weight regular :height 120 :foundry "bitstream" :family "Bitstream Charter"))))
- '(variable-pitch-text ((t (:inherit variable-pitch))) nil "Handled by `spw/maybe-scale-basic-faces' instead."))
-
-;; Set background colour but don't touch text terminals.
-(dolist (ws '(x pgtk w32 ns))
- (add-to-list
- 'window-system-default-frame-alist
- ;; If we were not started with --daemon or by 'emacsclient -a ""', then
- ;; we're probably a shortlived instance of Emacs just to test something.
- ;; Set a different background colour to more easily distinguish frames
- ;; belonging to shortlived instances from those belonging to main instance.
- `(,ws
- . ((background-color
- . ,(pcase (daemonp)
- ('nil "honeydew") ("gdbmacs" "linen") (_ "#FFFFF6")))))))
+
+ ;; The colour is from the Lucid build of Emacs.
+ '(region ((t (:extend t :background "#EECD82")))))
+
+;; Set background colours for graphical frames; leave TUI frames alone.
+;; If we were not started with --daemon or by 'emacsclient -a ""', then
+;; we're probably a shortlived instance of Emacs just to test something.
+;; Set a different background colour to more easily distinguish frames
+;; belonging to shortlived instances from those belonging to main instance.
+(let ((colour (pcase (daemonp)
+ ('nil "#F0FFF0") ("gdbmacs" "#F5F5DC") (_ "#FFFFF6"))))
+ (dolist (ws '(x pgtk w32 ns))
+ (add-to-list 'window-system-default-frame-alist
+ `(,ws . ((background-color . ,colour))))))
(defun spw/maybe-scale-basic-faces (frame)
- "Entry for `window-size-change-functions' to increase font sizes
-from those set by `custom-set-faces' for frames on wide monitors,
-except where doing so would itself prevent fitting two 80-column
-windows side-by-side in the frame."
+ "Entry for `window-size-change-functions' to increase font sizes,
+relative to those set by the call to `custom-theme-set-faces' above, for
+frames on wide monitors, except where doing so would itself prevent fitting
+two 80-column windows side-by-side in the frame."
(when (display-graphic-p frame)
(let ((wide-monitor-p (> (cadddr (assoc 'geometry
(frame-monitor-attributes frame)))
@@ -167,32 +171,22 @@ windows side-by-side in the frame."
(set-terminal-parameter nil 'background-mode 'light)))
(add-hook 'tty-setup-hook #'spw/set-tmux-background-mode)
-(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.
+(custom-theme-set-variables
+ 'user
'(Man-notify-method 'aggressive)
'(after-save-hook '(executable-make-buffer-file-executable-if-script-p))
- '(appt-display-diary nil)
- '(appt-display-interval 6)
'(async-shell-command-buffer 'rename-buffer)
+
+ ;; Always update buffers when files change on disk -- if we want to go back
+ ;; to the version of the file we had in Emacs, we can just hit C-/.
+ '(auto-revert-use-notify nil)
+ '(global-auto-revert-mode 1)
+
'(auth-source-save-behavior nil)
'(auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-saves/" t)))
'(backup-by-copying-when-linked t)
'(backup-directory-alist '(("." . "~/.emacs.d/backups/")))
- '(bongo-default-directory "~/annex/music/")
- '(bongo-insert-album-covers t)
- '(bongo-insert-whole-directory-trees t)
- '(bongo-mode-line-indicator-mode nil)
- '(bongo-prefer-library-buffers nil)
- '(c-default-style "linux")
'(calc-kill-line-numbering nil)
- '(calendar-date-display-form
- '((format "%s-%.2d-%.2d %.3s" year (string-to-number month)
- (string-to-number day) dayname)))
- '(calendar-date-style 'iso)
- '(calendar-week-start-day 1)
'(column-number-mode t)
'(comint-prompt-read-only t)
'(compilation-scroll-output 'first-error)
@@ -202,223 +196,67 @@ windows side-by-side in the frame."
'(copy-region-blink-delay 0)
'(copyright-names-regexp "Sean Whitton")
'(copyright-year-ranges t)
- '(cperl-close-paren-offset -4 nil nil "See `cperl-indent-parens-as-block'.")
- '(cperl-indent-level 4)
- '(cperl-indent-parens-as-block t nil nil "Makes it easier to use longer names for subroutines.")
- '(cperl-lineup-step 1)
'(cursor-type 'box)
- '(cycle-spacing-actions '(just-one-space) nil nil "Restore Emacs 28 behaviour of M-SPC.")
+
+ ;; C-u M-\ to delete only before point, M-SPC M-SPC to delete only after.
+ '(cycle-spacing-actions '(just-one-space (delete-space-after -)))
+
'(dabbrev-case-fold-search t)
- '(diary-file "~/doc/emacs-diary")
- '(diary-list-entries-hook '(diary-include-other-diary-files diary-sort-entries))
- '(diary-mark-entries-hook '(diary-mark-included-diary-files))
- '(dired-clean-up-buffers-too nil)
- '(dired-dwim-target t)
- '(dired-free-space 'separate)
- '(dired-isearch-filenames t)
- '(dired-listing-switches "--group-directories-first -alh")
- '(dired-omit-files "\\`[.]?#\\|\\`[.][.]?\\'\\|\\`\\.git\\'")
- '(dired-recursive-copies 'always)
'(display-fill-column-indicator-character 32)
'(ediff-split-window-function 'split-window-horizontally)
'(eldoc-minor-mode-string nil)
'(emacs-lisp-docstring-fill-column 75)
'(enable-recursive-minibuffers t)
- '(eshell-cmpl-cycle-completions nil nil nil "This makes Eshell completions a bit more like bash's.")
- '(eshell-cmpl-ignore-case t)
- '(eshell-hist-ignoredups 'erase)
- '(eshell-history-append t)
- '(eshell-history-size 5000)
- '(eshell-save-history-on-exit nil)
- '(eshell-visual-commands
- '("vi" "screen" "tmux" "top" "htop" "less" "more" "mutt" "locmaint" "gen-DSA"
- "gen-DLA" "gen-ELA"))
'(fill-column 78)
- '(font-lock-maximum-decoration '((lisp-mode . 1) (consfigurator-lisp-mode . 1) (t . t)))
+ '(font-lock-maximum-decoration
+ '((lisp-mode . 1) (consfigurator-lisp-mode . 1) (t . t)))
'(gc-cons-threshold 16777216)
'(gdb-many-windows t)
- '(gdb-show-main t nil nil "This is helpful when gdb-many-windows is turned off.")
- '(git-rebase-confirm-cancel nil)
+
+ ;; This is helpful when gdb-many-windows is turned off.
+ '(gdb-show-main t)
+
'(global-so-long-mode t)
- '(gnus-article-skip-boring t)
- '(gnus-auto-center-summary nil)
- '(gnus-auto-select-next 'slightly-quietly)
- '(gnus-buttonized-mime-types
- '("text/x-\\(?:diff\\|patch\\)" "multipart/\\(?:alternative\\|signed\\)"))
- '(gnus-directory "~/local/News/")
- '(gnus-extra-headers '(To Cc List-Id))
- '(gnus-gcc-mark-as-read t)
- '(gnus-global-score-files '("~/doc/News/"))
- '(gnus-interactive-exit 'quiet)
- '(gnus-kill-files-directory "~/src/athpriv/News/")
- '(gnus-kill-summary-on-exit t nil nil "Would prefer nil but t seems advisable for notmuch groups.")
- '(gnus-large-ephemeral-newsgroup 8000)
- '(gnus-large-newsgroup 8000)
- '(gnus-mark-article-hook '(spw/gnus-mark-article-hook))
- '(gnus-message-archive-group "sent")
- '(gnus-message-archive-method '(nnmaildir "fmail" (directory "~/.fmail/")))
- '(gnus-permanently-visible-groups "^nnmaildir\\+fmail:\\(?:notes\\|sent\\)$")
- '(gnus-read-newsrc-file nil)
- '(gnus-refer-thread-use-search '(("nnmaildir:fmail")))
- '(gnus-save-killed-list
- "^\\(?:[^n]\\|n[^n]\\|nn[^s]\\|nns[^e]\\|nnse[^l]\\|nnsel[^e]\\|nnsele[^c]\\|nnselec[^t]\\|nnselect[^:]\\)")
- '(gnus-save-newsrc-file nil)
- '(gnus-search-default-engines '((nnmaildir . notmuch)))
- '(gnus-search-notmuch-remove-prefix "~/.fmail/")
- '(gnus-secondary-select-methods '((nnmaildir "fmail" (directory "~/.fmail/"))))
- '(gnus-sum-thread-tree-false-root "")
- '(gnus-sum-thread-tree-indent " ")
- '(gnus-sum-thread-tree-leaf-with-other "├► ")
- '(gnus-sum-thread-tree-root "")
- '(gnus-sum-thread-tree-single-leaf "╰► ")
- '(gnus-sum-thread-tree-vertical "│")
- '(gnus-summary-line-format "%U%R%z %(%12&user-date; %*%-23,23f%) %B%s\12")
- '(gnus-summary-mode-line-format "Gnus: %u&summary;%g [%A] %Z")
- '(gnus-summary-thread-gathering-function 'gnus-gather-threads-by-references)
- '(gnus-suppress-duplicates t)
- '(gnus-thread-sort-functions
- '(gnus-thread-sort-by-number gnus-thread-sort-by-total-score))
- '(gnus-topic-display-empty-topics nil)
- '(gnus-update-message-archive-method t)
- '(gnus-user-date-format-alist
- '((32042 . "%2l:%M%#p") (118823 . "Yest %2l:%M%#p") (604800 . "%a %2l:%M%#p")
- (16102447 . "%d %B") (t . "%Y-%b-%d")))
- '(haskell-indentation-layout-offset 4)
- '(haskell-indentation-left-offset 4)
+ '(help-display-function-type nil)
'(help-window-keep-selected t)
- '(holiday-bahai-holidays nil)
- '(holiday-hebrew-holidays nil)
- '(holiday-islamic-holidays nil)
- '(howm-directory "~/doc/howm/")
- '(howm-file-name-format "%Y/%Y-%m-%d-%H%M.org")
- '(howm-keyword-file "~/doc/howm/.howm-keys")
- '(howm-view-use-grep t)
- '(icomplete-hide-common-prefix nil)
- '(icomplete-in-buffer t)
- '(icomplete-mode t)
- '(icomplete-show-matches-on-no-input t)
- '(icomplete-tidy-shadowed-file-names t)
'(imenu-auto-rescan t)
+ '(inferior-lisp-program "sbcl")
'(initial-major-mode 'spw/scratch-lisp-interaction-mode)
'(kill-read-only-ok t)
- '(log-edit-hook
- '(log-edit-insert-message-template log-edit-insert-cvs-template
- log-edit-insert-changelog
- spw/log-edit-show-diff) nil nil "Drop log-edit-show-files to avoid its window becoming most recently used for C-x o.")
- '(mail-envelope-from 'header nil nil "Bypass MTA rewriting user@localhost.")
- '(mail-specify-envelope-from t nil nil "Bypass MTA rewriting user@localhost.")
+
+ ;; Bypass MTA rewriting user@localhost.
+ '(mail-envelope-from 'header)
+ '(mail-specify-envelope-from t)
+
'(mail-user-agent 'gnus-user-agent)
'(mailscripts-detach-head-from-existing-branch 'ask)
'(mailscripts-extract-patches-branch-prefix "mail/")
'(mailscripts-project-library 'project)
- '(major-mode-remap-alist '((perl-mode . cperl-mode)) nil nil "cperl-mode doesn't try to indent lines within a POD, and usefully font locks scalars that are members of hashes and arrays.")
- '(make-pointer-invisible t nil nil "Works only for self-insert chars and undone by changes in window manager focus, but less annoying than `mouse-avoidance-mode'.")
- '(message-auto-save-directory "~/tmp/" nil nil "So locmaint will catch them.")
- '(message-citation-line-format "On %a %d %b %Y at %I:%M%p %Z, %N wrote:\12")
- '(message-citation-line-function 'message-insert-formatted-citation-line)
- '(message-forward-as-mime nil nil nil "For compatibility.")
- '(message-forward-before-signature nil nil nil "For compatibility.")
- '(message-forward-included-headers
- '("^From:" "^Subject:" "^Date:" "^To:" "^Cc:" "^Message-ID:") nil nil "For compatibility.")
- '(message-ignored-resent-headers
- "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:\\|^>?From \\|^Delivered-To:\\|^\\(?:X-\\)?Content-Length:\\|^X-UIDL:\\|^X-TUID:\\|^\\(?:X-\\)?Status:\\|^Lines:")
- '(message-make-forward-subject-function '(message-forward-subject-fwd) nil nil "For compatibility.")
- '(message-sendmail-envelope-from 'header nil nil "Bypass MTA rewriting user@localhost.")
- '(message-wash-forwarded-subjects t)
+
+ ;; `cperl-mode' doesn't try to indent lines within a POD, and usefully font
+ ;; locks scalars that are members of hashes and arrays.
+ '(major-mode-remap-alist '((perl-mode . cperl-mode)))
+
+ ;; Works only for self-insert chars and undone by changes in window manager
+ ;; focus, but less annoying than `mouse-avoidance-mode'.
+ '(make-pointer-invisible t)
+
'(minibuffer-follows-selected-frame nil)
- '(mm-decrypt-option 'known)
- '(mm-default-directory "~/tmp/")
- '(mm-file-name-rewrite-functions
- '(mm-file-name-delete-control mm-file-name-delete-gotchas
- mm-file-name-trim-whitespace
- mm-file-name-collapse-whitespace
- mm-file-name-replace-whitespace))
- '(mml-secure-openpgp-encrypt-to-self t nil nil "So I can read copies in my sent mail directory.")
- '(mml-secure-openpgp-sign-with-sender t)
'(mode-line-compact 'long)
- '(mouse-drag-copy-region t nil nil "X primary selection-like behaviour within Emacs even when not available outside.")
- '(mouse-highlight 1 nil nil "See `make-pointer-invisible'.")
+
+ ;; X primary selection-like behaviour within Emacs even when not available
+ ;; outside.
+ '(mouse-drag-copy-region t)
+
+ ;; See `make-pointer-invisible'.
+ '(mouse-highlight 1)
+
'(mouse-yank-at-point t)
'(native-comp-async-jobs-number 1)
'(native-comp-async-report-warnings-errors 'silent)
- '(nnmail-extra-headers '(To Cc List-Id))
- '(notmuch-address-use-company nil)
- '(nov-text-width 78)
- '(org-adapt-indentation t nil nil "Sometimes set to nil in .dir-locals.el, e.g. in ~/doc/newpapers.")
- '(org-agenda-entry-text-maxlines 3)
- '(org-agenda-files "~/doc/emacs-org-agenda-files")
- '(org-agenda-persistent-filter t)
- '(org-agenda-remove-times-when-in-prefix 'beg)
- '(org-agenda-restore-windows-after-quit nil nil nil "Interacts badly with `tab-bar-history-mode'.")
- '(org-agenda-skip-deadline-if-done t)
- '(org-agenda-skip-deadline-prewarning-if-scheduled 3)
- '(org-agenda-skip-scheduled-if-deadline-is-shown 'not-today)
- '(org-agenda-skip-scheduled-if-done t)
- '(org-agenda-skip-timestamp-if-done t)
- '(org-agenda-start-on-weekday nil)
- '(org-agenda-sticky t)
- '(org-agenda-timegrid-use-ampm t)
- '(org-agenda-todo-ignore-scheduled 'future)
- '(org-agenda-window-setup 'current-window)
- '(org-archive-location "~/doc/archive/howm/archive.org::* From %s")
- '(org-archive-save-context-info '(time file olpath))
- '(org-archive-subtree-save-file-p t)
- '(org-blank-before-new-entry '((heading . t) (plain-list-item . auto)))
- '(org-bookmark-names-plist nil nil nil "Turn off to avoid git merge conflicts.")
- '(org-cycle-separator-lines 0)
- '(org-deadline-warning-days 60)
- '(org-default-notes-file "~/doc/howm/refile.org")
- '(org-directory "~/doc/howm/")
- '(org-enforce-todo-checkbox-dependencies t)
- '(org-enforce-todo-dependencies t)
- '(org-fold-catch-invisible-edits 'show)
- '(org-fold-show-context-detail
- '((agenda . local) (bookmark-jump . lineage) (isearch . lineage)
- (default . ancestors-full)))
- '(org-footnote-section "Notes")
- '(org-imenu-depth 4)
- '(org-list-allow-alphabetical nil nil nil "So I can start lines with \"P. 211 - \" to refer to p. 211 not start a list.")
- '(org-list-demote-modify-bullet
- '(("-" . "+") ("+" . "*") ("*" . "-") ("1." . "-") ("1)" . "-")))
- '(org-list-use-circular-motion t)
- '(org-log-done 'time)
- '(org-log-into-drawer t)
- '(org-log-repeat nil nil nil "Cluttering, and information probably in git.")
- '(org-log-states-order-reversed nil)
- '(org-outline-path-complete-in-steps nil nil nil "Desirable with `icomplete-mode'.")
- '(org-read-date-prefer-future 'time)
- '(org-refile-allow-creating-parent-nodes 'confirm)
- '(org-refile-targets '((org-agenda-files :maxlevel . 5) (nil :maxlevel . 5)))
- '(org-refile-use-outline-path 'file)
- '(org-special-ctrl-a/e t)
- '(org-special-ctrl-k t)
- '(org-startup-folded nil)
- '(org-startup-indented nil nil nil "Ensures buffer text doesn't go beyond 80 columns.")
- '(org-tags-match-list-sublevels 'indented)
- '(org-todo-keyword-faces
- '(("SOMEDAY" :foreground "#0000FF" :weight bold)
- ("NEXT" :foreground "#DD0000" :weight bold)))
- '(org-todo-keywords
- '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
- (sequence "WAITING(w@)" "SOMEDAY(s)" "|" "CANCELLED(c)")))
- '(org-treat-S-cursor-todo-selection-as-state-change nil)
- '(org-treat-insert-todo-heading-as-state-change t)
- '(org-use-fast-todo-selection 'expert)
- '(org-yank-folded-subtrees nil)
'(proced-enable-color-flag t)
'(proced-show-remote-processes t)
'(project-switch-commands 'project-prefix-or-any-command)
- '(rcirc-default-full-name "Sean Whitton [spwhitton@spwhitton.name]")
- '(rcirc-default-nick "spwhitton")
- '(rcirc-default-user-name "spwhitton")
- '(rcirc-display-server-buffer nil)
- '(rcirc-log-directory "~/local/irclogs")
- '(rcirc-log-filename-function 'spw/rcirc-generate-log-filename)
- '(rcirc-log-flag t)
- '(rcirc-time-format "%b/%d %H:%M ")
- '(rcirc-track-abbreviate-flag nil)
- '(rcirc-track-ignore-server-buffer-flag t)
- '(rcirc-track-minor-mode t)
'(read-buffer-completion-ignore-case t)
'(read-file-name-completion-ignore-case t)
'(read-mail-command 'gnus)
@@ -427,39 +265,55 @@ windows side-by-side in the frame."
'(remember-notes-buffer-name "*scratch*")
'(remote-file-name-inhibit-delete-by-moving-to-trash t)
'(require-final-newline t)
- '(save-interprogram-paste-before-kill nil nil nil "See <https://debbugs.gnu.org/53728>.")
- '(save-place-mode t nil nil "If quitting Emacs is slow, set `save-place-forget-unreadable-files' to nil.")
+
+ ;; See <https://debbugs.gnu.org/53728>.
+ '(save-interprogram-paste-before-kill nil)
+
+ ;; If quitting Emacs is slow set `save-place-forget-unreadable-files' to nil.
+ '(save-place-mode t)
+
'(savehist-additional-variables '(compile-history log-edit-comment-ring))
'(savehist-mode t)
'(select-active-regions 'only)
'(select-enable-primary t)
'(send-mail-function 'sendmail-send-it)
'(shell-command-prompt-show-cwd t)
- '(show-paren-when-point-in-periphery t nil nil "Useful for C-M-d.")
+
+ ;; Useful for C-M-d.
+ '(show-paren-when-point-in-periphery t)
+
'(shr-max-width 78)
'(slime-load-failed-fasl 'never)
'(tab-bar-history-mode t)
'(tab-bar-show 1)
'(text-mode-ispell-word-completion nil)
- '(tramp-auto-save-directory "~/.emacs.d/auto-saves/" nil nil "Put TRAMP auto-saves under local `user-emacs-directory'.")
- '(tramp-backup-directory-alist '(("." . "~/.emacs.d/backups/")) nil nil "Put TRAMP backups under remote ~/.emacs.d/.")
+
+ ;; Put TRAMP auto-saves under local `user-emacs-directory'.
+ '(tramp-auto-save-directory "~/.emacs.d/auto-saves/")
+ ;; Put TRAMP backups under remote ~/.emacs.d/.
+ '(tramp-backup-directory-alist '(("." . "~/.emacs.d/backups/")))
+
'(tramp-copy-size-limit nil)
'(tramp-default-method "rsync")
- '(tramp-use-connection-share nil nil nil "Rely on my ~/.ssh/config.")
- '(tramp-verbose 1 nil nil "Manual says this should improve performance.")
+
+ ;; Rely on my ~/.ssh/config.
+ '(tramp-use-connection-share nil)
+
+ ;; Manual says this should improve performance.
+ '(tramp-verbose 1)
+
'(transient-cycles-buffer-siblings-mode t)
'(transient-cycles-tab-bar-mode t)
- '(transient-cycles-window-buffers-cycle-backwards-key [134217777] nil nil "M-1.")
- '(transient-cycles-window-buffers-cycle-forwards-key [134217780] nil nil "M-4.")
+ '(transient-cycles-window-buffers-cycle-backwards-key [134217777]) ; M-1
+ '(transient-cycles-window-buffers-cycle-forwards-key [134217780]) ; M-4
'(transient-cycles-window-buffers-mode t)
'(uniquify-buffer-name-style 'forward nil (uniquify))
'(use-short-answers t)
- '(vc-deduce-backend-nonvc-modes t)
- '(vc-find-revision-no-save t)
- '(vc-follow-symlinks t)
- '(vc-git-diff-switches '("--patch-with-stat" "-M" "-C") nil nil "We might also consider -B.")
- '(vc-git-print-log-follow t)
- '(view-read-only t nil nil "Rebind otherwise useless self-insert keys, and means existing C-x C-r, C-x 4 r etc. usable for getting into mode.")
+
+ ;; Rebind otherwise useless self-insert keys, and means existing C-x C-r,
+ ;; C-x 4 r etc. usable for getting into the mode.
+ '(view-read-only t)
+
'(warning-suppress-types '((comp)))
'(window-combination-resize t)
'(x-stretch-cursor t))
@@ -523,6 +377,11 @@ available are present in the `load-path'."
for form = `(add-hook ',hook #',function)
if name collect `(with-eval-after-load ',name ,form) else collect form)))
+(defmacro spw/feature-add-to-list (list-var feature &rest elements)
+ (declare (indent 2))
+ `(with-eval-after-load ',feature
+ ,@(cl-loop for el in elements collect `(add-to-list ',list-var ,el))))
+
(cl-defmacro spw/define-skeleton
(command (mode &key abbrev key (file `',mode)
(map (intern (concat (symbol-name mode) "-map")))
@@ -1005,11 +864,6 @@ To be used only when it seems to be necessary."
;; calling emacsclient(1), this is like '<ESC>ZZ' in vi.
(global-set-key "\C-cz" "\C-x\C-s\C-x#")
-;; always update buffers when files change on disk -- if we want to go back to
-;; the version of the file we had in Emacs, we can just hit undo
-(setq auto-revert-use-notify nil)
-(global-auto-revert-mode 1)
-
;; C-x x g should not ask for confirmation.
(global-set-key "\C-xxg" (lambda ()
(interactive)
@@ -1057,10 +911,30 @@ To be used only when it seems to be necessary."
(add-hook 'text-mode-hook #'goto-address-mode)
(add-hook 'prog-mode-hook #'goto-address-prog-mode)
+;; message-mode is sensitive to trailing whitespace in sig dashes and empty
+;; headers. markdown-mode is sensitive in empty headers (e.g. "# " which I
+;; use in writing essays) and newlines that indicate paragraph flow (obscure
+;; Markdown feature)
+;;
+;; The message-mode case is handled by `spw/normalise-message', which is
+;; better than setting `ws-butler-trim-predicate' to a complicated function
+;; because the code in `spw/normalise-message' gets called less often. Could
+;; try setting `ws-butler-trim-predicate' to handle the markdown-mode case,
+;; but chances are someday I'll want to use that obscure markdown-mode feature
+(define-globalized-minor-mode spw/ws-butler-global-mode ws-butler-mode
+ (lambda () (when (buffer-file-name) (ws-butler-mode 1)))
+ :predicate '((not markdown-mode
+ message-mode
+ lisp-interaction-mode)
+ prog-mode text-mode))
+(spw/ws-butler-global-mode 1)
+
+(spw/feature-add-hook rainbow-mode (sgml-mode html-mode-hook) css-mode)
+
(global-set-key "\C-cih" #'add-file-local-variable-prop-line)
;; don't do anything with abbrevs if ~/doc is not checked out
-(defvar spw/doc-abbrevs-file (expand-file-name "~/doc/emacs-abbrevs"))
+(defvar spw/doc-abbrevs-file (expand-file-name "~/doc/abbrevs"))
(when (file-exists-p spw/doc-abbrevs-file)
(setq abbrev-file-name spw/doc-abbrevs-file)
(quietly-read-abbrev-file)
@@ -1071,7 +945,7 @@ To be used only when it seems to be necessary."
(setf (cadr (assq 'abbrev-mode minor-mode-alist)) nil))
;; similar
-(defvar spw/doc-bookmarks-file (expand-file-name "~/doc/emacs-bookmarks"))
+(defvar spw/doc-bookmarks-file (expand-file-name "~/doc/bookmarks"))
(when (file-exists-p spw/doc-bookmarks-file)
(setq bookmark-default-file spw/doc-bookmarks-file
bookmark-save-flag 1))
@@ -1188,6 +1062,14 @@ To be used only when it seems to be necessary."
;;; Icomplete
+(custom-theme-set-variables
+ 'user
+ '(icomplete-hide-common-prefix nil)
+ '(icomplete-in-buffer t)
+ '(icomplete-mode t)
+ '(icomplete-show-matches-on-no-input t)
+ '(icomplete-tidy-shadowed-file-names t))
+
;; Possibly we could call `minibuffer-complete-word' if we know we're
;; completing the name of a Lisp symbol.
(spw/reclaim-keys-from minibuffer minibuffer-local-completion-map " " "?")
@@ -1295,45 +1177,6 @@ To be used only when it seems to be necessary."
;;;; Buffers and windows
-(defvar spw/arrow-keys-mode-map
- (let ((map (make-sparse-keymap)))
- (dolist (key '(up down left right
- S-up S-down S-left S-right
- M-up M-down M-left M-right))
- (define-key map (vector ?\C-z key) #'spw/arrow-keys-mode-passthru))
- map)
- "Keymap for `spw/arrow-keys-mode'.")
-
-(define-minor-mode spw/arrow-keys-mode
- "Apply the bindings in `spw/arrow-keys-mode-map', but
-additionally bind the sequences of C-z followed by each of the
-four arrow keys to activate a transient map in which the four
-arrow keys have the bindings they would have absent this mode.
-
-Permits globally re-binding the four arrow keys without rendering
-it impossible to access mode-specific bindings for those four
-keys (e.g. the use of the left and right arrow keys in
-`fido-mode' minibuffers)."
- ;; :init-value t
- :lighter nil :keymap spw/arrow-keys-mode-map :global t)
-
-(defun spw/arrow-keys-mode-passthru ()
- (interactive)
- ;; Possibly we could cache the map in a buffer-local variable. It'd get
- ;; cleared if the major mode changes, but we'd also need to figure out
- ;; clearing it (but not recomputing it until and unless this function is
- ;; called) if the minor modes change.
- (let ((map (make-sparse-keymap))
- (cell (cl-find 'spw/arrow-keys-mode minor-mode-map-alist :key #'car)))
- (cl-letf (((car cell) nil))
- (dolist (key '([up] [down] [left] [right]
- [S-up] [S-down] [S-left] [S-right]
- [M-up] [M-down] [M-left] [M-right]))
- (define-key map key (key-binding key))))
- (let ((key (vector last-command-event)))
- (call-interactively (lookup-key map key) t key))
- (set-transient-map map t)))
-
(defun spw/get-mru-window (&optional exclude)
"Like `get-mru-window' but also consider the minibuffer, and
don't consider windows satisfying the predicate EXCLUDE."
@@ -1377,8 +1220,8 @@ don't consider windows satisfying the predicate EXCLUDE."
;;; <left>/<right>. We could still put something on unmodified <down>/<up>,
;;; which I used to use for `tab-bar-history-mode' forward & back commands.
;;; (`spw/arrow-keys-mode' made it feasible to bind things to unmodified arrow
-;;; keys in the global map. That's disabled at present, as the unmodified
-;;; arrow keys are not in use.)
+;;; keys in the global map. That's archived to git history at present, as the
+;;; unmodified arrow keys are not in use.)
;;;
;;; We might put one of the other sets of windmove commands, such as
;;; windmove-swap-states-* commands, on C-z M-7/8/9/0, or possibly
@@ -1555,9 +1398,8 @@ state, attempt to produce some useful side window(s)."
(let ((default-directory (expand-file-name "~/")))
(slime))))
(t (error "No side windows state & no heuristic")))))))
-;; Possibly this command should go on M-5 or M-6.
-(global-set-key [remap window-toggle-side-windows]
- #'spw/window-toggle-side-windows)
+(define-key spw/personal-bindings-mode-map "\M-6"
+ #'spw/window-toggle-side-windows)
(defun spw/delete-other-windows--toggle-side-windows
(&optional window &rest _ignore)
@@ -1584,54 +1426,20 @@ the non-side windows deleted by `delete-other-windows' will also reappear."
(define-key ctl-x-5-map "\C-j" "\C-x55\C-x\C-j")
(define-key tab-prefix-map "\C-j" "\C-xtt\C-x\C-j")
-;;; For when the buffer's name isn't much help for switching to it, as is
-;;; often the case with `notmuch-show' buffers. We select the most recent
-;;; buffer but then transient cycling can take us to other buffers of the same
-;;; major mode.
-
-(defun spw/read-major-mode-recent-buffer ()
- (let ((buffers (make-hash-table)))
- (dolist (buffer (buffer-list))
- (with-current-buffer buffer
- (unless (gethash major-mode buffers)
- (puthash major-mode buffer buffers))))
- (list
- (gethash
- (intern
- (completing-read
- "Most recent buffer of major mode: " (hash-table-keys buffers) nil t))
- buffers))))
-
-(spw/transient-cycles-define-buffer-switch
- ((("\C-zb" . spw/switch-to-recent-major-mode-buffer) (buffer)
- (interactive (spw/read-major-mode-recent-buffer))
- (switch-to-buffer buffer t))
-
- (("\C-z4b" . spw/switch-to-recent-major-mode-buffer-other-window) (buffer)
- (interactive (spw/read-major-mode-recent-buffer))
- (switch-to-buffer-other-window buffer t))
-
- (("\C-z5b" . spw/switch-to-recent-major-mode-buffer-other-frame) (buffer)
- (interactive (spw/read-major-mode-recent-buffer))
- (switch-to-buffer-other-frame buffer t))
-
- (("\C-z4\C-o" . spw/display-recent-major-mode-buffer) (buffer)
- (interactive (spw/read-major-mode-recent-buffer))
- (display-buffer buffer))))
+(autoload 'redtick "redtick")
+(global-set-key "\C-cP" #'redtick)
+(autoload 'redtick-mode "redtick")
+(global-set-key "\C-cgP" #'redtick-mode)
;;;; TRAMP
-(with-eval-after-load 'tramp
- (add-to-list 'tramp-connection-properties
- ;; Activate direct-async-process for all non-multihop SSH
- ;; connections.
- '("/ssh:" "direct-async-process" t)
- ;; session-timeout is about dropping a connection for security
- ;; reasons alone: never do that.
- '(nil "session-timeout" nil))
-
- (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
+(spw/feature-add-to-list tramp-connection-properties tramp
+ ;; Activate `direct-async-process' for all non-multihop SSH connections.
+ '("/ssh:" "direct-async-process" t)
+ ;; Don't drop connections for security reasons alone.
+ '(nil "session-timeout" nil))
+(spw/feature-add-to-list tramp-remote-path tramp 'tramp-own-remote-path)
(unless (string-match ; Emacs 28: unquote and `string-search'
(regexp-quote tramp-file-name-regexp) vc-ignore-dir-regexp)
@@ -1642,6 +1450,21 @@ the non-side windows deleted by `delete-other-windows' will also reappear."
;;;; The Emacs shell
+(custom-theme-set-variables
+ 'user
+ ;; This makes Eshell completions a bit more like bash's.
+ '(eshell-cmpl-cycle-completions nil)
+
+ '(eshell-cmpl-ignore-case t)
+ '(eshell-hist-ignoredups 'erase)
+ '(eshell-history-append t)
+ '(eshell-history-size 5000)
+ '(eshell-save-history-on-exit nil))
+(spw/feature-add-to-list eshell-modules-list esh-module
+ 'eshell-elecslash 'eshell-tramp 'eshell-xtra)
+(spw/feature-add-to-list eshell-visual-commands em-term
+ "locmaint" "gen-DSA" "gen-ELA")
+
(with-eval-after-load 'esh-cmd
(add-hook 'eshell-pre-command-hook
(lambda ()
@@ -1676,19 +1499,6 @@ the non-side windows deleted by `delete-other-windows' will also reappear."
;; history of recent dirs is effectively buffer-local.
(setq eshell-last-dir-ring-file-name nil)
-(defun spw/eshell-cd-project-root ()
- (interactive)
- (if-let ((project (project-current)))
- (spw/eshell-cd (project-root project))
- (user-error "No current project")))
-(with-eval-after-load 'esh-mode
- (define-key eshell-mode-map "\C-zp" #'spw/eshell-cd-project-root))
-
-;; Work around Emacs bug #54977.
-(with-eval-after-load 'esh-module
- (mapc (apply-partially #'add-to-list 'eshell-modules-list)
- '(eshell-elecslash eshell-tramp eshell-xtra)))
-
(spw/define-skeleton spw/eshell-libexec
(eshell-mode :abbrev "le" :file "esh-mode")
"" "" "~/" '(eshell-electric-forward-slash) "src/dotfiles/scripts/")
@@ -1885,7 +1695,11 @@ Some ideas behind these behaviours are as follows.
(spw/transient-cycles-define-buffer-switch
((("e" . spw/project-eshell) ()
(interactive)
- (spw/eshell-jump 'project 'interactive)))
+ (prog1 (spw/eshell-jump 'project 'interactive)
+ ;; Make it possible to use M-& to repeat C-x p e.
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\M-&" #'transient-cycles-cmd-spw/project-eshell)
+ (set-transient-map map)))))
;; Bind into project-prefix-map, rather than adding a remap, so that we
;; have it under C-x 4 p, C-x 5 p etc. too.
:keymap project-prefix-map)))
@@ -1893,8 +1707,6 @@ Some ideas behind these behaviours are as follows.
;;;; Miscellaneous functions & commands
-;;;; This is meant to be like ~/src/dotfiles/bin & ~/src/dotfiles/scripts, not
-;;;; so much about Emacs startup, except that we do want them always loaded.
;; This is an alternative way to activate the mark temporarily when
;; `transient-mark-mode' is off, and whether it's on or off, makes it
@@ -1938,15 +1750,6 @@ Some ideas behind these behaviours are as follows.
(add-hook 'isearch-mode-end-hook hook nil t)))
(define-key spw/ctl-z-map "\s" #'spw/ensure-whole-lines-mode)
-;; If know the name of group might try `gnus-read-ephemeral-gmane-group' (and
-;; if that works well, might want to make this function prompt for a group to
-;; pass to that function, and if blank, do what function does now).
-(defun spw/browse-gmane ()
- (interactive)
- (gnus-no-server)
- (gnus-group-browse-foreign-server '(nntp "news.gmane.io")))
-(global-set-key "\C-cgG" #'spw/browse-gmane)
-
(defun spw/org-reformat-subtree ()
(interactive)
;; we have to set the mark, rather than just narrowing to the subtree, or
@@ -2023,14 +1826,6 @@ Some ideas behind these behaviours are as follows.
(global-set-key "\C-cD" #'spw/delete-visited-file)
(global-set-key "\C-cvD" #'spw/vc-delete-visited-file)
-(defun spw/link-stat-block (start end)
- (interactive "r")
- (when-let ((region-text (buffer-substring start end)))
- (org-insert-link
- nil
- (concat "file:~/annex/gaming/5eblocks/" region-text ".png")
- region-text)))
-
;; Possibly this should be replaced with something like `project-find-regexp'
;;
;; Input e.g.: lisp "Emacs configuration"
@@ -2044,21 +1839,6 @@ Some ideas behind these behaviours are as follows.
nil (expand-file-name "~/doc")))
(global-set-key "\C-cog" #'spw/git-grep-docs)
-;; this is called by .dir-locals.el in ~/doc/{pres,papers}
-(defun spw/set-pandoc-compile-command (&rest exts)
- (setq-local compile-command
- (concat "make "
- (mapconcat
- (lambda (ext)
- (file-name-nondirectory
- (concat (file-name-sans-extension
- (buffer-file-name))
- "."
- ext)))
- (or exts '("pdf"))
- " ")))
- (local-set-key "\C-z\C-c" #'compile))
-
(defun spw/all-programming-projects ()
(call-process "src-register-all")
(let ((default-directory (expand-file-name "~/src")))
@@ -2134,36 +1914,6 @@ Some ideas behind these behaviours are as follows.
(display-buffer buffer))))
(global-set-key "\C-cvc" #'spw/clone-repo)
-;; author unknown
-(defun spw/toggle-frame-split ()
- "Toggle the orientation of a two-window split.
-
-Useful after resizing the frame."
- (interactive)
- (when (= (count-windows) 2)
- (let* ((this-win-buffer (window-buffer))
- (next-win-buffer (window-buffer (next-window)))
- (this-win-edges (window-edges (selected-window)))
- (next-win-edges (window-edges (next-window)))
- (this-win-2nd (not (and (<= (car this-win-edges)
- (car next-win-edges))
- (<= (cadr this-win-edges)
- (cadr next-win-edges)))))
- (splitter
- (if (= (car this-win-edges)
- (car (window-edges (next-window))))
- 'split-window-horizontally
- 'split-window-vertically)))
- (delete-other-windows)
- (let ((first-win (selected-window)))
- (funcall splitter)
- (when this-win-2nd (other-window 1))
- (set-window-buffer (selected-window) this-win-buffer)
- (set-window-buffer (next-window) next-win-buffer)
- (select-window first-win)
- (when this-win-2nd (other-window 1))))))
-(define-key spw/personal-bindings-mode-map "\M-5" #'spw/toggle-frame-split)
-
(defun spw/maybe-toggle-split-after-resize (frame)
(when (and (framep frame)
(frame-size-changed-p frame)
@@ -2251,78 +2001,6 @@ Useful after resizing the frame."
(interactive)
(spw/myrepos-global-action "sync")))
-;; There are many variations on this online. This one by Robert Bost, based
-;; on work by Steve Yegge, Colin Doering and others
-(defun spw/rotate-windows (arg)
- "Rotate your windows, reversing direction if ARG."
- (interactive "P")
- (if (not (> (count-windows) 1))
- (message "You can't rotate a single window!")
- (let* ((rotate-times (prefix-numeric-value arg))
- (direction (if (or (< rotate-times 0) (equal arg '(4)))
- 'reverse 'identity)))
- (dotimes (_ (abs rotate-times))
- (dotimes (i (- (count-windows) 1))
- (let* ((w1 (elt (funcall direction (window-list)) i))
- (w2 (elt (funcall direction (window-list)) (+ i 1)))
- (b1 (window-buffer w1))
- (b2 (window-buffer w2))
- (s1 (window-start w1))
- (s2 (window-start w2))
- (p1 (window-point w1))
- (p2 (window-point w2)))
- (set-window-buffer-start-and-point w1 b2 s2 p2)
- (set-window-buffer-start-and-point w2 b1 s1 p1)))))))
-;; This gets this key because we're likely to want to invoke it repeatedly.
-(define-key spw/personal-bindings-mode-map "\M-6" #'spw/rotate-windows)
-
-;; some influence here from Michael Stapelberg's config -- we both had a
-;; function to do this, I discovered
-(defun spw/recipient-first-name ()
- "Attempt to extract the first name of the recipient of a `message-mode' message.
-
-Used in my `message-mode' yasnippets."
- (if-let ((to (save-excursion
- (save-restriction
- (message-narrow-to-headers-or-head)
- (message-fetch-field "To")))))
- (let ((full-name (car (mail-extract-address-components to))))
- (if (string-match "\\([^ ]+\\)" full-name)
- (let ((first-name (match-string 0 full-name)))
- (cond
- ;; some names which may be in a longer form in the From header
- ;; but which I would never type out in full in a salutation
- ((string= first-name "Nathaniel") "Nathan")
- ((string= first-name "Thomas") "Tom")
- (t first-name)))
- ;; no spaces -- assume whole thing is an alias and use it
- full-name))
- ""))
-
-(spw/define-skeleton spw/message-dear
- (message-mode :abbrev "dear" :file "message")
- ""
- (completing-read "Dear " (ignore-errors (list (spw/recipient-first-name))))
- '(when (setq v1 (looking-at ">")) (forward-line -2))
- "Dear " str "," \n \n
- '(when v1 (forward-line 2)))
-
-(spw/define-skeleton spw/message-hello
- (message-mode :abbrev "hl" :file "message")
- ""
- (completing-read "Hello " (ignore-errors (list (spw/recipient-first-name))))
- '(when (setq v1 (looking-at ">")) (forward-line -2))
- "Hello " str '(when (zerop (length str)) (delete-backward-char 1)) "," \n \n
- '(when v1 (forward-line 2)))
-
-(spw/define-skeleton spw/message-thanks
- (message-mode :abbrev "ty" :file "message")
- ""
- (completing-read "Dear " (ignore-errors (list (spw/recipient-first-name))))
- '(when (setq v1 (looking-at ">")) (forward-line -2))
- "Dear " str "," \n \n "Thank you for your e-mail." \n \n
- '(when v1 (forward-line 2)))
-
(defun spw/copy-to-annotated ()
(interactive)
(let* ((source (expand-file-name (dired-file-name-at-point)))
@@ -2572,56 +2250,6 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
(not (string= (daemonp) "gdbmacs"))
(eq (server-running-p "gdbmacs") t)))
-;; open a frame on a new workspace with only the relevant dired buffer open,
-;; eval this form: (global-set-key "\C-cG" #'spw/grading-advance)
-;; and then use C-c G to open the first item (will need C-c f t after just
-;; this first one, and also maybe C-i =)
-(defun spw/grading-advance ()
- (interactive)
- (unless (eq major-mode 'dired-mode)
- (when (eq major-mode 'org-mode)
- (ignore-errors (org-ctrl-c-ctrl-c)))
- (save-buffer)
- (other-window 1))
- (dired-display-file)
- (dired-next-line 1)
- (let ((pdf (dired-get-filename)))
- (dired-next-line 1)
- (other-window 1)
- (goto-char (point-min))
-
- ;; assignment-specific
- (search-forward "Grammar")
- (org-cycle)
- (set-goal-column nil)
- ;; (overwrite-mode 1)
-
- (start-process "pdf" "pdf" "xdg-open" pdf)
- (sleep-for 1)
- (call-process-shell-command
- (concat (if (executable-find "i3-msg") "i3-msg" "swaymsg")
- " move right"))
- (let ((pdf-words (substring (with-temp-buffer
- (call-process-shell-command
- (concat "pdftotext "
- (shell-quote-argument pdf)
- " - | wc -w")
- nil
- (current-buffer))
- (buffer-string))
- 0
- -1)))
- (message (concat pdf-words " words")))))
-
-(defun spw/untabify-project ()
- (interactive)
- (save-window-excursion
- (dolist (file (project-files
- (project-current nil (project-prompt-project-dir))))
-
- (find-file file)
- (untabify (point-min) (point-max)))))
-
(defun spw/go-to-consfig ()
(interactive)
;; (let ((repo (expand-file-name "~/src/cl/consfig")))
@@ -2707,32 +2335,6 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
(string-join (cons "rm -f config.cache; ./configure -C" (cdr conf)) " ")
nil :system t)))
-(defun spw/read-athenet-lxc ()
- (let (lxcs
- (file (expand-file-name "~/src/cl/consfig/hosts.lisp")))
- (unless (file-exists-p file)
- (user-error "Looks like consfig not checked out"))
- (with-current-buffer (find-file-noselect file)
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-min))
- (while (re-search-forward
- "(define-athenet-container \\([a-z0-9-.]+\\)
-\\s-*\"\\([a-z0-9-.]+\\)"
- nil t)
- (push (list (substring-no-properties (match-string 1))
- (substring-no-properties (match-string 2)))
- lxcs)))))
- (assoc (completing-read "LXC: " lxcs nil t) lxcs #'string=)))
-
-(defun spw/ssh-and-lxc-attach-term (container host)
- (interactive (spw/read-athenet-lxc))
- (start-process "ssh-and-tmux" nil "foot" "ssh-and-tmux" host
- (format "--container-name=%s" container)
-"--container-cmd=lxc-unpriv-attach -n %s --keep-var TERM --clear-env -vHOME=/root"))
-(global-set-key "\C-cgL" #'spw/ssh-and-lxc-attach-term)
-
(defun spw/proced-root ()
(interactive)
(require 'proced)
@@ -2797,6 +2399,7 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
;; `compile' or `project-compile' is called, and one Emacs frame/tab for GUD.
(defun spw/run-or-restore-gud (arg)
(interactive "P")
+ (require 'gdb-mi)
(if (or arg (not (and (bound-and-true-p gud-comint-buffer)
(get-buffer-process gud-comint-buffer))))
;; Start a new debugging session even if one already exists.
@@ -2825,7 +2428,7 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
(interactive)
(let ((string (ignore-errors (cdr (bounds-of-thing-at-point 'string)))))
(fill-region-as-paragraph
- (car (bounds-of-thing-at-point 'sentence))
+ (point)
(cond (string (min string (cdr (bounds-of-thing-at-point 'paragraph))))
((cl-fifth (syntax-ppss))
(min (cdr (bounds-of-thing-at-point 'paragraph))
@@ -2848,6 +2451,7 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
(global-set-key "\C-ce" #'spw/fill-rest-of-paragraph)
(global-set-key "\C-cj" "\M-j\C-ce")
+;;;; "Miscellaneous functions & commands" page ends here
;;;; Terminal emulation
@@ -2876,6 +2480,43 @@ Called by '~/src/dotfiles/bin/emacsclient --spw/update-environment'."
;;;; Composing mail
+(custom-theme-set-variables
+ 'user
+ ;; So locmaint will catch them.
+ '(message-auto-save-directory "~/tmp/")
+
+ '(message-citation-line-format "On %a %d %b %Y at %I:%M%p %Z, %N wrote:\12")
+ '(message-citation-line-function 'message-insert-formatted-citation-line)
+
+ ;; For compatibility.
+ '(message-forward-as-mime nil)
+ '(message-forward-before-signature nil)
+ '(message-forward-included-headers
+ '("^From:" "^Subject:" "^Date:" "^To:" "^Cc:" "^Message-ID:"))
+ '(message-make-forward-subject-function '(message-forward-subject-fwd))
+
+ '(message-ignored-resent-headers
+ "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:\\|^>?From \\|^Delivered-To:\\|^\\(?:X-\\)?Content-Length:\\|^X-UIDL:\\|^X-TUID:\\|^\\(?:X-\\)?Status:\\|^Lines:")
+
+ ;; Bypass MTA rewriting user@localhost.
+ '(message-sendmail-envelope-from 'header)
+
+ '(message-wash-forwarded-subjects t)
+ '(mm-decrypt-option 'known)
+ '(mm-default-directory "~/tmp/")
+ '(mm-file-name-rewrite-functions
+ '(mm-file-name-delete-control mm-file-name-delete-gotchas
+ mm-file-name-trim-whitespace
+ mm-file-name-collapse-whitespace
+ mm-file-name-replace-whitespace))
+
+ ;; So I can read copies in my sent mail directory.
+ '(mml-secure-openpgp-encrypt-to-self t)
+
+ '(mml-secure-openpgp-sign-with-sender t)
+ '(nnmail-extra-headers '(To Cc List-Id))
+ '(notmuch-address-use-company nil))
+
(defvar spw/debian-bts-pseudoheader-regexp
;; "^\\([A-Za-z][a-z]+: [^ ]+\\|[cC]ontrol: .+\\)$"
"^[A-Za-z][a-z]+: [^ ]+"
@@ -3064,6 +2705,9 @@ mutt's review view, after exiting EDITOR."
(require 'notmuch-address) (notmuch-address-setup))
(add-hook 'message-mode-hook #'footnote-mode)
+ (spw/when-library-available orgalist
+ (add-hook 'message-mode-hook #'orgalist-mode))
+ (add-hook 'message-mode-hook #'orgtbl-mode)
(define-key message-mode-map
[remap message-newline-and-reformat] #'spw/message-newline-and-reformat)
@@ -3076,6 +2720,15 @@ mutt's review view, after exiting EDITOR."
;;;; Dired
+(custom-theme-set-variables
+ 'user
+ '(dired-clean-up-buffers-too nil)
+ '(dired-dwim-target t)
+ '(dired-free-space 'separate)
+ '(dired-listing-switches "--group-directories-first -alh")
+ '(dired-omit-files "\\`[.]?#\\|\\`[.][.]?\\'\\|\\`\\.git\\'")
+ '(dired-recursive-copies 'always))
+
;; this is the way you're meant to request dired-aux, not just dired-x,
;; according to (info "(dired-x) Installation")
(with-eval-after-load 'dired (require 'dired-x))
@@ -3152,7 +2805,7 @@ mutt's review view, after exiting EDITOR."
"&" #'spw/dired-copy-filename-as-kill)
-;;;; EWW
+;;;; EWW / shr
;; this should ensure that M-a and M-e work for most webpages
(add-hook 'eww-mode-hook (lambda ()
@@ -3182,9 +2835,66 @@ mutt's review view, after exiting EDITOR."
(setq-local bookmark-make-record-function
#'spw/bookmark-eww-bookmark-make-record)))
+(customize-set-variable 'nov-text-width 78)
+(spw/when-library-available nov
+ (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))
+
;;;; Gnus
+(custom-theme-set-variables
+ 'user
+ '(gnus-article-skip-boring t)
+ '(gnus-auto-center-summary nil)
+ '(gnus-auto-select-next 'slightly-quietly)
+ '(gnus-buttonized-mime-types
+ '("text/x-\\(?:diff\\|patch\\)" "multipart/\\(?:alternative\\|signed\\)"))
+ '(gnus-directory "~/local/News/")
+ '(gnus-extra-headers '(To Cc List-Id))
+ '(gnus-gcc-mark-as-read t)
+ '(gnus-global-score-files '("~/doc/News/"))
+ '(gnus-interactive-exit 'quiet)
+ '(gnus-kill-files-directory "~/src/athpriv/News/")
+
+ ;; Would prefer nil but t seems advisable for notmuch groups.
+ '(gnus-kill-summary-on-exit t)
+
+ '(gnus-large-ephemeral-newsgroup 8000)
+ '(gnus-large-newsgroup 8000)
+ '(gnus-mark-article-hook '(spw/gnus-mark-article-hook))
+ '(gnus-message-archive-group "sent")
+ '(gnus-message-archive-method '(nnmaildir "fmail" (directory "~/.fmail/")))
+ '(gnus-permanently-visible-groups "^nnmaildir\\+fmail:\\(?:notes\\|sent\\)$")
+ '(gnus-read-newsrc-file nil)
+ '(gnus-refer-thread-use-search '(("nnmaildir:fmail")))
+ '(gnus-save-killed-list
+ "^\\(?:[^n]\\|n[^n]\\|nn[^s]\\|nns[^e]\\|nnse[^l]\\|nnsel[^e]\\|nnsele[^c]\\|nnselec[^t]\\|nnselect[^:]\\)")
+ '(gnus-save-newsrc-file nil)
+ '(gnus-search-default-engines '((nnmaildir . notmuch)))
+ '(gnus-search-notmuch-remove-prefix "~/.fmail/")
+ '(gnus-secondary-select-methods
+ '((nnmaildir "fmail" (directory "~/.fmail/"))))
+ '(gnus-sum-thread-tree-false-root "")
+ '(gnus-sum-thread-tree-indent " ")
+ '(gnus-sum-thread-tree-leaf-with-other "├► ")
+ '(gnus-sum-thread-tree-root "")
+ '(gnus-sum-thread-tree-single-leaf "╰► ")
+ '(gnus-sum-thread-tree-vertical "│")
+ '(gnus-summary-line-format "%U%R%z %(%12&user-date; %*%-23,23f%) %B%s\12")
+ '(gnus-summary-mode-line-format "Gnus: %u&summary;%g [%A] %Z")
+ '(gnus-summary-thread-gathering-function 'gnus-gather-threads-by-references)
+ '(gnus-suppress-duplicates t)
+ '(gnus-thread-sort-functions
+ '(gnus-thread-sort-by-number gnus-thread-sort-by-total-score))
+ '(gnus-topic-display-empty-topics nil)
+ '(gnus-update-message-archive-method t)
+ '(gnus-user-date-format-alist
+ '((32042 . "%2l:%M%#p")
+ (118823 . "Yest %2l:%M%#p")
+ (604800 . "%a %2l:%M%#p")
+ (16102447 . "%d %B")
+ (t . "%Y-%b-%d"))))
+
(with-eval-after-load 'gnus
(cond ((spw/on-host-p "chiark.greenend.org.uk")
(setq gnus-select-method
@@ -3890,7 +3600,8 @@ unread."
;; `gnus-summary-save-parts' has some alternative ways to get the handles
;; if `gnus-article-mime-handles' is nil.
(let ((handles gnus-article-mime-handles))
- (when (stringp (car handles)) (pop handles))
+ (when (stringp (car handles))
+ (setq handles (cdr handles)))
(mapc #'mm-save-part (cl-remove-if-not #'mm-handle-filename handles)))))
(with-eval-after-load 'gnus-sum
@@ -3906,25 +3617,39 @@ unread."
(gnus-summary-goto-article article)))
(advice-add 'org-gnus-follow-link :around #'spw/org-gnus-follow-link)
-(defun spw/gnus-fastmail-trash (n)
+(defun spw/gnus-purelymail-trash (n)
(interactive "p")
(gnus-summary-move-article n "nnmaildir+fmail:trash"))
(with-eval-after-load 'gnus-sum
(define-key gnus-summary-mode-map
- [remap gnus-summary-delete-article] #'spw/gnus-fastmail-trash))
+ [remap gnus-summary-delete-article] #'spw/gnus-purelymail-trash))
-(defun spw/gnus-fastmail-learn-spam (n)
+(defun spw/gnus-purelymail-learn-spam (n)
(interactive "p")
(save-excursion (gnus-summary-mark-forward n))
- (gnus-summary-move-article n "nnmaildir+fmail:spam")
+ (gnus-summary-move-article n "nnmaildir+fmail:junk")
(gnus-summary-next-unread-article))
(with-eval-after-load 'gnus-sum
- (define-key gnus-summary-mode-map [f5] #'spw/gnus-fastmail-learn-spam)
- (define-key gnus-summary-mode-map "\C-z\C-s" #'spw/gnus-fastmail-learn-spam))
+ (define-key gnus-summary-mode-map [f5] #'spw/gnus-purelymail-learn-spam)
+ (define-key gnus-summary-mode-map "\C-z\C-s" #'spw/gnus-purelymail-learn-spam))
;;;; rcirc
+(custom-theme-set-variables
+ 'user
+ '(rcirc-default-full-name "Sean Whitton [spwhitton@spwhitton.name]")
+ '(rcirc-default-nick "spwhitton")
+ '(rcirc-default-user-name "spwhitton")
+ '(rcirc-display-server-buffer nil)
+ '(rcirc-log-directory "~/local/irclogs")
+ '(rcirc-log-filename-function 'spw/rcirc-generate-log-filename)
+ '(rcirc-log-flag t)
+ '(rcirc-time-format "%b/%d %H:%M ")
+ '(rcirc-track-abbreviate-flag nil)
+ '(rcirc-track-ignore-server-buffer-flag t)
+ '(rcirc-track-minor-mode t))
+
(defun spw/rcirc-generate-log-filename (process target)
(concat (file-name-concat (format-time-string "%Y/%m")
(process-name process) (or target "server"))
@@ -4004,6 +3729,30 @@ unread."
;;;; VC
+(custom-theme-set-variables
+ 'user
+ '(git-rebase-confirm-cancel nil)
+ '(vc-deduce-backend-nonvc-modes t)
+ '(vc-find-revision-no-save t)
+ '(vc-follow-symlinks t)
+
+ ;; We might also consider -B.
+ '(vc-git-diff-switches '("--patch-with-stat" "-M" "-C"))
+
+ '(vc-git-print-log-follow t)
+
+ ;; Drop the name & date to make more of the commit message visible.
+ '(vc-git-root-log-format
+ '("%d%h..: %s"
+ "^\\(?:[*/\\| ]+ \\)?\\(?2: ([^)]+)\\)?\\(?1:[0-9a-z]+\\)\\.\\.: "
+ ((1 'log-view-message) (2 'change-log-list nil lax)))))
+
+;; Avoid `log-edit-show-files' window becoming most recently used for C-x o.
+(with-eval-after-load 'log-edit
+ (customize-set-variable 'log-edit-hook
+ (cons 'spw/log-edit-show-diff
+ (delete 'log-edit-show-files log-edit-hook))))
+
(require 'git-commit nil t)
(spw/when-library-available mailscripts
@@ -4016,7 +3765,7 @@ unread."
"vt" notmuch-extract-thread-patches-to-project
"vw" mailscripts-extract-message-patches-to-project))
-;; Emacs 30: move into `custom-set-variables'.
+;; Emacs 30: move into `custom-theme-set-variables' call.
(when (>= emacs-major-version 30)
(setopt vc-git-log-switches '("--format=fuller" "--stat")))
@@ -4269,70 +4018,12 @@ unread."
(global-set-key "\C-cvf" 'spw/vc-next-action-for-git-fixup)
-;;;; Assorted packages
-
-;; message-mode is sensitive to trailing whitespace in sig dashes and empty
-;; headers. markdown-mode is sensitive in empty headers (e.g. "# " which I
-;; use in writing essays) and newlines that indicate paragraph flow (obscure
-;; Markdown feature)
-;;
-;; The message-mode case is handled by `spw/normalise-message', which is
-;; better than setting `ws-butler-trim-predicate' to a complicated function
-;; because the code in `spw/normalise-message' gets called less often. Could
-;; try setting `ws-butler-trim-predicate' to handle the markdown-mode case,
-;; but chances are someday I'll want to use that obscure markdown-mode feature
-(define-globalized-minor-mode spw/ws-butler-global-mode ws-butler-mode
- (lambda () (when (buffer-file-name) (ws-butler-mode 1)))
- :predicate '((not markdown-mode
- message-mode
- lisp-interaction-mode)
- prog-mode text-mode))
-(spw/ws-butler-global-mode 1)
-
-(autoload 'redtick "redtick")
-(global-set-key "\C-cP" #'redtick)
-(autoload 'redtick-mode "redtick")
-(global-set-key "\C-cgP" #'redtick-mode)
-
-(with-eval-after-load 'org-d20
- (setq org-d20-dice-sound
- "~/annex/media/sounds/147531__ziembee__diceland.wav"
- org-d20-display-rolls-buffer t
- ;; the roll20 tokens I'm using for NPCs are lettered
- org-d20-letter-monsters t
- ;; ... and they come in only two colours, so let's just have
- ;; one monster per letter
- org-d20-continue-monster-numbering t)
-
- (define-key org-d20-mode-map [f5] #'org-d20-initiative-dwim)
- (define-key org-d20-mode-map [f6] #'org-d20-damage)
-
- (define-key org-d20-mode-map [f7] (lambda (arg)
- (interactive "P")
- (call-interactively
- (if arg
- #'org-d20-roll-last
- #'org-d20-roll))))
- (define-key org-d20-mode-map [f8] #'org-d20-roll-at-point)
- (define-key org-d20-mode-map [f9] (lambda (arg)
- (interactive "P")
- (call-interactively
- (if arg
- #'org-d20-d%
- #'org-d20-d20)))))
+;;;; Haskell
-(spw/when-library-available nov
- (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))
-
-(setq ggtags-mode-line-project-name nil)
-
-(spw/when-library-available ggtags
- (dolist (hook '(cperl-mode-hook c-mode-hook))
- (add-hook hook #'ggtags-mode)))
-
-(spw/when-library-available rainbow-mode
- (dolist (hook '(html-mode-hook css-mode-hook))
- (add-hook hook 'rainbow-mode)))
+(custom-theme-set-variables
+ 'user
+ '(haskell-indentation-layout-offset 4)
+ '(haskell-indentation-left-offset 4))
(spw/feature-add-hook subword-mode haskell-mode)
@@ -4349,10 +4040,16 @@ unread."
nil t))
haskell-mode))
-(spw/when-library-available orgalist
- (spw/feature-add-hook orgalist-mode message))
+
+;;;; Bongo
-(spw/feature-add-hook orgtbl-mode message)
+(custom-theme-set-variables
+ 'user
+ '(bongo-default-directory "~/annex/music/")
+ '(bongo-insert-album-covers t)
+ '(bongo-insert-whole-directory-trees t)
+ '(bongo-mode-line-indicator-mode nil)
+ '(bongo-prefer-library-buffers nil))
(spw/feature-add-hook (lambda ()
(dired-hide-details-mode
@@ -4388,14 +4085,6 @@ unread."
;; 'v' again to exit
(global-set-key "\C-cgv" #'volume)
-(with-eval-after-load 'elpher
- ;; standard Emacs conventions
- (define-key elpher-mode-map "l" #'elpher-back)
- (define-key elpher-mode-map "d" #'elpher-back-to-start)
- (define-key elpher-mode-map "<" #'elpher-root-dir)
-
- (add-hook 'elpher-mode-hook (lambda () (variable-pitch-mode 1))))
-
;;;; Lisp
@@ -4465,15 +4154,6 @@ unread."
(with-temp-buffer (call-interactively #'hyperspec-lookup)))
(global-set-key "\C-cgh" #'spw/hyperspec-lookup)
-;; `inf-lisp' says this is a defcustom and `slime' says it is a defvar, so
-;; `custom-save-variables' will print the NOW field in the corresponding
-;; argument to `custom-set-variables' as t or nil depending on whether or not
-;; `inf-lisp' and/or `slime' happen to be loaded, and possibly even depending
-;; on the order in which they were loaded. To prevent spurious changes to the
-;; NOW field randomly showing up in git diffs of init.el, set the variable
-;; without using the customisation interface.
-(setq inferior-lisp-program "sbcl")
-
(defvar spw/last-command-was-slime-async-eval nil)
(defvar spw/last-slime-async-eval-command-frame nil)
@@ -4537,22 +4217,6 @@ that the user is expecting that it might pop up."
(defslime-repl-shortcut nil ("clear-source-registry")
(:handler #'spw/slime-clear-source-registry)))
-(defun spw/comment-form (n)
- "Replacement for \\[comment-line] in Lisp modes which is more
-likely to keep parentheses balanced."
- (interactive "p")
- (if (use-region-p)
- (comment-line n)
- (let ((begin (point))
- (end (line-end-position)))
- (skip-chars-forward "; \t" end)
- (forward-sexp)
- (unless (> (point) (line-end-position))
- (comment-or-uncomment-region begin (point))))))
-(define-key lisp-mode-shared-map [?\C-x ?\C-\;] #'spw/comment-form)
-(when (boundp 'lisp-data-mode-map) ; Emacs 27
- (define-key lisp-data-mode-map [?\C-x ?\C-\;] #'spw/comment-form))
-
;; Loading `slime' puts `slime-macrostep' on `load-path'.
;; `slime-macrostep' knows how to load an embedded copy of `macrostep'.
(with-eval-after-load 'slime (require 'slime-macrostep))
@@ -4787,6 +4451,97 @@ before uploading to NEW again." \n \n
;;;; Org-mode
+(custom-theme-set-faces
+ 'user
+ '(org-code ((t (:inherit (shadow fixed-pitch)))))
+ '(org-date ((t (:inherit fixed-pitch :foreground "Purple" :underline t))))
+ '(org-verbatim ((t (:inherit (shadow fixed-pitch))))))
+
+(custom-theme-set-variables
+ 'user
+ ;; Sometimes set to nil in .dir-locals.el, e.g. in ~/doc/newpapers.
+ '(org-adapt-indentation t nil)
+
+ '(org-agenda-entry-text-maxlines 3)
+ '(org-agenda-files "~/doc/org-agenda-files")
+ '(org-agenda-persistent-filter t)
+ '(org-agenda-remove-times-when-in-prefix 'beg)
+
+ ;; Interacts badly with `tab-bar-history-mode'.
+ '(org-agenda-restore-windows-after-quit nil)
+
+ '(org-agenda-skip-deadline-if-done t)
+ '(org-agenda-skip-deadline-prewarning-if-scheduled 3)
+ '(org-agenda-skip-scheduled-if-deadline-is-shown 'not-today)
+ '(org-agenda-skip-scheduled-if-done t)
+ '(org-agenda-skip-timestamp-if-done t)
+ '(org-agenda-start-on-weekday nil)
+ '(org-agenda-sticky t)
+ '(org-agenda-timegrid-use-ampm t)
+ '(org-agenda-todo-ignore-scheduled 'future)
+ '(org-agenda-window-setup 'current-window)
+ '(org-archive-location "~/doc/archive/howm/archive.org::* From %s")
+ '(org-archive-save-context-info '(time file olpath))
+ '(org-archive-subtree-save-file-p t)
+ '(org-blank-before-new-entry '((heading . t) (plain-list-item . auto)))
+
+ ;; Turn off to avoid git merge conflicts.
+ '(org-bookmark-names-plist nil)
+
+ '(org-cycle-separator-lines 0)
+ '(org-deadline-warning-days 60)
+ '(org-default-notes-file "~/doc/howm/refile.org")
+ '(org-directory "~/doc/howm/")
+ '(org-enforce-todo-checkbox-dependencies t)
+ '(org-enforce-todo-dependencies t)
+ '(org-fold-catch-invisible-edits 'show)
+ '(org-fold-show-context-detail
+ '((agenda . local) (bookmark-jump . lineage) (isearch . lineage)
+ (default . ancestors-full)))
+ '(org-footnote-section "Notes")
+ '(org-imenu-depth 4)
+
+ ;; So I can start lines with \"P. 211 - \" to refer to p. 211, rather than
+ ;; starting a list.
+ '(org-list-allow-alphabetical nil)
+
+ '(org-list-demote-modify-bullet
+ '(("-" . "+") ("+" . "*") ("*" . "-") ("1." . "-") ("1)" . "-")))
+ '(org-list-use-circular-motion t)
+ '(org-log-done 'time)
+ '(org-log-into-drawer t)
+
+ ;; Cluttering, and information probably in git.
+ '(org-log-repeat nil)
+
+ '(org-log-states-order-reversed nil)
+
+ ;; Desirable with `icomplete-mode'.
+ '(org-outline-path-complete-in-steps nil)
+
+ '(org-read-date-prefer-future 'time)
+ '(org-refile-allow-creating-parent-nodes 'confirm)
+ '(org-refile-targets '((org-agenda-files :maxlevel . 5) (nil :maxlevel . 5)))
+ '(org-refile-use-outline-path 'file)
+ '(org-special-ctrl-a/e t)
+ '(org-special-ctrl-k t)
+ '(org-startup-folded nil)
+
+ ;; Ensures buffer text doesn't go beyond 80 columns.
+ '(org-startup-indented nil)
+
+ '(org-tags-match-list-sublevels 'indented)
+ '(org-todo-keyword-faces
+ '(("SOMEDAY" :foreground "#0000FF" :weight bold)
+ ("NEXT" :foreground "#DD0000" :weight bold)))
+ '(org-todo-keywords
+ '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
+ (sequence "WAITING(w@)" "SOMEDAY(s)" "|" "CANCELLED(c)")))
+ '(org-treat-S-cursor-todo-selection-as-state-change nil)
+ '(org-treat-insert-todo-heading-as-state-change t)
+ '(org-use-fast-todo-selection 'expert)
+ '(org-yank-folded-subtrees nil))
+
(global-set-key "\C-coc" #'org-capture)
(global-set-key "\C-col" #'org-store-link)
(global-set-key "\C-coa" #'org-agenda)
@@ -4841,17 +4596,17 @@ before uploading to NEW again." \n \n
("m" ((in-mode . "gnus-summary-mode"))))
org-capture-templates
'(("t" "Task to be refiled" entry (file org-default-notes-file)
- "* TODO %^{Title}\n%?")
+ "* TODO %^{Title}\n%?"
+ :empty-lines 1)
("T" "Task to be refiled" entry (file org-default-notes-file)
- "* TODO %^{Title}\n%?")
+ "* TODO %^{Title}\n%?"
+ :empty-lines 1)
("n" "Information to be refiled" entry (file org-default-notes-file)
- "* %^{Title}\n%?")
+ "* %^{Title}\n%?"
+ :empty-lines 1)
("m" "Task from mail to be refiled" entry (file org-default-notes-file)
- ;; Lisp is to filter square brackets out of the subject as these mean that
- ;; the Org-mode link does not properly form. In Org 9.3, the escaping
- ;; syntax for links has changed, so might be able to do something smarter
- ;; than this
- "* TODO [[gnus:%:group#%:message-id][%^{Title|\"%(replace-regexp-in-string \"\\\\\\[\\\\\\|\\\\\\]\" \"\" \"%:subject\")\" from %:fromname}]]\n%?")
+ "* TODO [[gnus:%:group#%:message-id][%^{Title|%:fromname ⁘ %:subject}]]\n%?"
+ :empty-lines 1)
;; ("a" "Appointment" entry (file+datetree "~/doc/howm/diary.org")
;; "* %^{Time} %^{Title & location}
@@ -4861,11 +4616,13 @@ before uploading to NEW again." \n \n
;; %^t" :immediate-finish t)
("s" "Task for the future to be refiled" entry (file org-default-notes-file)
- "* SOMEDAY %^{Title}\n%?")
- ("d" "Diary entry" entry (file+datetree "~/.labbook.gpg")
- "* %^{Title}\n%U\n\n%?")
+ "* SOMEDAY %^{Title}\n%?"
+ :empty-lines 1)
+ ("d" "Diary entry" entry (file+olp+datetree "~/.labbook.gpg") "* %U\n\n%?"
+ :jump-to-captured t :empty-lines 1 :tree-type month)
("u" "URI on clipboard" entry (file org-default-notes-file)
- "* SOMEDAY [[%^{URI|%x}][%^{Title}]]" :immediate-finish t)))
+ "* SOMEDAY [[%^{URI|%x}][%^{Title}]]"
+ :immediate-finish t :empty-lines 1)))
;; `org-forward-paragraph', `org-backward-paragraph' and `org-mark-element' do
;; not leave point where someone who uses `forward-paragraph',
@@ -4988,8 +4745,7 @@ Called by doccheckin script."
;; setting this means if we type C-c C-e o O then the PDF opens for inspection
(setq org-odt-preferred-output-format "pdf")
-(with-eval-after-load 'org
- (add-to-list 'org-file-apps '(system . "xdg-open %s")))
+(spw/feature-add-to-list org-file-apps org '(system . "xdg-open %s"))
;; ... but also ensure we get a .docx (would be better to make
;; `org-odt-preferred-output-format' accept a list)
@@ -4999,6 +4755,29 @@ Called by doccheckin script."
(org-odt-convert org-input "docx")))
(advice-add 'org-odt-export-to-odt :after #'spw/org-odt-export-docx)
+(custom-theme-set-variables
+ 'user
+ '(org-d20-dice-sound "~/annex/media/sounds/147531__ziembee__diceland.wav")
+ '(org-d20-display-rolls-buffer t)
+ ;; The Roll20 tokens I'm using for NPCs are lettered, and they come in only
+ ;; two colours, so one monster per letter.
+ '(org-d20-letter-monsters t)
+ '(org-d20-continue-monster-numbering t))
+(spw/feature-define-keys org-d20
+ [f5] org-d20-initiative-dwim
+ [f6] org-d20-damage
+ [f7] (lambda (arg)
+ (interactive "P")
+ (call-interactively (if arg
+ #'org-d20-roll-last
+ #'org-d20-roll)))
+ [f8] org-d20-roll-at-point
+ [f9] (lambda (arg)
+ (interactive "P")
+ (call-interactively (if arg
+ #'org-d20-d%
+ #'org-d20-d20))))
+
;;;; Org-mode agenda
@@ -5329,17 +5108,34 @@ different occasions."
;;;; Diary
+(custom-theme-set-variables
+ 'user
+ '(appt-display-diary nil)
+ '(appt-display-interval 6)
+ '(calendar-date-display-form
+ '((format "%s-%.2d-%.2d %.3s" year (string-to-number month)
+ (string-to-number day) dayname)))
+ '(calendar-date-style 'iso)
+ '(calendar-week-start-day 1)
+ '(diary-file "~/doc/diary")
+ '(diary-list-entries-hook
+ '(diary-include-other-diary-files diary-sort-entries))
+ '(diary-mark-entries-hook '(diary-mark-included-diary-files))
+ '(holiday-bahai-holidays nil)
+ '(holiday-hebrew-holidays nil)
+ '(holiday-islamic-holidays nil))
+
;; Don't bind `diary' globally as for viewing purposes we use Org agenda
;; bindings, and for editing purposes just C-x b suffices.
(global-set-key "\C-cC" #'calendar)
-(when (file-readable-p "~/doc/emacs-diary")
+(when (file-readable-p "~/doc/diary")
(require 'org-agenda) ; for `org-class'
(unless
(bound-and-true-p appt-timer) ; avoid msgs when `eval-buffer' init.el
(appt-activate 1))
(add-to-list 'auto-mode-alist
- `(,(format "\\`%s\\'" (expand-file-name "~/doc/emacs-diary"))
+ `(,(format "\\`%s\\'" (expand-file-name "~/doc/diary"))
. diary-mode)))
(defun spw/diary-archive-entry (year)
@@ -5350,7 +5146,7 @@ different occasions."
(let ((start (point)))
(forward-line 1)
(while (looking-at "[[:blank:]]+") (forward-line 1))
- (append-to-file start (point) (format "~/doc/archive/emacs-diary-%d" year))
+ (append-to-file start (point) (format "~/doc/archive/diary-%d" year))
(delete-region start (point))
(when (and (bolp) (eolp)) (delete-blank-lines))))
(with-eval-after-load 'diary-lib
@@ -5423,6 +5219,13 @@ We don't use the FILES parameter in the entry for \"d\" in
;;;; Howm
+(custom-theme-set-variables
+ 'user
+ '(howm-directory "~/doc/howm/")
+ '(howm-file-name-format "%Y/%Y-%m-%d-%H%M.org")
+ '(howm-keyword-file "~/doc/howm/.howm-keys")
+ '(howm-view-use-grep t))
+
(setq howm-prefix "\C-cc"
;; Use Org-mode style because our notes are in `org-mode'.
@@ -5491,59 +5294,52 @@ We don't use the FILES parameter in the entry for \"d\" in
(when (file-directory-p "~/doc/howm/") (require 'howm nil t))
-;;;; C and friends
-
-;; following setting also part of Linux kernel style, but it's from
-;; newcomment.el, not cc-mode, so must be set in addition to
-;; `c-default-style' -- and it's my preference in general
-(setq comment-style 'extra-line)
+;;;; CC mode
-(with-eval-after-load 'cc-mode
- ;; Use the mode-specific paren binding. Default M-( binding will insert
- ;; spaces before the paren which is not called for by all C styles
- (define-key c-mode-base-map "\M-(" #'c-electric-paren)
-
- ;; I've seen this interact badly with electric-indent-mode (which is now on
- ;; globally by default, and has been on locally in c-mode for longer I
- ;; believe) outside of comments, but I cannot currently reproduce the
- ;; problem. Can always just use C-M-j and M-q within comments
- (define-key c-mode-base-map (kbd "RET") #'c-context-line-break)
+(custom-theme-set-variables
+ 'user
+ '(c-default-style "linux")
+ '(comment-style 'extra-line))
- ;; would be nice to have a global version of this
- (define-key c-mode-base-map "\C-o" #'c-context-open-line))
+(spw/feature-define-keys ((cc-mode c-mode-base-map))
+ " " c-context-line-break
+ "\C-o" c-context-open-line)
-;; M-; is adequate for GNU-style comments. This is for other styles.
+;; M-; is enough for GNU-style comments. This is for other styles.
(spw/define-skeleton spw/cc-com (c-mode :abbrev "comm" :file 'cc-mode)
"" nil "/*" \n
" * " '(c-indent-line-or-region) - \n "*/" '(c-indent-line-or-region))
+(setq ggtags-mode-line-project-name nil)
+(spw/when-library-available ggtags
+ (spw/feature-add-hook ggtags-mode (cc-mode c-mode-hook) cperl-mode))
+
;;;; Perl
-(defun spw/perl-add-use (module)
- (interactive "suse ")
- (let ((line (concat "use " module
- (and (not (string-match ";$" module)) ";"))))
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "^use " nil t))
- (forward-line 1)
- (open-line 1)
- (insert line)
- (message (concat "Inserted: " line)))))
+(custom-theme-set-variables
+ 'user
+ ;; See `cperl-indent-parens-as-block'.
+ '(cperl-close-paren-offset -4)
+
+ '(cperl-indent-level 4)
+
+ ;; Makes it easier to use longer names for subroutines.
+ '(cperl-indent-parens-as-block t)
+
+ '(cperl-lineup-step 1))
(defun spw/perltidy-region (begin end)
(interactive "r")
- (let ((perltidy-env (getenv "PERLTIDY")))
- (setenv "PERLTIDY"
- (or (concat (expand-file-name
- (locate-dominating-file
- (buffer-file-name)
- ".perltidyrc")) ".perltidyrc")
- perltidy-env))
- (shell-command-on-region begin end "perltidy -q" nil t)
- (font-lock-ensure)
- (setenv "PERLTIDY" perltidy-env)))
+ (let* ((dominating (locate-dominating-file default-directory ".perltidyrc"))
+ (process-environment
+ (if dominating
+ (cons (format "PERLTIDY=%s"
+ (expand-file-name ".perltidyrc" dominating))
+ process-environment)
+ process-environment)))
+ (shell-command-on-region begin end "perltidy -q" nil t))
+ (font-lock-ensure))
;; an older version of this would use the region if it's active, but that
;; rarely produces good results -- perltidy would get the indentation wrong
@@ -5576,11 +5372,9 @@ We don't use the FILES parameter in the entry for \"d\" in
(forward-sexp)
(forward-line)
(spw/perltidy-region begin (point))))))))
+(spw/feature-define-keys cperl-mode "\C-z\C-c" spw/perltidy-block-or-buffer)
-(spw/feature-define-keys cperl-mode
- "\C-ciu" spw/perl-add-use "\C-z\C-c" spw/perltidy-block-or-buffer)
-
-;; TODO Take "head" as input too so that we can do =method and =func too.
+;; Might adapt this so that it can do =func and =method too.
(spw/define-skeleton spw/cperl-headsub (cperl-mode :abbrev "headsub")
""
"Name and arguments: "
@@ -5591,14 +5385,6 @@ We don't use the FILES parameter in the entry for \"d\" in
> _ \n
"}")
-(spw/define-skeleton spw/cperl-trytiny (cperl-mode :abbrev "try")
- ""
- nil
- "#<<<" \n
- "try {" \n _ ?\n
- "} catch {" '(cperl-indent-line) \n _ \n "};" '(cperl-indent-line)
- \n "#>>>")
-
;; This is for turning one-liners into small scripts.
(spw/define-skeleton spw/cperl-shebang (cperl-mode :abbrev "shebang")
"" (read-string "Command line options: " "-w") ; e.g. -wln