From b171e954b60558f175ea56d5015a23fa4fdeabaf Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 26 Jun 2024 12:43:33 -0500 Subject: Emacs! I copied my files over wrong or something... anyway here's an updated emacs config --- emacs.d/early-init.el | 282 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 243 insertions(+), 39 deletions(-) (limited to 'emacs.d/early-init.el') 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 @@ (vertical-scroll-bars) (horizontal-scroll-bars))) +(when (getenv "IN_EXWM") + (add-to-list 'default-frame-alist '(fullscreen . fullboth))) + (defvar *fonts* - '((default - :family ;;("Recursive Mono Casual Static" "DejaVu Sans Mono") - ("Public Sans" "DejaVu Sans") - :height 100) - (variable-pitch - :family ("Public Sans" "DejaVu Sans") - :height 1.0) - (fixed-pitch - :family ("Recursive Mono Casual Static" "DejaVu Sans Mono")) - (fixed-pitch-serif - :family ("Recursive Mono Linear Static" "DejaVu Sans Mono")))) + (let ((fixed "Recursive Mono Casual Static") + (variable "Recursive Sans Casual Static")) + `((default + :family ,variable + :height 100) + (variable-pitch + :family ,variable) + (fixed-pitch + :family ,fixed) + (fixed-pitch-serif + :family "Recursive Mono Linear Static")))) (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) @@ -47,24 +50,6 @@ (delete-trailing-whitespace (line-end-position) (point-max)))) -(defun run-after-frame-init (func) - "Run FUNC after the first frame is initialized. -If already so, run FUNC immediately." - (cond - ((daemonp) - (add-hook 'server-after-make-frame-hook func) - (advice-add func :after (lambda () - (remove-hook 'server-after-make-frame-hook - func) - (advice-remove func - 'after-frame-init-removing-advice)) - - - '((name . after-frame-init-removing-advice)))) - ((not after-init-time) - (add-hook 'after-init-hook func)) - (:else (funcall func)))) - (defun first-found-font (&rest cands) "Return the first font of CANDS that is installed, or nil." (cl-loop with ffl = (font-family-list) @@ -77,8 +62,7 @@ If already so, run FUNC immediately." ;; Default faces (cl-loop for (face . spec) in *fonts* do (set-face-attribute face nil - :family (apply #'first-found-font - (plist-get spec :family)) + :family (plist-get spec :family) :height (or (plist-get spec :height) 'unspecified))) ;; Specialized fonts @@ -171,20 +155,40 @@ With ARG, edit in the other window." file-name) (funcall (if arg #'find-file-other-window #'find-file) ,file-name)))) -(defun indent-buffer+ () +(defun fixup-whitespace () "Indent the current buffer and (un)`tabify'. Whether it tabifies or untabifies depends on `space-indent-modes'." (interactive) (save-mark-and-excursion (indent-region (point-min) (point-max)) - (if (apply #'derived-mode-p space-indent-modes) - (untabify (point-min) (point-max)) - (tabify (point-min) (point-max))))) + (if indent-tabs-mode + (tabify (point-min) (point-max)) + (untabify (point-min) (point-max))) + (replace-regexp-in-region " $" "" (point-min) (point-max)))) -(defun package-ensure (pkg) - "Install PKG if it's not already installed." - (unless (package-installed-p pkg) - (package-vc-install pkg))) +(defun package-ensure (pkgspec &optional require) + "Install PKG if it's not already installed. +REQUIRE means require it after ensuring it's installed." + (let ((pkg (if (listp pkgspec) (car pkgspec) pkgspec))) + (unless (package-installed-p pkg) + (if (symbolp pkgspec) + (or (ignore-errors + (package-install pkg) + t) + (ignore-errors + (message "Package `%s' not found, refreshing packages" pkg) + (package-refresh-contents) + (package-install pkg) + t) + (ignore-errors + (message "Package `%s' still not found, trying `%s'" + pkg 'pkg-vc-install) + (package-vc-install pkgspec) + t) + (if no-error nil + (error "Can't find package: %s" pkg)))) + (package-vc-install pkgspec)) + (when require (require pkg)))) (defun minibuffer-delete-directory () "Delete the last directory in a file-completing minibuffer." @@ -214,3 +218,203 @@ If ARG is 16, kill emacs without asking about processes." (defun regexp-concat (&rest regexps) (string-join regexps "\\|")) + +;; There is a bug in M-x finger +(defun acdw/finger (user host) + "Finger USER on HOST. +This command uses `finger-X.500-host-regexps' +and `network-connection-service-alist', which see." + ;; One of those great interactive statements that's actually + ;; longer than the function call! The idea is that if the user + ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the + ;; host name. If we don't see an "@", we'll prompt for the host. + (interactive + (let* ((answer (let ((default (ffap-url-at-point))) + (read-string (format-prompt "Finger User" default) nil nil default))) + (index (string-match (regexp-quote "@") answer))) + (if index + (list (substring answer 0 index) + (substring answer (1+ index))) + (list answer + (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "At Host" default) nil nil default)))))) + (let* ((user-and-host (concat user "@" host)) + (process-name (concat "Finger [" user-and-host "]")) + (regexps finger-X.500-host-regexps) + ) ;; found + (and regexps + (while (not (string-match (car regexps) host)) + (setq regexps (cdr regexps)))) + (when regexps + (setq user-and-host user)) + (run-network-program + process-name + host + (cdr (assoc 'finger network-connection-service-alist)) + user-and-host))) + +(advice-add 'finger :override #'acdw-finger) + +(defun hide-minor-mode (mode &optional hook) + "Hide MODE from the mode-line. +HOOK is used to trigger the action, and defaults to MODE-hook." + (setf (alist-get mode minor-mode-alist) (list "")) + (add-hook (intern (or hook (format "%s-hook" mode))) + (lambda () (hide-minor-mode mode)))) + +(defun switch-to-other-buffer () + "Switch to the `other-buffer'." + (interactive) + (switch-to-buffer nil)) + +(defun popup-eshell (arg) + "Popup an eshell buffer in the current window." + (interactive "P") + (let ((dd default-directory)) + (eshell arg) + (unless (equal dd default-directory) + (setq default-directory dd) + ;; Is this a good idea, really? + (eshell-bol) + (unless (eolp) + (insert "# ")) + (eshell-send-input)))) + +(defun vc-jump (arg) + "Jump to the current project's VC buffer. +With ARG, prompt for the directory." + (interactive "P") + (if arg + (let ((current-prefix-arg nil)) + (call-interactively #'vc-dir)) + (project-vc-dir))) + +(defun custom-show-all-widgets () + "toggle all \"More/Hide\" widgets in the current buffer." + ;; From unpackaged + (interactive) + (widget-map-buttons (lambda (widget _) + (pcase (widget-get widget :off) + ("More" (widget-apply-action widget))) + nil))) + +(defun quit-minibuffer () + (interactive) + (switch-to-minibuffer) + (minibuffer-keyboard-quit)) + +(defun keyboard-quit* (arg) + (interactive "P") + (if arg + (quit-minibuffer) + (keyboard-quit))) + +(defun sort-sexps (beg end) + "Sort sexps in region. +Comments stay with the code below." + ;; From unpackaged + (interactive "r") + (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n")))) + (goto-char (match-end 0)))) + (skip-both () (while (cond ((or (nth 4 (syntax-ppss)) + (ignore-errors + (save-excursion + (forward-char 1) + (nth 4 (syntax-ppss))))) + (forward-line 1)) + ((looking-at (rx (1+ (or space "\n")))) + (goto-char (match-end 0))))))) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (goto-char beg) + (skip-both) + (cl-destructuring-bind (sexps markers) + (cl-loop do (skip-whitespace) + for start = (point-marker) + for sexp = (ignore-errors + (read (current-buffer))) + for end = (point-marker) + while sexp + ;; Collect the real string, then one used for sorting. + collect (cons (buffer-substring (marker-position start) + (marker-position end)) + (save-excursion + (goto-char (marker-position start)) + (skip-both) + (buffer-substring (point) + (marker-position end)))) + into sexps + collect (cons start end) + into markers + finally return (list sexps markers)) + (setq sexps (sort sexps (lambda (a b) + (string< (cdr a) (cdr b))))) + (cl-loop for (real . sort) in sexps + for (start . end) in markers + do (progn + (goto-char (marker-position start)) + (insert-before-markers real) + (delete-region (point) (marker-position end))))))))) + +(defun ^turn-off (mode) + "Higher-order function: returns a lambda to turn off MODE." + (lambda () + (funcall mode -1))) + +(defun ^local-hook (hook fn) + "Hook FN to HOOK locally in a lambda. +Good for adding to an add-hook." + (lambda () (add-hook hook fn t))) + +(defun ^local-unhook (hook fn) + "Remove FN from HOOK locally." + (lambda () (remove-hook hook fn t))) + +;; This needs to be a macro to take advantage of setf magic +(defmacro setf/alist (alist key val &optional testfn) + `(setf (alist-get ,key ,alist nil nil (or ,testfn #'equal)) + ,val)) + +(defun unfill-region (beg end) + (interactive "*r") + (let ((fill-column most-positive-fixnum)) + (fill-region beg end))) + +(defun unfill-paragraph () + (interactive) + (let ((fill-column most-positive-fixnum)) + (fill-paragraph beg end))) + +(defun unfill-buffer () + (interactive) + (unfill-region (point-min) (point-max))) + +(defun unfill-buffer/force () + (interactive) + (let ((buffer-read-only nil)) + (unfill-buffer) + (visual-line-mode t))) + +(defmacro after (event &rest body) + "Do BODY after EVENT, which can be: +- A feature +- A hook -- if it requires arguments they'll be in the list `args' +- The symbol 'init, which runs on after-init-hook" + (declare (indent 1)) + (let ((lambda-form `(lambda (&rest args) ,@body))) + (pcase event + (`(timer ,ev) `(run-with-timer ,ev nil ,lambda-form)) + (`(idle ,ev) `(run-with-idle-timer ,ev nil ,lambda-form)) + (`(hook ,ev) `(add-hook ',ev ,lambda-form)) + (`init `(after (hook after-init-hook) ,@body)) + ((pred numberp) `(after (timer ,event) ,@body)) + ((pred (lambda (ev) + (and (symbolp ev) + (or (string-suffix-p "-hook" (symbol-name ev)) + (string-suffix-p "-function" (symbol-name ev)) + (string-suffix-p "-functions" (symbol-name ev)))))) + `(after (hook ,event) ,@body)) + ((pred symbolp) `(with-eval-after-load ',event ,@body)) + + (_ (error "Can't determine event type" event))))) -- cgit 1.4.1-21-gabe81