about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorCase Duckworth2024-07-10 21:17:26 -0500
committerCase Duckworth2024-07-10 21:17:26 -0500
commit88ce9336138822d41b9b03a642bb92be4f54d987 (patch)
tree0ac76b1c17c43beab0ba7e1803c083a662d1daa4
parentUpdate xinitrc (diff)
downloaddots-88ce9336138822d41b9b03a642bb92be4f54d987.tar.gz
dots-88ce9336138822d41b9b03a642bb92be4f54d987.zip
Updates!
-rw-r--r--emacs9
-rw-r--r--emacs.d/bob-theme.el7
-rw-r--r--emacs.d/brianna-theme.el114
-rw-r--r--emacs.d/early-init.el539
-rw-r--r--exwm3
5 files changed, 343 insertions, 329 deletions
diff --git a/emacs b/emacs index 26e5bbb..9d467a1 100644 --- a/emacs +++ b/emacs
@@ -19,7 +19,7 @@
19 (set-file-modes user-private-file #o600)) 19 (set-file-modes user-private-file #o600))
20(load user-private-file :no-error) 20(load user-private-file :no-error)
21 21
22(load-theme 'bob :no-confirm) ; see ~/.emacs.d/bob-theme.el 22(load-theme 'brianna :no-confirm) ; see ~/.emacs.d/brianna-theme.el
23(add-hook 'after-init-hook #'setup-faces) 23(add-hook 'after-init-hook #'setup-faces)
24 24
25(define-advice startup-echo-area-message (:override ()) 25(define-advice startup-echo-area-message (:override ())
@@ -93,7 +93,8 @@
93(define-globalized-minor-mode auto-fixed-pitch-mode 93(define-globalized-minor-mode auto-fixed-pitch-mode
94 fixed-pitch-mode fixed-pitch-mode 94 fixed-pitch-mode fixed-pitch-mode
95 :predicate '(special-mode 95 :predicate '(special-mode
96 prog-mode)) 96 prog-mode
97 comint-mode))
97 98
98(setopt cursor-type 'bar) 99(setopt cursor-type 'bar)
99(hide-minor-mode 'buffer-face-mode) 100(hide-minor-mode 'buffer-face-mode)
@@ -495,8 +496,8 @@
495 (locate-user-emacs-file "early-init.el")) 496 (locate-user-emacs-file "early-init.el"))
496 "c" (find-user-file custom custom-file) 497 "c" (find-user-file custom custom-file)
497 "p" (find-user-file private) 498 "p" (find-user-file private)
498 "t" (find-user-file bob 499 "t" (find-user-file brianna
499 (locate-user-emacs-file "bob-theme.el")) 500 (locate-user-emacs-file "brianna-theme.el"))
500 "x" (find-user-file exwm 501 "x" (find-user-file exwm
501 (expand-file-name "~/.exwm")) 502 (expand-file-name "~/.exwm"))
502 "s" #'scratch-buffer)) 503 "s" #'scratch-buffer))
diff --git a/emacs.d/bob-theme.el b/emacs.d/bob-theme.el index 63c84db..b3efc9a 100644 --- a/emacs.d/bob-theme.el +++ b/emacs.d/bob-theme.el
@@ -37,7 +37,7 @@
37 `(font-lock-escape-face ,fclear) 37 `(font-lock-escape-face ,fclear)
38 `(font-lock-function-call-face ,fclear) 38 `(font-lock-function-call-face ,fclear)
39 `(font-lock-function-name-face ,fclear) 39 `(font-lock-function-name-face ,fclear)
40 ;; `(font-lock-keyword-face ,fclear) 40 `(font-lock-keyword-face ,fclear)
41 `(font-lock-misc-punctuation-face ,fclear) 41 `(font-lock-misc-punctuation-face ,fclear)
42 `(font-lock-negation-char-face ,fclear) 42 `(font-lock-negation-char-face ,fclear)
43 `(font-lock-number-face ,fclear) 43 `(font-lock-number-face ,fclear)
@@ -59,17 +59,16 @@
59 '(font-lock-comment-delimiter-face ((t (:slant italic)))) 59 '(font-lock-comment-delimiter-face ((t (:slant italic))))
60 '(font-lock-comment-face ((t (:slant italic)))) 60 '(font-lock-comment-face ((t (:slant italic))))
61 '(font-lock-doc-face ((t (:slant italic)))) 61 '(font-lock-doc-face ((t (:slant italic))))
62 '(font-lock-keyword-face ((t (:weight bold))))
63 62
64 ;; Propertized text 63 ;; Propertized text
65 '(bold ((t (:weight bold)))) 64 '(bold ((t (:weight bold))))
66 '(error ((t (:foreground "red" :slant italic)))) 65 '(error ((t (:foreground "red" :slant italic))))
67 '(highlight ((t (:background "yellow")))) 66 '(highlight ((t (:background "yellow"))))
68 '(isearch ((t (:background "yellow")))) 67 '(isearch ((t (:background "yellow" :foreground "black"))))
69 '(isearch-fail ((t (:inherit error)))) 68 '(isearch-fail ((t (:inherit error))))
70 '(italic ((t (:slant italic)))) 69 '(italic ((t (:slant italic))))
71 '(lazy-highlight ((t (:background "#808080")))) 70 '(lazy-highlight ((t (:background "#808080"))))
72 '(link ((t (:foreground "000080" :underline t)))) 71 '(link ((t (:foreground "#000080" :underline t))))
73 '(match ((t (:background "yellow")))) 72 '(match ((t (:background "yellow"))))
74 '(pulse-highlight-start-face ((t (:background "#000080")))) 73 '(pulse-highlight-start-face ((t (:background "#000080"))))
75 '(query-replace ((t (:background "yellow")))) 74 '(query-replace ((t (:background "yellow"))))
diff --git a/emacs.d/brianna-theme.el b/emacs.d/brianna-theme.el index 43223f6..a4cd74d 100644 --- a/emacs.d/brianna-theme.el +++ b/emacs.d/brianna-theme.el
@@ -17,7 +17,11 @@
17 ;; :inverse-video nil :extend nil))) 17 ;; :inverse-video nil :extend nil)))
18 "Specification to clear a given face.") 18 "Specification to clear a given face.")
19 19
20(defface brianna-prompt '((t (:foreground "purple"))) 20(defun fclear (face)
21 "Set FACE spec to `fclear' --- inside `custom-theme-set-faces'."
22 (list face fclear))
23
24(defface brianna-prompt '((t (:inherit bold)))
21 "A face for prompts.") 25 "A face for prompts.")
22 26
23(defface brianna-input-field '((t ( :background "lavender" 27(defface brianna-input-field '((t ( :background "lavender"
@@ -31,40 +35,37 @@
31 :background "alice blue")))) 35 :background "alice blue"))))
32 36
33 ;; Font lock -- clear 37 ;; Font lock -- clear
34 `(font-lock-bracket-face ,fclear) 38 (fclear 'font-lock-bracket-face)
35 `(font-lock-builtin-face ,fclear) 39 (fclear 'font-lock-builtin-face)
36 ;; `(font-lock-comment-delimiter-face ,fclear) 40 (fclear 'font-lock-constant-face)
37 ;; `(font-lock-comment-face ,fclear) 41 (fclear 'font-lock-delimiter-face)
38 `(font-lock-constant-face ,fclear) 42 (fclear 'font-lock-doc-markup-face)
39 `(font-lock-delimiter-face ,fclear) 43 (fclear 'font-lock-escape-face)
40 ;; `(font-lock-doc-face ,fclear) 44 (fclear 'font-lock-function-call-face)
41 `(font-lock-doc-markup-face ,fclear) 45 (fclear 'font-lock-function-name-face)
42 `(font-lock-escape-face ,fclear) 46 (fclear 'font-lock-keyword-face)
43 `(font-lock-function-call-face ,fclear) 47 (fclear 'font-lock-misc-punctuation-face)
44 `(font-lock-function-name-face ,fclear) 48 (fclear 'font-lock-negation-char-face)
45 ;; `(font-lock-keyword-face ,fclear) 49 (fclear 'font-lock-number-face)
46 `(font-lock-misc-punctuation-face ,fclear) 50 (fclear 'font-lock-operator-face)
47 `(font-lock-negation-char-face ,fclear) 51 (fclear 'font-lock-preprocessor-face)
48 `(font-lock-number-face ,fclear) 52 (fclear 'font-lock-property-name-face)
49 `(font-lock-operator-face ,fclear) 53 (fclear 'font-lock-property-use-face)
50 `(font-lock-preprocessor-face ,fclear) 54 (fclear 'font-lock-punctuation-face)
51 `(font-lock-property-name-face ,fclear) 55 (fclear 'font-lock-regexp-face)
52 `(font-lock-property-use-face ,fclear) 56 (fclear 'font-lock-regexp-grouping-backslash)
53 `(font-lock-punctuation-face ,fclear) 57 (fclear 'font-lock-regexp-grouping-construct)
54 `(font-lock-regexp-face ,fclear) 58 (fclear 'font-lock-type-face)
55 `(font-lock-regexp-grouping-backslash ,fclear) 59 (fclear 'font-lock-variable-name-face)
56 `(font-lock-regexp-grouping-construct ,fclear) 60 (fclear 'font-lock-variable-use-face)
57 `(font-lock-string-face ,fclear) 61 (fclear 'font-lock-warning-face)
58 `(font-lock-type-face ,fclear)
59 `(font-lock-variable-name-face ,fclear)
60 `(font-lock-variable-use-face ,fclear)
61 `(font-lock-warning-face ,fclear)
62 62
63 ;; Font lock 63 ;; Font lock
64 '(font-lock-comment-delimiter-face ((t (:slant italic)))) 64 '(font-lock-comment-delimiter-face ((t (:slant italic))))
65 '(font-lock-comment-face ((t (:slant italic)))) 65 '(font-lock-comment-face ((t (:slant italic))))
66 '(font-lock-doc-face ((t (:slant italic)))) 66 '(font-lock-string-face ((t (:weight bold))))
67 '(font-lock-keyword-face ((t (:weight bold)))) 67 '(font-lock-doc-face ((t (:inherit (font-lock-string-face
68 font-lock-comment-face)))))
68 69
69 ;; Propertized text 70 ;; Propertized text
70 '(bold ((t (:weight bold)))) 71 '(bold ((t (:weight bold))))
@@ -105,6 +106,16 @@
105 '(vertical-border ((t (:foreground "gray")))) 106 '(vertical-border ((t (:foreground "gray"))))
106 107
107 ;;; Specific modes &c 108 ;;; Specific modes &c
109 ;; Outline --- these go first b/c so many other headlines inherit from them
110 '(outline-1 ((t (:inherit (bold underline italic) :extend t))))
111 '(outline-2 ((t (:inherit (bold underline)))))
112 '(outline-3 ((t (:inherit (italic underline)))))
113 '(outline-3 ((t (:inherit (italic underline)))))
114 '(outline-4 ((t (:inherit (italic underline)))))
115 '(outline-5 ((t (:inherit (italic underline)))))
116 '(outline-6 ((t (:inherit (italic underline)))))
117 '(outline-7 ((t (:inherit (italic underline)))))
118 '(outline-8 ((t (:inherit (italic underline)))))
108 ;; Dired 119 ;; Dired
109 '(dired-header ((t (:underline t :extend t)))) 120 '(dired-header ((t (:underline t :extend t))))
110 ;; Elastic indent 121 ;; Elastic indent
@@ -114,17 +125,14 @@
114 ;; Eww 125 ;; Eww
115 '(eww-form-text ((t (:inherit brianna-input-field)))) 126 '(eww-form-text ((t (:inherit brianna-input-field))))
116 ;; Gemtext mode 127 ;; Gemtext mode
117 '(gemtext-face-heading1 ((t ( :weight bold 128 '(gemtext-face-heading1 ((t (:inherit outline-1))))
118 :inherit variable-pitch)))) 129 '(gemtext-face-heading2 ((t (:inherit outline-2))))
119 '(gemtext-face-heading2 ((t ( :weight bold 130 '(gemtext-face-heading3 ((t (:inherit outline-3))))
120 :inherit variable-pitch))))
121 '(gemtext-face-heading3 ((t ( :weight bold
122 :inherit variable-pitch))))
123 ;; Info 131 ;; Info
124 '(info-title-1 ((t (:inherit variable-pitch)))) 132 '(info-title-1 ((t (:inherit outline-1))))
125 '(info-title-2 ((t (:inherit variable-pitch)))) 133 '(info-title-2 ((t (:inherit outline-2))))
126 '(info-title-3 ((t (:inherit variable-pitch)))) 134 '(info-title-3 ((t (:inherit outline-3))))
127 '(info-title-4 ((t (:inherit variable-pitch)))) 135 '(info-title-4 ((t (:inherit outline-4))))
128 ;; Jabber 136 ;; Jabber
129 '(jabber-activity-face ((t (:inherit italic)))) 137 '(jabber-activity-face ((t (:inherit italic))))
130 '(jabber-activity-personal-face ((t (:inherit rcirc-track-nick)))) 138 '(jabber-activity-personal-face ((t (:inherit rcirc-track-nick))))
@@ -136,23 +144,13 @@
136 '(jabber-chat-text-local ((t (:inherit default)))) 144 '(jabber-chat-text-local ((t (:inherit default))))
137 '(jabber-muc-presence-dim ((t (:inherit shadow)))) 145 '(jabber-muc-presence-dim ((t (:inherit shadow))))
138 '(jabber-rare-time-face ((t (:inherit shadow)))) 146 '(jabber-rare-time-face ((t (:inherit shadow))))
139 '(jabber-title-large ((t (:inherit (variable-pitch outline-1))))) 147 '(jabber-title-large ((t (:inherit outline-1))))
140 '(jabber-title-medium ((t (:inherit (variable-pitch outline-2))))) 148 '(jabber-title-medium ((t (:inherit outline-2))))
141 '(jabber-title-small ((t (:inherit (variable-pitch outline-3))))) 149 '(jabber-title-small ((t (:inherit outline-3))))
142 ;; Outline
143 '(outline-1 ((t (:inherit (bold underline italic) :extend t))))
144 '(outline-2 ((t (:inherit (bold underline)))))
145 '(outline-3 ((t (:inherit (italic underline)))))
146 '(outline-3 ((t (:inherit (italic underline)))))
147 '(outline-4 ((t (:inherit (italic underline)))))
148 '(outline-5 ((t (:inherit (italic underline)))))
149 '(outline-6 ((t (:inherit (italic underline)))))
150 '(outline-7 ((t (:inherit (italic underline)))))
151 '(outline-8 ((t (:inherit (italic underline)))))
152 ;; Org 150 ;; Org
153 '(org-document-info-keyword ((t (:inherit default)))) 151 (fclear 'org-document-info-keyword)
154 '(org-document-info ((t (:foreground "navy")))) 152 (fclear 'org-document-info)
155 '(org-document-title ((t (:inherit org-document-info)))) 153 (fclear 'org-document-title)
156 '(org-drawer ((t (:inherit font-lock-comment-face)))) 154 '(org-drawer ((t (:inherit font-lock-comment-face))))
157 ;; RCIRC 155 ;; RCIRC
158 '(rcirc-my-nick ((t (:weight bold :slant italic)))) 156 '(rcirc-my-nick ((t (:weight bold :slant italic))))
@@ -165,7 +163,7 @@
165 ;; Sh 163 ;; Sh
166 '(sh-heredoc ((t ( :background "azure" :extend t 164 '(sh-heredoc ((t ( :background "azure" :extend t
167 :inherit font-lock-string-face)))) 165 :inherit font-lock-string-face))))
168 '(sh-quoted-exec ((t ()))) 166 (fclear 'sh-quoted-exec)
169 ;; Widgets 167 ;; Widgets
170 '(widget-field ((t (:inherit brianna-input-field)))) 168 '(widget-field ((t (:inherit brianna-input-field))))
171 '(widget-single-line-field ((t (:inherit brianna-input-field)))) 169 '(widget-single-line-field ((t (:inherit brianna-input-field))))
diff --git a/emacs.d/early-init.el b/emacs.d/early-init.el index bbf9464..1a5d9a5 100644 --- a/emacs.d/early-init.el +++ b/emacs.d/early-init.el
@@ -1,40 +1,103 @@
1;;; ~/.emacs.d/early-init.el -*- lexical-binding: t; -*- 1;;; ~/.emacs.d/early-init.el -*- lexical-binding: t; -*-
2;; Author: Case Duckworth <acdw@acdw.net> 2;; Author: Case Duckworth <acdw@acdw.net>
3;; In this file there are custom functions and macros and early-init settings,
4;; all alphabetically ordered.
3 5
4(setopt frame-inhibit-implied-resize t) 6;; There is a bug in M-x finger
5(setopt frame-resize-pixelwise t) 7(define-advice finger (:override (user host) acdw-fix)
6(setopt window-resize-pixelwise t) 8 "Finger USER on HOST.
7(setopt default-frame-alist 9This command uses `finger-X.500-host-regexps'
8 '((menu-bar-lines . 0) 10and `network-connection-service-alist', which see."
9 (tool-bar-lines . 0) 11 ;; One of those great interactive statements that's actually
10 ;;(vertical-scroll-bars) 12 ;; longer than the function call! The idea is that if the user
11 (horizontal-scroll-bars))) 13 ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the
14 ;; host name. If we don't see an "@", we'll prompt for the host.
15 (interactive
16 (let* ((answer (let ((default (ffap-url-at-point)))
17 (read-string (format-prompt "Finger User" default)
18 nil nil default)))
19 (index (string-match (regexp-quote "@") answer)))
20 (if index
21 (list (substring answer 0 index)
22 (substring answer (1+ index)))
23 (list answer
24 (let ((default (ffap-machine-at-point)))
25 (read-string (format-prompt "At Host" default)
26 nil nil default))))))
27 (let* ((user-and-host (concat user "@" host))
28 (process-name (concat "Finger [" user-and-host "]"))
29 (regexps finger-X.500-host-regexps)
30 ) ;; found
31 (and regexps
32 (while (not (string-match (car regexps) host))
33 (setq regexps (cdr regexps))))
34 (when regexps
35 (setq user-and-host user))
36 (run-network-program
37 process-name
38 host
39 (cdr (assoc 'finger network-connection-service-alist))
40 user-and-host)))
12 41
13(when (getenv "IN_EXWM") 42(defmacro after (event &rest body)
14 (add-to-list 'default-frame-alist '(fullscreen . fullboth))) 43 "Do BODY after EVENT, which can be:
44- A feature
45- A hook -- if it requires arguments they'll be in the list `args'
46- The symbol 'init, which runs on after-init-hook"
47 (declare (indent 1))
48 (let ((lambda-form `(lambda (&rest args) ,@body)))
49 (pcase event
50 (`(timer ,ev) `(run-with-timer ,ev nil ,lambda-form))
51 (`(idle ,ev) `(run-with-idle-timer ,ev nil ,lambda-form))
52 (`(hook ,ev) `(add-hook ',ev ,lambda-form))
53 (`init `(after (hook after-init-hook) ,@body))
54 ((pred numberp) `(after (timer ,event) ,@body))
55 ((pred (lambda (ev)
56 (and (symbolp ev)
57 (or (string-suffix-p "-hook" (symbol-name ev))
58 (string-suffix-p "-function" (symbol-name ev))
59 (string-suffix-p "-functions" (symbol-name ev))))))
60 `(after (hook ,event) ,@body))
61 ((pred symbolp) `(with-eval-after-load ',event ,@body))
15 62
16(defvar *fonts* 63 (_ (error "Can't determine event type" event)))))
17 (let ((fixed "Recursive Mono Casual Static")
18 (variable "Recursive Sans Casual Static"))
19 `((default
20 :family ,variable
21 :height 100)
22 (variable-pitch
23 :family ,variable)
24 (fixed-pitch
25 :family ,fixed)
26 (fixed-pitch-serif
27 :family "Recursive Mono Linear Static"))))
28
29(require 'package)
30(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
31(package-initialize)
32
33;;; Custom functions
34 64
35(defun pulse@eval (start end &rest _) 65(defmacro find-user-file (name &optional file-name)
36 "ADVICE: makes `pulse-momentary-highlight-region' accept other arities." 66 "Template macro to generate user file finding functions."
37 (pulse-momentary-highlight-region start end)) 67 (declare (indent 1))
68 (let ((file-name (or file-name (intern (format "user-%s-file" name))))
69 (func-name (intern (format "find-user-%s-file" name))))
70 `(defun ,func-name (&optional arg)
71 ,(format "Edit `%s' in the current window.
72With ARG, edit in the other window." file-name)
73 (interactive "P")
74 (funcall (if arg #'find-file-other-window #'find-file)
75 ,file-name))))
76
77(defmacro inhibit-messages (&rest body)
78 "Inhibit all messages in BODY."
79 (declare (indent defun))
80 `(cl-letf (((symbol-function 'message) #'ignore))
81 ,@body))
82
83;; This needs to be a macro to take advantage of setf magic
84(defmacro setf/alist (alist key val &optional testfn)
85 `(setf (alist-get ,key ,alist nil nil (or ,testfn #'equal))
86 ,val))
87
88(defun ^local-hook (hook fn)
89 "Hook FN to HOOK locally in a lambda.
90Good for adding to an add-hook."
91 (lambda () (add-hook hook fn t)))
92
93(defun ^local-unhook (hook fn)
94 "Remove FN from HOOK locally."
95 (lambda () (remove-hook hook fn t)))
96
97(defun ^turn-off (mode)
98 "Higher-order function: returns a lambda to turn off MODE."
99 (lambda ()
100 (funcall mode -1)))
38 101
39(defun create-missing-directories () 102(defun create-missing-directories ()
40 "Automatically create missing directories." 103 "Automatically create missing directories."
@@ -42,6 +105,20 @@
42 (unless (file-exists-p target-dir) 105 (unless (file-exists-p target-dir)
43 (make-directory target-dir :parents)))) 106 (make-directory target-dir :parents))))
44 107
108(defun custom-show-all-widgets ()
109 "toggle all \"More/Hide\" widgets in the current buffer."
110 ;; From unpackaged
111 (interactive)
112 (widget-map-buttons (lambda (widget _)
113 (pcase (widget-get widget :off)
114 ("More" (widget-apply-action widget)))
115 nil)))
116
117(defun cycle-spacing* (&optional n)
118 "Negate N argument on `cycle-spacing'."
119 (interactive "*p")
120 (cycle-spacing (- n)))
121
45(defun delete-trailing-whitespace-except-current-line () 122(defun delete-trailing-whitespace-except-current-line ()
46 "Delete all trailing whitespace except current line." 123 "Delete all trailing whitespace except current line."
47 (save-excursion 124 (save-excursion
@@ -50,6 +127,14 @@
50 (delete-trailing-whitespace (line-end-position) 127 (delete-trailing-whitespace (line-end-position)
51 (point-max)))) 128 (point-max))))
52 129
130(defun delete-window-dwim ()
131 "Delete the current window or bury its buffer.
132If the current window is alone in its frame, bury the buffer
133instead."
134 (interactive)
135 (unless (ignore-errors (delete-window) t)
136 (bury-buffer)))
137
53(defun first-found-font (&rest cands) 138(defun first-found-font (&rest cands)
54 "Return the first font of CANDS that is installed, or nil." 139 "Return the first font of CANDS that is installed, or nil."
55 (cl-loop with ffl = (font-family-list) 140 (cl-loop with ffl = (font-family-list)
@@ -57,56 +142,29 @@
57 if (member font ffl) 142 if (member font ffl)
58 return font)) 143 return font))
59 144
60(defun setup-faces () 145(defun fixup-whitespace ()
61 "Setup Emacs faces." 146 "Indent the current buffer and (un)`tabify'.
62 ;; Default faces 147Whether it tabifies or untabifies depends on `space-indent-modes'."
63 (cl-loop for (face . spec) in *fonts* 148 (interactive)
64 do (set-face-attribute face nil 149 (save-mark-and-excursion
65 :family (plist-get spec :family) 150 (indent-region (point-min) (point-max))
66 :height (or (plist-get spec :height) 151 (if indent-tabs-mode
67 'unspecified))) 152 (tabify (point-min) (point-max))
68 ;; Specialized fonts 153 (untabify (point-min) (point-max)))
69 (cl-loop with ffl = (font-family-list) 154 (replace-regexp-in-region " $" "" (point-min) (point-max))))
70 for (charset . font)
71 in '((latin . "Noto Sans")
72 (han . "Noto Sans CJK SC Regular")
73 (kana . "Noto Sans CJK JP Regular")
74 (hangul . "Noto Sans CJK KR Regular")
75 (cjk-misc . "Noto Sans CJK KR Regular")
76 (khmer . "Noto Sans Khmer")
77 (lao . "Noto Sans Lao")
78 (burmese . "Noto Sans Myanmar")
79 (thai . "Noto Sans Thai")
80 (ethiopic . "Noto Sans Ethiopic")
81 (hebrew . "Noto Sans Hebrew")
82 (arabic . "Noto Sans Arabic")
83 (gujarati . "Noto Sans Gujarati")
84 (devanagari . "Noto Sans Devanagari")
85 (kannada . "Noto Sans Kannada")
86 (malayalam . "Noto Sans Malayalam")
87 (oriya . "Noto Sans Oriya")
88 (sinhala . "Noto Sans Sinhala")
89 (tamil . "Noto Sans Tamil")
90 (telugu . "Noto Sans Telugu")
91 (tibetan . "Noto Sans Tibetan")
92 ;; emojis
93 (symbol . "Noto Emoji")
94 (symbol . "Noto Color Emoji")
95 (symbol . "Segoe UI Emoji")
96 (symbol . "Apple Color Emoji")
97 (symbol . "FreeSans")
98 (symbol . "FreeMono")
99 (symbol . "FreeSerif")
100 (symbol . "Unifont")
101 (symbol . "Symbola"))
102 if (member font ffl)
103 do (set-fontset-font t charset font)))
104 155
105(defmacro inhibit-messages (&rest body) 156(defun hide-minor-mode (mode &optional hook)
106 "Inhibit all messages in BODY." 157 "Hide MODE from the mode-line.
107 (declare (indent defun)) 158HOOK is used to trigger the action, and defaults to MODE-hook."
108 `(cl-letf (((symbol-function 'message) #'ignore)) 159 (setf (alist-get mode minor-mode-alist) (list ""))
109 ,@body)) 160 (add-hook (intern (or hook (format "%s-hook" mode)))
161 (lambda () (hide-minor-mode mode))))
162
163(defun keyboard-quit* (arg)
164 (interactive "P")
165 (if arg
166 (quit-minibuffer)
167 (keyboard-quit)))
110 168
111(defun kill-buffer-dwim (&optional buffer-or-name) 169(defun kill-buffer-dwim (&optional buffer-or-name)
112 "Kill BUFFER-OR-NAME or the current buffer." 170 "Kill BUFFER-OR-NAME or the current buffer."
@@ -119,6 +177,30 @@
119 (:else 177 (:else
120 (kill-buffer (read-buffer "Kill: " nil :require-match))))) 178 (kill-buffer (read-buffer "Kill: " nil :require-match)))))
121 179
180(defun minibuffer-delete-directory (&optional n)
181 "Delete the last directory in a file-completing minibuffer."
182 ;; Cribbed from `vertico-directory-up' (github.com/minad/vertico)
183 (interactive "p")
184 (let ((here (point))
185 (meta (completion-metadata
186 "" minibuffer-completion-table
187 minibuffer-completion-predicate)))
188 (when (and (> (point) (minibuffer-prompt-end))
189 (eq 'file (completion-metadata-get meta 'category)))
190 (let ((path (buffer-substring-no-properties (minibuffer-prompt-end)
191 (point)))
192 found)
193 (when (string-match-p "\\`~[^/]*/\\'" path)
194 (delete-minibuffer-contents)
195 (insert (expand-file-name path)))
196 (dotimes (_ (or n 1) found)
197 (save-excursion
198 (let ((end (point)))
199 (goto-char (1- end))
200 (when (search-backward "/" (minibuffer-prompt-end) t)
201 (delete-region (1+ (point)) end)
202 (setq found t)))))))))
203
122(defun other-window-dwim (&optional arg) 204(defun other-window-dwim (&optional arg)
123 "Switch to another window/buffer. 205 "Switch to another window/buffer.
124Calls `other-window', which see, unless 206Calls `other-window', which see, unless
@@ -130,42 +212,6 @@ In these cases, switch to the last-used buffer."
130 (switch-to-buffer (other-buffer) nil t) 212 (switch-to-buffer (other-buffer) nil t)
131 (other-window 1))) 213 (other-window 1)))
132 214
133(defun delete-window-dwim ()
134 "Delete the current window or bury its buffer.
135If the current window is alone in its frame, bury the buffer
136instead."
137 (interactive)
138 (unless (ignore-errors (delete-window) t)
139 (bury-buffer)))
140
141(defun cycle-spacing* (&optional n)
142 "Negate N argument on `cycle-spacing'."
143 (interactive "*p")
144 (cycle-spacing (- n)))
145
146(defmacro find-user-file (name &optional file-name)
147 "Template macro to generate user file finding functions."
148 (declare (indent 1))
149 (let ((file-name (or file-name (intern (format "user-%s-file" name))))
150 (func-name (intern (format "find-user-%s-file" name))))
151 `(defun ,func-name (&optional arg)
152 ,(format "Edit `%s' in the current window.
153With ARG, edit in the other window." file-name)
154 (interactive "P")
155 (funcall (if arg #'find-file-other-window #'find-file)
156 ,file-name))))
157
158(defun fixup-whitespace ()
159 "Indent the current buffer and (un)`tabify'.
160Whether it tabifies or untabifies depends on `space-indent-modes'."
161 (interactive)
162 (save-mark-and-excursion
163 (indent-region (point-min) (point-max))
164 (if indent-tabs-mode
165 (tabify (point-min) (point-max))
166 (untabify (point-min) (point-max)))
167 (replace-regexp-in-region " $" "" (point-min) (point-max))))
168
169(defun package-ensure (pkgspec &optional require) 215(defun package-ensure (pkgspec &optional require)
170 "Install PKG if it's not already installed. 216 "Install PKG if it's not already installed.
171REQUIRE means require it after ensuring it's installed." 217REQUIRE means require it after ensuring it's installed."
@@ -190,83 +236,6 @@ REQUIRE means require it after ensuring it's installed."
190 (package-vc-install pkgspec)) 236 (package-vc-install pkgspec))
191 (when require (require pkg)))) 237 (when require (require pkg))))
192 238
193(defun minibuffer-delete-directory ()
194 "Delete the last directory in a file-completing minibuffer."
195 (interactive)
196 (let ((here (point))
197 (meta (completion-metadata
198 "" minibuffer-completion-table
199 minibuffer-completion-predicate)))
200 (if (eq (completion-metadata-get meta 'category) 'file)
201 (when (search-backward "/" (minibuffer-prompt-end) t)
202 (delete-region (point) here))
203 (backward-kill-word 1))))
204
205(defun save-buffers-kill* (arg)
206 "Save all the buffers and kill ... something.
207If ARG is 1 (called normally), kill the current terminal.
208If ARG is 4 (with C-u), kill emacs but ask if there are processes running.
209If ARG is 16, kill emacs without asking about processes."
210 (interactive "p")
211 (pcase arg
212 (1 (save-buffers-kill-terminal))
213 (4 (save-buffers-kill-emacs t))
214 (16 (let ((confirm-kill-processes nil)
215 (kill-emacs-query-functions nil)
216 (confirm-kill-emacs nil))
217 (save-buffers-kill-emacs t)))))
218
219(defun regexp-concat (&rest regexps)
220 (string-join regexps "\\|"))
221
222;; There is a bug in M-x finger
223(defun acdw/finger (user host)
224 "Finger USER on HOST.
225This command uses `finger-X.500-host-regexps'
226and `network-connection-service-alist', which see."
227 ;; One of those great interactive statements that's actually
228 ;; longer than the function call! The idea is that if the user
229 ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the
230 ;; host name. If we don't see an "@", we'll prompt for the host.
231 (interactive
232 (let* ((answer (let ((default (ffap-url-at-point)))
233 (read-string (format-prompt "Finger User" default) nil nil default)))
234 (index (string-match (regexp-quote "@") answer)))
235 (if index
236 (list (substring answer 0 index)
237 (substring answer (1+ index)))
238 (list answer
239 (let ((default (ffap-machine-at-point)))
240 (read-string (format-prompt "At Host" default) nil nil default))))))
241 (let* ((user-and-host (concat user "@" host))
242 (process-name (concat "Finger [" user-and-host "]"))
243 (regexps finger-X.500-host-regexps)
244 ) ;; found
245 (and regexps
246 (while (not (string-match (car regexps) host))
247 (setq regexps (cdr regexps))))
248 (when regexps
249 (setq user-and-host user))
250 (run-network-program
251 process-name
252 host
253 (cdr (assoc 'finger network-connection-service-alist))
254 user-and-host)))
255
256(advice-add 'finger :override #'acdw-finger)
257
258(defun hide-minor-mode (mode &optional hook)
259 "Hide MODE from the mode-line.
260HOOK is used to trigger the action, and defaults to MODE-hook."
261 (setf (alist-get mode minor-mode-alist) (list ""))
262 (add-hook (intern (or hook (format "%s-hook" mode)))
263 (lambda () (hide-minor-mode mode))))
264
265(defun switch-to-other-buffer ()
266 "Switch to the `other-buffer'."
267 (interactive)
268 (switch-to-buffer nil))
269
270(defun popup-eshell (arg) 239(defun popup-eshell (arg)
271 "Popup an eshell buffer in the current window." 240 "Popup an eshell buffer in the current window."
272 (interactive "P") 241 (interactive "P")
@@ -280,34 +249,76 @@ HOOK is used to trigger the action, and defaults to MODE-hook."
280 (insert "# ")) 249 (insert "# "))
281 (eshell-send-input)))) 250 (eshell-send-input))))
282 251
283(defun vc-jump (arg) 252(defun pulse@eval (start end &rest _)
284 "Jump to the current project's VC buffer. 253 "ADVICE: makes `pulse-momentary-highlight-region' accept other arities."
285With ARG, prompt for the directory." 254 (pulse-momentary-highlight-region start end))
286 (interactive "P")
287 (if arg
288 (let ((current-prefix-arg nil))
289 (call-interactively #'vc-dir))
290 (project-vc-dir)))
291
292(defun custom-show-all-widgets ()
293 "toggle all \"More/Hide\" widgets in the current buffer."
294 ;; From unpackaged
295 (interactive)
296 (widget-map-buttons (lambda (widget _)
297 (pcase (widget-get widget :off)
298 ("More" (widget-apply-action widget)))
299 nil)))
300 255
301(defun quit-minibuffer () 256(defun quit-minibuffer ()
302 (interactive) 257 (interactive)
303 (switch-to-minibuffer) 258 (switch-to-minibuffer)
304 (minibuffer-keyboard-quit)) 259 (minibuffer-keyboard-quit))
305 260
306(defun keyboard-quit* (arg) 261(defun regexp-concat (&rest regexps)
307 (interactive "P") 262 (string-join regexps "\\|"))
308 (if arg 263
309 (quit-minibuffer) 264(defun save-buffers-kill* (arg)
310 (keyboard-quit))) 265 "Save all the buffers and kill ... something.
266If ARG is 1 (called normally), kill the current terminal.
267If ARG is 4 (with C-u), kill emacs but ask if there are processes running.
268If ARG is 16, kill emacs without asking about processes."
269 (interactive "p")
270 (pcase arg
271 (1 (save-buffers-kill-terminal))
272 (4 (save-buffers-kill-emacs t))
273 (16 (let ((confirm-kill-processes nil)
274 (kill-emacs-query-functions nil)
275 (confirm-kill-emacs nil))
276 (save-buffers-kill-emacs t)))))
277
278(defun setup-faces ()
279 "Setup Emacs faces."
280 ;; Default faces
281 (cl-loop for (face . spec) in *fonts*
282 do (set-face-attribute face nil
283 :family (plist-get spec :family)
284 :height (or (plist-get spec :height)
285 'unspecified)))
286 ;; Specialized fonts
287 (cl-loop with ffl = (font-family-list)
288 for (charset . font)
289 in '((latin . "Noto Sans")
290 (han . "Noto Sans CJK SC Regular")
291 (kana . "Noto Sans CJK JP Regular")
292 (hangul . "Noto Sans CJK KR Regular")
293 (cjk-misc . "Noto Sans CJK KR Regular")
294 (khmer . "Noto Sans Khmer")
295 (lao . "Noto Sans Lao")
296 (burmese . "Noto Sans Myanmar")
297 (thai . "Noto Sans Thai")
298 (ethiopic . "Noto Sans Ethiopic")
299 (hebrew . "Noto Sans Hebrew")
300 (arabic . "Noto Sans Arabic")
301 (gujarati . "Noto Sans Gujarati")
302 (devanagari . "Noto Sans Devanagari")
303 (kannada . "Noto Sans Kannada")
304 (malayalam . "Noto Sans Malayalam")
305 (oriya . "Noto Sans Oriya")
306 (sinhala . "Noto Sans Sinhala")
307 (tamil . "Noto Sans Tamil")
308 (telugu . "Noto Sans Telugu")
309 (tibetan . "Noto Sans Tibetan")
310 ;; emojis
311 (symbol . "Noto Emoji")
312 ;; (symbol . "Noto Color Emoji")
313 (symbol . "Segoe UI Emoji")
314 (symbol . "Apple Color Emoji")
315 (symbol . "FreeSans")
316 (symbol . "FreeMono")
317 (symbol . "FreeSerif")
318 (symbol . "Unifont")
319 (symbol . "Symbola"))
320 if (member font ffl)
321 do (set-fontset-font t charset font)))
311 322
312(defun sort-sexps (beg end) 323(defun sort-sexps (beg end)
313 "Sort sexps in region. 324 "Sort sexps in region.
@@ -357,34 +368,10 @@ Comments stay with the code below."
357 (insert-before-markers real) 368 (insert-before-markers real)
358 (delete-region (point) (marker-position end))))))))) 369 (delete-region (point) (marker-position end)))))))))
359 370
360(defun ^turn-off (mode) 371(defun switch-to-other-buffer ()
361 "Higher-order function: returns a lambda to turn off MODE." 372 "Switch to the `other-buffer'."
362 (lambda ()
363 (funcall mode -1)))
364
365(defun ^local-hook (hook fn)
366 "Hook FN to HOOK locally in a lambda.
367Good for adding to an add-hook."
368 (lambda () (add-hook hook fn t)))
369
370(defun ^local-unhook (hook fn)
371 "Remove FN from HOOK locally."
372 (lambda () (remove-hook hook fn t)))
373
374;; This needs to be a macro to take advantage of setf magic
375(defmacro setf/alist (alist key val &optional testfn)
376 `(setf (alist-get ,key ,alist nil nil (or ,testfn #'equal))
377 ,val))
378
379(defun unfill-region (beg end)
380 (interactive "*r")
381 (let ((fill-column most-positive-fixnum))
382 (fill-region beg end)))
383
384(defun unfill-paragraph ()
385 (interactive) 373 (interactive)
386 (let ((fill-column most-positive-fixnum)) 374 (switch-to-buffer nil))
387 (fill-paragraph beg end)))
388 375
389(defun unfill-buffer () 376(defun unfill-buffer ()
390 (interactive) 377 (interactive)
@@ -396,25 +383,51 @@ Good for adding to an add-hook."
396 (unfill-buffer) 383 (unfill-buffer)
397 (visual-line-mode t))) 384 (visual-line-mode t)))
398 385
399(defmacro after (event &rest body) 386(defun unfill-paragraph ()
400 "Do BODY after EVENT, which can be: 387 (interactive)
401- A feature 388 (let ((fill-column most-positive-fixnum))
402- A hook -- if it requires arguments they'll be in the list `args' 389 (fill-paragraph beg end)))
403- The symbol 'init, which runs on after-init-hook"
404 (declare (indent 1))
405 (let ((lambda-form `(lambda (&rest args) ,@body)))
406 (pcase event
407 (`(timer ,ev) `(run-with-timer ,ev nil ,lambda-form))
408 (`(idle ,ev) `(run-with-idle-timer ,ev nil ,lambda-form))
409 (`(hook ,ev) `(add-hook ',ev ,lambda-form))
410 (`init `(after (hook after-init-hook) ,@body))
411 ((pred numberp) `(after (timer ,event) ,@body))
412 ((pred (lambda (ev)
413 (and (symbolp ev)
414 (or (string-suffix-p "-hook" (symbol-name ev))
415 (string-suffix-p "-function" (symbol-name ev))
416 (string-suffix-p "-functions" (symbol-name ev))))))
417 `(after (hook ,event) ,@body))
418 ((pred symbolp) `(with-eval-after-load ',event ,@body))
419 390
420 (_ (error "Can't determine event type" event))))) 391(defun unfill-region (beg end)
392 (interactive "*r")
393 (let ((fill-column most-positive-fixnum))
394 (fill-region beg end)))
395
396(defun vc-jump (arg)
397 "Jump to the current project's VC buffer.
398With ARG, prompt for the directory."
399 (interactive "P")
400 (if arg
401 (let ((current-prefix-arg nil))
402 (call-interactively #'vc-dir))
403 (project-vc-dir)))
404
405(progn (defvar *fonts*
406 (let ((fixed "Recursive Mono Casual Static")
407 (variable "Recursive Sans Linear Static"))
408 `((default
409 :family ,variable
410 :height 100)
411 (variable-pitch :family ,variable)
412 (fixed-pitch :family ,fixed)
413 (fixed-pitch-serif :family ,fixed)
414 (font-lock-string-face :family "Recursive Mono Linear Static"))))
415 ;; (setup-faces)
416 )
417
418(setopt default-frame-alist
419 '((menu-bar-lines . 0)
420 (tool-bar-lines . 0)
421 ;;(vertical-scroll-bars)
422 (horizontal-scroll-bars)))
423
424(setopt frame-inhibit-implied-resize t)
425(setopt frame-resize-pixelwise t)
426(setopt window-resize-pixelwise t)
427
428(when (getenv "IN_EXWM")
429 (add-to-list 'default-frame-alist '(fullscreen . fullboth)))
430
431(when (require 'package)
432 (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
433 (package-initialize))
diff --git a/exwm b/exwm index 08d410f..55f33fb 100644 --- a/exwm +++ b/exwm
@@ -109,6 +109,9 @@ BUFFER-NAME defaults to the first word of COMMAND."
109 109
110;;; Window management 110;;; Window management
111 111
112(after exwm-mode-hook
113 (setq-local mode-line-format nil))
114
112(after exwm-update-class-hook 115(after exwm-update-class-hook
113 (exwm-workspace-rename-buffer exwm-class-name)) 116 (exwm-workspace-rename-buffer exwm-class-name))
114 117