about summary refs log tree commit diff stats
path: root/emacs.d/early-init.el
diff options
context:
space:
mode:
authorCase Duckworth2024-06-26 12:43:33 -0500
committerCase Duckworth2024-06-26 12:43:33 -0500
commitb171e954b60558f175ea56d5015a23fa4fdeabaf (patch)
treeef29d99215935f1ad2ee044d75478b319d9203e9 /emacs.d/early-init.el
parentEXWM (diff)
downloaddots-b171e954b60558f175ea56d5015a23fa4fdeabaf.tar.gz
dots-b171e954b60558f175ea56d5015a23fa4fdeabaf.zip
Emacs!
I copied my files over wrong or something... anyway here's an updated emacs config
Diffstat (limited to 'emacs.d/early-init.el')
-rw-r--r--emacs.d/early-init.el282
1 files changed, 243 insertions, 39 deletions
diff --git a/emacs.d/early-init.el b/emacs.d/early-init.el index 7374bd1..b2de2f2 100644 --- a/emacs.d/early-init.el +++ b/emacs.d/early-init.el
@@ -10,18 +10,21 @@
10 (vertical-scroll-bars) 10 (vertical-scroll-bars)
11 (horizontal-scroll-bars))) 11 (horizontal-scroll-bars)))
12 12
13(when (getenv "IN_EXWM")
14 (add-to-list 'default-frame-alist '(fullscreen . fullboth)))
15
13(defvar *fonts* 16(defvar *fonts*
14 '((default 17 (let ((fixed "Recursive Mono Casual Static")
15 :family ;;("Recursive Mono Casual Static" "DejaVu Sans Mono") 18 (variable "Recursive Sans Casual Static"))
16 ("Public Sans" "DejaVu Sans") 19 `((default
17 :height 100) 20 :family ,variable
18 (variable-pitch 21 :height 100)
19 :family ("Public Sans" "DejaVu Sans") 22 (variable-pitch
20 :height 1.0) 23 :family ,variable)
21 (fixed-pitch 24 (fixed-pitch
22 :family ("Recursive Mono Casual Static" "DejaVu Sans Mono")) 25 :family ,fixed)
23 (fixed-pitch-serif 26 (fixed-pitch-serif
24 :family ("Recursive Mono Linear Static" "DejaVu Sans Mono")))) 27 :family "Recursive Mono Linear Static"))))
25 28
26(require 'package) 29(require 'package)
27(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) 30(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
@@ -47,24 +50,6 @@
47 (delete-trailing-whitespace (line-end-position) 50 (delete-trailing-whitespace (line-end-position)
48 (point-max)))) 51 (point-max))))
49 52
50(defun run-after-frame-init (func)
51 "Run FUNC after the first frame is initialized.
52If already so, run FUNC immediately."
53 (cond
54 ((daemonp)
55 (add-hook 'server-after-make-frame-hook func)
56 (advice-add func :after (lambda ()
57 (remove-hook 'server-after-make-frame-hook
58 func)
59 (advice-remove func
60 'after-frame-init-removing-advice))
61
62
63 '((name . after-frame-init-removing-advice))))
64 ((not after-init-time)
65 (add-hook 'after-init-hook func))
66 (:else (funcall func))))
67
68(defun first-found-font (&rest cands) 53(defun first-found-font (&rest cands)
69 "Return the first font of CANDS that is installed, or nil." 54 "Return the first font of CANDS that is installed, or nil."
70 (cl-loop with ffl = (font-family-list) 55 (cl-loop with ffl = (font-family-list)
@@ -77,8 +62,7 @@ If already so, run FUNC immediately."
77 ;; Default faces 62 ;; Default faces
78 (cl-loop for (face . spec) in *fonts* 63 (cl-loop for (face . spec) in *fonts*
79 do (set-face-attribute face nil 64 do (set-face-attribute face nil
80 :family (apply #'first-found-font 65 :family (plist-get spec :family)
81 (plist-get spec :family))
82 :height (or (plist-get spec :height) 66 :height (or (plist-get spec :height)
83 'unspecified))) 67 'unspecified)))
84 ;; Specialized fonts 68 ;; Specialized fonts
@@ -171,20 +155,40 @@ With ARG, edit in the other window." file-name)
171 (funcall (if arg #'find-file-other-window #'find-file) 155 (funcall (if arg #'find-file-other-window #'find-file)
172 ,file-name)))) 156 ,file-name))))
173 157
174(defun indent-buffer+ () 158(defun fixup-whitespace ()
175 "Indent the current buffer and (un)`tabify'. 159 "Indent the current buffer and (un)`tabify'.
176Whether it tabifies or untabifies depends on `space-indent-modes'." 160Whether it tabifies or untabifies depends on `space-indent-modes'."
177 (interactive) 161 (interactive)
178 (save-mark-and-excursion 162 (save-mark-and-excursion
179 (indent-region (point-min) (point-max)) 163 (indent-region (point-min) (point-max))
180 (if (apply #'derived-mode-p space-indent-modes) 164 (if indent-tabs-mode
181 (untabify (point-min) (point-max)) 165 (tabify (point-min) (point-max))
182 (tabify (point-min) (point-max))))) 166 (untabify (point-min) (point-max)))
167 (replace-regexp-in-region " $" "" (point-min) (point-max))))
183 168
184(defun package-ensure (pkg) 169(defun package-ensure (pkgspec &optional require)
185 "Install PKG if it's not already installed." 170 "Install PKG if it's not already installed.
186 (unless (package-installed-p pkg) 171REQUIRE means require it after ensuring it's installed."
187 (package-vc-install pkg))) 172 (let ((pkg (if (listp pkgspec) (car pkgspec) pkgspec)))
173 (unless (package-installed-p pkg)
174 (if (symbolp pkgspec)
175 (or (ignore-errors
176 (package-install pkg)
177 t)
178 (ignore-errors
179 (message "Package `%s' not found, refreshing packages" pkg)
180 (package-refresh-contents)
181 (package-install pkg)
182 t)
183 (ignore-errors
184 (message "Package `%s' still not found, trying `%s'"
185 pkg 'pkg-vc-install)
186 (package-vc-install pkgspec)
187 t)
188 (if no-error nil
189 (error "Can't find package: %s" pkg))))
190 (package-vc-install pkgspec))
191 (when require (require pkg))))
188 192
189(defun minibuffer-delete-directory () 193(defun minibuffer-delete-directory ()
190 "Delete the last directory in a file-completing minibuffer." 194 "Delete the last directory in a file-completing minibuffer."
@@ -214,3 +218,203 @@ If ARG is 16, kill emacs without asking about processes."
214 218
215(defun regexp-concat (&rest regexps) 219(defun regexp-concat (&rest regexps)
216 (string-join 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)
271 "Popup an eshell buffer in the current window."
272 (interactive "P")
273 (let ((dd default-directory))
274 (eshell arg)
275 (unless (equal dd default-directory)
276 (setq default-directory dd)
277 ;; Is this a good idea, really?
278 (eshell-bol)
279 (unless (eolp)
280 (insert "# "))
281 (eshell-send-input))))
282
283(defun vc-jump (arg)
284 "Jump to the current project's VC buffer.
285With ARG, prompt for the directory."
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
301(defun quit-minibuffer ()
302 (interactive)
303 (switch-to-minibuffer)
304 (minibuffer-keyboard-quit))
305
306(defun keyboard-quit* (arg)
307 (interactive "P")
308 (if arg
309 (quit-minibuffer)
310 (keyboard-quit)))
311
312(defun sort-sexps (beg end)
313 "Sort sexps in region.
314Comments stay with the code below."
315 ;; From unpackaged
316 (interactive "r")
317 (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n"))))
318 (goto-char (match-end 0))))
319 (skip-both () (while (cond ((or (nth 4 (syntax-ppss))
320 (ignore-errors
321 (save-excursion
322 (forward-char 1)
323 (nth 4 (syntax-ppss)))))
324 (forward-line 1))
325 ((looking-at (rx (1+ (or space "\n"))))
326 (goto-char (match-end 0)))))))
327 (save-excursion
328 (save-restriction
329 (narrow-to-region beg end)
330 (goto-char beg)
331 (skip-both)
332 (cl-destructuring-bind (sexps markers)
333 (cl-loop do (skip-whitespace)
334 for start = (point-marker)
335 for sexp = (ignore-errors
336 (read (current-buffer)))
337 for end = (point-marker)
338 while sexp
339 ;; Collect the real string, then one used for sorting.
340 collect (cons (buffer-substring (marker-position start)
341 (marker-position end))
342 (save-excursion
343 (goto-char (marker-position start))
344 (skip-both)
345 (buffer-substring (point)
346 (marker-position end))))
347 into sexps
348 collect (cons start end)
349 into markers
350 finally return (list sexps markers))
351 (setq sexps (sort sexps (lambda (a b)
352 (string< (cdr a) (cdr b)))))
353 (cl-loop for (real . sort) in sexps
354 for (start . end) in markers
355 do (progn
356 (goto-char (marker-position start))
357 (insert-before-markers real)
358 (delete-region (point) (marker-position end)))))))))
359
360(defun ^turn-off (mode)
361 "Higher-order function: returns a lambda to turn off MODE."
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)
386 (let ((fill-column most-positive-fixnum))
387 (fill-paragraph beg end)))
388
389(defun unfill-buffer ()
390 (interactive)
391 (unfill-region (point-min) (point-max)))
392
393(defun unfill-buffer/force ()
394 (interactive)
395 (let ((buffer-read-only nil))
396 (unfill-buffer)
397 (visual-line-mode t)))
398
399(defmacro after (event &rest body)
400 "Do BODY after EVENT, which can be:
401- A feature
402- A hook -- if it requires arguments they'll be in the list `args'
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
420 (_ (error "Can't determine event type" event)))))