From daeeecee613987bd821b4e15d03b2cb925cd88b0 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Fri, 3 Apr 2026 02:09:58 +0200 Subject: emacs: Mark the config as legacy --- .config/emacs-old/.gitignore | 2 + .config/emacs-old/combobulate-c.el | 25 ++ .config/emacs-old/early-init.el | 105 +++++ .config/emacs-old/editing.el | 271 +++++++++++++ .config/emacs-old/init.el | 358 ++++++++++++++++ .config/emacs-old/mango-light-theme.el | 347 ++++++++++++++++ .config/emacs-old/mango-theme.el | 331 +++++++++++++++ .config/emacs-old/modules/mm-abbrev.el | 110 +++++ .config/emacs-old/modules/mm-buffer-menu.el | 15 + .config/emacs-old/modules/mm-calc.el | 13 + .config/emacs-old/modules/mm-completion.el | 256 ++++++++++++ .config/emacs-old/modules/mm-darwin.el | 30 ++ .config/emacs-old/modules/mm-dired.el | 24 ++ .config/emacs-old/modules/mm-documentation.el | 44 ++ .config/emacs-old/modules/mm-editing.el | 449 +++++++++++++++++++++ .config/emacs-old/modules/mm-humanwave.el | 254 ++++++++++++ .config/emacs-old/modules/mm-keybindings.el | 188 +++++++++ .config/emacs-old/modules/mm-lsp.el | 45 +++ .config/emacs-old/modules/mm-modeline.el | 147 +++++++ .config/emacs-old/modules/mm-org.el | 6 + .config/emacs-old/modules/mm-projects.el | 114 ++++++ .config/emacs-old/modules/mm-search.el | 57 +++ .config/emacs-old/modules/mm-spellcheck.el | 24 ++ .config/emacs-old/modules/mm-tetris.el | 20 + .config/emacs-old/modules/mm-theme.el | 246 +++++++++++ .config/emacs-old/modules/mm-treesit.el | 240 +++++++++++ .config/emacs-old/modules/mm-window.el | 72 ++++ .config/emacs-old/site-lisp/emmet.el | 349 ++++++++++++++++ .config/emacs-old/site-lisp/gh.el | 62 +++ .config/emacs-old/site-lisp/grab.el | 215 ++++++++++ .config/emacs-old/site-lisp/highlighter.el | 128 ++++++ .config/emacs-old/site-lisp/html-escape.el | 55 +++ .config/emacs-old/site-lisp/increment.el | 132 ++++++ .config/emacs-old/site-lisp/line-selection-mode.el | 18 + .config/emacs-old/site-lisp/live-jq.el | 101 +++++ .config/emacs-old/site-lisp/number-format-mode.el | 129 ++++++ .config/emacs-old/site-lisp/surround.el | 122 ++++++ .config/emacs-old/templates | 38 ++ .config/emacs/.gitignore | 2 - .config/emacs/combobulate-c.el | 25 -- .config/emacs/early-init.el | 105 ----- .config/emacs/editing.el | 271 ------------- .config/emacs/init.el | 358 ---------------- .config/emacs/mango-light-theme.el | 347 ---------------- .config/emacs/mango-theme.el | 331 --------------- .config/emacs/modules/mm-abbrev.el | 110 ----- .config/emacs/modules/mm-buffer-menu.el | 15 - .config/emacs/modules/mm-calc.el | 13 - .config/emacs/modules/mm-completion.el | 256 ------------ .config/emacs/modules/mm-darwin.el | 30 -- .config/emacs/modules/mm-dired.el | 24 -- .config/emacs/modules/mm-documentation.el | 44 -- .config/emacs/modules/mm-editing.el | 449 --------------------- .config/emacs/modules/mm-humanwave.el | 254 ------------ .config/emacs/modules/mm-keybindings.el | 188 --------- .config/emacs/modules/mm-lsp.el | 45 --- .config/emacs/modules/mm-modeline.el | 147 ------- .config/emacs/modules/mm-org.el | 6 - .config/emacs/modules/mm-projects.el | 114 ------ .config/emacs/modules/mm-search.el | 57 --- .config/emacs/modules/mm-spellcheck.el | 24 -- .config/emacs/modules/mm-tetris.el | 20 - .config/emacs/modules/mm-theme.el | 246 ----------- .config/emacs/modules/mm-treesit.el | 240 ----------- .config/emacs/modules/mm-window.el | 72 ---- .config/emacs/site-lisp/emmet.el | 349 ---------------- .config/emacs/site-lisp/gh.el | 62 --- .config/emacs/site-lisp/grab.el | 215 ---------- .config/emacs/site-lisp/highlighter.el | 128 ------ .config/emacs/site-lisp/html-escape.el | 55 --- .config/emacs/site-lisp/increment.el | 132 ------ .config/emacs/site-lisp/line-selection-mode.el | 18 - .config/emacs/site-lisp/live-jq.el | 101 ----- .config/emacs/site-lisp/number-format-mode.el | 129 ------ .config/emacs/site-lisp/surround.el | 122 ------ .config/emacs/templates | 38 -- 76 files changed, 5142 insertions(+), 5142 deletions(-) create mode 100644 .config/emacs-old/.gitignore create mode 100644 .config/emacs-old/combobulate-c.el create mode 100644 .config/emacs-old/early-init.el create mode 100644 .config/emacs-old/editing.el create mode 100644 .config/emacs-old/init.el create mode 100644 .config/emacs-old/mango-light-theme.el create mode 100644 .config/emacs-old/mango-theme.el create mode 100644 .config/emacs-old/modules/mm-abbrev.el create mode 100644 .config/emacs-old/modules/mm-buffer-menu.el create mode 100644 .config/emacs-old/modules/mm-calc.el create mode 100644 .config/emacs-old/modules/mm-completion.el create mode 100644 .config/emacs-old/modules/mm-darwin.el create mode 100644 .config/emacs-old/modules/mm-dired.el create mode 100644 .config/emacs-old/modules/mm-documentation.el create mode 100644 .config/emacs-old/modules/mm-editing.el create mode 100644 .config/emacs-old/modules/mm-humanwave.el create mode 100644 .config/emacs-old/modules/mm-keybindings.el create mode 100644 .config/emacs-old/modules/mm-lsp.el create mode 100644 .config/emacs-old/modules/mm-modeline.el create mode 100644 .config/emacs-old/modules/mm-org.el create mode 100644 .config/emacs-old/modules/mm-projects.el create mode 100644 .config/emacs-old/modules/mm-search.el create mode 100644 .config/emacs-old/modules/mm-spellcheck.el create mode 100644 .config/emacs-old/modules/mm-tetris.el create mode 100644 .config/emacs-old/modules/mm-theme.el create mode 100644 .config/emacs-old/modules/mm-treesit.el create mode 100644 .config/emacs-old/modules/mm-window.el create mode 100644 .config/emacs-old/site-lisp/emmet.el create mode 100644 .config/emacs-old/site-lisp/gh.el create mode 100644 .config/emacs-old/site-lisp/grab.el create mode 100644 .config/emacs-old/site-lisp/highlighter.el create mode 100644 .config/emacs-old/site-lisp/html-escape.el create mode 100644 .config/emacs-old/site-lisp/increment.el create mode 100644 .config/emacs-old/site-lisp/line-selection-mode.el create mode 100644 .config/emacs-old/site-lisp/live-jq.el create mode 100644 .config/emacs-old/site-lisp/number-format-mode.el create mode 100644 .config/emacs-old/site-lisp/surround.el create mode 100644 .config/emacs-old/templates delete mode 100644 .config/emacs/.gitignore delete mode 100644 .config/emacs/combobulate-c.el delete mode 100644 .config/emacs/early-init.el delete mode 100644 .config/emacs/editing.el delete mode 100644 .config/emacs/init.el delete mode 100644 .config/emacs/mango-light-theme.el delete mode 100644 .config/emacs/mango-theme.el delete mode 100644 .config/emacs/modules/mm-abbrev.el delete mode 100644 .config/emacs/modules/mm-buffer-menu.el delete mode 100644 .config/emacs/modules/mm-calc.el delete mode 100644 .config/emacs/modules/mm-completion.el delete mode 100644 .config/emacs/modules/mm-darwin.el delete mode 100644 .config/emacs/modules/mm-dired.el delete mode 100644 .config/emacs/modules/mm-documentation.el delete mode 100644 .config/emacs/modules/mm-editing.el delete mode 100644 .config/emacs/modules/mm-humanwave.el delete mode 100644 .config/emacs/modules/mm-keybindings.el delete mode 100644 .config/emacs/modules/mm-lsp.el delete mode 100644 .config/emacs/modules/mm-modeline.el delete mode 100644 .config/emacs/modules/mm-org.el delete mode 100644 .config/emacs/modules/mm-projects.el delete mode 100644 .config/emacs/modules/mm-search.el delete mode 100644 .config/emacs/modules/mm-spellcheck.el delete mode 100644 .config/emacs/modules/mm-tetris.el delete mode 100644 .config/emacs/modules/mm-theme.el delete mode 100644 .config/emacs/modules/mm-treesit.el delete mode 100644 .config/emacs/modules/mm-window.el delete mode 100644 .config/emacs/site-lisp/emmet.el delete mode 100644 .config/emacs/site-lisp/gh.el delete mode 100644 .config/emacs/site-lisp/grab.el delete mode 100644 .config/emacs/site-lisp/highlighter.el delete mode 100644 .config/emacs/site-lisp/html-escape.el delete mode 100644 .config/emacs/site-lisp/increment.el delete mode 100644 .config/emacs/site-lisp/line-selection-mode.el delete mode 100644 .config/emacs/site-lisp/live-jq.el delete mode 100644 .config/emacs/site-lisp/number-format-mode.el delete mode 100644 .config/emacs/site-lisp/surround.el delete mode 100644 .config/emacs/templates diff --git a/.config/emacs-old/.gitignore b/.config/emacs-old/.gitignore new file mode 100644 index 0000000..fb7fa52 --- /dev/null +++ b/.config/emacs-old/.gitignore @@ -0,0 +1,2 @@ +-*.el +custom.el diff --git a/.config/emacs-old/combobulate-c.el b/.config/emacs-old/combobulate-c.el new file mode 100644 index 0000000..5ac844d --- /dev/null +++ b/.config/emacs-old/combobulate-c.el @@ -0,0 +1,25 @@ +;;; combobulate-c.el --- C support for combobulate -*- lexical-binding: t; -*- + +(require 'combobulate-manipulation) +(require 'combobulate-navigation) +(require 'combobulate-rules) +(require 'combobulate-settings) +(require 'combobulate-setup) + +(eval-and-compile + (defvar combobulate-c-definitions + '((context-nodes + '("char_literal" "false" "field_identifier" "identifier" "null" + "number_literal" "statement_identifier" "string_literal" "true" + "type_identifier"))))) + +(define-combobulate-language + :name c + :language c + :major-modes (c-ts-mode) + :custom combobulate-c-definitions + :setup-fn combobulate-c-setup) + +(defun combobulate-c-setup (_)) + +(provide 'combobulate-c) diff --git a/.config/emacs-old/early-init.el b/.config/emacs-old/early-init.el new file mode 100644 index 0000000..ccae20b --- /dev/null +++ b/.config/emacs-old/early-init.el @@ -0,0 +1,105 @@ +;;; early-init.el --- Emacs early init file -*- lexical-binding: t; -*- + +;;; XDG Base Directory Specification Compliance + +(eval-when-compile + (require 'xdg)) + +(defconst mm-cache-directory + (expand-file-name "emacs" (xdg-cache-home)) + "The XDG-conformant cache directory that Emacs should use.") + +(defconst mm-config-directory + (expand-file-name "emacs" (xdg-config-home)) + "The XDG-conformant config directory that Emacs should use.") + +(defconst mm-data-directory + (expand-file-name "emacs" (xdg-data-home)) + "The XDG-conformant data directory that Emacs should use.") + +(mapc (lambda (directory) + (make-directory directory :parents)) + (list mm-cache-directory mm-config-directory mm-data-directory)) + +(setopt user-emacs-directory mm-cache-directory + auto-save-list-file-prefix (expand-file-name + "auto-save-list-" + mm-cache-directory) + backup-directory-alist `(("." . ,(expand-file-name + "backups" mm-cache-directory)))) +(when (native-comp-available-p) + (startup-redirect-eln-cache + (expand-file-name (expand-file-name "eln/" mm-cache-directory)))) + + +;;; Useful Constants + +(defconst mm-darwin-p (eq system-type 'darwin) + "This variable is non-nil if Emacs is running on a Darwin system.") + +(defconst mm-humanwave-p (file-exists-p "~/.humanwavep") + "This variable is non-nil if Emacs is running on a Humanwave system.") + + +;;; Basic Frame Settings + +(setopt frame-resize-pixelwise t + frame-inhibit-implied-resize t + ring-bell-function #'ignore + use-short-answers t + inhibit-splash-screen t + inhibit-startup-buffer-menu t) +(if mm-darwin-p + (progn + (add-to-list 'default-frame-alist '(fullscreen . maximized)) + (when (featurep 'ns) + (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)))) + (add-to-list 'default-frame-alist '(undecorated . t)) + (menu-bar-mode -1)) +(scroll-bar-mode -1) +(tool-bar-mode -1) + + +;;; Startup Performance + +(setopt gc-cons-threshold most-positive-fixnum + gc-cons-percentage 0.5) +(setopt read-process-output-max + (let ((pipe-size-file "/proc/sys/fs/pipe-max-size")) + (if (file-exists-p pipe-size-file) + (with-temp-buffer + (insert-file-contents pipe-size-file) + (number-at-point)) + (* 1024 1024)))) + +;; Set ‘file-name-handler-alist’ and ‘vc-handled-backends’ to nil +;; temporarily and restore them once Emacs has properly initialized. We +;; set threshold to 8 MiB which seems to be a good middleground for now. +;; A higher threshold means less garbage collections but I’ve had issues +;; with those garbage collections causing long freezes when they occur. +(let ((saved-file-name-handler-alist file-name-handler-alist)) + (setopt file-name-handler-alist nil) + (add-hook + 'emacs-startup-hook + (defun mm-restore-emacs-settings () + (setopt gc-cons-threshold (* 1024 1024 8) + gc-cons-percentage 0.1 + file-name-handler-alist saved-file-name-handler-alist)))) + + +;;; Avoid Flashbang + +(setq-default mode-line-format nil) ; This will be set in init.el + +;; Colors taken from ‘mango-theme’ +(let ((background "#2B303B") + (foreground "#C5C8C6")) + (set-face-attribute + 'default nil + :background background + :foreground foreground) + (set-face-attribute + 'mode-line nil + :background background + :foreground foreground + :box 'unspecified)) diff --git a/.config/emacs-old/editing.el b/.config/emacs-old/editing.el new file mode 100644 index 0000000..0b96867 --- /dev/null +++ b/.config/emacs-old/editing.el @@ -0,0 +1,271 @@ +;;; editing.el --- Text editing commands -*- lexical-binding: t; -*- + +(defun e/align-regexp (regexp repeat) + "Align the marked region on REGEXP. +When called interactively REGEXP is read from the minibuffer and the +user is prompted about whether they would like to REPEAT the alignment. + +This function wraps `align-regexp' and implicitly prepends REGEXP with +\"\\(\\s-*\\)\"." + (interactive + (progn (barf-if-buffer-read-only) + (list (concat "\\(\\s-*\\)" + (read-string + (format-prompt "Align regexp" nil))) + (y-or-n-p "Repeat?")))) + (let ((start (min (mark) (point))) + (end (max (mark) (point)))) + (align-regexp start end regexp 1 1 repeat))) + +(defun e/join-current-and-next-line (&optional arg beg end) + "Join the current- and next lines. +This function is identical to `join-line' but it joins the current line +with the next one instead of the previous one." + (interactive + (progn (barf-if-buffer-read-only) + (cons current-prefix-arg + (and (use-region-p) + (list (region-beginning) (region-end)))))) + (delete-indentation + (unless (or beg end) (not arg)) + beg end)) + +(defun e/mark-entire-word (&optional arg allow-extend) + "Mark ARG words beginning at point. +This command is a wrapper around `mark-word' that moves the point such +that the word under point is entirely marked. ARG and ALLOW-EXTEND are +just as they are with `mark-word.'" + (interactive "P\np") + (if (eq last-command this-command) + (mark-word arg allow-extend) + (let ((bounds (bounds-of-thing-at-point 'word)) + (numeric-arg (or allow-extend 0))) + (if bounds + (goto-char (if (< numeric-arg 0) + (cdr bounds) + (car bounds))) + (forward-to-word (when (< numeric-arg 0) -1)))) + (mark-word arg allow-extend))) + +(defun e/mark-entire-sexp (&optional arg allow-extend) + "Mark ARG sexps beginning at point. +This command is a wrapper around `mark-sexp' that moves the point such +that the sexp under point is entirely marked. ARG and ALLOW-EXTEND are +just as they are with `mark-sexp.'" + (interactive "P\np") + (if (eq last-command this-command) + (mark-sexp arg allow-extend) + (let ((bounds (bounds-of-thing-at-point 'sexp)) + (numeric-arg allow-extend)) + (if bounds + (goto-char (if (< numeric-arg 0) + (cdr bounds) + (car bounds))) + (if (< numeric-arg 0) + (progn + (backward-sexp) + (forward-sexp)) + (forward-sexp) + (backward-sexp)))) + (mark-sexp arg allow-extend))) + +(defun e/mark-line-dwim (&optional arg) + "Mark ARG lines beginning at point. +If the region is active then it is extended by ARG lines. If called +without a prefix argument this command marks one line forwards unless +point is ahead of the mark in which case this command marks one line +backwards. + +If this function is called with a negative prefix argument and no region +active, the current line is marked." + (interactive "P") + (let ((numeric-arg (prefix-numeric-value arg))) + (if (region-active-p) + (progn + (exchange-point-and-mark) + (goto-char (1+ (pos-eol (if arg numeric-arg + (when (< (point) (mark)) -1))))) + (exchange-point-and-mark)) + (if (< numeric-arg 0) + (progn + (push-mark (pos-bol (+ 2 numeric-arg)) nil :activate) + (goto-char (1+ (pos-eol)))) + (push-mark (1+ (pos-eol numeric-arg)) nil :activate) + (goto-char (pos-bol)))))) + +(defun e/kill-ring-save-dwim () + "Save the region as if killed, but don't kill it. +This function is the same as `kill-ring-save' in Transient Mark mode, +but when there is no active region it saves the line at point to the kill +ring excluding any potential trailing newline." + (interactive) + (if (region-active-p) + (kill-ring-save -1 -1 :region) + (kill-ring-save (pos-bol) (pos-eol)))) + +(defun e/scroll-down () + "Scroll down one page. +This function is identical to `cua-scroll-down' except it recenters the +screeen after scrolling. If the user scrolls to the top of the document +then no recentering occurs." + (interactive) + (let ((line-number (line-number-at-pos))) + (cua-scroll-down) + (when (= line-number (line-number-at-pos)) + (goto-char (point-min))) + (recenter))) + +(defun e/scroll-up () + "Scroll up one page. +This function is identical to `cua-scroll-up' except it recenters the +screen after scrolling." + (interactive) + (mm-do-and-center #'cua-scroll-up)) + +(defun e/open-line (arg) + "Insert and move to a new empty line after point. +With prefix argument ARG, inserts and moves to a new empty line before +point." + (interactive "*P") + (end-of-line) + (newline-and-indent) + (when arg + (transpose-lines 1) + (previous-line 2) + (end-of-line))) + +(defun e/split-line (&optional above) + "Split the line at point. +Place the contents after point on a new line, indenting the new line +according to the current major mode. With prefix argument ABOVE the +contents after point are placed on a new line before point." + (interactive "*P") + (save-excursion + (let* ((start (point)) + (end (pos-eol)) + (string (buffer-substring start end))) + (delete-region start end) + (when above + (goto-char (1- (pos-bol)))) + (newline) + (insert string) + (indent-according-to-mode)))) + +(defun e/mc/sort-regions (&optional reverse) + "Sort marked regions. +This command is an exact replica of `mc/sort-regions' except that +calling this command with a prefix argument REVERSE sorts the marked +regions in reverse order." + (interactive "*P") + (unless (use-region-p) + (user-error "No active region.")) + (setq mc--strings-to-replace (sort (mc--ordered-region-strings) + (if reverse #'string> #'string<))) + (mc--replace-region-strings)) + +(defun e/sort-dwim (&optional reverse) + "Sort regions do-what-i-mean. +When multiple cursors are not being used this command functions just +like `sort-lines' with the start- and end bounds set to the current +region beginning and -end. + +When using multiple cursors this command sorts the regions marked by +each cursor (effectively calling `e/mc/sort-regions'. + +When called with a prefix argument REVERSE, sorting occurs in reverse +order." + (interactive "*P") + (if (and (fboundp #'mc/num-cursors) + (< 1 (mc/num-cursors))) + (e/mc/sort-regions reverse) + (sort-lines reverse (region-beginning) (region-end)))) + +(defun e/yank (&optional arg) + "Yank text from the kill-ring. +Yank the most recent kill from the kill ring via `yank'. If called with +prefix argument ARG then interactively yank from the kill ring via +`yank-from-kill-ring'. + +If `consult' is available than this command instead calls +`consult-yank-from-kill-ring' when called with non-nil ARG." + (declare (interactive-only t)) + (interactive "*P") + ;; Avoid ‘current-prefix-arg’ cascading down to ‘yank-from-kill-ring’ + (let (current-prefix-arg) + (cond ((null arg) + (yank)) + ((featurep 'consult) + (call-interactively #'consult-yank-from-kill-ring)) + (t + (call-interactively #'yank-from-kill-ring))))) + +(defun mm-search-forward-char (char &optional n) + "Search forwards to the Nth occurance of CHAR. +If called interactively CHAR is read from the minibuffer and N is given +by the prefix argument. + +If N is negative then this function searches backwards. + +When searching forwards point is left before CHAR while when searching +backwards point is left after CHAR." + (interactive + (list (read-char) + (prefix-numeric-value current-prefix-arg))) + (when (and (> n 0) (= char (char-after (point)))) + (forward-char)) + (search-forward (char-to-string char) nil nil n) + (when (> n 0) + (backward-char))) + +(defun mm-search-backward-char (char &optional n) + "Search backwards to the Nth occurance of CHAR. +This function is identical to `mm-search-forward-char' with N negated." + (declare (interactive-only t)) + (interactive + (list (read-char) + (prefix-numeric-value current-prefix-arg))) + (mm-search-forward-char char (- n))) + +(defun mm-add-cursor-to-next-thing (thing) + "Add a fake cursor to the next occurance of THING. +THING is any symbol that can be given to ‘bounds-of-thing-at-point’. + +If there is an active region, the next THING will be marked." + (let ((bounds (bounds-of-thing-at-point thing))) + (if (null bounds) + (progn + (forward-thing thing) + (goto-char (car (bounds-of-thing-at-point thing)))) + (mc/save-excursion + (when (> (mc/num-cursors) 1) + (goto-char (overlay-end (mc/furthest-cursor-after-point)))) + (goto-char (cdr (bounds-of-thing-at-point thing))) + (forward-thing thing) + (let ((bounds (bounds-of-thing-at-point thing))) + (goto-char (car bounds)) + (when (use-region-p) + (push-mark (cdr bounds))) + (mc/create-fake-cursor-at-point)))))) + +(defun mm-add-cursor-to-next-word () + "Add a fake cursor to the next word." + (declare (interactive-only t)) + (interactive) + (mm-add-cursor-to-next-thing 'word) + (mc/maybe-multiple-cursors-mode)) + +(defun mm-transpose-cursor-regions (n) + "Interchange the regions of each cursor. +With prefix arg N, the regions are rotated N places (backwards if N is +negative)." + (interactive "p") + (when (= (mc/num-cursors) 1) + (user-error "Cannot transpose with only one cursor.")) + (unless (use-region-p) + (user-error "No active region.")) + (setq mc--strings-to-replace + (funcall (if (< n 0) #'mm-rotate-left #'mm-rotate-right) + (abs n) (mc--ordered-region-strings))) + (mc--replace-region-strings)) + +(provide 'editing) diff --git a/.config/emacs-old/init.el b/.config/emacs-old/init.el new file mode 100644 index 0000000..0bda7f6 --- /dev/null +++ b/.config/emacs-old/init.el @@ -0,0 +1,358 @@ +;;; init.el --- Main Emacs configuration file -*- lexical-binding: t; -*- + +;;; Preamble + +;; To inhibit this message you must do this in init.el (not +;; early-init.el!), you must use ‘setq’ (not ‘setopt’!), and you must +;; write your login name as a string (you shan’t use ‘user-login-name’!). +;; Lord knows why this needs to be so complicated… +;; +;; The ‘eval’ is required in the case that this file is byte-compiled. +(if mm-humanwave-p + (eval '(setq inhibit-startup-echo-area-message "thomasvoss")) + (eval '(setq inhibit-startup-echo-area-message "thomas"))) + +;; Add all my custom lisp code into the load path +(dolist (directory + (list mm-config-directory + (expand-file-name "modules" mm-config-directory) + (expand-file-name "site-lisp" mm-config-directory))) + (add-to-list 'load-path directory)) + + +;;; Disable or Enable LSP? + +;; I’m not decided on LSP… so make it a variable + +(defvar mm-lsp-p nil + "Enable LSP support if non-nil.") + + +;;; Convenience Macros and -Functions + +(defun mm-mode-to-hook (mode) + "Get the hook corresponding to MODE." + (declare (ftype (function (symbol) symbol)) + (pure t) (side-effect-free t)) + (intern (concat (symbol-name mode) "-hook"))) + +(defun mm-mode-to-ts-mode (mode) + "Get the Tree-Sitter mode corresponding to MODE." + (declare (ftype (function (symbol) symbol)) + (pure t) (side-effect-free t)) + (intern (concat + (string-remove-suffix "-mode" (symbol-name mode)) + "-ts-mode"))) + +(defun mm-ts-mode-to-mode (ts-mode) + "Get the non-Tree-Sitter mode corresponding to TS-MODE." + (declare (ftype (function (symbol) symbol)) + (pure t) (side-effect-free t)) + (intern (concat + (string-remove-suffix "-ts-mode" (symbol-name ts-mode)) + "-mode"))) + +(defsubst mm-string-split (separators string) + "Split STRING on SEPARATORS. +Wrapper around `string-split' that puts separators first. This makes it +convenient to use in `thread-last'." + (declare (ftype (function (string string) (list string))) + (pure t) (side-effect-free t)) + (string-split string separators)) + +(defun mm-as-number (string-or-number) + "Ensure STRING-OR-NUMBER is a number. +If given a number return STRING-OR-NUMBER as-is, otherwise convert it to +a number and then return it. + +This function is meant to be used in conjuction with `read-string' and +`format-prompt'." + (declare (ftype (function (or string number) number)) + (pure t) (side-effect-free t)) + (if (stringp string-or-number) + (string-to-number string-or-number) + string-or-number)) + +(defun mm-camel-to-lisp (string) + "Convert STRING from camelCase to lisp-case." + (declare (ftype (function (string) string)) + (pure t) (side-effect-free t)) + (let ((case-fold-search nil)) + (downcase + (replace-regexp-in-string + (rx (group (or lower digit)) (group upper)) "\\1-\\2" string)))) + +(defun mm-do-and-center (function &rest arguments) + "Call FUNCTION with ARGUMENTS and then center the screen." + (apply function arguments) + (when (called-interactively-p) + (recenter))) + +(defmacro mm-comment (&rest _body) + "Comment out BODY. A cleaner alternative to line-commenting a region." + (declare (indent 0)) + nil) + +(defun mm-nil (&rest _) + "Return nil." + nil) + +(defmacro mm-with-suppressed-output (&rest body) + "Execute BODY while suppressing output. +Execute BODY as given with all output to the echo area or the *Messages* +buffer suppressed." + (declare (indent 0)) + `(let ((inhibit-message t) + (message-log-max nil)) + ,@body)) + +(defun mm-rotate-left (n list) + "Rotate the elements of LIST N places to the left." + (declare (ftype (function (number (list t)) (list t))) + (pure t) (side-effect-free t)) + (append (nthcdr n list) (butlast list (- (length list) n)))) + +(defun mm-rotate-right (n list) + "Rotate the elements of LIST N places to the right." + (declare (ftype (function (number (list t)) (list t))) + (pure t) (side-effect-free t)) + (mm-rotate-left (- (length list) n) list)) + + +;;; Silent Native Compilation + +(when (native-comp-available-p) + (setopt + native-comp-async-report-warnings-errors nil + native-compile-prune-cache t)) + + +;;; Package Management + +(setopt + package-vc-register-as-project nil + package-user-dir (expand-file-name "pkg" mm-data-directory) + package-gnupghome-dir (or (getenv "GNUPGHOME") + (expand-file-name "gnupg" package-user-dir)) + package-archives (cl-loop with proto = (if (gnutls-available-p) "https" "http") + for (name . url) in + '(("gnu" . "elpa.gnu.org/packages/") + ("melpa" . "melpa.org/packages/") + ("nongnu" . "elpa.nongnu.org/nongnu/")) + collect (cons name (concat proto "://" url))) + package-archive-priorities '(("gnu" . 3) + ("nongnu" . 2) + ("melpa" . 1))) +(setopt use-package-always-defer t) + +(package-initialize) + +(defun mm-package-sync () + "Remove unused packages and install missing ones." + (interactive) + (let ((window-configuration (current-window-configuration))) + (package-autoremove) + (package-install-selected-packages) + (package-upgrade-all) + (package-vc-install-selected-packages) + (package-vc-upgrade-all) + (set-window-configuration window-configuration)) + (message "Done syncing packages.")) + + +;;; Generic Emacs Configuration + +(defvar mm-initial-scratch-message + (substitute-quotes + (format + ";; This is `%s'. Use `%s' to evaluate and print results.\n\n" + initial-major-mode + (substitute-command-keys + "\\\\[eval-print-last-sexp]"))) + "The initial message to display in the scratch buffer.") + +(use-package emacs + :demand t + :custom + (ad-redefinition-action 'accept) + (case-fold-search nil) + (create-lockfiles nil) + (custom-file (expand-file-name "custom.el" mm-config-directory)) + (custom-safe-themes t) + (delete-pair-blink-delay 0) + (disabled-command-function nil) + (duplicate-line-final-position -1) + (duplicate-region-final-position -1) + (echo-keystrokes 0.01) ; 0 disables echoing + (echo-keystrokes-help nil) + (extended-command-suggest-shorter nil) + (initial-buffer-choice nil) + (initial-scratch-message mm-initial-scratch-message) + (kill-do-not-save-duplicates t) + (large-file-warning-threshold nil) + (make-backup-files nil) + (mode-require-final-newline t) + (next-error-recenter '(4)) ; ‘center of window’ + (read-extended-command-predicate #'command-completion-default-include-p) + (remote-file-name-inhibit-auto-save t) + (remote-file-name-inhibit-delete-by-moving-to-trash t) + (require-final-newline mm-humanwave-p) + (save-interprogram-paste-before-kill t) + (user-full-name "Thomas Voss") + (user-mail-address "mail@thomasvoss.com") + :config + (load custom-file :noerror) + (setq-default fill-column 80) + (dolist (mode '(text-mode emacs-lisp-mode lisp-mode)) + (add-hook (mm-mode-to-hook mode) + (defun mm-set-fill-column () + (setq-local fill-column 73)))) + (add-hook 'text-mode-hook #'auto-fill-mode) + (add-hook 'before-save-hook + (defun mm-delete-final-newline () + (let ((end (point-max))) + (unless (or require-final-newline + mode-require-final-newline + (not (= (char-before end) ?\n))) + (delete-region (1- end) end))))) + (add-hook 'before-save-hook #'delete-trailing-whitespace) + (prefer-coding-system 'utf-8) + + ;; Disabled modes + (blink-cursor-mode -1) + (line-number-mode -1) + (tooltip-mode -1)) + + +;;; Instantly highlight matching parens + +(use-package paren + :custom + (show-paren-delay 0)) + + +;;; Auto Revert Buffers + +(use-package autorevert + :custom + (global-auto-revert-non-file-buffers t) + :init + (add-hook + 'after-change-major-mode-hook + (defun mm-enable-autorevert () + (unless (derived-mode-p 'Buffer-menu-mode) + (auto-revert-mode))))) + + +;;; Bookmarks + +(use-package bookmark + :custom + (bookmark-save-flag 1)) + + +;;; Automatically Create- and Delete Directories + +(defun mm-auto-create-directories (function filename &rest arguments) + "Automatically create and delete parent directories of files. +This is an `:override' advice for `find-file' and friends. It +automatically creates the parent directories of the file being visited +if necessary. It also sets a buffer-local variable so that the user +will be prompted to delete the newly created directories if they kill +the buffer without saving it." + (let (dirs-to-delete) + (let* ((dir-to-create (file-name-directory filename)) + (current-dir dir-to-create)) + ;; Add each directory component to ‘dirs-to-delete’ + (while (not (file-exists-p current-dir)) + (push current-dir dirs-to-delete) + (setq current-dir (file-name-directory + (directory-file-name current-dir)))) + (unless (file-exists-p dir-to-create) + (make-directory dir-to-create :parents))) + (prog1 + (apply function filename arguments) + (when dirs-to-delete + (setq-local mm-find-file--dirs-to-delete (reverse dirs-to-delete)) + (add-hook 'kill-buffer-hook #'mm-find-file--maybe-delete-directories + :depth :local) + (add-hook 'after-save-hook #'mm-find-file--remove-hooks + :depth :local))))) + +(defun mm-find-file--maybe-delete-directories () + (unless (file-exists-p buffer-file-name) + (dolist (directory mm-find-file--dirs-to-delete) + (when (and (stringp directory) + (file-exists-p directory) + (thread-last + (directory-file-name directory) + (format "Also delete directory `%s'?") + (substitute-quotes) + (y-or-n-p))) + (delete-directory directory))))) + +(defun mm-find-file--remove-hooks () + (remove-hook 'kill-buffer-hook + #'mm-find-file--maybe-delete-directories + :local) + (remove-hook 'after-save-hook + #'mm-find-file--remove-hooks + :local)) + +(dolist (command #'(find-file find-alternate-file write-file)) + (advice-add command :around #'mm-auto-create-directories)) + + +;;; Load Modules + +(require 'mm-abbrev) ; Text Expansion +(require 'mm-buffer-menu) ; Buffer Menu +(require 'mm-calc) ; Emacs Calc +(require 'mm-completion) ; Completions +(require 'mm-dired) ; Dired +(require 'mm-documentation) ; Documentation +(require 'mm-editing) ; Text Editing +(require 'mm-keybindings) ; Keybindings +(require 'mm-modeline) ; Modeline +(require 'mm-org) ; Org-Mode +(require 'mm-projects) ; Project Management +(require 'mm-search) ; Text Searching +(require 'mm-spellcheck) ; Spell Checking +(require 'mm-tetris) ; Emacs Tetris +(require 'mm-theme) ; Themeing +(require 'mm-treesit) ; Tree-Sitter +(require 'mm-window) ; Windowing +(when mm-darwin-p + (require 'mm-darwin)) ; MacOS +(when mm-lsp-p + (require 'mm-lsp)) ; Language Server Protocol +(when mm-humanwave-p + (require 'mm-humanwave)) ; Humanwave Extras + +;; TODO: Put this somewhere reasonable + +(defvar mm-placeholder-text "‹XX›") + +(defun mm-placeholder-insert () + (interactive) + (insert mm-placeholder-text)) + +(defun mm-placeholder-next () + (interactive) + (let ((point (point))) + (if (search-forward mm-placeholder-text nil :noerror) + (delete-region (match-beginning 0) (match-end 0)) + (goto-char point) + (message "No more placeholders after point.")))) + +(keymap-global-set "C-c i p" #'mm-placeholder-insert) +(keymap-global-set "C-c n" #'mm-placeholder-next) + + + +;;; Postamble + +(add-hook 'after-init-hook + (defun mm-echo-init-time () + (message (emacs-init-time "Emacs initialized in %.2f seconds"))) + 100) diff --git a/.config/emacs-old/mango-light-theme.el b/.config/emacs-old/mango-light-theme.el new file mode 100644 index 0000000..4cbda4f --- /dev/null +++ b/.config/emacs-old/mango-light-theme.el @@ -0,0 +1,347 @@ +;;; mango-light-theme.el --- Just your average light theme -*- lexical-binding: t; -*- + +(deftheme mango-light + "Mildly light, light theme. +Your average not-so-light light theme, because none of the other options +were exactly to my liking. It’s about time I had a theme to call my +own.") + +;; Colors are defined as: (GUI-HEX 256-COLOR 16-COLOR) +(defconst mango-light-theme-colors-alist + '(;; (foreground . ("#3B4252" "color-238" "black")) + ;; (background . ("#ECEFF4" "color-255" "white")) + ;; (background-cool . ("#E5E9F0" "color-254" "white")) + ;; (background-dark . ("#FAFBFC" "color-231" "brightwhite")) + ;; (background-faint . ("#D8DEE9" "color-253" "brightwhite")) + ;; (middleground . ("#C8D0E0" "color-252" "brightwhite")) + (disabled . ("#9BA6B5" "color-247" "brightblack")) + (foreground . ("#000000" "color-0" "black")) + (background . ("#ffffff" "color-0" "black")) + (middleground . ("#c4c4c4" "color-0" "black")) + (background-cool . ("#e0e0e0" "color-0" "black")) + ;; TODO: Rename to foreground-light + (background-dark . ("#595959" "color-0" "black")) + (background-faint . ("#e6e6e6" "color-0" "black")) + + (celestial-blue . ("#1B61CE" "color-26" "blue")) + (dark-red . ("#A12027" "color-124" "red")) + (khaki . ("#8A6C23" "color-94" "yellow")) + (lime . ("#358A2A" "color-28" "green")) + (magenta . ("#9A35B3" "color-127" "magenta")) + (pale-azure . ("#0A74B8" "color-31" "cyan")) + (red . ("#D22129" "color-160" "brightred")) + (salmon . ("#D1570B" "color-166" "brightyellow")) + (violet . ("#7A3B9E" "color-97" "magenta"))) + "The color palette used throughout `mango-light-theme'. +Each color is mapped to a list of colors of the form +(GUI-HEX 256-COLOR 16-COLOR) for use in true-color, 256-color, and +16-color modes.") + +(defsubst mango-light-theme-color (name &optional display) + "Get the color value of NAME for the given DISPLAY. +DISPLAY can be 'gui, '256, or '16." + (let ((colors (alist-get name mango-light-theme-colors-alist))) + (pcase display + ('gui (nth 0 colors)) + ('256 (nth 1 colors)) + ('16 (nth 2 colors)) + (_ (nth 0 colors))))) + +(custom-theme-set-faces + 'mango-light + + ;; Standard Stuff + `(default + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'foreground 'gui) + :background ,(mango-light-theme-color 'background 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'foreground '256) + :background ,(mango-light-theme-color 'background '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'foreground '16) + :background ,(mango-light-theme-color 'background '16))))) + `(fringe + ((t (:inherit default)))) + + ;; Lines + `(hl-line + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'background-faint 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'background-faint '256))) + (((type tty)) + (:background ,(mango-light-theme-color 'background-faint '16))))) + `(region + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'middleground '256))) + (((type tty)) + (:background ,(mango-light-theme-color 'middleground '16))))) + `(header-line + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'middleground '256))) + (((type tty)) + (:background ,(mango-light-theme-color 'middleground '16))))) + `(mode-line-active + ((t ( :box ,(mango-light-theme-color 'celestial-blue 'gui) + :inherit header-line)))) + `(mode-line-inactive + ((((type graphic tty) (min-colors 16777216)) + ( :background ,(mango-light-theme-color 'background-cool 'gui) + :box ,(mango-light-theme-color 'background-faint 'gui) + :weight light)) + (((type tty) (min-colors 256)) + ( :background ,(mango-light-theme-color 'background-cool '256) + :box ,(mango-light-theme-color 'background-faint 'gui) + :weight light)) + (((type tty)) + ( :background ,(mango-light-theme-color 'background-cool '16) + :box ,(mango-light-theme-color 'background-faint 'gui) + :weight light)))) + `(window-divider + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'background-cool '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'background-cool '16))))) + `(window-divider-first-pixel + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'background-cool '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'background-cool '16))))) + `(window-divider-last-pixel + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'background-cool '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'background-cool '16))))) + + ;; Line Numbers + `(line-number + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'disabled 'gui) + :background ,(mango-light-theme-color 'background 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'disabled '256) + :background ,(mango-light-theme-color 'background '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'disabled '16) + :background ,(mango-light-theme-color 'background '16))))) + `(line-number-current-line + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'salmon 'gui) + :background ,(mango-light-theme-color 'background 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'salmon '256) + :background ,(mango-light-theme-color 'background '256) :weight bold)) + (((type tty)) + (:foreground ,(mango-light-theme-color 'salmon '16) + :background ,(mango-light-theme-color 'background '16) :weight bold)))) + + ;; Documentation + `(font-lock-comment-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'khaki 'gui) :weight semi-bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'khaki '256) :weight semi-bold)) + (((type tty)) + (:foreground ,(mango-light-theme-color 'khaki '16) :weight semi-bold)))) + `(font-lock-doc-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'disabled 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'disabled '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'disabled '16))))) + + ;; Modeline + `(mm-modeline-overwrite-face ((t (:weight normal)))) + `(mm-modeline-readonly-face ((t (:weight normal)))) + `(mm-modeline-buffer-name-face ((t (:inherit font-lock-constant-face)))) + `(mm-modeline-buffer-modified-face ((t (:inherit shadow)))) + `(mm-modeline-major-mode-name-face ((t (:weight normal)))) + `(mm-modeline-major-mode-symbol-face ((t (:inherit shadow)))) + `(mm-modeline-git-branch-face ((t (:inherit font-lock-constant-face)))) + `(mm-modeline-narrow-face + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'dark-red 'gui) :foreground ,(mango-light-theme-color 'background-dark 'gui) :box ,(mango-light-theme-color 'dark-red 'gui) :weight normal)) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'dark-red '256) :foreground ,(mango-light-theme-color 'background-dark '256) :box ,(mango-light-theme-color 'dark-red '256) :weight normal)) + (((type tty)) + (:background ,(mango-light-theme-color 'dark-red '16) :foreground ,(mango-light-theme-color 'background-dark '16) :box ,(mango-light-theme-color 'dark-red '16) :weight normal)))) + + ;; Core Language + `(font-lock-builtin-face ((t (:inherit font-lock-preprocessor-face)))) + `(font-lock-keyword-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'violet 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'violet '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'violet '16))))) + `(font-lock-type-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'celestial-blue 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'celestial-blue '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'celestial-blue '16))))) + + ;; Function-likes + `(font-lock-function-name-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'khaki 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'khaki '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'khaki '16))))) + `(font-lock-preprocessor-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'magenta 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'magenta '256) :weight bold)) + (((type tty)) + (:foreground ,(mango-light-theme-color 'magenta '16) :weight bold)))) + + ;; Variables + `(font-lock-constant-face ((t (:inherit font-lock-variable-name-face :weight bold)))) + `(font-lock-variable-name-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'pale-azure 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'pale-azure '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'pale-azure '16))))) + + ;; Other literals + `(help-key-binding ((t (:inherit font-lock-constant-face)))) + `(font-lock-string-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'salmon 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'salmon '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'salmon '16))))) + `(font-lock-number-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'salmon 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'salmon '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'salmon '16))))) + + ;; Org Mode + `(org-quote ((t (:inherit org-block :slant italic)))) + `(org-code + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'salmon 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'salmon '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'salmon '16))))) + `(org-verbatim + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'lime 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'lime '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'lime '16))))) + `(org-block + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'background-cool '256))) + (((type tty)) + (:background ,(mango-light-theme-color 'background-cool '16))))) + `(org-hide + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'background 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'background '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'background '16))))) + + ;; Info Page + `(Info-quoted ((t (:inherit default)))) + + ;; Magit + `(magit-diff-context-highlight ((t (:inherit hl-line)))) + `(magit-section-highlight ((t (:inherit hl-line)))) + `(magit-diff-hunk-heading + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'background-cool '256))) + (((type tty)) + (:background ,(mango-light-theme-color 'background-cool '16))))) + `(magit-diff-hunk-heading-highlight + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-light-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-light-theme-color 'middleground '256))) + (((type tty)) + (:background ,(mango-light-theme-color 'middleground '16))))) + `(git-commit-summary + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'khaki 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'khaki '256))) + (((type tty)) + (:foreground ,(mango-light-theme-color 'khaki '16))))) + `(git-commit-overlong-summary + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'background-dark 'gui) + :background ,(mango-light-theme-color 'red 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'background-dark '256) + :background ,(mango-light-theme-color 'red '256) :weight bold)) + (((type tty)) + (:foreground ,(mango-light-theme-color 'background-dark '16) + :background ,(mango-light-theme-color 'red '16) :weight bold)))) + + ;; Vertico + `(vertico-current ((t (:inherit hl-line)))) + + ;; Marginalia + `(mm-diffstat-counter-added ((t (:foreground "green" :weight bold)))) + `(mm-diffstat-counter-removed ((t (:foreground "red" :weight bold)))) + `(marginalia-documentation + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-light-theme-color 'disabled 'gui) :underline nil)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-light-theme-color 'disabled '256) :underline nil)) + (((type tty)) + (:foreground ,(mango-light-theme-color 'disabled '16) :underline nil)))) + + ;; Tempel + `(tempel-default + ((((type graphic tty) (min-colors 16777216)) + (:slant italic :background ,(mango-light-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:slant italic :background ,(mango-light-theme-color 'middleground '256))) + (((type tty)) + (:slant italic :background ,(mango-light-theme-color 'middleground '16))))) + `(tempel-field + ((((type graphic tty) (min-colors 16777216)) + (:slant italic :background ,(mango-light-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:slant italic :background ,(mango-light-theme-color 'middleground '256))) + (((type tty)) + (:slant italic :background ,(mango-light-theme-color 'middleground '16))))) + `(tempel-form + ((((type graphic tty) (min-colors 16777216)) + (:slant italic :background ,(mango-light-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:slant italic :background ,(mango-light-theme-color 'middleground '256))) + (((type tty)) + (:slant italic :background ,(mango-light-theme-color 'middleground '16)))))) + +(provide-theme 'mango-light) diff --git a/.config/emacs-old/mango-theme.el b/.config/emacs-old/mango-theme.el new file mode 100644 index 0000000..72a76f9 --- /dev/null +++ b/.config/emacs-old/mango-theme.el @@ -0,0 +1,331 @@ +;;; mango-theme.el --- Just your average dark theme -*- lexical-binding: t; -*- + +(deftheme mango + "Mildly dark, dark theme. +Your average not-so-dark dark theme, because none of the other options +were exactly to my liking. It’s about time I had a theme to call my +own.") + +(defconst mango-theme-colors-alist + '((foreground . ("#C5C8C6" "color-251" "white")) + (background . ("#2B303B" "color-236" "black")) + (background-cool . ("#363C4A" "color-237" "black")) + (background-dark . ("#1D2635" "color-234" "black")) + (background-faint . ("#414859" "color-238" "brightblack")) + (middleground . ("#4F5561" "color-239" "brightblack")) + (disabled . ("#999999" "color-246" "brightblack")) + (celestial-blue . ("#569CD6" "color-74" "brightblue")) + (dark-red . ("#841A11" "color-88" "red")) + (khaki . ("#F0E68C" "color-228" "yellow")) + (lime . ("#B8F182" "color-156" "green")) + (magenta . ("#ED97F5" "color-213" "magenta")) + (pale-azure . ("#9CDCFE" "color-117" "cyan")) + (red . ("#E60026" "color-160" "brightred")) + (salmon . ("#F1B282" "color-216" "brightyellow")) + (violet . ("#E57AE5" "color-176" "brightmagenta"))) + "The color palette used throughout `mango-theme'. +Each color is mapped to a list of colors of the form +(GUI-HEX 256-COLOR 16-COLOR) for use in true-color, 256-color, and +16-color modes.") + +(defsubst mango-theme-color (name &optional display) + "Get the color value of NAME for the given DISPLAY. +DISPLAY can be 'gui, '256, or '16." + (let ((colors (alist-get name mango-theme-colors-alist))) + (pcase display + ('gui (nth 0 colors)) + ('256 (nth 1 colors)) + ('16 (nth 2 colors)) + (_ (nth 0 colors))))) + +(custom-theme-set-faces + 'mango + + ;; Standard Stuff + `(default + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'foreground 'gui) + :background ,(mango-theme-color 'background 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'foreground '256) + :background ,(mango-theme-color 'background '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'foreground '16) + :background ,(mango-theme-color 'background '16))))) + `(fringe + ((t (:inherit default)))) + + ;; Lines + `(hl-line + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'background-faint 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'background-faint '256))) + (((type tty)) + (:background ,(mango-theme-color 'background-faint '16))))) + `(region + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'middleground '256))) + (((type tty)) + (:background ,(mango-theme-color 'middleground '16))))) + `(header-line + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'middleground '256))) + (((type tty)) + (:background ,(mango-theme-color 'middleground '16))))) + `(mode-line-active + ((t (:inherit header-line)))) + `(mode-line-inactive + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'background-cool 'gui) :weight light)) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'background-cool '256) :weight light)) + (((type tty)) + (:background ,(mango-theme-color 'background-cool '16) :weight light)))) + `(window-divider + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'background-cool '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'background-cool '16))))) + `(window-divider-first-pixel + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'background-cool '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'background-cool '16))))) + `(window-divider-last-pixel + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'background-cool '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'background-cool '16))))) + + ;; Line Numbers + `(line-number + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'background-faint 'gui) + :background ,(mango-theme-color 'background 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'background-faint '256) + :background ,(mango-theme-color 'background '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'background-faint '16) + :background ,(mango-theme-color 'background '16))))) + `(line-number-current-line + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'salmon 'gui) + :background ,(mango-theme-color 'background 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'salmon '256) + :background ,(mango-theme-color 'background '256) :weight bold)) + (((type tty)) + (:foreground ,(mango-theme-color 'salmon '16) + :background ,(mango-theme-color 'background '16) :weight bold)))) + + ;; Documentation + `(font-lock-comment-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'khaki 'gui) :weight semi-bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'khaki '256) :weight semi-bold)) + (((type tty)) + (:foreground ,(mango-theme-color 'khaki '16) :weight semi-bold)))) + `(font-lock-doc-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'disabled 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'disabled '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'disabled '16))))) + + ;; Modeline + `(mm-modeline-overwrite-face ((t (:weight bold)))) + `(mm-modeline-readonly-face ((t (:weight bold)))) + `(mm-modeline-buffer-name-face ((t (:inherit font-lock-constant-face)))) + `(mm-modeline-buffer-modified-face ((t (:inherit shadow)))) + `(mm-modeline-major-mode-name-face ((t (:weight bold)))) + `(mm-modeline-major-mode-symbol-face ((t (:inherit shadow)))) + `(mm-modeline-git-branch-face ((t (:inherit font-lock-constant-face)))) + `(mm-modeline-narrow-face + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'dark-red 'gui) :box ,(mango-theme-color 'dark-red 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'dark-red '256) :box ,(mango-theme-color 'dark-red '256) :weight bold)) + (((type tty)) + (:background ,(mango-theme-color 'dark-red '16) :box ,(mango-theme-color 'dark-red '16) :weight bold)))) + + ;; Core Language + `(font-lock-builtin-face ((t (:inherit font-lock-preprocessor-face)))) + `(font-lock-keyword-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'violet 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'violet '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'violet '16))))) + `(font-lock-type-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'celestial-blue 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'celestial-blue '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'celestial-blue '16))))) + + ;; Function-likes + `(font-lock-function-name-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'khaki 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'khaki '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'khaki '16))))) + `(font-lock-preprocessor-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'magenta 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'magenta '256) :weight bold)) + (((type tty)) + (:foreground ,(mango-theme-color 'magenta '16) :weight bold)))) + + ;; Variables + `(font-lock-constant-face ((t (:inherit font-lock-variable-name-face :weight bold)))) + `(font-lock-variable-name-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'pale-azure 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'pale-azure '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'pale-azure '16))))) + + ;; Other literals + `(help-key-binding ((t (:inherit font-lock-constant-face)))) + `(font-lock-string-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'salmon 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'salmon '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'salmon '16))))) + `(font-lock-number-face + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'salmon 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'salmon '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'salmon '16))))) + + ;; Org Mode + `(org-quote ((t (:inherit org-block :slant italic)))) + `(org-code + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'salmon 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'salmon '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'salmon '16))))) + `(org-verbatim + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'lime 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'lime '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'lime '16))))) + `(org-block + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'background-cool '256))) + (((type tty)) + (:background ,(mango-theme-color 'background-cool '16))))) + `(org-hide + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'background 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'background '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'background '16))))) + + ;; Info Page + `(Info-quoted ((t (:inherit default)))) + + ;; Magit + `(magit-diff-context-highlight ((t (:inherit hl-line)))) + `(magit-section-highlight ((t (:inherit hl-line)))) + `(magit-diff-hunk-heading + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'background-cool 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'background-cool '256))) + (((type tty)) + (:background ,(mango-theme-color 'background-cool '16))))) + `(magit-diff-hunk-heading-highlight + ((((type graphic tty) (min-colors 16777216)) + (:background ,(mango-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:background ,(mango-theme-color 'middleground '256))) + (((type tty)) + (:background ,(mango-theme-color 'middleground '16))))) + `(git-commit-summary + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'khaki 'gui))) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'khaki '256))) + (((type tty)) + (:foreground ,(mango-theme-color 'khaki '16))))) + `(git-commit-overlong-summary + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'foreground 'gui) + :background ,(mango-theme-color 'red 'gui) :weight bold)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'foreground '256) + :background ,(mango-theme-color 'red '256) :weight bold)) + (((type tty)) + (:foreground ,(mango-theme-color 'foreground '16) + :background ,(mango-theme-color 'red '16) :weight bold)))) + + ;; Vertico + `(vertico-current ((t (:inherit hl-line)))) + + ;; Marginalia + `(mm-diffstat-counter-added ((t (:foreground "green" :weight bold)))) + `(mm-diffstat-counter-removed ((t (:foreground "red" :weight bold)))) + `(marginalia-documentation + ((((type graphic tty) (min-colors 16777216)) + (:foreground ,(mango-theme-color 'disabled 'gui) :underline nil)) + (((type tty) (min-colors 256)) + (:foreground ,(mango-theme-color 'disabled '256) :underline nil)) + (((type tty)) + (:foreground ,(mango-theme-color 'disabled '16) :underline nil)))) + + ;; Tempel + `(tempel-default + ((((type graphic tty) (min-colors 16777216)) + (:slant italic :background ,(mango-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:slant italic :background ,(mango-theme-color 'middleground '256))) + (((type tty)) + (:slant italic :background ,(mango-theme-color 'middleground '16))))) + `(tempel-field + ((((type graphic tty) (min-colors 16777216)) + (:slant italic :background ,(mango-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:slant italic :background ,(mango-theme-color 'middleground '256))) + (((type tty)) + (:slant italic :background ,(mango-theme-color 'middleground '16))))) + `(tempel-form + ((((type graphic tty) (min-colors 16777216)) + (:slant italic :background ,(mango-theme-color 'middleground 'gui))) + (((type tty) (min-colors 256)) + (:slant italic :background ,(mango-theme-color 'middleground '256))) + (((type tty)) + (:slant italic :background ,(mango-theme-color 'middleground '16)))))) + +(provide-theme 'mango) diff --git a/.config/emacs-old/modules/mm-abbrev.el b/.config/emacs-old/modules/mm-abbrev.el new file mode 100644 index 0000000..d32ec0d --- /dev/null +++ b/.config/emacs-old/modules/mm-abbrev.el @@ -0,0 +1,110 @@ +;;; mm-abbrev.el --- Emacs abbreviations and templates -*- lexical-binding: t; -*- + +;;; Helpers + +(defmacro mm-define-abbreviations (table &rest definitions) + "Define abbrevations for an abbreviation TABLE. +Expand abbrev DEFINITIONS for the given TABLE. DEFINITIONS are a +sequence of either string pairs mapping an abbreviation to its +expansion, or a string and symbol pair mapping an abbreviation to a +function. + +After adding all abbreviations to TABLE, this macro marks TABLE as +case-sensitive to avoid unexpected abbreviation expansions." + (declare (indent 1)) + (unless (cl-evenp (length definitions)) + (user-error "expected an even number of elements in DEFINITIONS")) + `(progn + ,@(cl-loop for (abbrev expansion) in (seq-partition definitions 2) + if (stringp expansion) + collect (list #'define-abbrev table abbrev expansion) + else + collect (list #'define-abbrev table abbrev "" expansion)) + (abbrev-table-put ,table :case-fixed t))) + + +;;; Abbreviation Configuration + +(use-package abbrev + :hook prog-mode + :custom + (abbrev-file-name (expand-file-name "abbev-defs" mm-data-directory)) + (save-abbrevs 'silently)) + + +;;; Abbreviation Definitions + +(defvar mm-c-mode-abbrev-table (make-abbrev-table) + "Abbreviations shared between `c-mode', `c++-mode', `c-ts-mode', and +`c++-ts-mode'.") + +(mm-define-abbreviations mm-c-mode-abbrev-table + "flf" "flockfile" + "fpf" "fprintf" + "fuf" "funlockfile" + "pf" "printf" + "sde" "stderr" + "sdi" "stdin" + "sdo" "stdout") + +(with-eval-after-load 'cc-mode + (setq c-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table) + c++-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table))) +(with-eval-after-load 'c-ts-mode + (setq c-ts-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table) + c++-ts-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table))) + +(mm-define-abbreviations emacs-lisp-mode-abbrev-table + "ald" ";;;###autoload" + "gc" "goto-char" + "ins" "insert" + "itv" "interactive" + "mtb" "match-beginning" + "mte" "match-end" + "ntr" "narrow-to-region" + "pbl" "pos-bol" + "pel" "pos-eol" + "pmn" "point-min" + "pmx" "point-max" + "pnt" "point" + "rap" "region-active-p" + "rb" "region-beginning" + "re" "region-end" + "rsb" "re-search-backward" + "rsf" "re-search-forward" + "sb" "search-backward" + "se" "save-excursion" + "sf" "search-forward" + "sme" "save-mark-and-excursion" + "sr" "save-restriction") + +(when mm-humanwave-p + (with-eval-after-load 'python + (mm-define-abbreviations python-ts-mode-abbrev-table + "empb" "with emphasize.Block():" + "empf" "@emphasize.func" + "empi" "from shared.system import emphasize" + "empt" "emphasize.this"))) + + +;;; Template Configuration + +(use-package tempel + :ensure t + :demand t + :pin gnu + :bind ( :map tempel-map + ("TAB" . tempel-next) + ("S-TAB" . tempel-previous)) + :custom + (tempel-trigger-prefix "<") + :init + (setopt tempel-path (expand-file-name "templates" mm-config-directory)) + (dolist (mode '(conf-mode prog-mode text-mode)) + (add-hook (mm-mode-to-hook mode) + (defun mm-setup-tempel-capf () + (add-hook 'completion-at-point-functions + #'tempel-complete -10 :local)))) + (add-to-list 'auto-mode-alist (cons tempel-path #'lisp-data-mode))) + +(provide 'mm-abbrev) diff --git a/.config/emacs-old/modules/mm-buffer-menu.el b/.config/emacs-old/modules/mm-buffer-menu.el new file mode 100644 index 0000000..7b725c6 --- /dev/null +++ b/.config/emacs-old/modules/mm-buffer-menu.el @@ -0,0 +1,15 @@ +;;; mm-buffer-menu.el --- Buffer Menu configuration -*- lexical-binding: t; -*- + +(defun mm-Buffer-menu-delete-all () + "Mark all buffers for deletion." + (interactive nil Buffer-menu-mode) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (Buffer-menu-delete)))) + +(use-package buff-menu + :bind ( :map Buffer-menu-mode-map + ("D" . mm-Buffer-menu-delete-all))) + +(provide 'mm-buffer-menu) \ No newline at end of file diff --git a/.config/emacs-old/modules/mm-calc.el b/.config/emacs-old/modules/mm-calc.el new file mode 100644 index 0000000..af45b15 --- /dev/null +++ b/.config/emacs-old/modules/mm-calc.el @@ -0,0 +1,13 @@ +;;; mm-calc.el --- Emacs configurations for ‘calc-mode’ -*- lexical-binding: t; -*- + +(use-package calc + ;; TODO: Can this be done in :custom? + :init + (setopt + calc-display-trail nil + calc-group-digits t + ;; Optimize for Europeans + calc-point-char "," + calc-group-char ".")) + +(provide 'mm-calc) \ No newline at end of file diff --git a/.config/emacs-old/modules/mm-completion.el b/.config/emacs-old/modules/mm-completion.el new file mode 100644 index 0000000..3367aa1 --- /dev/null +++ b/.config/emacs-old/modules/mm-completion.el @@ -0,0 +1,256 @@ +;;; mm-completion.el --- Configuration for Emacs completion -*- lexical-binding: t; -*- + + +;;; Vertical Completions + +(use-package vertico + :ensure t + :hook after-init + :custom + (vertico-cycle t) + :config + (require 'hl-line) + ;; When working with ‘file-name-shadow-mode’ enabled, if I shadow old + ;; input (i.e.) by typing ‘~/’ after ‘foo/bar’ Vertico will clear the + ;; old path to keep only the current input (the old path is hidden by + ;; ‘rfn-shadow’ anyways). + (with-eval-after-load 'rfn-shadow + (add-hook 'rfn-shadow-update-overlay-hook #'vertico-directory-tidy))) + + +;;; Annotate Completions + +(use-package marginalia + :ensure t + :hook after-init + :config + (with-eval-after-load 'magit + (defvar mm-marginalia--magit-cache nil) + (add-hook 'minibuffer-setup-hook + (lambda () (setq mm-marginalia--magit-cache nil))) + + (defvar-local mm-marginalia-magit-base-branch "master") + + (defface mm-diffstat-counter-added + '((t :inherit magit-diffstat-added)) + "TODO") + (defface mm-diffstat-counter-removed + '((t :inherit magit-diffstat-removed)) + "TODO") + + (defun mm-marginalia-populate-magit-cache () + "Batch-fetch all Git branch descriptions and stats into the cache." + (setq mm-marginalia--magit-cache (make-hash-table :test #'equal)) + (when-let ((default-directory (magit-toplevel))) + (dolist (line (magit-git-lines "config" "list")) + (when (string-match "^branch\\.\\(.*?\\)\\.description=\\(.*\\)$" line) + (puthash (match-string 1 line) + (list :desc (match-string 2 line) :stats "") + mm-marginalia--magit-cache))) + (dolist (line (magit-git-lines + "for-each-ref" + (format + "--format=%%(refname:short)\x1F%%(ahead-behind:%s)" + mm-marginalia-magit-base-branch) + "refs/heads/")) + (when (string-match (rx bol (group (1+ (not #x1F))) + #x1F (group (1+ digit)) + " " (group (1+ digit)) eol) + line) + (let* ((branch (match-string 1 line)) + (ahead (+ (string-to-number (match-string 2 line)))) + (behind (- (string-to-number (match-string 3 line)))) + (ahead-str (if (zerop ahead) + "" + (propertize (format "%+d" ahead) + 'face 'mm-diffstat-counter-added))) + (behind-str (if (zerop behind) + "" + (propertize (format "%+d" behind) + 'face 'mm-diffstat-counter-removed))) + (stats-str (format "%5s %5s" ahead-str behind-str)) + (existing (gethash branch mm-marginalia--magit-cache + (list :desc "" :stats "")))) + (puthash branch (plist-put existing :stats stats-str) + mm-marginalia--magit-cache)))))) + + (defun mm-marginalia-annotate-magit-branch (cand) + "Annotate Git branch CAND with ahead/behind stats and description." + (unless mm-marginalia--magit-cache + (mm-marginalia-populate-magit-cache)) + (let* ((data (gethash cand mm-marginalia--magit-cache '(:desc "" :stats ""))) + (desc (or (plist-get data :desc) "")) + (stats (or (plist-get data :stats) ""))) + (marginalia--fields + (stats :width 10) + (desc :truncate 1.0 :face 'marginalia-documentation)))) + + (add-to-list 'marginalia-annotators + '(magit-branch mm-marginalia-annotate-magit-branch builtin none)) + (dolist (cmd '(magit-branch-and-checkout + magit-branch-checkout + magit-branch-delete + magit-checkout + magit-merge + magit-rebase-branch)) + (add-to-list 'marginalia-command-categories (cons cmd 'magit-branch)))) + :custom + (marginalia-field-width 50) + (marginalia-max-relative-age 0)) + + +;;; Minibuffer Completion Styles + +(use-package minibuffer + :bind ( :map minibuffer-local-completion-map + ("SPC" . nil) + ("?" . nil)) + :custom + (completion-styles '(basic substring orderless)) + (completion-category-defaults nil) ; Avoid needing to override things + (completion-category-overrides + '((file (styles . (basic partial-completion orderless))) + (bookmark (styles . (basic substring))) + (library (styles . (basic substring))) + (imenu (styles . (basic substring orderless))) + (consult-location (styles . (basic substring orderless))) + (kill-ring (styles . (basic substring orderless))))) + (completion-ignore-case t) + (read-buffer-completion-ignore-case t) + (read-file-name-completion-ignore-case t)) + +(use-package orderless + :ensure t + :after minibuffer + :custom + (orderless-matching-styles '(orderless-prefixes orderless-regexp))) + + +;;; Disable Minibuffer Recursion Level + +(use-package mb-depth + :hook (after-init . minibuffer-depth-indicate-mode) + :custom + (enable-recursive-minibuffers t)) + + +;;; Don’t Show Defaults After Typing + +;; Usually if a minibuffer prompt has a default value you can access by +;; hitting RET, the prompt will remain even if you begin typing (meaning +;; the default will no longer take effect on RET). Enabling this mode +;; disables that behaviour. + +(use-package minibuf-eldef + :hook (after-init . minibuffer-electric-default-mode) + :custom + (minibuffer-default-prompt-format " [%s]")) + + +;;; Hide Shadowed Filepaths + +(use-package rfn-eshadow + :hook (after-init . file-name-shadow-mode) + :custom + (file-name-shadow-properties '(invisible t intangilble t))) + + +;;; Completion Popups + +(mm-comment + (use-package corfu + :ensure t + :hook prog-mode + :bind ( :map corfu-map + ("C-" . newline)) + :custom + (corfu-auto t) + (corfu-cycle t) + (corfu-auto-prefix 1) + (corfu-auto-delay .1) + (corfu-min-width 20) + :config + ;; I complete with RET and this interferes with ‘tempel-next’ + (keymap-unset corfu-map "TAB" :remove) + (with-eval-after-load 'savehist + (corfu-history-mode) + (add-to-list 'savehist-additional-variables 'corfu-history)) + (with-eval-after-load 'multiple-cursors + (add-to-list 'mc/unsupported-minor-modes #'corfu-mode)))) + + +;;; Save Minibuffer History + +(use-package savehist-mode + :hook (after-init . savehist-mode) + :custom + (history-length 200) + (history-delete-duplicates t) + :config + (add-to-list 'savehist-additional-variables 'kill-ring)) + + +;;; Enhanced Replacements for Builtins + +;; TODO: Investigate other commands +(use-package consult + :ensure t + :hook (completion-list-mode . consult-preview-at-point-mode) + :bind ( ([remap switch-to-buffer] . consult-buffer) + ([remap imenu] . consult-imenu) + ([remap goto-line] . consult-goto-line) + ("M-F" . consult-focus-lines) + :map project-prefix-map + ("b" . consult-project-buffer) + :map consult-narrow-map + ("?" . consult-narrow-help)) + :custom + (consult-find-args + (string-join + '("find . -not (" + " -path '*/.git*' -prune" + " -or -path '*/vendor/*' -prune" + ")") + " "))) + + +;;; Dynamic Abbreviations + +(use-package dabbrev + :commands (dabbrev-completion dabbrev-expand) + :custom + (dabbrev-upcase-means-case-search t)) + + +;;; Finding Things + +(use-package find-func + :custom + (find-library-include-other-files nil)) + + +;;; Completion at Point Functions + +(defun mm-cape-file--not-dot-path-p (cand) + (declare (ftype (function (string) boolean)) + (pure t) (side-effect-free t)) + (not (or (string= cand "./") + (string= cand "../")))) + +(use-package cape + :ensure t + :init + (add-hook 'completion-at-point-functions + (cape-capf-predicate #'cape-file #'mm-cape-file--not-dot-path-p)) + (add-hook 'completion-at-point-functions + (cape-capf-prefix-length #'cape-dabbrev 3))) + + +;;; Completion at Point Live Completions + +(use-package completion-preview + :hook (after-init . global-completion-preview-mode) + :custom + (completion-preview-minimum-symbol-length 1)) + +(provide 'mm-completion) diff --git a/.config/emacs-old/modules/mm-darwin.el b/.config/emacs-old/modules/mm-darwin.el new file mode 100644 index 0000000..90dbedd --- /dev/null +++ b/.config/emacs-old/modules/mm-darwin.el @@ -0,0 +1,30 @@ +;;; mm-darwin.el --- MacOS Configuration -*- lexical-binding: t; -*- + +(unless (featurep 'ns) + (error "'NS not available. Something has gone horribly wrong.")) + + +;;; Launch Emacs Properly + +(defun mm-ns-raise-emacs () + (ns-do-applescript "tell application \"Emacs\" to activate")) + +(add-hook + 'after-make-frame-functions + (defun mm-ns-raise-emacs-with-frame (frame) + (when (display-graphic-p) + (with-selected-frame frame + (mm-ns-raise-emacs))))) + +(when (display-graphic-p) + (mm-ns-raise-emacs)) + + +;;; Set Modifier Keys + +(setopt mac-option-key-is-meta nil + mac-command-key-is-meta t) +(setopt mac-option-modifier 'none + mac-command-modifier 'meta) + +(provide 'mm-darwin) diff --git a/.config/emacs-old/modules/mm-dired.el b/.config/emacs-old/modules/mm-dired.el new file mode 100644 index 0000000..9e78466 --- /dev/null +++ b/.config/emacs-old/modules/mm-dired.el @@ -0,0 +1,24 @@ +;;; mm-dired.el --- Configure the directory editor -*- lexical-binding: t; -*- + +(use-package dired + :hook ((dired-mode . dired-omit-mode) + (dired-mode . dired-hide-details-mode)) + :bind ( :map dired-mode-map + ("f" . find-file)) + :custom + (dired-auto-revert-buffer #'dired-directory-changed-p) + (dired-dwim-target t) + (dired-free-space nil) + (dired-recursive-copies 'always) + (dired-recursive-deletes 'always) + (dired-listing-switches + (combine-and-quote-strings + '("-AFGhlv" "--group-directories-first" "--time-style=+%d %b %Y %T")))) + +(use-package dired-aux + :custom + (dired-create-destination-dirs 'ask) + (dired-create-destination-dirs-on-trailing-dirsep t) + (dired-isearch-filenames 'dwim)) + +(provide 'mm-dired) \ No newline at end of file diff --git a/.config/emacs-old/modules/mm-documentation.el b/.config/emacs-old/modules/mm-documentation.el new file mode 100644 index 0000000..1bd94da --- /dev/null +++ b/.config/emacs-old/modules/mm-documentation.el @@ -0,0 +1,44 @@ +;;; mm-documentation.el --- Configuration related to documentation -*- lexical-binding: t; -*- + +;;; Enhance Describe Commands + +(use-package helpful + :ensure t + :bind (([remap describe-command] . helpful-command) + ([remap describe-function] . helpful-callable) + ([remap describe-key] . helpful-key) + ([remap describe-symbol] . helpful-symbol) + ([remap describe-variable] . helpful-variable) + (("C-h C-p" . helpful-at-point)))) + + +;;; Open Manpage for Symbol + +(defun mm-documentation-man-at-point () + "Open a UNIX manual page for the symbol at point." + (declare (modes (c-mode c++-mode c-ts-mode c++-ts-mode))) + (interactive) + (if-let ((symbol + (pcase major-mode + ((or 'c-mode 'c++-mode) + (thing-at-point 'symbol :no-properties)) + ((or 'c-ts-mode 'c++-ts-mode) + (when-let ((node (treesit-thing-at-point "identifier" 'nested))) + (treesit-node-text node :no-properties)))))) + (man symbol) + (message "No symbol at point."))) + + +;;; Browse RFC Pages + +(use-package rfc-mode + :ensure t + :custom + (rfc-mode-directory (expand-file-name "rfc" (xdg-user-dir "DOCUMENTS"))) + :config + (unless (featurep 'consult) + (keymap-set rfc-mode-map "g" #'imenu)) + (with-eval-after-load 'consult + (keymap-set rfc-mode-map "g" #'consult-imenu))) + +(provide 'mm-documentation) \ No newline at end of file diff --git a/.config/emacs-old/modules/mm-editing.el b/.config/emacs-old/modules/mm-editing.el new file mode 100644 index 0000000..24aa7ea --- /dev/null +++ b/.config/emacs-old/modules/mm-editing.el @@ -0,0 +1,449 @@ +;;; mm-editing.el --- Text editing configuation -*- lexical-binding: t; -*- + +;;; Delete Region When Typing + +(use-package delsel + :hook (after-init . delete-selection-mode)) + + +;;; Capitalize ‘ß’ into ‘ẞ’ + +;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2024-11/msg00030.html +(set-case-syntax-pair ?ẞ ?ß (standard-case-table)) +(put-char-code-property ?ß 'special-uppercase nil) + + +;;; Force Spaces For Alignment + +(defun mm-editing-force-space-indentation (function &rest arguments) + "Call FUNCTION with ARGUMENTS in an environment in which +`indent-tabs-mode' is nil." + (let (indent-tabs-mode) + (apply function arguments))) + +(dolist (command #'(align-region + c-backslash-region + comment-dwim + makefile-backslash-region + sh-backslash-region)) + (advice-add command :around #'mm-editing-force-space-indentation)) + + +;;; Recenter The Screen When Jumping + +(mm-comment + (dolist (command #'(backward-page + backward-paragraph + forward-page + forward-paragraph + pop-global-mark)) + (advice-add command :around #'mm-do-and-center))) + + +;;; Indentation Settings + +(setq-default + tab-width 4 + indent-tabs-mode (not mm-humanwave-p)) + +(defvar mm-editing-indentation-settings-alist + '((awk-ts-mode . (:extras awk-ts-mode-indent-level)) + (c-mode . (:extras c-basic-offset)) + (c-ts-mode . (:extras c-ts-mode-indent-offset)) + (css-mode . (:extras css-indent-offset)) + (elixir-ts-mode . (:width 2 :extras elixir-ts-indent-offset)) + (emacs-lisp-mode . (:width 8 :spaces t)) ; GNU code uses 8-column tabs + (go-mod-ts-mode . (:extras go-ts-mode-indent-offset)) + (go-ts-mode . (:extras go-ts-mode-indent-offset)) + (gsp-ts-mode . (:width 2 :extras gsp-ts-mode-indent-rules)) + (helpful-mode . (:width 8)) ; GNU code uses 8-column tabs + (json-ts-mode . (:extras json-ts-mode-indent-offset)) + (latex-mode . (:width 2)) + (lisp-data-mode . (:spaces t)) + (lisp-interaction-mode . (:spaces t)) + (lisp-mode . (:spaces t)) + (mhtml-mode . (:extras sgml-basic-offset)) + (org-mode . (:width 8 :spaces t)) + (python-mode . (:extras python-indent-offset)) + (python-ts-mode . (:extras python-indent-offset)) + (sgml-mode . (:extras sgml-basic-offset)) + (sh-mode . (:extras sh-basic-offset)) + (sql-mode . (:extras sqlind-basic-offset)) + (tex-mode . (:width 2)) + (typescript-ts-mode . (:extras typescript-ts-mode-indent-offset)) + (vimscript-ts-mode . (:extras vimscript-ts-mode-indent-level)) + (vue-ts-mode . (:extras (typescript-ts-mode-indent-offset + vue-ts-mode-indent-offset)))) + "Alist of indentation settings. +Each pair in this alist is of the form (MODE . SETTINGS) where MODE +specifies the mode for which the given SETTINGS should apply. + +SETTINGS is a plist of one-or-more of the following keys: + + `:spaces' -- If nil force tabs for indentation, if non-nil for spaces + for indentation. If this key is not provided then the + value of `indent-tabs-mode' is used. + `:width' -- Specifies a non-negative number to be used as the tab + width and indentation offset. If this key is not + provided then the default value of `tab-width' is used. + `:extras' -- A list of mode-specific variables which control + indentation settings that need to be set for + configurations to properly be applied.") + +(defun mm-editing-set-indentation-settings () + "Set indentation settings for the current major mode. +The indentation settings are set based on the configured values in +`mm-editing-indentation-settings-alist'." + (let* ((plist (alist-get major-mode mm-editing-indentation-settings-alist)) + (spaces (plist-member plist :spaces)) + (width (plist-member plist :width)) + (extras (plist-member plist :extras))) + ;; Some modes like ‘python-mode’ explicitly set ‘tab-width’ and + ;; ‘indent-tabs-mode’ so we must override them explicitly. + (setq-local indent-tabs-mode (if spaces (not (cadr spaces)) + (default-value 'indent-tabs-mode)) + tab-width (or (cadr width) (default-value 'tab-width))) + (when extras + (setq extras (cadr extras)) + (when (symbolp extras) + (setq extras (list extras))) + (dolist (extra extras) + (set extra tab-width))))) + +(add-hook 'after-change-major-mode-hook #'mm-editing-set-indentation-settings) + +(defun mm-editing-set-tabsize () + "Set the tabsize for the current buffer. +If the current buffer’s major mode requires setting additional variables, +those should be listed in `mm-editing-indentation-settings'." + (interactive) + (let* ((prompt-default (default-value 'tab-width)) + (prompt (format-prompt "Tabsize" prompt-default)) + (tabsize (mm-as-number (read-string prompt nil nil prompt-default)))) + (setq-local tab-width tabsize) + (when-let* ((plist (alist-get major-mode mm-editing-indentation-settings)) + (extras (plist-get plist :extras))) + (dolist (extra (if (symbolp extras) + (list extras) + extras)) + (set (make-local-variable extra) tabsize))))) + +(use-package sh-mode + :custom + (sh-indent-for-case-label 0) + (sh-indent-for-case-alt #'+)) + + +;;; Code Commenting + +(defun mm-newcomment-c-config () + (setq-local comment-continue " ")) + +(defun mm-newcomment-html-config () + (setq-local comment-continue " ")) + +(defun mm-newcomment-rust-config () + (setq-local comment-start "/* " + comment-end " */" + comment-continue " * " ; rustfmt doesn’t play nice + comment-quote-nested nil)) + +(use-package newcomment + :custom + (comment-style 'multi-line) + :config + (dolist (mode '(c-mode c++-mode)) + (add-hook (mm-mode-to-hook mode) #'mm-newcomment-c-config) + (when-let ((ts-mode (mm-mode-to-ts-mode mode)) + ((fboundp ts-mode))) + (add-hook (mm-mode-to-hook ts-mode) #'mm-newcomment-c-config))) + (add-hook 'mhtml-mode-hook #'mm-newcomment-html-config) + (add-hook 'rust-ts-mode-hook #'mm-newcomment-rust-config)) + + +;;; Multiple Cursors + +(defmacro mm--define-mc-marking-command (name search-function noun) + (let ((noun-symbol (intern noun))) + `(defun ,name (beg end ,noun-symbol) + ,(format "Mark all occurances of %s between BEG and END. +If called interactively with an active region then all matches in the +region are marked, otherwise all matches in the buffer are marked." + (upcase noun)) + (interactive + (list (or (use-region-beginning) (point-min)) + (or (use-region-end) (point-max)) + (read-string + (format-prompt ,(concat "Match " noun) nil)))) + (if (string-empty-p ,noun-symbol) + (message "Command aborted") + (catch 'mm--no-match + (mc/remove-fake-cursors) + (goto-char beg) + (let (did-match-p) + (while (,search-function ,noun-symbol end :noerror) + (setq did-match-p t) + (push-mark (match-beginning 0)) + (exchange-point-and-mark) + (mc/create-fake-cursor-at-point) + (goto-char (mark))) + (unless did-match-p + (message "No match for `%s'" ,noun-symbol) + (throw 'mm--no-match nil))) + (when-let ((first (mc/furthest-cursor-before-point))) + (mc/pop-state-from-overlay first)) + (if (> (mc/num-cursors) 1) + (multiple-cursors-mode 1) + (multiple-cursors-mode 0))))))) + +(mm--define-mc-marking-command + mm-mark-all-in-region search-forward "string") +(mm--define-mc-marking-command + mm-mark-all-in-region-regexp re-search-forward "regexp") + +(mm-comment + (defun mm-silent-mc-load (args) + "Advice to `load' to force it to be silent. +The `multiple-cursors' package loads an `.mc-lists.el' file without +passing `:nomessage' which causes messages to be sent in the minibuffer +and *Messages* buffer. This forces that to not happen." + (when (and (boundp 'mc/list-file) + (string= (file-truename (car args)) + (file-truename mc/list-file))) + (pcase (length args) + (1 (setq args (list (car args) nil :nomessage))) + (2 (add-to-list 'args :nomessage :append)) + (_ (setf (caddr args) :nomessage))) + (advice-remove #'load #'mm-silent-mc-load)) + args)) + +(use-package multiple-cursors + :ensure t + :demand t + :bind (("C->" . #'mc/mark-next-like-this) + ("C-<" . #'mc/mark-previous-like-this) + ("C-M-<" . #'mc/mark-all-like-this-dwim) + ("C-M->" . #'mc/edit-lines) + :map search-map + ("$" . #'mm-mark-all-in-region) + ("M-$" . #'mm-mark-all-in-region-regexp)) + :commands ( mm-mark-all-in-region mm-mark-all-in-region-regexp + mm-add-cursor-to-next-thing mm-transpose-cursor-regions) + :init + (mm-comment + (advice-add #'load :filter-args #'mm-silent-mc-load) + (with-eval-after-load 'multiple-cursors-core + (dolist (command #'(backward-delete-char + capitalize-dwim + delete-backward-char + delete-forward-char + downcase-dwim + upcase-dwim)) + (add-to-list 'mc/cmds-to-run-for-all command)) + (dolist (command #'(helpful-callable + helpful-key + helpful-symbol + helpful-variable)) + (add-to-list 'mc/cmds-to-run-once command)))) + (with-eval-after-load 'multiple-cursors-core + (keymap-unset mc/keymap "" :remove))) + + +;;; Increment Numbers + +(use-package increment + :bind (("C-c i i" . #'increment-number-at-point) + ("C-c i d" . #'decrement-number-at-point)) + :commands (increment-number-at-point decrement-number-at-point)) + + +;;; Move Line or Region + +(defun mm-move-text-indent (&rest _) + (let ((deactivate deactivate-mark)) + (if (region-active-p) + (indent-region (region-beginning) (region-end)) + (indent-region (line-beginning-position) (line-end-position))) + (setq deactivate-mark deactivate))) + +(use-package move-text + :ensure t + :bind (("M-n" . move-text-down) + ("M-p" . move-text-up)) + :config + (dolist (command #'(move-text-up move-text-down)) + (advice-add command :after #'mm-move-text-indent))) + + +;;; Surround With Delimeters + +(defun mm-editing-surround-with-spaces (char) + "Surrounds region or current symbol with a pair defined by CHAR. +This is the same as `surround-insert' except it pads the contents of the +surround with spaces." + (interactive + (list (char-to-string (read-char "Character: ")))) + (let* ((pair (surround--make-pair char)) + (left (car pair)) + (right (cdr pair)) + (bounds (surround--infer-bounds t))) + (save-excursion + (goto-char (cdr bounds)) + (insert " " right) + (goto-char (car bounds)) + (insert left " ")) + (when (eq (car bounds) (point)) + (forward-char)))) + +;; TODO: Implement this manually +(use-package surround + :ensure t + :bind-keymap ("M-'" . surround-keymap) + :bind (:map surround-keymap + ("S" . #'mm-editing-surround-with-spaces)) + :config + (dolist (pair '(("‘" . "’") + ("“" . "”") + ("»" . "«") + ("⟮" . "⟯"))) + (push pair surround-pairs)) + (make-variable-buffer-local 'surround-pairs) + (add-hook 'emacs-lisp-mode-hook + (defun mm-editing-add-elisp-quotes-pair () + (push '("`" . "'") surround-pairs)))) + + +;;; Insert Webpage Contents + +(defun mm-insert-from-url (url) + "Insert the contents of URL at point." + (interactive + (let ((url-at-point (thing-at-point 'url))) + (list (read-string + (format-prompt "URL" url-at-point) + nil nil url-at-point)))) + (call-process "curl" nil '(t nil) nil url)) + + +;;; Emmet Mode + +(defun mm-editing-emmet-dwim (arg) + "Do-What-I-Mean Emmet expansion. +If the region is active then the region will be surrounded by an emmet +expansion read from the minibuffer. Otherwise the emmet expression +before point is expanded. When provided a prefix argument the behaviour +is as described by `emmet-expand-line'." + (interactive "P") + (if (region-active-p) + (call-interactively #'emmet-wrap-with-markup) + (emmet-expand-line arg))) + +(use-package emmet-mode + :ensure t + :bind ("C-," . mm-editing-emmet-dwim) + :custom + (emmet-self-closing-tag-style "")) + + +;;; JQ Manipulation in JSON Mode + +(defun mm-jq-filter (query &optional beg end) + "TODO" + (interactive + (list + (read-string (format-prompt "Query" nil)) + (when (use-region-p) (region-beginning)) + (when (use-region-p) (region-end)))) + (let* ((beg (or beg (point-min))) + (end (or end (point-max))) + (temp-buffer (generate-new-buffer "* jq temp*")) + (exit-code (call-process-region beg end "jq" nil temp-buffer nil + "--tab" query)) + (output (with-current-buffer temp-buffer (buffer-string)))) + (if (zerop exit-code) + (atomic-change-group + (delete-region beg end) + (insert output) + (indent-region beg (point))) + (message "%s" output)) + (kill-buffer temp-buffer))) + +(use-package json-ts-mode + :bind ( :map json-ts-mode-map + ("C-|" . #'mm-jq-filter)) + :config + (require 'live-jq)) + + +;;; Number Formatting + +(use-package number-format-mode + :commands ( number-format-buffer number-format-region + number-unformat-buffer number-unformat-region + number-format-mode)) + + +;;; Additional Major Modes + +(use-package awk-ts-mode :ensure t) +(use-package cmake-mode :ensure t) +(use-package git-modes :ensure t) +(use-package kdl-mode :ensure t) +(use-package po-mode :ensure t) +(use-package sed-mode :ensure t) + +(use-package csv-mode + :ensure t + :custom + (csv-align-style 'auto) + (csv-align-padding 2)) + +(use-package xcompose-mode + :vc ( :url "https://git.thomasvoss.com/xcompose-mode" + :branch "master" + :rev :newest + :vc-backend Git) + :ensure t) + +(use-package yaml-pro + :hook ((yaml-mode . yaml-pro-mode) + (yaml-ts-mode . yaml-pro-ts-mode))) + + +;;; Mode-Specific Configurations + +(use-package make-mode + :custom + (makefile-backslash-column 80)) + +(use-package python-mode + :custom + (python-indent-def-block-scale 1) + (python-indent-guess-indent-offset-verbose nil)) + + +;;; Add Missing Extensions + +(dolist (pattern '("\\.tmac\\'" "\\.mom\\'")) + (add-to-list 'auto-mode-alist (cons pattern #'nroff-mode))) + + +;;; Subword Navigation + +(use-package subword + :hook prog-mode) + + +;;; Edit Files via Doas/Sudo + +(defvar mm-root-editing-program + (if (string= (system-name) "mangobox") "doas" "sudo")) + +(defun mm-edit-root-protected-file-buffer () + (interactive) + (when (and buffer-file-name (not (file-writable-p buffer-file-name))) + (find-alternate-file (format "/%s:root@localhost:%s" + mm-root-editing-program + buffer-file-name)))) + +(provide 'mm-editing) diff --git a/.config/emacs-old/modules/mm-humanwave.el b/.config/emacs-old/modules/mm-humanwave.el new file mode 100644 index 0000000..d52546e --- /dev/null +++ b/.config/emacs-old/modules/mm-humanwave.el @@ -0,0 +1,254 @@ +;;; mm-humanwave.el --- Humanwave extras -*- lexical-binding: t; -*- + + +;;; Query the Backend + +(defvar mm--humanwave-query-history nil + "History for endpoints given to `mm-humanwave-query'.") + +(defun mm-humanwave-query (endpoint &optional method) + "Query and display the result of an HTTP reqiest on ENDPOINT. +If METHOD is nil, a GET request is performed." + (interactive + (let* ((query (read-string (format-prompt "Query" nil) + (car-safe mm--humanwave-query-history) + 'mm--humanwave-query-history)) + (parts (string-split (string-trim query) " " :omit-nulls))) + (when (length> parts 2) + (user-error "Queries must be of the form `METHOD ENDPOINT' or `ENDPOINT'.")) + (nreverse parts))) + (let* ((project-root (project-root (project-current :maybe-prompt))) + (qry-path (expand-file-name "qry" project-root)) + extras) + (unless (file-executable-p qry-path) + (user-error "No `qry' executable found in the project root")) + (let ((output-buffer (get-buffer-create "*Query Response*"))) + (with-current-buffer output-buffer + (delete-region (point-min) (point-max)) + (call-process qry-path nil t nil + (string-trim endpoint) "-X" (or method "GET")) + (unless (eq major-mode 'json-ts-mode) + (json-ts-mode)) + (goto-char (point-min))) + (display-buffer output-buffer)))) + + +;;; IMenu Support for Handlers + +(require 'imenu) +(require 'which-func) + +(defvar mm-humanwave-handler--regexp + (rx bol + (* blank) + (or "if" "elif") + (* blank) + (or "dialog" "topic" "schedule") + (* blank) + "==" + (* blank) + (or ?\' ?\") + (group (+ (not (or ?\' ?\")))) + (or ?\' ?\") + (* blank) + ?: + (* blank) + eol)) + +(defun mm-humanwave-handler--insert-entry (topic-index function-parts route pos) + (if (null function-parts) + (cons (cons (format "%s (route)" route) pos) topic-index) + (let* ((current-group (car function-parts)) + (rest-parts (cdr function-parts)) + (existing-sublist (assoc current-group topic-index))) + (if existing-sublist + (progn + (setcdr existing-sublist + (mm-humanwave-handler--insert-entry + (cdr existing-sublist) rest-parts route pos)) + topic-index) + (cons (cons current-group + (mm-humanwave-handler--insert-entry + nil rest-parts route pos)) + topic-index))))) + +(defun mm-humanwave-handler-topic-imenu-index () + (let ((case-fold-search nil) + (tree-index (python-imenu-treesit-create-index)) + (topic-index '())) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward mm-humanwave-handler--regexp nil :noerror) + (let ((route (match-string-no-properties 1)) + (pos (match-beginning 0)) + (function-parts (split-string (which-function) "\\."))) + (setq topic-index (mm-humanwave-handler--insert-entry + topic-index function-parts route pos))))) + (append (nreverse topic-index) tree-index))) + +(defun mm-humanwave-handler-topic-imenu-setup () + "Setup custom imenu index for `python-ts-mode'." + (when (and (string-match-p "/handlers?/" (or (buffer-file-name) "")) + (derived-mode-p #'python-ts-mode)) + (setq-local imenu-create-index-function + #'mm-humanwave-handler-topic-imenu-index))) + +(add-hook 'after-change-major-mode-hook + #'mm-humanwave-handler-topic-imenu-setup) + + +;;; Insert Imports in Vue + +(defun mm-humanwave-insert-vue-import-path (base-directory target-file) + "Insert an import directive at POINT. +The import directive imports TARGET-FILE relative from BASE-DIRECTORY. +When called interactively BASE-DIRECTORY is the directory of the current +open Vue file and TARGET-FILE is a file in the current project that is +queried interactively. + +When called interactively the prefix argument can be used to emulate the +behaviour of the INCLUDE-ALL-P argument to `mm-project-read-file-name'." + (interactive + (list + default-directory + (mm-humanwave-project-read-file-name current-prefix-arg))) + (let ((path (file-name-sans-extension + (file-relative-name target-file base-directory)))) + (unless (string-match-p "/" path) + (setq path (concat "./" path))) + (insert "import ") + (save-excursion + (insert (thread-last + (file-name-base path) + (mm-string-split "-") + (mapconcat #'capitalize))) + (push-mark (point)) + (insert (format " from '%s';" path))))) + +(defun mm-humanwave-project-read-file-name (&optional include-all-p) + "Prompt for a project file. +This function is similar to `project-find-file', but it returns the path +to the selected file instead of opening it. + +When called interactively the selected file is printed to the minibuffer, +otherwise it is returned. + +The prefix argument INCLUDE-ALL-P is the same as the INCLUDE-ALL argument +to the `project-find-file' command." + (interactive "P") + (let* ((project (project-current :maybe-prompt)) + (root (project-root project)) + (files (if include-all-p + (let ((vc-ignores (mapcar + (lambda (dir) (concat dir "/")) + vc-directory-exclusion-list))) + (project--files-in-directory root vc-ignores)) + (project-files project))) + (canditates (mapcar (lambda (f) (file-relative-name f root)) + files)) + (table (lambda (string predicate action) + (if (eq action 'metadata) + '(metadata (category . file)) + (complete-with-action action canditates string predicate)))) + (default-directory root) + (choice (completing-read (format-prompt "Find project file" nil) + table nil :require-match))) + (let ((path (expand-file-name choice root))) + (if (called-interactively-p 'any) + (message "%s" path) + path)))) + +(defun mm-humanwave-insert-last-commit-message () + "TODO" + (interactive) + (insert + (with-temp-buffer + (call-process "git" nil t nil "log" "-1" "--pretty=%s") + (goto-char (point-min)) + (replace-regexp "\\`HW-[0-9]+ " "") + (string-trim (buffer-string))))) + + +;;; Jira Integration + +(use-package jira + :ensure t + :custom + (jira-api-version 3) + (jira-base-url "https://humanwave.atlassian.net") + (jira-detail-show-announcements nil) + (jira-issues-max-results 100) + (jira-issues-table-fields '(:key :status-name :assignee-name :summary)) + (jira-token-is-personal-access-token nil)) + + +;;; Icon Autocompletion + +(defvar mm-humanwave-icon-component-file "web/src/components/icon.vue" + "Path to the component definition.") + +(defun mm-humanwave--find-icon-map () + (let* ((project (project-current :maybe-prompt)) + (path (expand-file-name mm-humanwave-icon-component-file + (project-root project)))) + (unless (file-exists-p path) + (user-error "File `%s' does not exist." path)) + (with-current-buffer (find-file-noselect path) + (let* ((parser (treesit-parser-create 'typescript)) + (root-node (treesit-parser-root-node parser)) + (query `((((lexical_declaration + (variable_declarator + name: (identifier) @name)) @the_catch) + (:equal @name "ICON_MAP")) + (((variable_declaration + (variable_declarator + name: (identifier) @name)) @the_catch) + (:equal @name "ICON_MAP")))) + (captures (treesit-query-capture root-node query)) + (found-node (alist-get 'the_catch captures))) + found-node)))) + +(defun mm-humanwave--icon-list (found-node) + (let ((captures (treesit-query-capture found-node '((pair) @the_pair))) + (pairs nil)) + (when captures + (dolist (capture captures) + (let* ((pair-node (cdr capture)) + (key-node (treesit-node-child-by-field-name pair-node "key")) + (val-node (treesit-node-child-by-field-name pair-node "value"))) + (when (and key-node val-node) + (push (cons (mm-camel-to-lisp + (treesit-node-text key-node :no-property)) + (treesit-node-text val-node :no-property)) + pairs)))) + (sort pairs :key #'car :lessp #'string<)))) + +(defun mm-humanwave-insert-icon-component () + "Insert an icon at point with completion. + +This command provides completion for the available props that can be +given to the component. The parser searches for the `ICON_MAP' +definition in the file specified by `mm-humanwave-icon-component-file'." + (interactive "" vue-ts-mode) + (if-let* ((node (mm-humanwave--find-icon-map)) + (alist (mm-humanwave--icon-list node))) + (let* ((max-key-width + (thread-last + alist + (mapcar (lambda (pair) (length (car pair)))) + (apply #'max) + (+ 4))) + (completion-extra-properties + `(:annotation-function + ,(lambda (key) + (concat + (propertize " " + 'display `(space :align-to ,max-key-width)) + (propertize (cdr (assoc key alist)) + 'face 'font-lock-string-face))))) + (prompt (format-prompt "Icon" nil)) + (icon (completing-read prompt alist nil :require-match))) + (insert (format "" icon))) + (error "Unable to find ICON_MAP definitions"))) + +(provide 'mm-humanwave) diff --git a/.config/emacs-old/modules/mm-keybindings.el b/.config/emacs-old/modules/mm-keybindings.el new file mode 100644 index 0000000..1480451 --- /dev/null +++ b/.config/emacs-old/modules/mm-keybindings.el @@ -0,0 +1,188 @@ +;;; mm-keybindings.el --- Emacs keybindings -*- lexical-binding: t; -*- + +(require 'editing) + +;; The following keys are either unbound and are free to populate, or are +;; bound to functions I don’t care for: +;; ‘C-i’, ‘C-j’, ‘C-o’, ‘C-{’, ‘C-}’, ‘C-|’, ‘C-/’, ‘C-\;’, ‘C-:’ + + +;;; Helper Macros + +(defmacro mm-keymap-set (keymap &rest definitions) + (declare (indent 1)) + (unless (cl-evenp (length definitions)) + (user-error "Expected an even-number of elements in DEFINITIONS.")) + `(cl-loop for (from to) on (list ,@definitions) by #'cddr + do (keymap-set ,keymap from to))) + +(defmacro mm-keymap-set-repeating (keymap &rest definitions) + (declare (indent 1)) + (unless (cl-evenp (length definitions)) + (user-error "Expected an even-number of elements in DEFINITIONS.")) + (let ((keymap-gen (gensym "mm-keybindings--repeat-map-"))) + `(progn + (defvar-keymap ,keymap-gen) + (cl-loop for (from to) on (list ,@definitions) by #'cddr + do (progn + (keymap-set ,keymap-gen from to) + (put to 'repeat-map ',keymap-gen)))))) + +(defmacro mm-keymap-remap (keymap &rest commands) + "Define command remappings for a given KEYMAP. +COMMANDS is a sequence of unquoted commands. For each pair of COMMANDS +the first command is remapped to the second command." + (declare (indent 1)) + (unless (cl-evenp (length commands)) + (user-error "Expected an even-number of elements in COMMANDS.")) + (macroexp-progn + (cl-loop for (from to) in (seq-partition commands 2) + collect `(keymap-set + ,keymap + ,(concat " <" (symbol-name from) ">") + #',to)))) + + +;;; Support the Kitty Keyboard Protocol + +(use-package kkp + :ensure t + :unless (or (display-graphic-p) mm-humanwave-p) + :hook (tty-setup . global-kkp-mode)) + + +;;; Support QMK Hyper + +(defun mm-qmk-hyper-as-hyper (args) + (let ((chord (cadr args))) + (when (string-prefix-p "H-" chord) + (setf (cadr args) (concat "C-M-S-s" (substring chord 1))))) + args) + +;; Both ‘keymap-global-set’ and ‘keymap-local-set’ call ‘keymap-set’ +;; internally, so this advice covers all cases +(advice-add #'keymap-set :filter-args #'mm-qmk-hyper-as-hyper) + + +;;; Disable ESC as Meta + +(keymap-global-set "" #'ignore) + + +;;; Enable Repeat Bindings + +(defun mm-enable-repeat-mode () + "Enable `repeat-mode' without polluting the echo area." + (mm-with-suppressed-output + (repeat-mode))) + +(use-package repeat + :hook (after-init . mm-enable-repeat-mode) + :custom + (repeat-exit-timeout 5)) + + +;;; Remap Existing Bindings + +(mm-keymap-remap global-map + backward-delete-char-untabify backward-delete-char + + capitalize-word capitalize-dwim + downcase-word downcase-dwim + upcase-word upcase-dwim + + delete-indentation e/join-current-and-next-line + kill-ring-save e/kill-ring-save-dwim + mark-sexp e/mark-entire-sexp + mark-word e/mark-entire-word + open-line e/open-line + yank e/yank) + +(with-eval-after-load 'cc-vars + (setopt c-backspace-function #'backward-delete-char)) + + +;;; Remove Unwanted Bindings + +(keymap-global-unset "C-x C-c" :remove) ; ‘capitalize-region’ +(keymap-global-unset "C-x C-l" :remove) ; ‘downcase-region’ +(keymap-global-unset "C-x C-u" :remove) ; ‘upcase-region’ + +;; The following conflict with ‘ace-window’ +(with-eval-after-load 'mhtml-mode + (keymap-unset html-mode-map "M-o" :remove)) + + +;;; Bind Commands Globally + +(mm-keymap-set global-map + ;; "" #'e/scroll-up + ;; "" #'e/scroll-down + "C-" #'forward-page + "C-" #'backward-page + + "C-." #'repeat + "C-^" #'e/split-line + "C-/" #'e/mark-line-dwim + + "C-]" #'mm-search-forward-char + "M-]" #'mm-search-backward-char + + "M-\\" #'cycle-spacing + + "C-M-@" #'mm-add-cursor-to-next-word + + "C-c c a" #'mc/vertical-align-with-space + "C-c c i" #'mc/insert-numbers + "C-c c t" #'mm-transpose-cursor-regions + "C-c d" #'duplicate-dwim + "C-c t a" #'e/align-regexp + "C-c t f" #'fill-paragraph + "C-c t s" #'e/sort-dwim) + +(mm-keymap-set-repeating global-map + "j" #'e/join-current-and-next-line + "J" #'join-line) + +(mm-keymap-set-repeating global-map + "n" #'next-error + "p" #'previous-error) + +(with-eval-after-load 'increment + (mm-keymap-set-repeating global-map + "d" #'decrement-number-at-point + "i" #'increment-number-at-point)) + + +;;; Other Bindings + +(with-eval-after-load 'project + (mm-keymap-set project-prefix-map + "g" #'mm-project-find-regexp + "G" #'project-git-grab) + + (when mm-humanwave-p + (mm-keymap-set project-prefix-map + "q" #'mm-humanwave-query))) + +(with-eval-after-load 'eat + (with-eval-after-load 'ace-window + (mm-keymap-set eat-semi-char-mode-map + "M-o" #'ace-window))) + +(with-eval-after-load 'minibuffer + (when mm-humanwave-p + (mm-keymap-set minibuffer-mode-map + "C-c m" #'mm-humanwave-insert-last-commit-message))) + + +;;; Display Available Keybindings + +(use-package which-key + :hook after-init + :custom + (which-key-dont-use-unicode nil) + (which-key-ellipsis "…") + (wihch-key-idle-delay .5)) + +(provide 'mm-keybindings) diff --git a/.config/emacs-old/modules/mm-lsp.el b/.config/emacs-old/modules/mm-lsp.el new file mode 100644 index 0000000..3a64f49 --- /dev/null +++ b/.config/emacs-old/modules/mm-lsp.el @@ -0,0 +1,45 @@ +;;; mm-lsp.el --- Language Server Protocol configuration -*- lexical-binding: t; -*- + +;;; Configure LSP + +(defun mm-lsp-eglot-no-inlay-hints () + "Disable inlay hints when `eglot' is enabled." + (eglot-inlay-hints-mode -1)) + +(use-package eglot + :hook (((c-mode c-ts-mode + c++-mode c++-ts-mode + go-ts-mode + js-mode js-ts-mode) + . eglot-ensure) + (eglot-managed-mode . mm-lsp-eglot-no-inlay-hints)) + :init + (fset #'jsonrpc--log-event #'ignore) + :custom + (eglot-events-buffer 0) + (eglot-extend-to-xref t) + :config + (add-to-list 'eglot-stay-out-of 'flymake) + (add-to-list 'eglot-server-programs + '((c-mode c-ts-mode c++-mode c++-ts-mode) + . ("clangd" "--header-insertion=never")))) + +(use-package eglot-booster + :after eglot + :config + (eglot-booster-mode)) + + +;;; Use Tempel for Snippets + +(defun mm-lsp-eglot-tempel-enable () + "Enable `eglot-tempel-mode'. +If `eglot-tempel-mode' is already enabled this function does nothing." + (unless (default-value eglot-tempel-mode) + (eglot-tempel-mode))) + +(use-package eglot-tempel + :after eglot + :hook (eglot-managed-mode . mm-lsp-eglot-tempel-enable)) + +(provide 'mm-lsp) \ No newline at end of file diff --git a/.config/emacs-old/modules/mm-modeline.el b/.config/emacs-old/modules/mm-modeline.el new file mode 100644 index 0000000..9a35d04 --- /dev/null +++ b/.config/emacs-old/modules/mm-modeline.el @@ -0,0 +1,147 @@ +;;; mm-modeline.el --- Pluggable modeline components -*- lexical-binding: t; -*- + +(defmacro mm-modeline--define-component (name &rest forms) + (declare (indent 1)) + `(progn + (defface ,(intern (format "%s-face" name)) + '((t)) + ,(format "Face for the `%s' component." name)) + (defvar-local ,name '(:eval (or ,(macroexp-progn forms) ""))) + (put ',name 'risky-local-variable t))) + + +;;; Support Icons + +(use-package all-the-icons + :ensure t + :init + (defvar mm-all-the-icons-cookie + (expand-file-name ".all-the-icons-installed-p" mm-cache-directory)) + (unless (file-exists-p mm-all-the-icons-cookie) + (all-the-icons-install-fonts) + (make-empty-file mm-all-the-icons-cookie :parents)) + (set-char-table-range char-width-table #xE907 2)) + + +;;; Modeline Components + +(mm-modeline--define-component mm-modeline-overwrite + (when overwrite-mode + (propertize " OVERWRITE" 'face 'mm-modeline-overwrite-face))) + +(mm-modeline--define-component mm-modeline-readonly + (when buffer-read-only + (propertize " READONLY" 'face 'mm-modeline-readonly-face))) + +(mm-modeline--define-component mm-modeline-buffer-name + (propertize "%b" 'face 'mm-modeline-buffer-name-face)) + +(mm-modeline--define-component mm-modeline-buffer-modified + (when (and (buffer-modified-p) + (buffer-file-name)) + (propertize " (modified)" 'face 'mm-modeline-buffer-modified-face))) + +(defconst mm-modeline-mode-acronyms + '("css" "csv" "gsp" "html" "json" "mhtml" "rfc" "scss" "sql" "toml" "tsv" + "url" "yaml") + "List of acronyms in major mode names that should be capitalized.") + +(defconst mm-modeline-remap-alist + '(("Bmenu" . "BMenu") + ("Bsdmake" . "BSD Make") + ("Gitattributes" . "Git Attributes") + ("Gitconfig" . "Git Config") + ("Gitignore" . "Git Ignore") + ("Gmake" . "GMake") + ("Imake" . "IMake") + ("Js" . "JavaScript") + ("Ts Mode" . "Tree-Sitter Mode") + ("Wdired" . "WDired") + ("Xcompose" . "XCompose")) + "Alist of substrings in major mode names that should be remapped. +Some major modes have substrings that would be better displayed in +another manner. For example expanding an abbreviation such as ‘Js’ to +its expanded form ‘JavaScript’, or fixing the casing of words with a +prefix such as ‘Gmake’ to ‘GMake’. This alist maps the original text to +the text it should be mapped to.") + +(mm-modeline--define-component mm-modeline-major-mode-name + (propertize + (let ((string (thread-last + major-mode + (symbol-name) + (capitalize) + (string-replace "-" " "))) + (case-fold-search nil)) + (save-match-data + (dolist (pair mm-modeline-remap-alist) + (setq string + (replace-regexp-in-string + (format "\\<%s\\>" (regexp-quote (car pair))) + (cdr pair) string))) + (setq case-fold-search t) + (if (string-match (regexp-opt mm-modeline-mode-acronyms 'words) string) + (concat + (substring string 0 (match-beginning 0)) + (upcase (substring string (match-beginning 0) (match-end 0))) + (substring string (match-end 0) (length string))) + string))) + 'face 'mm-modeline-major-mode-name-face)) + +(mm-modeline--define-component mm-modeline-major-mode-symbol + (propertize + (cond + ((derived-mode-p 'comint-mode) "$ ") + ((derived-mode-p 'conf-mode) "# ") + ((derived-mode-p 'prog-mode) "λ ") + ((derived-mode-p 'special-mode) "★ ") + ((derived-mode-p 'text-mode) "§ ") + (:default "")) + 'face 'mm-modeline-major-mode-symbol-face)) + +(mm-modeline--define-component mm-modeline-narrow + (when (buffer-narrowed-p) + (propertize + " NARROW " + 'face 'mm-modeline-narrow-face))) + +(mm-modeline--define-component mm-modeline-git-branch + (when-let ((branch (car (and (featurep 'vc-git) + (vc-git-branches))))) + (concat + (propertize "\uE907" 'display '(raise 0)) + " " + (propertize branch 'face 'mm-modeline-git-branch-face) + " │ "))) + + +;;; Padding Between Left and Right + +(mm-modeline--define-component mm-modeline-left-right-padding + (let ((length (string-width (format-mode-line mm-modeline-right)))) + (propertize " " 'display `(space :align-to (- right ,length))))) + + +;;; Configure Modeline + +(setopt mode-line-format-right-align 'right-margin) + +(setq + mm-modeline-left (list mm-modeline-narrow + mm-modeline-overwrite + mm-modeline-readonly + " " + mm-modeline-buffer-name + mm-modeline-buffer-modified + " │ " + mm-modeline-major-mode-symbol + mm-modeline-major-mode-name + mm-modeline-left-right-padding + mode-line-end-spaces) + mm-modeline-right (list mm-modeline-git-branch + "%l:%c ")) + +(setq-default + mode-line-format + (list mm-modeline-left mm-modeline-left-right-padding mm-modeline-right)) +(provide 'mm-modeline) diff --git a/.config/emacs-old/modules/mm-org.el b/.config/emacs-old/modules/mm-org.el new file mode 100644 index 0000000..b4d0f31 --- /dev/null +++ b/.config/emacs-old/modules/mm-org.el @@ -0,0 +1,6 @@ +;;; mm-org.el --- Org-Mode configuration -*- lexical-binding: t; -*- + +(use-package org + :hook (org-mode . org-indent-mode)) + +(provide 'mm-org) \ No newline at end of file diff --git a/.config/emacs-old/modules/mm-projects.el b/.config/emacs-old/modules/mm-projects.el new file mode 100644 index 0000000..02d7af4 --- /dev/null +++ b/.config/emacs-old/modules/mm-projects.el @@ -0,0 +1,114 @@ +;;; mm-projects.el --- Configuration for project management -*- lexical-binding: t; -*- + +;;; Project Configuration + +(defun mm-projects-project-magit-status () + "Open a Git status buffer for the current project. +This is intended to be called interactively via + `project-switch-commands'." + (interactive) + (thread-last + (project-current t) + (project-root) + (magit-status-setup-buffer))) + +(use-package project + :custom + (project-switch-commands + '((project-dired "Dired" ?d) + (project-find-file "Find File" ?f) + (mm-projects-project-magit-status "Git Status" ?s))) + :config + (unless mm-humanwave-p + (if-let ((repo-directory (getenv "REPODIR"))) + (let* ((list-dir + (lambda (path) + (directory-files path :full "\\`[^.]"))) + (directories + (cl-loop for author in (funcall list-dir (getenv "REPODIR")) + append (cl-loop for path in (funcall list-dir author) + collect (list (concat path "/")))))) + (with-temp-buffer + (prin1 directories (current-buffer)) + (write-file project-list-file)) + (project--read-project-list)) + (warn "The REPODIR environment variable is not set.")))) + + +;;; Emacs VC + +(use-package vc-hooks + :custom + (vc-follow-symlinks t) + (vc-handled-backends '(Git))) + + +;;; Git Client + +(use-package magit + :ensure t + :bind (("C-c b" . magit-blame-addition) + :map magit-status-mode-map + ("[" . magit-section-backward-sibling) + ("]" . magit-section-forward-sibling)) + :custom + (git-commit-style-convention-checks + '(non-empty-second-line overlong-summary-line)) + (git-commit-summary-max-length 50) + (magit-diff-refine-hunk t) + (magit-display-buffer-function + #'magit-display-buffer-same-window-except-diff-v1) + (transient-default-level 7) + :config + (transient-define-suffix mm-projects-magit-push-current-to-all-remotes (args) + "Push the current branch to all remotes." + :if #'magit-get-current-branch + (interactive (list (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (let ((branch (magit-get-current-branch))) + (dolist (remote (magit-list-remotes)) + (magit-run-git-async + "push" "-v" args remote + (format "refs/heads/%s:refs/heads/%s" branch branch))))) + (transient-append-suffix #'magit-push '(1 -1) + '("a" "all remotes" mm-projects-magit-push-current-to-all-remotes)) + (add-to-list 'magit-blame-styles + '(margin + (show-lines . t) + (margin-format . (" %C %a" " %s%f" " ")) + (margin-width . 73) + (margin-face . magit-blame-margin) + (margin-body-face . (magit-blame-dimmed))))) + +(use-package magit-repos + :ensure nil ; Part of ‘magit’ + :if (not mm-humanwave-p) + :commands (magit-list-repositories) + :init + (if-let ((directory (getenv "REPODIR"))) + (setopt magit-repository-directories `((,directory . 2))) + (warn "The REPODIR environment variable is not set."))) + +(use-package magit-todos + :ensure t + :after magit + :hook magit-mode + :custom + (magit-todos-exclude-globs '("vendor/"))) + + +;; Project Compilation + +(use-package compile + :config + (require 'ansi-color) + (add-hook 'compilation-filter-hook #'ansi-color-compilation-filter)) + + +;;; GitHub Pull Requests + +(require 'gh) +(keymap-global-set "C-c p c" #'gh-create-pr) +(keymap-global-set "C-c p o" #'gh-open-previous-pr) + +(provide 'mm-projects) diff --git a/.config/emacs-old/modules/mm-search.el b/.config/emacs-old/modules/mm-search.el new file mode 100644 index 0000000..c89b9d0 --- /dev/null +++ b/.config/emacs-old/modules/mm-search.el @@ -0,0 +1,57 @@ +;;; mm-search.el --- Emacs text searching -*- lexical-binding: t; -*- + +;;; Classic Emacs text search + +(use-package isearch + :demand t + :bind ( :map isearch-mode-map + ("M-/" . isearch-complete) + :map minibuffer-local-isearch-map + ("M-/" . isearch-complete-edit)) + :custom + (search-whitespace-regexp ".*?") + (isearch-lax-whitespace t) + (isearch-regexp-lax-whitespace nil) + (isearch-lazy-count t) + (lazy-highlight-initial-delay 0) + (lazy-count-prefix-format "(%s/%s) ") + (isearch-repeat-on-direction-change t)) + +(defun mm--project-find-wrapper (command regexp) + (let (csf) + (cond ((string-suffix-p "/i" regexp) + (setq regexp (string-remove-suffix "/i" regexp) + csf t)) + ((string-suffix-p "/I" regexp) + (setq regexp (string-remove-suffix "/I" regexp) + csf nil)) + (:else + (setq csf case-fold-search))) + (let ((case-fold-search csf)) + (funcall-interactively command regexp)))) + +(defun mm-project-find-regexp (regexp) + "Find all matches for REGEXP in the current project’s roots. +This is a thin wrapper around `project-find-regexp' that supports the +`/i' and `/I' suffixes to enable and disable case-sensitive matching +respectively." + (interactive (list (project--read-regexp))) + (mm--project-find-wrapper #'project-find-regexp regexp)) + +(defun mm-project-or-external-find-regexp (regexp) + "Find all matches for REGEXP in the project roots or external roots. +This is a thin wrapper around `project-or-external-find-regexp' that +supports the `/i' and `/I' suffixes to enable and disable case-sensitive +matching respectively." + (interactive (list (project--read-regexp))) + (mm--project-find-wrapper #'project-or-external-find-regexp regexp)) + + +;;; Grab Integration + +(use-package grab + :commands (grab git-grab project-grab project-git-grab) + :custom + (grab-default-pattern '("x/^.*?$/ g// h//" . 12))) + +(provide 'mm-search) diff --git a/.config/emacs-old/modules/mm-spellcheck.el b/.config/emacs-old/modules/mm-spellcheck.el new file mode 100644 index 0000000..95db7ac --- /dev/null +++ b/.config/emacs-old/modules/mm-spellcheck.el @@ -0,0 +1,24 @@ +;;; mm-spellcheck.el --- Spell checking configuration -*- lexical-binding: t; -*- + +;;; ISpell Spell Checking + +(use-package ispell + :hook (flyspell-mode . ispell-minor-mode) + :custom + (ispell-program-name "hunspell") + (ispell-local-dictionary "en_US") + (ispell-local-dictionary-alist + '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[’']" + nil ("-d" "en_US") nil utf-8))) + (ispell-hunspell-dictionary-alist ispell-local-dictionary-alist)) + + +;;; On-The-Fly Spell Checking + +(use-package flyspell + :defer t + :config + ;; I use ‘C-,’ for ‘emmet-expand-line’ + (keymap-unset flyspell-mode-map "C-," :remove)) + +(provide 'mm-spellcheck) diff --git a/.config/emacs-old/modules/mm-tetris.el b/.config/emacs-old/modules/mm-tetris.el new file mode 100644 index 0000000..06fae58 --- /dev/null +++ b/.config/emacs-old/modules/mm-tetris.el @@ -0,0 +1,20 @@ +;;; mm-tetris.el --- Emacs configurations for ‘tetris’ -*- lexical-binding: t; -*- + +(defun mm-tetris-rotate-mirror () + "Rotate the current piece by 180°." + (declare (modes tetris-mode)) + (interactive) + (tetris-rotate-next) + (tetris-rotate-next)) + +(use-package tetris + :bind (:map tetris-mode-map + ("a" . tetris-move-left) + ("d" . tetris-move-right) + ("k" . tetris-rotate-next) + (";" . tetris-rotate-prev) + ("l" . tetris-move-down) + ("o" . mm-tetris-rotate-mirror) + ("SPC" . tetris-move-bottom))) + +(provide 'mm-tetris) diff --git a/.config/emacs-old/modules/mm-theme.el b/.config/emacs-old/modules/mm-theme.el new file mode 100644 index 0000000..89cdffd --- /dev/null +++ b/.config/emacs-old/modules/mm-theme.el @@ -0,0 +1,246 @@ +;;; mm-theme.el --- Emacs theme settings -*- lexical-binding: t; -*- + + +;;; Custom Theme + +(load-theme 'mango :no-confirm) + + +;;; Fonts + +(defvar mm-theme-monospace-font `(,(if mm-humanwave-p + "Iosevka Custom" + "Iosevka Smooth") + :weight regular + :height 162) + "The default monospace font. +This is a plist containing a font name, -weight, and -height.") + +(defvar mm-theme-proportional-font + `(,(if mm-darwin-p "Microsoft Sans Serif" "Source Sans 3 Medium") + :weight regular :height 162) + "The default proportional font. +This is a plist containing a font name, -weight, and -height.") + +(defun mm-theme-set-fonts (&optional _frame) + "Set frame font settings. +Sets the frame font settings according to the fonts specified by +`mm-theme-monospace-font' and `mm-theme-proportional-font'. + +This function can be used as a hook in `after-make-frame-functions' and +_FRAME is ignored." + (interactive) + (let* ((mono-family (car mm-theme-monospace-font)) + (mono-props (cdr mm-theme-monospace-font)) + (prop-family (car mm-theme-proportional-font)) + (prop-props (cdr mm-theme-proportional-font)) + (mono-weight (plist-get mono-props :weight)) + (mono-height (plist-get mono-props :height)) + (prop-weight (plist-get prop-props :weight)) + (prop-height (plist-get prop-props :height))) + ;; Some characters in this font are larger than usual + (when (string= mono-family "Iosevka Smooth") + (dolist (rune '(?․ ?‥ ?… ?— ?← ?→ ?⇐ ?⇒ ?⇔)) + (set-char-table-range char-width-table rune 2))) + (set-face-attribute 'default nil + :font mono-family + :weight mono-weight + :height mono-height) + (set-face-attribute 'fixed-pitch nil + :font mono-family + :weight mono-weight + :height mono-height) + (set-face-attribute 'variable-pitch nil + :font prop-family + :weight prop-weight + :height prop-height))) + +(if (daemonp) + (add-hook 'after-make-frame-functions #'mm-theme-set-fonts) + (mm-theme-set-fonts)) + +;; Ligature Settings + +(defvar mm-theme-ligatures-alist + `(((c-mode c-ts-mode c++-mode c++-ts-mode) + . ("->")) + ((c++-mode c++-ts-mode) + . ("::")) + ((js-mode js-ts-mode typescript-ts-mode vue-ts-mode) + . (("=" ,(rx (or ?> (** 1 2 ?=)))) + ("!" ,(rx (** 1 2 ?=))))) + (go-ts-mode + . (":=" "<-")) + ((python-mode python-ts-mode) + . (":=" "->")) + ((mhtml-mode html-mode html-ts-mode vue-ts-mode) + . ("" "/>")) + (prog-mode + . ("<<=" "<=" ">=" "==" "!=" "*=" "__"))) + "Ligatures to enable in specific modes. +Elements of this alist are of the form: + + (SPEC . LIGATURES) + +Where LIGATURES is a list of ligatures to enable for the set of modes +described by SPEC. + +SPEC can be either a symbol, or a list of symbols. These symbols should +correspond to modes for which the associated LIGATURES should be enabled. + +A mode may also be specified in multiple entries. To configure +`go-ts-mode' to have its set of ligatures be a super-set of the +ligatures for `c-ts-mode', the following two entries could be added: + + \\='((c-ts-mode go-ts-mode) . (\">=\" \"<=\" \"!=\" \"==\")) + \\='(go-ts-mode . (\":=\"))") + +(defun mm-theme-update-ligatures () + "Update the ligature composition tables. +After running this function you may need to restart `ligature-mode'. + +Also see `mm-theme-ligatures-alist'." + (interactive) + (setopt ligature-composition-table nil) + (cl-loop for (spec . ligatures) in mm-theme-ligatures-alist + do (ligature-set-ligatures spec ligatures))) + +(use-package ligature + :ensure t + :if (or mm-darwin-p + (seq-contains-p (split-string system-configuration-features) + "HARFBUZZ")) + :hook prog-mode + :config + (mm-theme-update-ligatures)) + + +;;; Background Opacity + +(defvar mm-theme-background-opacity 100 + "Opacity of the graphical Emacs frame. +A value of 0 is fully transparent while 100 is fully opaque.") + +(defun mm-theme-background-opacity (opacity) + "Set the current frames' background opacity. +See also the `mm-theme-background-opacity' variable." + (interactive + (list (mm-as-number + (read-string + (format-prompt "Background opacity" + (default-value 'mm-theme-background-opacity)) + nil nil mm-theme-background-opacity)))) + (set-frame-parameter nil 'alpha-background opacity)) + +(add-to-list + 'default-frame-alist (cons 'alpha-background mm-theme-background-opacity)) + + +;;; Divider Between Windows + +(use-package frame + :hook (after-init . window-divider-mode)) + + +;;; Pulse Line on Jump + +(use-package pulsar + :ensure t + :hook (after-init . pulsar-global-mode) + :custom + (pulsar-pulse t) + (pulsar-delay .05) + (pulsar-iterations 10) + (pulsar-face 'hl-line) + :config + (dolist (command #'(backward-paragraph + e/scroll-down + e/scroll-up + forward-paragraph + jump-to-register + pop-global-mark)) + (add-to-list 'pulsar-pulse-functions command)) + ;; Integrate with ‘compilation-mode’ + (add-hook 'next-error-hook #'pulsar-pulse-line) + :bind + (("C-c h l" . pulsar-highlight-dwim))) + + +;;; In-buffer highlighting + +(require 'hi-lock) ; For extra face definitions +(use-package highlighter + :bind (("C-c h m" . #'highlighter-mark) + ("C-c h u" . #'highlighter-unmark) + ("C-c h U" . #'highlighter-unmark-buffer)) + :commands (highlighter-mark highlighter-unmark highlighter-unmark-buffer)) + + +;;; Add Padding + +(use-package spacious-padding + :ensure t + :hook after-init) + + +;;; Pretty Page Boundaries + +(use-package page-break-lines + :ensure t + :hook (after-init . global-page-break-lines-mode) + :config + (dolist (mode '(c-mode c++-mode gsp-ts-mode)) + (add-to-list 'page-break-lines-modes mode) + (let ((ts-mode (mm-mode-to-ts-mode mode))) + (when (fboundp ts-mode) + (add-to-list 'page-break-lines-modes ts-mode)))) + (add-hook + 'change-major-mode-hook + (defun mm-theme--set-page-break-max-width () + (setopt page-break-lines-max-width fill-column))) + ;; Since the ‘^L’ character is replaced by a horizontal rule, the + ;; cursor should appear below the horizontal rule. When moving + ;; backwards we need to account for the fact that the cursor is + ;; actually one character ahead of hte page break and adjust + ;; accordingly. + (advice-add + #'forward-page :after + (defun mm-theme--forward-char (&rest _) + (forward-char))) + (advice-add + #'backward-page :before + (defun mm-theme--backward-char (&rest _) + (backward-char)))) + + +;;; More Intuiative UI for Certain Modes + +(defun mm-disable-line-selection-mode () + (line-selection-mode -1)) + +(use-package line-selection-mode + :hook ((bookmark-bmenu-mode dired-mode ibuffer-mode magit-repolist-mode) + . line-selection-mode) + :config + (add-hook 'wdired-mode-hook #'mm-disable-line-selection-mode)) + + +;;; Line Highlighting + +(use-package hl-line + :custom + (hl-line-sticky-flag nil)) + + +;;; Indent Guides + +(when mm-humanwave-p + (use-package highlight-indent-guides + :ensure t + :hook ((jinja2-mode vue-ts-mode mhtml-mode) . highlight-indent-guides-mode) + :custom + (highlight-indent-guides-method 'fill) + (highlight-indent-guides-auto-even-face-perc 30) + (highlight-indent-guides-auto-odd-face-perc 0))) + +(provide 'mm-theme) diff --git a/.config/emacs-old/modules/mm-treesit.el b/.config/emacs-old/modules/mm-treesit.el new file mode 100644 index 0000000..81d0801 --- /dev/null +++ b/.config/emacs-old/modules/mm-treesit.el @@ -0,0 +1,240 @@ +;;; mm-treesit.el --- Tree-Sitter configuration -*- lexical-binding: t; -*- + +(unless (treesit-available-p) + (error "Tree-Sitter is not available.")) + + +;;; Tree-Sitter Variables + +(defvar mm-treesit-language-remap-alist + '((cpp . c++) + (gomod . go-mod) + (javascript . js) + (vim . vimscript)) + "TODO") + +(setopt treesit-font-lock-level 4) +(setopt treesit-language-source-alist + '((awk + "https://github.com/Beaglefoot/tree-sitter-awk") + (c + "https://github.com/tree-sitter/tree-sitter-c") + (cpp + "https://github.com/tree-sitter/tree-sitter-cpp") + (css + "https://github.com/tree-sitter/tree-sitter-css") + (dockerfile + "https://github.com/camdencheek/tree-sitter-dockerfile") + (elixir + "https://github.com/elixir-lang/tree-sitter-elixir") + (go + "https://github.com/tree-sitter/tree-sitter-go") + (gomod + "https://github.com/camdencheek/tree-sitter-go-mod") + (gsp + "git://git.thomasvoss.com/tree-sitter-gsp.git") + (heex + "https://github.com/phoenixframework/tree-sitter-heex") + (html + "https://github.com/tree-sitter/tree-sitter-html") + (java + "https://github.com/tree-sitter/tree-sitter-java") + (javascript + "https://github.com/tree-sitter/tree-sitter-javascript") + (json + "https://github.com/tree-sitter/tree-sitter-json") + (markdown + "https://github.com/tree-sitter-grammars/tree-sitter-markdown" + "split_parser" "tree-sitter-markdown/src") + (markdown-inline + "https://github.com/tree-sitter-grammars/tree-sitter-markdown" + "split_parser" "tree-sitter-markdown-inline/src") + (python + "https://github.com/tree-sitter/tree-sitter-python") + (rust + "https://github.com/tree-sitter/tree-sitter-rust") + (tsx + "https://github.com/tree-sitter/tree-sitter-typescript" + "master" "tsx/src") + (typescript + "https://github.com/tree-sitter/tree-sitter-typescript" + "master" "typescript/src") + (vim + "https://github.com/tree-sitter-grammars/tree-sitter-vim") + (vue + "https://github.com/ikatyang/tree-sitter-vue") + (yaml + "https://github.com/tree-sitter-grammars/tree-sitter-yaml"))) + + +;;; Install Missing Parsers + +(defun mm-treesit-install-all () + "Install all Tree-Sitter parsers. +This is like `mm-treesit-install-missing' but also reinstalls parsers +that are already installed." + (interactive) + (cl-loop for (lang) in treesit-language-source-alist + do (treesit-install-language-grammar lang))) + +(defun mm-treesit-install-missing () + "Install missing Tree-Sitter parsers. +The parsers are taken from `treesit-language-source-alist'." + (interactive) + (cl-loop for (lang) in treesit-language-source-alist + unless (treesit-language-available-p lang) + do (treesit-install-language-grammar lang))) + +(mm-treesit-install-missing) + + +;;; Install Additional TS Modes + +(use-package gsp-ts-mode + :vc (:url "https://git.thomasvoss.com/gsp-ts-mode" + :branch "master" + :rev :newest + :vc-backend Git) + :ensure t) + +;; NOTE: This package doesn’t autoload its ‘auto-mode-alist’ entries +(use-package vimscript-ts-mode + :ensure t + :mode (rx (or (seq (? (or ?. ?_)) (? ?g) "vimrc") + ".vim" + ".exrc") + eos)) + +;; NOTE: This package doesn’t autoload its ‘auto-mode-alist’ entries +(use-package vue-ts-mode + :vc ( :url "https://github.com/8uff3r/vue-ts-mode.git" + :branch "main" + :rev :newest + :vc-backend Git) + :ensure t + :mode "\\.vue\\'") + +;; NOTE: This package doesn’t autoload its ‘auto-mode-alist’ entries +(use-package markdown-ts-mode + :ensure t + :mode "\\.md\\'") + + +;;; Prefer Tree-Sitter Modes + +;; NOTE: ‘go-ts-mode’ already adds itself to ‘auto-mode-alist’ but it +;; isn’t autoloaded as of 2024-09-29 so we need to do it ourselves +;; anyway. Same goes for ‘typescript-ts-mode’. +(defvar mm-treesit-language-file-name-alist + '((dockerfile . "/[Dd]ockerfile\\'") + (elixir . "\\.exs?\\'") + (go . "\\.go\\'") + (gomod . "/go\\.mod\\'") + (heex . "\\.heex\\'") + (json . "\\.json\\'") + (rust . "\\.rs\\'") + (tsx . "\\.tsx\\'") + (typescript . "\\.ts\\'") + (yaml . "\\.ya?ml\\'")) + "Alist mapping languages to their associated file-names. +This alist is a set of pairs of the form (LANG . REGEXP) where LANG is +the symbol corresponding to a major mode with the `-ts-mode' suffix +removed. REGEXP is a regular expression matching filenames for which +the associated language’s major-mode should be enabled. + +This alist is used to configure `auto-mode-alist'.") + +(defvar mm-treesit-dont-have-modes + '(markdown-inline) + "List of languages that don't have modes. +Some languages may come with multiple parsers, (e.g. `markdown' and +`markdown-inline') and as a result one-or-more of the parsers won't be +associated with a mode. To avoid breaking the configuration, these +languages should be listed here.") + +(dolist (spec treesit-language-source-alist) + (let* ((lang (car spec)) + (lang-remap (alist-get lang mm-treesit-language-remap-alist lang)) + (name-mode (intern (format "%s-mode" lang-remap))) + (name-ts-mode (intern (format "%s-ts-mode" lang-remap)))) + ;; If ‘name-ts-mode’ is already in ‘auto-mode-alist’ then we don’t + ;; need to do anything, however if that’s not the case then if + ;; ‘name-ts-mode’ and ‘name-mode’ are both bound we do a simple + ;; remap. If the above is not true then we lookup the extensions in + ;; ‘mm-treesit-language-file-name-alist’. + (cond + ((memq lang mm-treesit-dont-have-modes) + nil) + ((not (fboundp name-ts-mode)) + (warn "`%s' is missing." name-ts-mode)) + ((rassq name-ts-mode auto-mode-alist) + nil) + ((fboundp name-mode) + (add-to-list 'major-mode-remap-alist (cons name-mode name-ts-mode))) + (t ; (and (fboundp name-ts-mode) (not (fboundp name-mode))) + (if-let ((file-regexp + (alist-get lang mm-treesit-language-file-name-alist))) + (add-to-list 'auto-mode-alist (cons file-regexp name-ts-mode)) + (warn "Unable to determine the extension for `%s'." name-ts-mode)))))) + +;; JavaScript being difficult as usual +(add-to-list 'major-mode-remap-alist '(javascript-mode . js-ts-mode)) + + +;;; Hack For C23 + +(advice-add #'c-ts-mode--keywords :filter-return + (defun mm-c-ts-mode-add-constexpr (keywords) + ;; NOTE: We can’t add ‘typeof’ until it’s added to the TS grammar + ;; https://github.com/tree-sitter/tree-sitter-c/issues/236 + (append keywords '("constexpr")))) + + +;;; Highlight Predefined Variables + +(with-eval-after-load 'treesit + (defvar mm-c-font-lock-rules + (treesit-font-lock-rules + :language 'c + :feature 'constant + :override t + `(((identifier) @font-lock-constant-face + (:match ,(rx bos (or "__func__" "__FUNCTION__") eos) + @font-lock-constant-face)))))) + +(add-hook 'c-ts-mode-hook + (defun mm-c-apply-font-lock-extras () + (setq treesit-font-lock-settings + (append treesit-font-lock-settings mm-c-font-lock-rules)))) + + +;;; Region Expansion + +(defun mm-expreg-expand (n) + "Expand to N syntactic units." + (interactive "p") + (dotimes (_ n) + (expreg-expand))) + +(defun mm-expreg-expand-dwim () + "Do-What-I-Mean `expreg-expand' to start with symbol or word. +If over a real symbol, mark that directly, else start with a word. Fall +back to regular `expreg-expand'." + (interactive) + (if (region-active-p) + (expreg-expand) + (let ((symbol (bounds-of-thing-at-point 'symbol))) + (cond + ((equal (bounds-of-thing-at-point 'word) symbol) + (mm-expreg-expand 1)) + (symbol + (mm-expreg-expand 2)) + (:else + (expreg-expand)))))) + +(use-package expreg + :ensure t + :commands (mm-expreg-expand mm-expreg-expand-dwim) + :bind ("M-SPC" . mm-expreg-expand-dwim)) + +(provide 'mm-treesit) diff --git a/.config/emacs-old/modules/mm-window.el b/.config/emacs-old/modules/mm-window.el new file mode 100644 index 0000000..0ce77c7 --- /dev/null +++ b/.config/emacs-old/modules/mm-window.el @@ -0,0 +1,72 @@ +;;; mm-window.el --- Window configurations -*- lexical-binding: t; -*- + + +;;; Unique Buffer Names + +(use-package uniquify + :custom + (uniquify-buffer-name-style 'forward)) + + +;;; Highlight Whitespace + +(use-package whitespace + :bind (("" . whitespace-mode) + ("C-c z" . delete-trailing-whitespace)) + :custom + (whitespace-style + '( face trailing spaces tabs space-mark tab-mark empty indentation + space-after-tab space-before-tab)) + (whitespace-display-mappings + '((space-mark 32 [?·] [?.]) ; Space + (space-mark 160 [?␣] [?_]) ; Non-Breaking Space + (tab-mark 9 [?» ?\t] [?> ?\t])))) + + +;;; Line Numbers + +(use-package display-line-numbers + :bind ("" . display-line-numbers-mode) + :custom + (display-line-numbers-grow-only t) + (display-line-numbers-type 'relative) + (display-line-numbers-width-start 99)) + + +;;; Select Help Windows + +(use-package help + :custom + (help-window-select t)) + + +;;; Window Scrolling + +(use-package window + :custom + (scroll-conservatively 101) ; (info "(Emacs)Auto Scrolling") + (scroll-error-top-bottom t) + (scroll-margin 10) + :config + (setq-default truncate-partial-width-windows nil)) + + +;;; Smoother Scrolling + +(mm-comment + (use-package pixel-scroll + :init + (pixel-scroll-precision-mode) + :config + ;; Make it easier to use custom scroll functions + (dolist (binding '("" "")) + (keymap-unset pixel-scroll-precision-mode-map binding :remove)))) + + +;;; Ace Window + +(use-package ace-window + :ensure t + :bind ("M-o" . ace-window)) + +(provide 'mm-window) \ No newline at end of file diff --git a/.config/emacs-old/site-lisp/emmet.el b/.config/emacs-old/site-lisp/emmet.el new file mode 100644 index 0000000..eefb4ba --- /dev/null +++ b/.config/emacs-old/site-lisp/emmet.el @@ -0,0 +1,349 @@ +;;; tree-exp-mode.el --- Minor mode for expanding tree-like syntax -*- lexical-binding: t; -*- + +(eval-when-compile + (require 'cl-macs) + (require 'tempo)) + +(defgroup tree-exp nil + "Customization group for `emmet-mode'." + :group 'convenience) + +(defcustom tree-exp-html-self-closing-style "" + "Self-closing tag style for HTML. +This setting specifies how `tree-exp' should generate self-closing tags +when expanding to HTML. When generating a self-closing tag the value of +`tree-exp-html-self-closing-style' is inserted verbatim between the end +of the element attributes and the closing angle-bracket. + +Note that the variable of this setting has no bearing on the validity of +the generated HTML; infact the HTML standard instructs parsers to ignore +a trailing slash." + :type '(choice (const :tag "") + (const :tag "/") + (const :tag " /")) + :package-version '(tree-exp . "1.0.0") + :group 'tree-exp) + +(defcustom tree-exp-set-marks t + "TODO" + :type 'boolean + :package-version '(tree-exp . "1.0.0") + :group 'tree-exp) + +(defvar-keymap tree-exp-mode-map + :doc "TODO") + +(defvar tree-exp-expand-functions + '(((html-mode mhtml-mode html-ts-mode) . tree-exp-expand-html) + (gsp-ts-mode . tree-exp-expand-gsp)) + "TODO") + +(defvar tree-exp-operator-alist-alist + '(((html-mode mhtml-mode html-ts-mode gsp-ts-mode) + . ((?+ . sibling) + (?^ . parent) + (?> . child) + (?. . extra) + (?# . extra) + (?@ . extra) + (?* . repeat)))) + "TODO") + +(defvar tree-exp-after-expansion-hook nil + "TODO") + + +;; Private Variables + +(defvar-local tree-exp--mark-index 0) + +(defconst tree-exp--html-void-elements + #s(hash-table size 13 + test equal + purecopy t + data ("area" t + "base" t + "br" t + "col" t + "embed" t + "hr" t + "img" t + "input" t + "link" t + "meta" t + "source" t + "track" t + "wbr" t))) + + +;; Parsing + +(defun tree-exp--pattern-start () + (max (save-excursion + (skip-syntax-backward "^ ") + (point)) + (pos-bol))) + +(defun tree-exp--pattern-bounds () + (if (use-region-p) + (progn + (when (region-noncontiguous-p) + (error "Noncontiguous regions are not supported yet.")) + (car (region-bounds))) + (cons (tree-exp--pattern-start) (point)))) + +(defun tree-exp--symbol-end (operator-alist) + (while (and (memq (car (syntax-after (point))) '(2 3)) + (not (assq (char-after (point)) operator-alist))) + (goto-char (1+ (point)))) + (point)) + +(defun tree-exp--set-children-of-leaves (tree values) + (dolist (node tree) + (if-let ((children (nth 2 node))) + (tree-exp--set-children-of-leaves children values) + (setf (nth 2 node) values))) + tree) + +(defun tree-exp--append-extra-to-leaves (tree value) + (dolist (node tree) + (if-let ((children (nth 2 node))) + (tree-exp--append-extra-to-leaves children value) + (setf + (nth 1 node) + (append (nth 1 node) (cons value nil))))) + tree) + +(defun tree-exp--parse-count () + (let* ((start (point)) + (end (+ start (skip-chars-forward "0-9"))) + (num (string-to-number + (buffer-substring-no-properties start end) + 10))) + (unless (zerop num) + num))) + +(defun tree-exp--parse-atom (operator-alist) + (let ((start (point)) + (end (tree-exp--symbol-end operator-alist))) + (if (= start end) + (when (= ?\( (char-after end)) + (goto-char (1+ end)) + (let ((tree (tree-exp--parse-expr operator-alist)) + (char (char-after (point)))) + (if (eq ?\) char) + (progn + (goto-char (1+ (point))) + tree) + (message (if char + (format "Invalid operator `%c'" char) + "Missing closing parenthesis")) + nil))) + (list (list (buffer-substring-no-properties start end) nil nil))))) + +(defun tree-exp--parse-term (operator-alist) + (let ((terms (tree-exp--parse-atom operator-alist))) + (catch 'loop + (while t + (let* ((operator (assq (char-after (point)) operator-alist)) + (op-char (car-safe operator)) + (op-type (cdr-safe operator)) + start end) + (unless (eq op-type 'extra) + (throw 'loop terms)) + (setq + start (goto-char (1+ (point))) + end (tree-exp--symbol-end operator-alist)) + (when (= start end) + (message "Operator `%c' missing right-hand side" op-char) + (throw 'loop nil)) + (tree-exp--append-extra-to-leaves + terms (cons op-char (buffer-substring-no-properties start end)))))))) + +;; Gross hack +(defun tree-exp--parse-expr-with-lhs (operator-alist lhs) + (let* ((op-char (char-after (point))) + (op-type (alist-get op-char operator-alist)) + rhs) + (cond + ((not lhs) + nil) + ((or (not op-char) + (not op-type)) + lhs) + (t + (goto-char (1+ (point))) + (setq rhs (if (eq op-type 'repeat) + (tree-exp--parse-count) + (tree-exp--parse-expr operator-alist))) + (when rhs + (pcase op-type + ('child (tree-exp--set-children-of-leaves lhs rhs)) + ('parent (tree-exp--set-children-of-leaves rhs lhs)) + ('sibling (append lhs rhs)) + ('repeat (tree-exp--parse-expr-with-lhs + operator-alist + ;; FIXME: We need to call ‘copy-tree’ or else the + ;; generated AST has cycles in it… why is that? How + ;; can we fix it? + (cl-loop for _ from 1 to rhs append (copy-tree lhs)))))))))) + +(defun tree-exp--parse-expr (operator-alist) + (tree-exp--parse-expr-with-lhs + operator-alist + (tree-exp--parse-term operator-alist))) + +(defun tree-exp--build-ast (bounds) + (save-excursion + (with-restriction (car bounds) (cdr bounds) + (goto-char 1) + (when-let* ((operator-alist (tree-exp--alist-get + major-mode tree-exp-operator-alist-alist)) + (tree (tree-exp--parse-expr operator-alist))) + (if (= (point) (point-max)) + tree + (message "Superfluous character `%c'" (char-after (point))) + nil))))) + + +;; Expansion + +(defun tree-exp--alist-get (key alist) + (cdr (or (assq key alist) + (catch 'tree-exp--break + (dolist (pair alist) + (when (and (listp (car pair)) + (memq key (car pair))) + (throw 'tree-exp--break pair))))))) + +(defun tree-exp--ast-siblings-p (ast) + (cond ((not ast) nil) + ((length> ast 1) t) + (t (tree-exp--ast-siblings-p (caddar ast))))) + +(defun tree-exp-expand-html--format-attr (attr) + (declare ((pure t) (side-effect-free t))) + (let* ((parts (string-split attr "=")) + (name (car parts)) + (value-parts (cdr parts))) + (if value-parts + (format "%s=\"%s\"" name (string-join value-parts "=")) + name))) + +(defun tree-exp-expand-html--helper (ast indentp) + (dolist (node ast) + (let* ((name (nth 0 node)) + (attrs (nth 1 node)) + (children (nth 2 node)) + (classes (cl-loop for (op . attr) in attrs + if (= ?. op) + collect attr))) + (insert (format "<%s" name)) + (when classes + (insert (format " class=\"%s\"" (string-join classes " ")))) + (cl-loop for (op . attr) in attrs + if (= ?# op) + do (insert (format " id=\"%s\"" attr)) + else if (= ?@ op) + do (thread-last + attr + (tree-exp-expand-html--format-attr) + (concat " ") + (insert))) + (if (and (not children) + (gethash name tree-exp--html-void-elements)) + (insert (format "%s>" tree-exp-html-self-closing-style)) + (insert ?>) + (if children + (progn + (when indentp + (insert ?\n)) + (tree-exp-expand-html--helper children indentp)) + (when tree-exp-set-marks + (insert #x1B))) + (insert (format "" name)))) + (when indentp + (insert ?\n)))) + +(defun tree-exp-expand-html (ast) + "TODO" + (tree-exp-expand-html--helper ast (tree-exp--ast-siblings-p ast)) + (when (= ?\n (char-before (point-max))) + (delete-region (1- (point-max)) (point-max))) + (when tree-exp-set-marks + (insert #x1B))) + +;; (defun tree-exp-expand-gsp--helper (ast indentp) +;; (dolist (node ast) +;; (let ((name (nth 0 node)) +;; (attrs (nth 1 node)) +;; (children (nth 2 node))) + + +;; ;; (insert (format "<%s" name)) +;; ;; (dolist (attr attrs) +;; ;; (insert (format " %s" (cdr attr)))) +;; ;; (if (and (not children) +;; ;; (gethash name tree-exp--html-void-elements)) +;; ;; (insert (format "%s>" tree-exp-html-self-closing-style)) +;; ;; (insert ?>) +;; ;; (if children +;; ;; (progn +;; ;; (when indentp +;; ;; (insert ?\n)) +;; ;; (tree-exp-expand-html--helper children indentp)) +;; ;; (when tree-exp-set-marks +;; ;; (insert #x1B))) +;; ;; (insert (format "" name))) +;; ) +;; (when indentp +;; (insert ?\n)))) + +(defun tree-exp-expand-gsp (ast) + "TODO" + (tree-exp-expand-gsp--helper ast (tree-exp--ast-siblings-p ast)) + (when (= ?\n (char-before (point-max))) + (delete-region (1- (point-max)) (point-max))) + (when tree-exp-set-marks + (insert #x1B))) + +;;;###autoload +(defun tree-exp-expand () + "TODO" + (interactive) + (when-let* ((current-buffer (current-buffer)) + (bounds (tree-exp--pattern-bounds)) + (ast (tree-exp--build-ast bounds)) + (expander (tree-exp--alist-get + major-mode tree-exp-expand-functions))) + (delete-region (car bounds) (cdr bounds)) + (with-temp-buffer + (funcall expander ast) + (insert-into-buffer current-buffer)) + (let ((start-pos (car bounds)) + (end-pos (point-marker)) + (delete-active-region nil) ; For ‘delete-backward-char’ + marks) + (when tree-exp-set-marks + (save-excursion + (goto-char start-pos) + (while (search-forward "\x1B" end-pos :noerror) + (delete-backward-char 1) + (push (point-marker) marks))) + (push (point-marker) marks) + (setq marks (nreverse marks)) + (goto-char (car marks)) + (mapc #'tempo-insert-mark marks)) + ;; Set the start of the region to the start bound + (unless (region-active-p) + (set-mark start-pos)) + (indent-region start-pos end-pos) + (run-hooks tree-exp-after-expansion-hook)))) + +;;;###autoload +(define-minor-mode tree-exp-mode + "TODO" + :lighter " Tree-Expand" + :keymap tree-exp-mode-map) + +(provide 'tree-exp) diff --git a/.config/emacs-old/site-lisp/gh.el b/.config/emacs-old/site-lisp/gh.el new file mode 100644 index 0000000..39dc339 --- /dev/null +++ b/.config/emacs-old/site-lisp/gh.el @@ -0,0 +1,62 @@ +;;; gh.el --- GitHub integration for Emacs -*- lexical-binding: t; -*- + +(defun gh-get-labels () + "Return a list of labels in the current GitHub repository." + (with-temp-buffer + (call-process "gh" nil t nil "label" "list" + "--sort" "name" "--json" "name" "--limit" "1000000") + (goto-char (point-min)) + (seq-map (lambda (x) (gethash "name" x)) + (json-parse-buffer)))) + +;; TODO: Set title and body in a buffer like Magit +(defun gh-create-pr (title &optional labels draftp) + "Create a GitHub pull request. +If DRAFTP is non-nil, the PR will be created as a draft. + +LABELS is a list of labels. A list of available labels can be fetched +via `gh-get-labels'." + (interactive + (list + (read-string (format-prompt "PR Title" nil)) + (completing-read-multiple (format-prompt "PR Labels" nil) + (gh-get-labels)) + (y-or-n-p "Create PR as a draft? "))) + (let* ((project (project-name (project-current))) + (flags `("--fill-verbose" "--assignee" "@me")) + (label-string (mapconcat #'identity labels ","))) + ;; TODO: Remove this + (when (string= project "blixem") + (setq title (format "%s %s" (car (vc-git-branches)) title)) + (when (member "Patch" labels) + (setq flags (append flags '("--base" "release"))))) + (setq flags (append flags `("--title" ,title))) + (when draftp + (setq flags (append flags '("--draft")))) + (when labels + (setq flags (append flags `("--label" ,label-string)))) + (with-temp-buffer + (apply #'call-process "gh" nil t nil "pr" "create" flags) + (message (buffer-string))))) + +(defvar gh-pr-regexp + "\\`https://\\(?:www\\.\\)?github\\.com/[^/]+/[^/]+/pull/[[:digit:]]+\\'") + +(defun gh--pr-link-p (s) + (declare (pure t) (side-effect-free t)) + (string-match-p gh-pr-regexp s)) + +(defun gh-open-previous-pr () + "Open the previous GitHub pull request. +Opens the previous pull request created by `gh-create-pr' by searching +for the echoed URL in the `*Messages*' buffer." + (interactive) + (with-current-buffer "*Messages*" + (goto-char (point-max)) + (while (not (gh--pr-link-p (buffer-substring-no-properties + (pos-bol) (pos-eol)))) + (unless (line-move -1 :noerror) + (user-error "No previous pull request found."))) + (browse-url-at-point))) + +(provide 'gh) diff --git a/.config/emacs-old/site-lisp/grab.el b/.config/emacs-old/site-lisp/grab.el new file mode 100644 index 0000000..2482d5d --- /dev/null +++ b/.config/emacs-old/site-lisp/grab.el @@ -0,0 +1,215 @@ +;;; grab.el --- Emacs integration for grab -*- lexical-binding: t; -*- + +;; Author: Thomas Voss +;; Description: TODO +;; Keywords: matching, tools + +;;; Commentary: + +;; TODO + +;;; Code: + +(require 'ansi-color) +(require 'dired) +(require 'project) +(require 'rx) +(require 'xref) + +(defgroup grab nil + "Settings for `grab'." + :group 'tools) + +(defcustom grab-command "grab" + "The base executable for the Grab tool." + :type 'string) + +(defcustom git-grab-command "git-grab" + "The base executable for the Git Grab tool." + :type 'string) + +(defcustom grab-command-arguments '("-c" "-Hmulti") + "Arguments to pass to `grab-command'." + :type '(repeat string)) + +(defcustom git-grab-command-arguments grab-command-arguments + "Arguments to pass to `git-grab-command'." + :type '(repeat string)) + +(defcustom grab-default-pattern '("x// h//" . 3) + "The default pattern in Grab prompts" + :type '(choice (cons string natnum) + (string))) + +(defvar grab-history nil + "Minibuffer history for Grab search patterns.") + + +;;; Xref Location Class + +(cl-defstruct grab-location + "A location in a file specified by a byte offset." + file offset) + +(cl-defmethod xref-location-marker ((loc grab-location)) + "Return a marker for the grab location LOC." + (let* ((file (grab-location-file loc)) + (offset (grab-location-offset loc)) + (buf (find-file-noselect file))) + (with-current-buffer buf + (save-restriction + (widen) + (goto-char (byte-to-position (1+ offset))) + (point-marker))))) + +(cl-defmethod xref-location-group ((loc grab-location)) + "Group matches by their file name in the xref buffer." + (grab-location-file loc)) + +(cl-defmethod xref-location-line ((loc grab-location)) + "Return the position of the match. + +`xref' internally performs a log on this value, so we need to handle the +0 case." + (max 1 (grab-location-offset loc))) + + +;;; Process Management & Parsing + +(defvar grab--header-regexp + (rx-let ((ansi-escape (seq "\e[" (* (any "0-9;")) "m")) + (highlighted (thing) + (seq (* ansi-escape) + thing + (* ansi-escape)))) + (rx line-start + (highlighted (group (+ (not (any ?: ?\e ?\n))))) + (highlighted ?:) + (highlighted (group (+ digit))) + (highlighted ?:))) + "Regular expression matching the grab output header.") + +(defun grab--format-summary (summary) + (let* ((summary (ansi-color-apply (string-trim-right summary))) + (pos 0) + (len (length summary))) + (while (< pos len) + (let ((next (next-property-change pos summary len))) + (when (or (get-text-property pos 'font-lock-face summary) + (get-text-property pos 'face summary)) + (put-text-property pos next 'font-lock-face 'xref-match summary) + (remove-list-of-text-properties pos next '(face) summary)) + (setq pos next))) + summary)) + +(defun grab--parse-output (dir) + (let (xrefs file offset match-start) + (goto-char (point-min)) + (while (re-search-forward grab--header-regexp nil :noerror) + (let ((next-file (match-string-no-properties 1)) + (next-offset (string-to-number (match-string-no-properties 2))) + (next-start (point))) + (when file + (let* ((summary (buffer-substring-no-properties + match-start (match-beginning 0))) + (summary (grab--format-summary summary)) + (full-path (expand-file-name file dir)) + (loc (make-grab-location :file full-path :offset offset))) + (push (xref-make summary loc) xrefs))) + (setq file next-file + offset next-offset + match-start next-start))) + (when file + (let* ((summary (buffer-substring-no-properties + match-start (point-max))) + (summary (grab--format-summary summary)) + (full-path (expand-file-name file dir)) + (loc (make-grab-location :file full-path :offset offset))) + (push (xref-make summary loc) xrefs))) + (unless xrefs + (user-error "No matches found for grab pattern")) + (nreverse xrefs))) + +(defun grab--directory (cmd args pattern dir) + (grab--files cmd args pattern dir + (directory-files-recursively dir "." nil t))) + +(defun grab--files (cmd args pattern dir files) + (lambda () + (let ((default-directory dir)) + (with-temp-buffer + (apply #'call-process cmd nil t nil + (flatten-tree (list args "--" pattern files))) + (grab--parse-output dir))))) + +(defun grab--read-pattern () + (read-string (format-prompt "Grab Pattern" nil) + grab-default-pattern + 'grab-history)) + + +;;; Interactive Commands + +;;;###autoload +(defun grab (pattern) + "Run grab with PATTERN in the current directory." + (interactive (list (grab--read-pattern))) + (xref-show-xrefs + (grab--directory grab-command + grab-command-arguments + pattern + default-directory) + nil)) + +;;;###autoload +(defun git-grab (pattern) + "Run git grab with PATTERN in the current directory." + (interactive (list (grab--read-pattern))) + (xref-show-xrefs + (grab--files git-grab-command + git-grab-command-arguments + pattern + default-directory + nil) + nil)) + +;;;###autoload +(defun project-grab (pattern) + "Run grab with PATTERN at the project root." + (interactive (list (grab--read-pattern))) + (let* ((project (project-current t)) + (default-directory (project-root project))) + (xref-show-xrefs + (grab--directory grab-command + grab-command-arguments + pattern + default-directory) + nil))) + +;;;###autoload +(defun project-git-grab (pattern) + "Run git grab with PATTERN at the project root." + (interactive (list (grab--read-pattern))) + (let* ((project (project-current t)) + (default-directory (project-root project))) + (xref-show-xrefs + (grab--files git-grab-command + git-grab-command-arguments + pattern + default-directory + nil) + nil))) + +;;;###autoload +(defun dired-grab-marked-files (pattern) + "TODO" + (interactive (list (grab--read-pattern))) + (let* ((project (project-current t)) + (default-directory (project-root project))) + (xref-show-xrefs + (grab--files grab-command grab-command-arguments pattern + default-directory (dired-get-marked-files)) + nil))) + +(provide 'grab) +;;; grab.el ends here diff --git a/.config/emacs-old/site-lisp/highlighter.el b/.config/emacs-old/site-lisp/highlighter.el new file mode 100644 index 0000000..ce67ac8 --- /dev/null +++ b/.config/emacs-old/site-lisp/highlighter.el @@ -0,0 +1,128 @@ +;;; highlighter.el --- In-buffer highlighting commands -*- lexical-binding: t; -*- + +(require 'seq) + +(defgroup highlighter nil + "Customization group for `highlighter'." + :group 'convenience) + +(defcustom highlighter-default-face 'match + "The default face used by `highlighter-mark'." + :type 'face + :package-version '(highlighter . "1.0.0") + :group 'highlighter) + +(defun highlighter-mark (arg) + "Highlight text in the buffer. +Highlight the current line or region if it is active. Text is +highlighted using the face specified by `highlighter-default-face'. + +With ARG, interactively pick a face to highlight with." + (declare (interactive-only t)) + (interactive "P") + (let ((bounds (if (use-region-p) + (region-bounds) + `((,(pos-bol) . ,(pos-eol))))) + (face (when arg + (highlighter--read-face-name "Highlight with face" #'facep)))) + (highlighter-mark-region bounds face)) + (when (region-active-p) + (deactivate-mark))) + +(defun highlighter-unmark (arg) + "Remove highlights in the buffer. + +Remove highlights from the current line or region if it is active. + +With ARG, interactively pick a face. Only highlights using the chosen +face will be removed." + (declare (interactive-only t)) + (interactive "P") + (let ((bounds (if (use-region-p) + (region-bounds) + `((,(pos-bol) . ,(pos-eol))))) + (face (when arg + (highlighter--read-face-name + "Clear highlights using face" + #'highlighter--used-face-p)))) + (highlighter-unmark-region bounds face)) + (when (region-active-p) + (deactivate-mark))) + +(defun highlighter-mark-region (bounds &optional face) + "Highlight text in the buffer within BOUNDS. +BOUNDS uses the same format as returned by `region-bounds'. + +Text is highlighted using the face specified by `highlighter-default-face'. + +If FACE is nil or omitted, `highlighter-default-face' is used." + (dolist (x bounds) (highlighter--mark-region (car x) (cdr x) face))) + +(defun highlighter-unmark-region (bounds &optional face) + "Remove highlights in the buffer within BOUNDS. +BOUNDS uses the same format as returned by `region-bounds'. + +If FACE is non-nil, only remove highlights using FACE." + (dolist (x bounds) (highlighter--unmark-region (car x) (cdr x) face))) + +(defun highlighter--mark-region (beg end &optional face) + (let ((ov (make-overlay beg end nil :front-advance)) + (face (or face highlighter-default-face 'match))) + (overlay-put ov 'priority 1) + (overlay-put ov 'face face) + (overlay-put ov 'evaporate t) + (overlay-put ov 'highlighter--mark-p t) + (overlay-put ov 'highlighter--face face))) + +(defun highlighter--unmark-region (beg end &optional face) + (if face + (remove-overlays beg end 'highlighter--face face) + (remove-overlays beg end 'highlighter--mark-p t))) + +(defun highlighter-unmark-buffer (arg) + "Remove highlights in the buffer. + +With ARG, interactively pick a face. Only highlights using the chosen +face will be removed." + (declare (interactive-only t)) + (interactive "P") + (let ((face (when arg + (highlighter--read-face-name + "Clear highlights using face" + #'highlighter--used-face-p)))) + (highlighter--unmark-region (point-min) (point-max) face))) + +(defun highlighter--read-face-name (prompt face-predicate) + (let (default defaults) + (let ((prompt (format "%s: " prompt)) + (completion-extra-properties + `(:affixation-function + ,(lambda (faces) + (mapcar + (lambda (face) + (list face + (concat (propertize read-face-name-sample-text + 'face face) + "\t") + "")) + faces)))) + aliasfaces nonaliasfaces faces) + ;; Build up the completion tables. + (mapatoms (lambda (s) + (when (apply face-predicate s nil) + (if (get s 'face-alias) + (push (symbol-name s) aliasfaces) + (push (symbol-name s) nonaliasfaces))))) + (let ((face (completing-read + prompt + (completion-table-in-turn nonaliasfaces aliasfaces) + nil t nil 'face-name-history defaults))) + (when (facep face) (if (stringp face) + (intern face) + face)))))) + +(defun highlighter--used-face-p (face) + (seq-filter (lambda (ov) (eq face (overlay-get ov 'highlighter--face))) + (overlays-in (point-min) (point-max)))) + +(provide 'highlighter) diff --git a/.config/emacs-old/site-lisp/html-escape.el b/.config/emacs-old/site-lisp/html-escape.el new file mode 100644 index 0000000..afdbb4d --- /dev/null +++ b/.config/emacs-old/site-lisp/html-escape.el @@ -0,0 +1,55 @@ +;;; html-escape.el --- HTML escaping functions -*- lexical-binding: t; -*- + +(defgroup html-escape nil + "Customization group for `html-escape'." + :group 'convenience) + +(defvar html-escape-table + (let ((table (make-hash-table :test #'eq))) + (puthash ?& "&" table) + (puthash ?< "<" table) + (puthash ?> ">" table) + (puthash ?\" """ table) + (puthash ?' "'" table) + table) + "Hash table mapping character codes to their HTML entity equivalents.") + +;;;###autoload +(defun html-escape () + "HTML escape text in the current buffer. + +Perform HTML escaping on the text in the current buffer. If the region +is active then only escape the contents of the active region." + (declare (interactive-only t)) + (interactive) + (if (use-region-p) + (html-escape-region (region-bounds)) + (html-escape-region-1 (pos-bol) (pos-eol))) + (when (region-active-p) + (deactivate-mark))) + +(defun html-escape-region (bounds) + "HTML escape text in the current buffer within BOUNDS. + +BOUNDS takes the same form as the return value of `region-bounds'. This +function is prefered as it supports noncontiguous regions, but there also +exists `html-escape-region-1' with a simpler bounds interface." + (dolist (x bounds) (html-escape-region-1 (car x) (cdr x)))) + +(defun html-escape-region-1 (beg end) + "HTML escape text in the current buffer within BEG and END. + +This function is the same as the prefered `html-escape-region', but takes +BEG and END parameters instead of a BOUNDS parameter. For noncontiguous +region support use `html-escape-region'." + (save-restriction + (narrow-to-region beg end) + (save-excursion + (goto-char (point-min)) + (save-match-data + (while (re-search-forward "[&<>\"']" nil :noerror) + (let* ((char (char-after (match-beginning 0))) + (replacement (gethash char html-escape-table))) + (replace-match replacement))))))) + +(provide 'html-escape) diff --git a/.config/emacs-old/site-lisp/increment.el b/.config/emacs-old/site-lisp/increment.el new file mode 100644 index 0000000..b5bea53 --- /dev/null +++ b/.config/emacs-old/site-lisp/increment.el @@ -0,0 +1,132 @@ +;;; increment.el -- Increment numbers at point -*- lexical-binding: t; -*- + +(require 'cl-macs) +(require 'rx) + +(defvar increment--binary-number-regexp + (rx (group (or ?- word-start)) + "0b" + (group (* ?0)) + (group (+ (any "01"))) + word-end)) + +(defvar increment--octal-number-regexp + (rx (group (or ?- word-start)) + "0o" + (group (* ?0)) + (group (+ (any "0-7"))) + word-end)) + +(defvar increment--decimal-number-regexp + (rx (group (? ?-)) + (group (* ?0)) + (group (+ (any digit))))) + +(defvar increment--hexadecimal-number-regexp + (rx (group (or ?- word-start)) + "0x" + (group (* ?0)) + (group (+ (any hex-digit))) + word-end)) + +(defvar increment--hexadecimal-lower-number-regexp + (rx (group (or ?- word-start)) + "0o" + (group (* ?0)) + (group (+ (any "0-9a-f"))) + word-end)) + +(defvar increment--number-regexp + (rx (or (seq (or ?- word-start) + (or (seq "0b" (+ (any "01"))) + (seq "0o" (+ (any "0-7"))) + (seq "0x" (+ (any hex-digit)))) + word-end) + (seq (? ?-) (+ (any digit)))))) + +(defun increment--number-to-binary-string (number) + (nreverse + (cl-loop for x = number then (ash x -1) + while (not (= x 0)) + concat (if (= 0 (logand x 1)) "0" "1")))) + +(defun increment--format-number-with-base + (number base leading-zeros buffer-substr hex-style) + (let* ((neg (> 0 number)) + (number (abs number)) + (number-string + (pcase base + (2 (increment--number-to-binary-string number)) + (8 (format "%o" number)) + (10 (number-to-string number)) + (16 (format (if (eq hex-style 'lower) "%x" "%X") number)))) + (length-diff (- (length buffer-substr) + (length number-string))) + (leading-zeros (if (> leading-zeros 0) + (+ leading-zeros length-diff) + 0))) + (concat + (when neg + "-") + (pcase base + (2 "0b") + (8 "0o") + (16 "0x")) + (when (> leading-zeros 0) + (make-string leading-zeros ?0)) + number-string))) + +(defun increment--match-number-at-point () + (cond ((thing-at-point-looking-at + increment--binary-number-regexp) + (cons 2 nil)) + ((thing-at-point-looking-at + increment--octal-number-regexp) + (cons 8 nil)) + ((thing-at-point-looking-at + increment--hexadecimal-number-regexp) + (cons 16 nil)) + ((thing-at-point-looking-at + increment--hexadecimal-lower-number-regexp) + (cons 16 'lower)) + ((thing-at-point-looking-at + increment--decimal-number-regexp) + (cons 10 nil)))) + +;;;###autoload +(cl-defun increment-number-at-point (&optional arg) + "Increment the number at point by ARG or 1 if ARG is nil. If called +interactively, the universal argument can be used to specify ARG. If +the number at point has leading zeros then the width of the number is +preserved." + (interactive "*p") + (save-match-data + (let (case-fold-search + (match-pair (increment--match-number-at-point))) + (unless match-pair + (let ((save-point (point))) + (unless (re-search-forward + increment--number-regexp + (line-end-position) :noerror) + (goto-char save-point) + (cl-return-from increment-number-at-point)) + (setq match-pair (increment--match-number-at-point)))) + (let* ((base (car match-pair)) + (hex-style (cdr match-pair)) + (substr (buffer-substring-no-properties + (match-beginning 3) (match-end 3))) + (sign (if (= (match-beginning 1) (match-end 1)) +1 -1)) + (result (+ (* (string-to-number substr base) sign) + (or arg 1)))) + (replace-match + (increment--format-number-with-base + result base (- (match-end 2) (match-beginning 2)) + substr hex-style)))))) + +;;;###autoload +(defun decrement-number-at-point (&optional arg) + "The same as `increment-number-at-point', but ARG is negated." + (interactive "*p") + (increment-number-at-point (- (or arg 1)))) + +(provide 'increment) diff --git a/.config/emacs-old/site-lisp/line-selection-mode.el b/.config/emacs-old/site-lisp/line-selection-mode.el new file mode 100644 index 0000000..83da013 --- /dev/null +++ b/.config/emacs-old/site-lisp/line-selection-mode.el @@ -0,0 +1,18 @@ +;;; line-selection-mode.el --- Minor mode for selection by lines -*- lexical-binding: t; -*- + +(defvar-local line-selection-mode--cursor-type nil) + +;;;###autoload +(define-minor-mode line-selection-mode + "Enable `hl-line-mode' and hide the current cursor." + :global nil + :init-value nil + (if line-selection-mode + (progn + (hl-line-mode) + (setq line-selection-mode--cursor-type cursor-type) + (setq-local cursor-type nil)) + (hl-line-mode -1) + (setq-local cursor-type line-selection-mode--cursor-type))) + +(provide 'line-selection-mode) diff --git a/.config/emacs-old/site-lisp/live-jq.el b/.config/emacs-old/site-lisp/live-jq.el new file mode 100644 index 0000000..f8a0a7f --- /dev/null +++ b/.config/emacs-old/site-lisp/live-jq.el @@ -0,0 +1,101 @@ +;; TODO: ‘defcustom’ this +(defvar live-jq-major-mode + (cond ((fboundp #'json-ts-mode) #'json-ts-mode) + ((fboundp #'json-mode) #'json-mode)) + "TODO") + +(defvar live-jq--input-buffer nil + "The buffer containing the original JSON data.") + +(defvar live-jq--preview-buffer "*JQ Preview*" + "The buffer showing the live jq results.") + +(defvar live-jq--last-query "") + +(defun live-jq--get-json-input () + "Return the contents of the input buffer as a string." + (with-current-buffer live-jq--input-buffer + (buffer-substring-no-properties (point-min) (point-max)))) + +(defun live-jq--run-jq (query) + "Run jq QUERY on the input buffer's content and return result string or nil on error." + (let ((json-input (live-jq--get-json-input))) + (with-temp-buffer + (insert json-input) + (let ((exit-code (call-process-region + (point-min) (point-max) + "jq" :delete t nil "--tab" query))) + (when (zerop exit-code) + (buffer-string)))))) + +(defun live-jq--render-jq-preview (query) + "Update preview buffer with the result or error of jq QUERY." + (let* ((preview-buffer (get-buffer-create live-jq--preview-buffer)) + (json-input (live-jq--get-json-input)) + (inhibit-read-only t)) + (with-current-buffer preview-buffer + (erase-buffer) + (condition-case err + (with-temp-buffer + (insert json-input) + (let ((exit-code (call-process-region + (point-min) (point-max) + "jq" nil preview-buffer nil "--tab" query))) + (when (not (zerop exit-code)) + (erase-buffer) + (insert "%s\n%s" + (propertize (format "jq error (exit %d): %s" exit-code query) + 'face 'error) + json-input)))) + (error + (insert "%s\n%s" + (propertize (format "Error: %s" err) 'face 'error) + input-json))) + (goto-char (point-min)) + (when live-jq-major-mode + (funcall live-jq-major-mode)))) + (display-buffer live-jq--preview-buffer)) + +(defun live-jq--minibuffer-update () + "Update preview as user types." + (let ((query (minibuffer-contents))) + (unless (equal query live-jq--last-query) + (setq live-jq--last-query query) + (live-jq--render-jq-preview query)))) + +;;;###autoload +(defun live-jq () + "Prompt for a jq query, show live results, and replace buffer on confirmation." + (interactive) + (unless (executable-find "jq") + (user-error "`jq' not found in PATH.")) + + (setq live-jq--input-buffer (current-buffer)) + (setq live-jq--last-query "") + + ;; Clean up preview buffer if user cancels with C-g + (let ((minibuffer-setup-hook + (list (lambda () + ;; Add post-command-hook for live preview + (add-hook 'post-command-hook #'live-jq--minibuffer-update nil t) + ;; Add abort cleanup + (add-hook 'minibuffer-exit-hook + (lambda () + (when (get-buffer live-jq--preview-buffer) + (kill-buffer live-jq--preview-buffer))) + nil t))))) + (let ((query (read-from-minibuffer (format-prompt "Query" nil)))) + (unwind-protect + (let ((result (live-jq--run-jq query))) + (if result + (with-current-buffer live-jq--input-buffer + (let ((inhibit-read-only t)) + (erase-buffer) + (insert result)) + (message "jq applied.")) + (user-error "Invalid jq query: see *jq-preview* for details"))) + ;; Cleanup preview buffer after any outcome + (when (get-buffer live-jq--preview-buffer) + (kill-buffer live-jq--preview-buffer)))))) + +(provide 'live-jq) diff --git a/.config/emacs-old/site-lisp/number-format-mode.el b/.config/emacs-old/site-lisp/number-format-mode.el new file mode 100644 index 0000000..cbc5937 --- /dev/null +++ b/.config/emacs-old/site-lisp/number-format-mode.el @@ -0,0 +1,129 @@ +;;; number-format-mode.el --- Format numbers in the current buffer -*- lexical-binding: t; -*- + +(eval-when-compile + (require 'cl-macs) + (require 'seq)) + +(defgroup number-format nil + "Customization group for `number-format'." + :group 'convenience) ; TODO: Is this the right group? + +(defcustom number-format-separator "." + "Thousands separator to use in numeric literals." + :type 'string + :package-version '(number-format-mode . "1.0.0") + :group 'number-format) + +(defcustom number-format-predicate nil + "Function determining if a number should be formatted. +When formatting a number, this function is called with the START and END +range of the number in the buffer. If this function returns non-nil the +number is formatted. + +If this function is nil then all numbers are formatted." + :type 'function + :package-version '(number-format-mode . "1.0.0") + :group 'number-format) + +(defvar-local number-format--overlays (make-hash-table :test 'eq)) +(defconst number-format--regexp "\\b[0-9]\\{4,\\}\\b") + +(defun number-format--add-separators (s) + (while (string-match "\\(.*[0-9]\\)\\([0-9][0-9][0-9].*\\)" s) + (setq s (concat (match-string 1 s) + number-format-separator + (match-string 2 s)))) + s) + +(defun number-format--adjust-overlays (ov _1 beg end &optional _2) + (let* ((ov-beg (overlay-start ov)) + (ov-end (overlay-end ov)) + (overlays (overlays-in ov-beg ov-end))) + (mapcar #'delete-overlay (gethash ov number-format--overlays)) + (save-excursion + (goto-char ov-beg) + (if (looking-at number-format--regexp :inhibit-modify) + (puthash ov (number-format--at-range ov-beg ov-end) + number-format--overlays) + (delete-overlay ov) + (remhash ov number-format--overlays))))) + +(defun number-format--at-range (beg end) + (when (or (null number-format-predicate) + (funcall number-format-predicate beg end)) + (let* ((offsets [3 1 2]) + (len (- end beg)) + (off (aref offsets (mod len 3)))) + (goto-char (+ beg off))) + (let (overlays) + (while (< (point) end) + (let* ((group-end (+ (point) 3)) + (ov (make-overlay (point) group-end))) + (overlay-put ov 'before-string ".") + (overlay-put ov 'evaporate t) + (push ov overlays) + (goto-char group-end))) + overlays))) + +(defun number-format--jit-lock (beg end) + (let ((line-beg (save-excursion (goto-char beg) (line-beginning-position))) + (line-end (save-excursion (goto-char end) (line-end-position)))) + (number-unformat-region line-beg line-end) + (number-format-region line-beg line-end))) + +;;;###autoload +(defun number-format-region (beg end) + "Format numbers between BEG and END. +When called interactively, format numbers in the active region." + (interactive "r") + (save-excursion + (goto-char beg) + (save-restriction + (narrow-to-region beg end) + (number-unformat-region beg end) + (while (re-search-forward number-format--regexp nil :noerror) + (save-excursion + (cl-destructuring-bind (beg end) (match-data) + (let ((ov (make-overlay beg end nil nil :rear-advance))) + (overlay-put ov 'evaporate t) + (dolist (sym '(insert-behind-hooks + insert-in-front-hooks + modification-hooks)) + (overlay-put ov sym '(number-format--adjust-overlays))) + (puthash ov (number-format--at-range beg end) + number-format--overlays)))))))) + +;;;###autoload +(defun number-unformat-region (beg end) + "Unformat numbers between BEG and END. +When called interactively, unformat numbers in the active region." + (interactive "r") + (dolist (ov (overlays-in beg end)) + (when-let ((overlays (gethash ov number-format--overlays))) + (mapcar #'delete-overlay overlays) + (remhash ov number-format--overlays) + (delete-overlay ov)))) + +;;;###autoload +(defun number-format-buffer () + "Format numbers in the current buffer." + (interactive) + (number-format-region (point-min) (point-max))) + +;;;###autoload +(defun number-unformat-buffer () + "Unformat numbers in the current buffer." + (interactive) + (number-unformat-region (point-min) (point-max))) + +;;;###autoload +(define-minor-mode number-format-mode + "TODO" + :lighter " Number-Format" + :group 'number-format + (number-unformat-buffer) + (if number-format-mode + (jit-lock-register #'number-format--jit-lock) + (jit-lock-unregister #'number-format--jit-lock))) + +(provide 'number-format) \ No newline at end of file diff --git a/.config/emacs-old/site-lisp/surround.el b/.config/emacs-old/site-lisp/surround.el new file mode 100644 index 0000000..b5f679d --- /dev/null +++ b/.config/emacs-old/site-lisp/surround.el @@ -0,0 +1,122 @@ +;;; surround.el --- Surround a region with delimeters -*- lexical-binding: t; -*- + +(require 'cl-macs) + +(defgroup surround nil + "Customization group for `surround'." + :group 'convenience) + +(defcustom surround-with-paired-bracket-p t + "Surround text with paired brackets. +If non-nil surrounding text with a character (assuming that character is +not configured in `surround-pairs-alist') will attempt to surround the +text with the supplied character and its paired bracket. + +As an example, if `surround-with-paired-bracket-p' is non-nil and the +user attempts to surround the word “foo” with the character “「” the +result would be “「foo」”. + +Whether or not an opening- or closing bracket is provided is not +important; the opening bracket will always be placed at the front of the +region and the closing bracket at the end of the region (assuming +left-to-right writing). + +In more technical terms this function surrounds text with both the +provided character and the characters corresponding Bidi_Paired_Bracket +Unicode property." + :type 'boolean + :package-version '(surround . "1.0.0") + :group 'surround) + +(defcustom surround-with-mirror-p t + "Surround text with mirrored characters. +If non-nil surrounding text with a character (assuming that character is +not configured in `surround-pairs-alist') will attempt to surround the +text with the supplied character and its mirror. + +As an example, if `surround-with-mirror-p' is non-nil and the user +attempts to surround the word “foo” with the character “«” the result +would be “«foo»”. + +Note that unlike `surround-with-paired-bracket-p', because there is no +concept of an “opening” or “closing” bracket — because this option +doesn't work in terms of brackets — ordering matters. This means that +surrounding “Ελλάδα” with “«” will result in “«Ελλάδα»” while +surrounding “Österreich” with “»” will result in “»Österreich«”. + +In more technical terms this function surrounds text with both the +provided character and the characters corresponding Bidi_Mirroring_Glyph +Unicode property." + :type 'boolean + :package-version '(surround . "1.0.0") + :group 'surround) + +(defvar surround-pairs-alist '((emacs-lisp-mode + . ((?` ("`" . "'"))))) + "TODO") + +(defun surround--get-pair-from-alist (char) + (declare (ftype (function (char) (cons string string))) + (side-effect-free t)) + (catch 'surround--break + (let ((char-as-string (char-to-string char))) + (dolist (pair surround-pairs-alist) + (let ((mode-or-t (car pair)) + (pairs (cdr pair))) + (when (or (derived-mode-p mode-or-t) + (eq t mode-or-t)) + (dolist (pair pairs) + (let ((open-or-trigger (car pair)) + (closing-or-pair (cdr pair))) + (if (numberp open-or-trigger) ; Implies trigger + (when (= char open-or-trigger) + (throw 'surround--break (car closing-or-pair))) + (when (string= char-as-string open-or-trigger) + (throw 'surround--break pair))))))))))) + +(defun surround--get-pair (char) + (declare (ftype (function (char) (cons string string))) + (side-effect-free t)) + (or (surround--get-pair-from-alist char) + (let ((char (char-to-string char)) + (other (char-to-string + (or (when surround-with-paired-bracket-p + (get-char-code-property char 'paired-bracket)) + (when surround-with-mirror-p + (get-char-code-property char 'mirroring)) + char))) + (bracket-type (get-char-code-property char 'bracket-type))) + (pcase bracket-type + ((or 'c 'n) (cons other char)) + ('o (cons char other)))))) + +(defun surround--region (pair beginning end) + (save-excursion + (goto-char beginning) + (insert (car pair)) + (goto-char end) + (insert (cdr pair)))) + +(defun surround-region (char) + (interactive + (list (read-char-from-minibuffer + (format-prompt "Surround with" nil)))) + (when-let ((pair (surround--get-pair char))) + (dolist (bounds (cl-loop for (beginning . end) in (region-bounds) + collect (cons (set-marker (make-marker) beginning) + (set-marker (make-marker) end)))) + (surround--region pair (car bounds) (cdr bounds))))) + +(defun surround-padded-region (char) + (interactive + (list (read-char-from-minibuffer + (format-prompt "Surround with" nil)))) + (when-let ((pair (surround--get-pair char)) + (pair (cons (concat (car pair) " ") + (concat " " (cdr pair))))) + (dolist (bounds (cl-loop for (beginning . end) in (region-bounds) + collect (cons (set-marker (make-marker) beginning) + (set-marker (make-marker) end)))) + (surround--region pair (car bounds) (cdr bounds))))) + +(provide 'surround) diff --git a/.config/emacs-old/templates b/.config/emacs-old/templates new file mode 100644 index 0000000..ad4e97a --- /dev/null +++ b/.config/emacs-old/templates @@ -0,0 +1,38 @@ +;; NOTE: https://github.com/minad/tempel/issues/23 + +c-mode c-ts-mode c++-mode c++-ts-mode + +(guard + "#ifndef " + (p + (thread-last + (file-name-base (or (buffer-file-name) + (buffer-name))) + (concat (when-let ((project (project-current))) + (concat (project-name project) "_"))) + (upcase) + (string-replace "-" "_") + (replace-regexp-in-string "^[0-9]+" "_\\&") + (replace-regexp-in-string "[^A-Z0-9_]+" "") + (format "%s_H")) + header) + n + "#define " header n n r n n + "#endif /* !" header " */") + +emacs-lisp-mode + +(header + ";;; " (file-name-nondirectory (or (buffer-file-name) + (buffer-name))) + " --- " p " -*- lexical-binding: t; -*-" n n q) + +(section "\f" n ";;; " p n n q) + +vue-ts-mode + +(fcrow + > "
" + n> "" + n> q + n> "
") \ No newline at end of file diff --git a/.config/emacs/.gitignore b/.config/emacs/.gitignore deleted file mode 100644 index fb7fa52..0000000 --- a/.config/emacs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ --*.el -custom.el diff --git a/.config/emacs/combobulate-c.el b/.config/emacs/combobulate-c.el deleted file mode 100644 index 5ac844d..0000000 --- a/.config/emacs/combobulate-c.el +++ /dev/null @@ -1,25 +0,0 @@ -;;; combobulate-c.el --- C support for combobulate -*- lexical-binding: t; -*- - -(require 'combobulate-manipulation) -(require 'combobulate-navigation) -(require 'combobulate-rules) -(require 'combobulate-settings) -(require 'combobulate-setup) - -(eval-and-compile - (defvar combobulate-c-definitions - '((context-nodes - '("char_literal" "false" "field_identifier" "identifier" "null" - "number_literal" "statement_identifier" "string_literal" "true" - "type_identifier"))))) - -(define-combobulate-language - :name c - :language c - :major-modes (c-ts-mode) - :custom combobulate-c-definitions - :setup-fn combobulate-c-setup) - -(defun combobulate-c-setup (_)) - -(provide 'combobulate-c) diff --git a/.config/emacs/early-init.el b/.config/emacs/early-init.el deleted file mode 100644 index ccae20b..0000000 --- a/.config/emacs/early-init.el +++ /dev/null @@ -1,105 +0,0 @@ -;;; early-init.el --- Emacs early init file -*- lexical-binding: t; -*- - -;;; XDG Base Directory Specification Compliance - -(eval-when-compile - (require 'xdg)) - -(defconst mm-cache-directory - (expand-file-name "emacs" (xdg-cache-home)) - "The XDG-conformant cache directory that Emacs should use.") - -(defconst mm-config-directory - (expand-file-name "emacs" (xdg-config-home)) - "The XDG-conformant config directory that Emacs should use.") - -(defconst mm-data-directory - (expand-file-name "emacs" (xdg-data-home)) - "The XDG-conformant data directory that Emacs should use.") - -(mapc (lambda (directory) - (make-directory directory :parents)) - (list mm-cache-directory mm-config-directory mm-data-directory)) - -(setopt user-emacs-directory mm-cache-directory - auto-save-list-file-prefix (expand-file-name - "auto-save-list-" - mm-cache-directory) - backup-directory-alist `(("." . ,(expand-file-name - "backups" mm-cache-directory)))) -(when (native-comp-available-p) - (startup-redirect-eln-cache - (expand-file-name (expand-file-name "eln/" mm-cache-directory)))) - - -;;; Useful Constants - -(defconst mm-darwin-p (eq system-type 'darwin) - "This variable is non-nil if Emacs is running on a Darwin system.") - -(defconst mm-humanwave-p (file-exists-p "~/.humanwavep") - "This variable is non-nil if Emacs is running on a Humanwave system.") - - -;;; Basic Frame Settings - -(setopt frame-resize-pixelwise t - frame-inhibit-implied-resize t - ring-bell-function #'ignore - use-short-answers t - inhibit-splash-screen t - inhibit-startup-buffer-menu t) -(if mm-darwin-p - (progn - (add-to-list 'default-frame-alist '(fullscreen . maximized)) - (when (featurep 'ns) - (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)))) - (add-to-list 'default-frame-alist '(undecorated . t)) - (menu-bar-mode -1)) -(scroll-bar-mode -1) -(tool-bar-mode -1) - - -;;; Startup Performance - -(setopt gc-cons-threshold most-positive-fixnum - gc-cons-percentage 0.5) -(setopt read-process-output-max - (let ((pipe-size-file "/proc/sys/fs/pipe-max-size")) - (if (file-exists-p pipe-size-file) - (with-temp-buffer - (insert-file-contents pipe-size-file) - (number-at-point)) - (* 1024 1024)))) - -;; Set ‘file-name-handler-alist’ and ‘vc-handled-backends’ to nil -;; temporarily and restore them once Emacs has properly initialized. We -;; set threshold to 8 MiB which seems to be a good middleground for now. -;; A higher threshold means less garbage collections but I’ve had issues -;; with those garbage collections causing long freezes when they occur. -(let ((saved-file-name-handler-alist file-name-handler-alist)) - (setopt file-name-handler-alist nil) - (add-hook - 'emacs-startup-hook - (defun mm-restore-emacs-settings () - (setopt gc-cons-threshold (* 1024 1024 8) - gc-cons-percentage 0.1 - file-name-handler-alist saved-file-name-handler-alist)))) - - -;;; Avoid Flashbang - -(setq-default mode-line-format nil) ; This will be set in init.el - -;; Colors taken from ‘mango-theme’ -(let ((background "#2B303B") - (foreground "#C5C8C6")) - (set-face-attribute - 'default nil - :background background - :foreground foreground) - (set-face-attribute - 'mode-line nil - :background background - :foreground foreground - :box 'unspecified)) diff --git a/.config/emacs/editing.el b/.config/emacs/editing.el deleted file mode 100644 index 0b96867..0000000 --- a/.config/emacs/editing.el +++ /dev/null @@ -1,271 +0,0 @@ -;;; editing.el --- Text editing commands -*- lexical-binding: t; -*- - -(defun e/align-regexp (regexp repeat) - "Align the marked region on REGEXP. -When called interactively REGEXP is read from the minibuffer and the -user is prompted about whether they would like to REPEAT the alignment. - -This function wraps `align-regexp' and implicitly prepends REGEXP with -\"\\(\\s-*\\)\"." - (interactive - (progn (barf-if-buffer-read-only) - (list (concat "\\(\\s-*\\)" - (read-string - (format-prompt "Align regexp" nil))) - (y-or-n-p "Repeat?")))) - (let ((start (min (mark) (point))) - (end (max (mark) (point)))) - (align-regexp start end regexp 1 1 repeat))) - -(defun e/join-current-and-next-line (&optional arg beg end) - "Join the current- and next lines. -This function is identical to `join-line' but it joins the current line -with the next one instead of the previous one." - (interactive - (progn (barf-if-buffer-read-only) - (cons current-prefix-arg - (and (use-region-p) - (list (region-beginning) (region-end)))))) - (delete-indentation - (unless (or beg end) (not arg)) - beg end)) - -(defun e/mark-entire-word (&optional arg allow-extend) - "Mark ARG words beginning at point. -This command is a wrapper around `mark-word' that moves the point such -that the word under point is entirely marked. ARG and ALLOW-EXTEND are -just as they are with `mark-word.'" - (interactive "P\np") - (if (eq last-command this-command) - (mark-word arg allow-extend) - (let ((bounds (bounds-of-thing-at-point 'word)) - (numeric-arg (or allow-extend 0))) - (if bounds - (goto-char (if (< numeric-arg 0) - (cdr bounds) - (car bounds))) - (forward-to-word (when (< numeric-arg 0) -1)))) - (mark-word arg allow-extend))) - -(defun e/mark-entire-sexp (&optional arg allow-extend) - "Mark ARG sexps beginning at point. -This command is a wrapper around `mark-sexp' that moves the point such -that the sexp under point is entirely marked. ARG and ALLOW-EXTEND are -just as they are with `mark-sexp.'" - (interactive "P\np") - (if (eq last-command this-command) - (mark-sexp arg allow-extend) - (let ((bounds (bounds-of-thing-at-point 'sexp)) - (numeric-arg allow-extend)) - (if bounds - (goto-char (if (< numeric-arg 0) - (cdr bounds) - (car bounds))) - (if (< numeric-arg 0) - (progn - (backward-sexp) - (forward-sexp)) - (forward-sexp) - (backward-sexp)))) - (mark-sexp arg allow-extend))) - -(defun e/mark-line-dwim (&optional arg) - "Mark ARG lines beginning at point. -If the region is active then it is extended by ARG lines. If called -without a prefix argument this command marks one line forwards unless -point is ahead of the mark in which case this command marks one line -backwards. - -If this function is called with a negative prefix argument and no region -active, the current line is marked." - (interactive "P") - (let ((numeric-arg (prefix-numeric-value arg))) - (if (region-active-p) - (progn - (exchange-point-and-mark) - (goto-char (1+ (pos-eol (if arg numeric-arg - (when (< (point) (mark)) -1))))) - (exchange-point-and-mark)) - (if (< numeric-arg 0) - (progn - (push-mark (pos-bol (+ 2 numeric-arg)) nil :activate) - (goto-char (1+ (pos-eol)))) - (push-mark (1+ (pos-eol numeric-arg)) nil :activate) - (goto-char (pos-bol)))))) - -(defun e/kill-ring-save-dwim () - "Save the region as if killed, but don't kill it. -This function is the same as `kill-ring-save' in Transient Mark mode, -but when there is no active region it saves the line at point to the kill -ring excluding any potential trailing newline." - (interactive) - (if (region-active-p) - (kill-ring-save -1 -1 :region) - (kill-ring-save (pos-bol) (pos-eol)))) - -(defun e/scroll-down () - "Scroll down one page. -This function is identical to `cua-scroll-down' except it recenters the -screeen after scrolling. If the user scrolls to the top of the document -then no recentering occurs." - (interactive) - (let ((line-number (line-number-at-pos))) - (cua-scroll-down) - (when (= line-number (line-number-at-pos)) - (goto-char (point-min))) - (recenter))) - -(defun e/scroll-up () - "Scroll up one page. -This function is identical to `cua-scroll-up' except it recenters the -screen after scrolling." - (interactive) - (mm-do-and-center #'cua-scroll-up)) - -(defun e/open-line (arg) - "Insert and move to a new empty line after point. -With prefix argument ARG, inserts and moves to a new empty line before -point." - (interactive "*P") - (end-of-line) - (newline-and-indent) - (when arg - (transpose-lines 1) - (previous-line 2) - (end-of-line))) - -(defun e/split-line (&optional above) - "Split the line at point. -Place the contents after point on a new line, indenting the new line -according to the current major mode. With prefix argument ABOVE the -contents after point are placed on a new line before point." - (interactive "*P") - (save-excursion - (let* ((start (point)) - (end (pos-eol)) - (string (buffer-substring start end))) - (delete-region start end) - (when above - (goto-char (1- (pos-bol)))) - (newline) - (insert string) - (indent-according-to-mode)))) - -(defun e/mc/sort-regions (&optional reverse) - "Sort marked regions. -This command is an exact replica of `mc/sort-regions' except that -calling this command with a prefix argument REVERSE sorts the marked -regions in reverse order." - (interactive "*P") - (unless (use-region-p) - (user-error "No active region.")) - (setq mc--strings-to-replace (sort (mc--ordered-region-strings) - (if reverse #'string> #'string<))) - (mc--replace-region-strings)) - -(defun e/sort-dwim (&optional reverse) - "Sort regions do-what-i-mean. -When multiple cursors are not being used this command functions just -like `sort-lines' with the start- and end bounds set to the current -region beginning and -end. - -When using multiple cursors this command sorts the regions marked by -each cursor (effectively calling `e/mc/sort-regions'. - -When called with a prefix argument REVERSE, sorting occurs in reverse -order." - (interactive "*P") - (if (and (fboundp #'mc/num-cursors) - (< 1 (mc/num-cursors))) - (e/mc/sort-regions reverse) - (sort-lines reverse (region-beginning) (region-end)))) - -(defun e/yank (&optional arg) - "Yank text from the kill-ring. -Yank the most recent kill from the kill ring via `yank'. If called with -prefix argument ARG then interactively yank from the kill ring via -`yank-from-kill-ring'. - -If `consult' is available than this command instead calls -`consult-yank-from-kill-ring' when called with non-nil ARG." - (declare (interactive-only t)) - (interactive "*P") - ;; Avoid ‘current-prefix-arg’ cascading down to ‘yank-from-kill-ring’ - (let (current-prefix-arg) - (cond ((null arg) - (yank)) - ((featurep 'consult) - (call-interactively #'consult-yank-from-kill-ring)) - (t - (call-interactively #'yank-from-kill-ring))))) - -(defun mm-search-forward-char (char &optional n) - "Search forwards to the Nth occurance of CHAR. -If called interactively CHAR is read from the minibuffer and N is given -by the prefix argument. - -If N is negative then this function searches backwards. - -When searching forwards point is left before CHAR while when searching -backwards point is left after CHAR." - (interactive - (list (read-char) - (prefix-numeric-value current-prefix-arg))) - (when (and (> n 0) (= char (char-after (point)))) - (forward-char)) - (search-forward (char-to-string char) nil nil n) - (when (> n 0) - (backward-char))) - -(defun mm-search-backward-char (char &optional n) - "Search backwards to the Nth occurance of CHAR. -This function is identical to `mm-search-forward-char' with N negated." - (declare (interactive-only t)) - (interactive - (list (read-char) - (prefix-numeric-value current-prefix-arg))) - (mm-search-forward-char char (- n))) - -(defun mm-add-cursor-to-next-thing (thing) - "Add a fake cursor to the next occurance of THING. -THING is any symbol that can be given to ‘bounds-of-thing-at-point’. - -If there is an active region, the next THING will be marked." - (let ((bounds (bounds-of-thing-at-point thing))) - (if (null bounds) - (progn - (forward-thing thing) - (goto-char (car (bounds-of-thing-at-point thing)))) - (mc/save-excursion - (when (> (mc/num-cursors) 1) - (goto-char (overlay-end (mc/furthest-cursor-after-point)))) - (goto-char (cdr (bounds-of-thing-at-point thing))) - (forward-thing thing) - (let ((bounds (bounds-of-thing-at-point thing))) - (goto-char (car bounds)) - (when (use-region-p) - (push-mark (cdr bounds))) - (mc/create-fake-cursor-at-point)))))) - -(defun mm-add-cursor-to-next-word () - "Add a fake cursor to the next word." - (declare (interactive-only t)) - (interactive) - (mm-add-cursor-to-next-thing 'word) - (mc/maybe-multiple-cursors-mode)) - -(defun mm-transpose-cursor-regions (n) - "Interchange the regions of each cursor. -With prefix arg N, the regions are rotated N places (backwards if N is -negative)." - (interactive "p") - (when (= (mc/num-cursors) 1) - (user-error "Cannot transpose with only one cursor.")) - (unless (use-region-p) - (user-error "No active region.")) - (setq mc--strings-to-replace - (funcall (if (< n 0) #'mm-rotate-left #'mm-rotate-right) - (abs n) (mc--ordered-region-strings))) - (mc--replace-region-strings)) - -(provide 'editing) diff --git a/.config/emacs/init.el b/.config/emacs/init.el deleted file mode 100644 index 0bda7f6..0000000 --- a/.config/emacs/init.el +++ /dev/null @@ -1,358 +0,0 @@ -;;; init.el --- Main Emacs configuration file -*- lexical-binding: t; -*- - -;;; Preamble - -;; To inhibit this message you must do this in init.el (not -;; early-init.el!), you must use ‘setq’ (not ‘setopt’!), and you must -;; write your login name as a string (you shan’t use ‘user-login-name’!). -;; Lord knows why this needs to be so complicated… -;; -;; The ‘eval’ is required in the case that this file is byte-compiled. -(if mm-humanwave-p - (eval '(setq inhibit-startup-echo-area-message "thomasvoss")) - (eval '(setq inhibit-startup-echo-area-message "thomas"))) - -;; Add all my custom lisp code into the load path -(dolist (directory - (list mm-config-directory - (expand-file-name "modules" mm-config-directory) - (expand-file-name "site-lisp" mm-config-directory))) - (add-to-list 'load-path directory)) - - -;;; Disable or Enable LSP? - -;; I’m not decided on LSP… so make it a variable - -(defvar mm-lsp-p nil - "Enable LSP support if non-nil.") - - -;;; Convenience Macros and -Functions - -(defun mm-mode-to-hook (mode) - "Get the hook corresponding to MODE." - (declare (ftype (function (symbol) symbol)) - (pure t) (side-effect-free t)) - (intern (concat (symbol-name mode) "-hook"))) - -(defun mm-mode-to-ts-mode (mode) - "Get the Tree-Sitter mode corresponding to MODE." - (declare (ftype (function (symbol) symbol)) - (pure t) (side-effect-free t)) - (intern (concat - (string-remove-suffix "-mode" (symbol-name mode)) - "-ts-mode"))) - -(defun mm-ts-mode-to-mode (ts-mode) - "Get the non-Tree-Sitter mode corresponding to TS-MODE." - (declare (ftype (function (symbol) symbol)) - (pure t) (side-effect-free t)) - (intern (concat - (string-remove-suffix "-ts-mode" (symbol-name ts-mode)) - "-mode"))) - -(defsubst mm-string-split (separators string) - "Split STRING on SEPARATORS. -Wrapper around `string-split' that puts separators first. This makes it -convenient to use in `thread-last'." - (declare (ftype (function (string string) (list string))) - (pure t) (side-effect-free t)) - (string-split string separators)) - -(defun mm-as-number (string-or-number) - "Ensure STRING-OR-NUMBER is a number. -If given a number return STRING-OR-NUMBER as-is, otherwise convert it to -a number and then return it. - -This function is meant to be used in conjuction with `read-string' and -`format-prompt'." - (declare (ftype (function (or string number) number)) - (pure t) (side-effect-free t)) - (if (stringp string-or-number) - (string-to-number string-or-number) - string-or-number)) - -(defun mm-camel-to-lisp (string) - "Convert STRING from camelCase to lisp-case." - (declare (ftype (function (string) string)) - (pure t) (side-effect-free t)) - (let ((case-fold-search nil)) - (downcase - (replace-regexp-in-string - (rx (group (or lower digit)) (group upper)) "\\1-\\2" string)))) - -(defun mm-do-and-center (function &rest arguments) - "Call FUNCTION with ARGUMENTS and then center the screen." - (apply function arguments) - (when (called-interactively-p) - (recenter))) - -(defmacro mm-comment (&rest _body) - "Comment out BODY. A cleaner alternative to line-commenting a region." - (declare (indent 0)) - nil) - -(defun mm-nil (&rest _) - "Return nil." - nil) - -(defmacro mm-with-suppressed-output (&rest body) - "Execute BODY while suppressing output. -Execute BODY as given with all output to the echo area or the *Messages* -buffer suppressed." - (declare (indent 0)) - `(let ((inhibit-message t) - (message-log-max nil)) - ,@body)) - -(defun mm-rotate-left (n list) - "Rotate the elements of LIST N places to the left." - (declare (ftype (function (number (list t)) (list t))) - (pure t) (side-effect-free t)) - (append (nthcdr n list) (butlast list (- (length list) n)))) - -(defun mm-rotate-right (n list) - "Rotate the elements of LIST N places to the right." - (declare (ftype (function (number (list t)) (list t))) - (pure t) (side-effect-free t)) - (mm-rotate-left (- (length list) n) list)) - - -;;; Silent Native Compilation - -(when (native-comp-available-p) - (setopt - native-comp-async-report-warnings-errors nil - native-compile-prune-cache t)) - - -;;; Package Management - -(setopt - package-vc-register-as-project nil - package-user-dir (expand-file-name "pkg" mm-data-directory) - package-gnupghome-dir (or (getenv "GNUPGHOME") - (expand-file-name "gnupg" package-user-dir)) - package-archives (cl-loop with proto = (if (gnutls-available-p) "https" "http") - for (name . url) in - '(("gnu" . "elpa.gnu.org/packages/") - ("melpa" . "melpa.org/packages/") - ("nongnu" . "elpa.nongnu.org/nongnu/")) - collect (cons name (concat proto "://" url))) - package-archive-priorities '(("gnu" . 3) - ("nongnu" . 2) - ("melpa" . 1))) -(setopt use-package-always-defer t) - -(package-initialize) - -(defun mm-package-sync () - "Remove unused packages and install missing ones." - (interactive) - (let ((window-configuration (current-window-configuration))) - (package-autoremove) - (package-install-selected-packages) - (package-upgrade-all) - (package-vc-install-selected-packages) - (package-vc-upgrade-all) - (set-window-configuration window-configuration)) - (message "Done syncing packages.")) - - -;;; Generic Emacs Configuration - -(defvar mm-initial-scratch-message - (substitute-quotes - (format - ";; This is `%s'. Use `%s' to evaluate and print results.\n\n" - initial-major-mode - (substitute-command-keys - "\\\\[eval-print-last-sexp]"))) - "The initial message to display in the scratch buffer.") - -(use-package emacs - :demand t - :custom - (ad-redefinition-action 'accept) - (case-fold-search nil) - (create-lockfiles nil) - (custom-file (expand-file-name "custom.el" mm-config-directory)) - (custom-safe-themes t) - (delete-pair-blink-delay 0) - (disabled-command-function nil) - (duplicate-line-final-position -1) - (duplicate-region-final-position -1) - (echo-keystrokes 0.01) ; 0 disables echoing - (echo-keystrokes-help nil) - (extended-command-suggest-shorter nil) - (initial-buffer-choice nil) - (initial-scratch-message mm-initial-scratch-message) - (kill-do-not-save-duplicates t) - (large-file-warning-threshold nil) - (make-backup-files nil) - (mode-require-final-newline t) - (next-error-recenter '(4)) ; ‘center of window’ - (read-extended-command-predicate #'command-completion-default-include-p) - (remote-file-name-inhibit-auto-save t) - (remote-file-name-inhibit-delete-by-moving-to-trash t) - (require-final-newline mm-humanwave-p) - (save-interprogram-paste-before-kill t) - (user-full-name "Thomas Voss") - (user-mail-address "mail@thomasvoss.com") - :config - (load custom-file :noerror) - (setq-default fill-column 80) - (dolist (mode '(text-mode emacs-lisp-mode lisp-mode)) - (add-hook (mm-mode-to-hook mode) - (defun mm-set-fill-column () - (setq-local fill-column 73)))) - (add-hook 'text-mode-hook #'auto-fill-mode) - (add-hook 'before-save-hook - (defun mm-delete-final-newline () - (let ((end (point-max))) - (unless (or require-final-newline - mode-require-final-newline - (not (= (char-before end) ?\n))) - (delete-region (1- end) end))))) - (add-hook 'before-save-hook #'delete-trailing-whitespace) - (prefer-coding-system 'utf-8) - - ;; Disabled modes - (blink-cursor-mode -1) - (line-number-mode -1) - (tooltip-mode -1)) - - -;;; Instantly highlight matching parens - -(use-package paren - :custom - (show-paren-delay 0)) - - -;;; Auto Revert Buffers - -(use-package autorevert - :custom - (global-auto-revert-non-file-buffers t) - :init - (add-hook - 'after-change-major-mode-hook - (defun mm-enable-autorevert () - (unless (derived-mode-p 'Buffer-menu-mode) - (auto-revert-mode))))) - - -;;; Bookmarks - -(use-package bookmark - :custom - (bookmark-save-flag 1)) - - -;;; Automatically Create- and Delete Directories - -(defun mm-auto-create-directories (function filename &rest arguments) - "Automatically create and delete parent directories of files. -This is an `:override' advice for `find-file' and friends. It -automatically creates the parent directories of the file being visited -if necessary. It also sets a buffer-local variable so that the user -will be prompted to delete the newly created directories if they kill -the buffer without saving it." - (let (dirs-to-delete) - (let* ((dir-to-create (file-name-directory filename)) - (current-dir dir-to-create)) - ;; Add each directory component to ‘dirs-to-delete’ - (while (not (file-exists-p current-dir)) - (push current-dir dirs-to-delete) - (setq current-dir (file-name-directory - (directory-file-name current-dir)))) - (unless (file-exists-p dir-to-create) - (make-directory dir-to-create :parents))) - (prog1 - (apply function filename arguments) - (when dirs-to-delete - (setq-local mm-find-file--dirs-to-delete (reverse dirs-to-delete)) - (add-hook 'kill-buffer-hook #'mm-find-file--maybe-delete-directories - :depth :local) - (add-hook 'after-save-hook #'mm-find-file--remove-hooks - :depth :local))))) - -(defun mm-find-file--maybe-delete-directories () - (unless (file-exists-p buffer-file-name) - (dolist (directory mm-find-file--dirs-to-delete) - (when (and (stringp directory) - (file-exists-p directory) - (thread-last - (directory-file-name directory) - (format "Also delete directory `%s'?") - (substitute-quotes) - (y-or-n-p))) - (delete-directory directory))))) - -(defun mm-find-file--remove-hooks () - (remove-hook 'kill-buffer-hook - #'mm-find-file--maybe-delete-directories - :local) - (remove-hook 'after-save-hook - #'mm-find-file--remove-hooks - :local)) - -(dolist (command #'(find-file find-alternate-file write-file)) - (advice-add command :around #'mm-auto-create-directories)) - - -;;; Load Modules - -(require 'mm-abbrev) ; Text Expansion -(require 'mm-buffer-menu) ; Buffer Menu -(require 'mm-calc) ; Emacs Calc -(require 'mm-completion) ; Completions -(require 'mm-dired) ; Dired -(require 'mm-documentation) ; Documentation -(require 'mm-editing) ; Text Editing -(require 'mm-keybindings) ; Keybindings -(require 'mm-modeline) ; Modeline -(require 'mm-org) ; Org-Mode -(require 'mm-projects) ; Project Management -(require 'mm-search) ; Text Searching -(require 'mm-spellcheck) ; Spell Checking -(require 'mm-tetris) ; Emacs Tetris -(require 'mm-theme) ; Themeing -(require 'mm-treesit) ; Tree-Sitter -(require 'mm-window) ; Windowing -(when mm-darwin-p - (require 'mm-darwin)) ; MacOS -(when mm-lsp-p - (require 'mm-lsp)) ; Language Server Protocol -(when mm-humanwave-p - (require 'mm-humanwave)) ; Humanwave Extras - -;; TODO: Put this somewhere reasonable - -(defvar mm-placeholder-text "‹XX›") - -(defun mm-placeholder-insert () - (interactive) - (insert mm-placeholder-text)) - -(defun mm-placeholder-next () - (interactive) - (let ((point (point))) - (if (search-forward mm-placeholder-text nil :noerror) - (delete-region (match-beginning 0) (match-end 0)) - (goto-char point) - (message "No more placeholders after point.")))) - -(keymap-global-set "C-c i p" #'mm-placeholder-insert) -(keymap-global-set "C-c n" #'mm-placeholder-next) - - - -;;; Postamble - -(add-hook 'after-init-hook - (defun mm-echo-init-time () - (message (emacs-init-time "Emacs initialized in %.2f seconds"))) - 100) diff --git a/.config/emacs/mango-light-theme.el b/.config/emacs/mango-light-theme.el deleted file mode 100644 index 4cbda4f..0000000 --- a/.config/emacs/mango-light-theme.el +++ /dev/null @@ -1,347 +0,0 @@ -;;; mango-light-theme.el --- Just your average light theme -*- lexical-binding: t; -*- - -(deftheme mango-light - "Mildly light, light theme. -Your average not-so-light light theme, because none of the other options -were exactly to my liking. It’s about time I had a theme to call my -own.") - -;; Colors are defined as: (GUI-HEX 256-COLOR 16-COLOR) -(defconst mango-light-theme-colors-alist - '(;; (foreground . ("#3B4252" "color-238" "black")) - ;; (background . ("#ECEFF4" "color-255" "white")) - ;; (background-cool . ("#E5E9F0" "color-254" "white")) - ;; (background-dark . ("#FAFBFC" "color-231" "brightwhite")) - ;; (background-faint . ("#D8DEE9" "color-253" "brightwhite")) - ;; (middleground . ("#C8D0E0" "color-252" "brightwhite")) - (disabled . ("#9BA6B5" "color-247" "brightblack")) - (foreground . ("#000000" "color-0" "black")) - (background . ("#ffffff" "color-0" "black")) - (middleground . ("#c4c4c4" "color-0" "black")) - (background-cool . ("#e0e0e0" "color-0" "black")) - ;; TODO: Rename to foreground-light - (background-dark . ("#595959" "color-0" "black")) - (background-faint . ("#e6e6e6" "color-0" "black")) - - (celestial-blue . ("#1B61CE" "color-26" "blue")) - (dark-red . ("#A12027" "color-124" "red")) - (khaki . ("#8A6C23" "color-94" "yellow")) - (lime . ("#358A2A" "color-28" "green")) - (magenta . ("#9A35B3" "color-127" "magenta")) - (pale-azure . ("#0A74B8" "color-31" "cyan")) - (red . ("#D22129" "color-160" "brightred")) - (salmon . ("#D1570B" "color-166" "brightyellow")) - (violet . ("#7A3B9E" "color-97" "magenta"))) - "The color palette used throughout `mango-light-theme'. -Each color is mapped to a list of colors of the form -(GUI-HEX 256-COLOR 16-COLOR) for use in true-color, 256-color, and -16-color modes.") - -(defsubst mango-light-theme-color (name &optional display) - "Get the color value of NAME for the given DISPLAY. -DISPLAY can be 'gui, '256, or '16." - (let ((colors (alist-get name mango-light-theme-colors-alist))) - (pcase display - ('gui (nth 0 colors)) - ('256 (nth 1 colors)) - ('16 (nth 2 colors)) - (_ (nth 0 colors))))) - -(custom-theme-set-faces - 'mango-light - - ;; Standard Stuff - `(default - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'foreground 'gui) - :background ,(mango-light-theme-color 'background 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'foreground '256) - :background ,(mango-light-theme-color 'background '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'foreground '16) - :background ,(mango-light-theme-color 'background '16))))) - `(fringe - ((t (:inherit default)))) - - ;; Lines - `(hl-line - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'background-faint 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'background-faint '256))) - (((type tty)) - (:background ,(mango-light-theme-color 'background-faint '16))))) - `(region - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'middleground '256))) - (((type tty)) - (:background ,(mango-light-theme-color 'middleground '16))))) - `(header-line - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'middleground '256))) - (((type tty)) - (:background ,(mango-light-theme-color 'middleground '16))))) - `(mode-line-active - ((t ( :box ,(mango-light-theme-color 'celestial-blue 'gui) - :inherit header-line)))) - `(mode-line-inactive - ((((type graphic tty) (min-colors 16777216)) - ( :background ,(mango-light-theme-color 'background-cool 'gui) - :box ,(mango-light-theme-color 'background-faint 'gui) - :weight light)) - (((type tty) (min-colors 256)) - ( :background ,(mango-light-theme-color 'background-cool '256) - :box ,(mango-light-theme-color 'background-faint 'gui) - :weight light)) - (((type tty)) - ( :background ,(mango-light-theme-color 'background-cool '16) - :box ,(mango-light-theme-color 'background-faint 'gui) - :weight light)))) - `(window-divider - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'background-cool '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'background-cool '16))))) - `(window-divider-first-pixel - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'background-cool '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'background-cool '16))))) - `(window-divider-last-pixel - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'background-cool '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'background-cool '16))))) - - ;; Line Numbers - `(line-number - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'disabled 'gui) - :background ,(mango-light-theme-color 'background 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'disabled '256) - :background ,(mango-light-theme-color 'background '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'disabled '16) - :background ,(mango-light-theme-color 'background '16))))) - `(line-number-current-line - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'salmon 'gui) - :background ,(mango-light-theme-color 'background 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'salmon '256) - :background ,(mango-light-theme-color 'background '256) :weight bold)) - (((type tty)) - (:foreground ,(mango-light-theme-color 'salmon '16) - :background ,(mango-light-theme-color 'background '16) :weight bold)))) - - ;; Documentation - `(font-lock-comment-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'khaki 'gui) :weight semi-bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'khaki '256) :weight semi-bold)) - (((type tty)) - (:foreground ,(mango-light-theme-color 'khaki '16) :weight semi-bold)))) - `(font-lock-doc-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'disabled 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'disabled '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'disabled '16))))) - - ;; Modeline - `(mm-modeline-overwrite-face ((t (:weight normal)))) - `(mm-modeline-readonly-face ((t (:weight normal)))) - `(mm-modeline-buffer-name-face ((t (:inherit font-lock-constant-face)))) - `(mm-modeline-buffer-modified-face ((t (:inherit shadow)))) - `(mm-modeline-major-mode-name-face ((t (:weight normal)))) - `(mm-modeline-major-mode-symbol-face ((t (:inherit shadow)))) - `(mm-modeline-git-branch-face ((t (:inherit font-lock-constant-face)))) - `(mm-modeline-narrow-face - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'dark-red 'gui) :foreground ,(mango-light-theme-color 'background-dark 'gui) :box ,(mango-light-theme-color 'dark-red 'gui) :weight normal)) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'dark-red '256) :foreground ,(mango-light-theme-color 'background-dark '256) :box ,(mango-light-theme-color 'dark-red '256) :weight normal)) - (((type tty)) - (:background ,(mango-light-theme-color 'dark-red '16) :foreground ,(mango-light-theme-color 'background-dark '16) :box ,(mango-light-theme-color 'dark-red '16) :weight normal)))) - - ;; Core Language - `(font-lock-builtin-face ((t (:inherit font-lock-preprocessor-face)))) - `(font-lock-keyword-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'violet 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'violet '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'violet '16))))) - `(font-lock-type-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'celestial-blue 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'celestial-blue '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'celestial-blue '16))))) - - ;; Function-likes - `(font-lock-function-name-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'khaki 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'khaki '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'khaki '16))))) - `(font-lock-preprocessor-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'magenta 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'magenta '256) :weight bold)) - (((type tty)) - (:foreground ,(mango-light-theme-color 'magenta '16) :weight bold)))) - - ;; Variables - `(font-lock-constant-face ((t (:inherit font-lock-variable-name-face :weight bold)))) - `(font-lock-variable-name-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'pale-azure 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'pale-azure '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'pale-azure '16))))) - - ;; Other literals - `(help-key-binding ((t (:inherit font-lock-constant-face)))) - `(font-lock-string-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'salmon 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'salmon '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'salmon '16))))) - `(font-lock-number-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'salmon 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'salmon '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'salmon '16))))) - - ;; Org Mode - `(org-quote ((t (:inherit org-block :slant italic)))) - `(org-code - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'salmon 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'salmon '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'salmon '16))))) - `(org-verbatim - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'lime 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'lime '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'lime '16))))) - `(org-block - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'background-cool '256))) - (((type tty)) - (:background ,(mango-light-theme-color 'background-cool '16))))) - `(org-hide - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'background 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'background '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'background '16))))) - - ;; Info Page - `(Info-quoted ((t (:inherit default)))) - - ;; Magit - `(magit-diff-context-highlight ((t (:inherit hl-line)))) - `(magit-section-highlight ((t (:inherit hl-line)))) - `(magit-diff-hunk-heading - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'background-cool '256))) - (((type tty)) - (:background ,(mango-light-theme-color 'background-cool '16))))) - `(magit-diff-hunk-heading-highlight - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-light-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-light-theme-color 'middleground '256))) - (((type tty)) - (:background ,(mango-light-theme-color 'middleground '16))))) - `(git-commit-summary - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'khaki 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'khaki '256))) - (((type tty)) - (:foreground ,(mango-light-theme-color 'khaki '16))))) - `(git-commit-overlong-summary - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'background-dark 'gui) - :background ,(mango-light-theme-color 'red 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'background-dark '256) - :background ,(mango-light-theme-color 'red '256) :weight bold)) - (((type tty)) - (:foreground ,(mango-light-theme-color 'background-dark '16) - :background ,(mango-light-theme-color 'red '16) :weight bold)))) - - ;; Vertico - `(vertico-current ((t (:inherit hl-line)))) - - ;; Marginalia - `(mm-diffstat-counter-added ((t (:foreground "green" :weight bold)))) - `(mm-diffstat-counter-removed ((t (:foreground "red" :weight bold)))) - `(marginalia-documentation - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-light-theme-color 'disabled 'gui) :underline nil)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-light-theme-color 'disabled '256) :underline nil)) - (((type tty)) - (:foreground ,(mango-light-theme-color 'disabled '16) :underline nil)))) - - ;; Tempel - `(tempel-default - ((((type graphic tty) (min-colors 16777216)) - (:slant italic :background ,(mango-light-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:slant italic :background ,(mango-light-theme-color 'middleground '256))) - (((type tty)) - (:slant italic :background ,(mango-light-theme-color 'middleground '16))))) - `(tempel-field - ((((type graphic tty) (min-colors 16777216)) - (:slant italic :background ,(mango-light-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:slant italic :background ,(mango-light-theme-color 'middleground '256))) - (((type tty)) - (:slant italic :background ,(mango-light-theme-color 'middleground '16))))) - `(tempel-form - ((((type graphic tty) (min-colors 16777216)) - (:slant italic :background ,(mango-light-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:slant italic :background ,(mango-light-theme-color 'middleground '256))) - (((type tty)) - (:slant italic :background ,(mango-light-theme-color 'middleground '16)))))) - -(provide-theme 'mango-light) diff --git a/.config/emacs/mango-theme.el b/.config/emacs/mango-theme.el deleted file mode 100644 index 72a76f9..0000000 --- a/.config/emacs/mango-theme.el +++ /dev/null @@ -1,331 +0,0 @@ -;;; mango-theme.el --- Just your average dark theme -*- lexical-binding: t; -*- - -(deftheme mango - "Mildly dark, dark theme. -Your average not-so-dark dark theme, because none of the other options -were exactly to my liking. It’s about time I had a theme to call my -own.") - -(defconst mango-theme-colors-alist - '((foreground . ("#C5C8C6" "color-251" "white")) - (background . ("#2B303B" "color-236" "black")) - (background-cool . ("#363C4A" "color-237" "black")) - (background-dark . ("#1D2635" "color-234" "black")) - (background-faint . ("#414859" "color-238" "brightblack")) - (middleground . ("#4F5561" "color-239" "brightblack")) - (disabled . ("#999999" "color-246" "brightblack")) - (celestial-blue . ("#569CD6" "color-74" "brightblue")) - (dark-red . ("#841A11" "color-88" "red")) - (khaki . ("#F0E68C" "color-228" "yellow")) - (lime . ("#B8F182" "color-156" "green")) - (magenta . ("#ED97F5" "color-213" "magenta")) - (pale-azure . ("#9CDCFE" "color-117" "cyan")) - (red . ("#E60026" "color-160" "brightred")) - (salmon . ("#F1B282" "color-216" "brightyellow")) - (violet . ("#E57AE5" "color-176" "brightmagenta"))) - "The color palette used throughout `mango-theme'. -Each color is mapped to a list of colors of the form -(GUI-HEX 256-COLOR 16-COLOR) for use in true-color, 256-color, and -16-color modes.") - -(defsubst mango-theme-color (name &optional display) - "Get the color value of NAME for the given DISPLAY. -DISPLAY can be 'gui, '256, or '16." - (let ((colors (alist-get name mango-theme-colors-alist))) - (pcase display - ('gui (nth 0 colors)) - ('256 (nth 1 colors)) - ('16 (nth 2 colors)) - (_ (nth 0 colors))))) - -(custom-theme-set-faces - 'mango - - ;; Standard Stuff - `(default - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'foreground 'gui) - :background ,(mango-theme-color 'background 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'foreground '256) - :background ,(mango-theme-color 'background '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'foreground '16) - :background ,(mango-theme-color 'background '16))))) - `(fringe - ((t (:inherit default)))) - - ;; Lines - `(hl-line - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'background-faint 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'background-faint '256))) - (((type tty)) - (:background ,(mango-theme-color 'background-faint '16))))) - `(region - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'middleground '256))) - (((type tty)) - (:background ,(mango-theme-color 'middleground '16))))) - `(header-line - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'middleground '256))) - (((type tty)) - (:background ,(mango-theme-color 'middleground '16))))) - `(mode-line-active - ((t (:inherit header-line)))) - `(mode-line-inactive - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'background-cool 'gui) :weight light)) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'background-cool '256) :weight light)) - (((type tty)) - (:background ,(mango-theme-color 'background-cool '16) :weight light)))) - `(window-divider - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'background-cool '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'background-cool '16))))) - `(window-divider-first-pixel - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'background-cool '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'background-cool '16))))) - `(window-divider-last-pixel - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'background-cool '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'background-cool '16))))) - - ;; Line Numbers - `(line-number - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'background-faint 'gui) - :background ,(mango-theme-color 'background 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'background-faint '256) - :background ,(mango-theme-color 'background '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'background-faint '16) - :background ,(mango-theme-color 'background '16))))) - `(line-number-current-line - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'salmon 'gui) - :background ,(mango-theme-color 'background 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'salmon '256) - :background ,(mango-theme-color 'background '256) :weight bold)) - (((type tty)) - (:foreground ,(mango-theme-color 'salmon '16) - :background ,(mango-theme-color 'background '16) :weight bold)))) - - ;; Documentation - `(font-lock-comment-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'khaki 'gui) :weight semi-bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'khaki '256) :weight semi-bold)) - (((type tty)) - (:foreground ,(mango-theme-color 'khaki '16) :weight semi-bold)))) - `(font-lock-doc-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'disabled 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'disabled '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'disabled '16))))) - - ;; Modeline - `(mm-modeline-overwrite-face ((t (:weight bold)))) - `(mm-modeline-readonly-face ((t (:weight bold)))) - `(mm-modeline-buffer-name-face ((t (:inherit font-lock-constant-face)))) - `(mm-modeline-buffer-modified-face ((t (:inherit shadow)))) - `(mm-modeline-major-mode-name-face ((t (:weight bold)))) - `(mm-modeline-major-mode-symbol-face ((t (:inherit shadow)))) - `(mm-modeline-git-branch-face ((t (:inherit font-lock-constant-face)))) - `(mm-modeline-narrow-face - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'dark-red 'gui) :box ,(mango-theme-color 'dark-red 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'dark-red '256) :box ,(mango-theme-color 'dark-red '256) :weight bold)) - (((type tty)) - (:background ,(mango-theme-color 'dark-red '16) :box ,(mango-theme-color 'dark-red '16) :weight bold)))) - - ;; Core Language - `(font-lock-builtin-face ((t (:inherit font-lock-preprocessor-face)))) - `(font-lock-keyword-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'violet 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'violet '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'violet '16))))) - `(font-lock-type-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'celestial-blue 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'celestial-blue '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'celestial-blue '16))))) - - ;; Function-likes - `(font-lock-function-name-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'khaki 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'khaki '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'khaki '16))))) - `(font-lock-preprocessor-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'magenta 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'magenta '256) :weight bold)) - (((type tty)) - (:foreground ,(mango-theme-color 'magenta '16) :weight bold)))) - - ;; Variables - `(font-lock-constant-face ((t (:inherit font-lock-variable-name-face :weight bold)))) - `(font-lock-variable-name-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'pale-azure 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'pale-azure '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'pale-azure '16))))) - - ;; Other literals - `(help-key-binding ((t (:inherit font-lock-constant-face)))) - `(font-lock-string-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'salmon 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'salmon '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'salmon '16))))) - `(font-lock-number-face - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'salmon 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'salmon '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'salmon '16))))) - - ;; Org Mode - `(org-quote ((t (:inherit org-block :slant italic)))) - `(org-code - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'salmon 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'salmon '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'salmon '16))))) - `(org-verbatim - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'lime 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'lime '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'lime '16))))) - `(org-block - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'background-cool '256))) - (((type tty)) - (:background ,(mango-theme-color 'background-cool '16))))) - `(org-hide - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'background 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'background '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'background '16))))) - - ;; Info Page - `(Info-quoted ((t (:inherit default)))) - - ;; Magit - `(magit-diff-context-highlight ((t (:inherit hl-line)))) - `(magit-section-highlight ((t (:inherit hl-line)))) - `(magit-diff-hunk-heading - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'background-cool 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'background-cool '256))) - (((type tty)) - (:background ,(mango-theme-color 'background-cool '16))))) - `(magit-diff-hunk-heading-highlight - ((((type graphic tty) (min-colors 16777216)) - (:background ,(mango-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:background ,(mango-theme-color 'middleground '256))) - (((type tty)) - (:background ,(mango-theme-color 'middleground '16))))) - `(git-commit-summary - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'khaki 'gui))) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'khaki '256))) - (((type tty)) - (:foreground ,(mango-theme-color 'khaki '16))))) - `(git-commit-overlong-summary - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'foreground 'gui) - :background ,(mango-theme-color 'red 'gui) :weight bold)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'foreground '256) - :background ,(mango-theme-color 'red '256) :weight bold)) - (((type tty)) - (:foreground ,(mango-theme-color 'foreground '16) - :background ,(mango-theme-color 'red '16) :weight bold)))) - - ;; Vertico - `(vertico-current ((t (:inherit hl-line)))) - - ;; Marginalia - `(mm-diffstat-counter-added ((t (:foreground "green" :weight bold)))) - `(mm-diffstat-counter-removed ((t (:foreground "red" :weight bold)))) - `(marginalia-documentation - ((((type graphic tty) (min-colors 16777216)) - (:foreground ,(mango-theme-color 'disabled 'gui) :underline nil)) - (((type tty) (min-colors 256)) - (:foreground ,(mango-theme-color 'disabled '256) :underline nil)) - (((type tty)) - (:foreground ,(mango-theme-color 'disabled '16) :underline nil)))) - - ;; Tempel - `(tempel-default - ((((type graphic tty) (min-colors 16777216)) - (:slant italic :background ,(mango-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:slant italic :background ,(mango-theme-color 'middleground '256))) - (((type tty)) - (:slant italic :background ,(mango-theme-color 'middleground '16))))) - `(tempel-field - ((((type graphic tty) (min-colors 16777216)) - (:slant italic :background ,(mango-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:slant italic :background ,(mango-theme-color 'middleground '256))) - (((type tty)) - (:slant italic :background ,(mango-theme-color 'middleground '16))))) - `(tempel-form - ((((type graphic tty) (min-colors 16777216)) - (:slant italic :background ,(mango-theme-color 'middleground 'gui))) - (((type tty) (min-colors 256)) - (:slant italic :background ,(mango-theme-color 'middleground '256))) - (((type tty)) - (:slant italic :background ,(mango-theme-color 'middleground '16)))))) - -(provide-theme 'mango) diff --git a/.config/emacs/modules/mm-abbrev.el b/.config/emacs/modules/mm-abbrev.el deleted file mode 100644 index d32ec0d..0000000 --- a/.config/emacs/modules/mm-abbrev.el +++ /dev/null @@ -1,110 +0,0 @@ -;;; mm-abbrev.el --- Emacs abbreviations and templates -*- lexical-binding: t; -*- - -;;; Helpers - -(defmacro mm-define-abbreviations (table &rest definitions) - "Define abbrevations for an abbreviation TABLE. -Expand abbrev DEFINITIONS for the given TABLE. DEFINITIONS are a -sequence of either string pairs mapping an abbreviation to its -expansion, or a string and symbol pair mapping an abbreviation to a -function. - -After adding all abbreviations to TABLE, this macro marks TABLE as -case-sensitive to avoid unexpected abbreviation expansions." - (declare (indent 1)) - (unless (cl-evenp (length definitions)) - (user-error "expected an even number of elements in DEFINITIONS")) - `(progn - ,@(cl-loop for (abbrev expansion) in (seq-partition definitions 2) - if (stringp expansion) - collect (list #'define-abbrev table abbrev expansion) - else - collect (list #'define-abbrev table abbrev "" expansion)) - (abbrev-table-put ,table :case-fixed t))) - - -;;; Abbreviation Configuration - -(use-package abbrev - :hook prog-mode - :custom - (abbrev-file-name (expand-file-name "abbev-defs" mm-data-directory)) - (save-abbrevs 'silently)) - - -;;; Abbreviation Definitions - -(defvar mm-c-mode-abbrev-table (make-abbrev-table) - "Abbreviations shared between `c-mode', `c++-mode', `c-ts-mode', and -`c++-ts-mode'.") - -(mm-define-abbreviations mm-c-mode-abbrev-table - "flf" "flockfile" - "fpf" "fprintf" - "fuf" "funlockfile" - "pf" "printf" - "sde" "stderr" - "sdi" "stdin" - "sdo" "stdout") - -(with-eval-after-load 'cc-mode - (setq c-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table) - c++-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table))) -(with-eval-after-load 'c-ts-mode - (setq c-ts-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table) - c++-ts-mode-abbrev-table (copy-abbrev-table mm-c-mode-abbrev-table))) - -(mm-define-abbreviations emacs-lisp-mode-abbrev-table - "ald" ";;;###autoload" - "gc" "goto-char" - "ins" "insert" - "itv" "interactive" - "mtb" "match-beginning" - "mte" "match-end" - "ntr" "narrow-to-region" - "pbl" "pos-bol" - "pel" "pos-eol" - "pmn" "point-min" - "pmx" "point-max" - "pnt" "point" - "rap" "region-active-p" - "rb" "region-beginning" - "re" "region-end" - "rsb" "re-search-backward" - "rsf" "re-search-forward" - "sb" "search-backward" - "se" "save-excursion" - "sf" "search-forward" - "sme" "save-mark-and-excursion" - "sr" "save-restriction") - -(when mm-humanwave-p - (with-eval-after-load 'python - (mm-define-abbreviations python-ts-mode-abbrev-table - "empb" "with emphasize.Block():" - "empf" "@emphasize.func" - "empi" "from shared.system import emphasize" - "empt" "emphasize.this"))) - - -;;; Template Configuration - -(use-package tempel - :ensure t - :demand t - :pin gnu - :bind ( :map tempel-map - ("TAB" . tempel-next) - ("S-TAB" . tempel-previous)) - :custom - (tempel-trigger-prefix "<") - :init - (setopt tempel-path (expand-file-name "templates" mm-config-directory)) - (dolist (mode '(conf-mode prog-mode text-mode)) - (add-hook (mm-mode-to-hook mode) - (defun mm-setup-tempel-capf () - (add-hook 'completion-at-point-functions - #'tempel-complete -10 :local)))) - (add-to-list 'auto-mode-alist (cons tempel-path #'lisp-data-mode))) - -(provide 'mm-abbrev) diff --git a/.config/emacs/modules/mm-buffer-menu.el b/.config/emacs/modules/mm-buffer-menu.el deleted file mode 100644 index 7b725c6..0000000 --- a/.config/emacs/modules/mm-buffer-menu.el +++ /dev/null @@ -1,15 +0,0 @@ -;;; mm-buffer-menu.el --- Buffer Menu configuration -*- lexical-binding: t; -*- - -(defun mm-Buffer-menu-delete-all () - "Mark all buffers for deletion." - (interactive nil Buffer-menu-mode) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (Buffer-menu-delete)))) - -(use-package buff-menu - :bind ( :map Buffer-menu-mode-map - ("D" . mm-Buffer-menu-delete-all))) - -(provide 'mm-buffer-menu) \ No newline at end of file diff --git a/.config/emacs/modules/mm-calc.el b/.config/emacs/modules/mm-calc.el deleted file mode 100644 index af45b15..0000000 --- a/.config/emacs/modules/mm-calc.el +++ /dev/null @@ -1,13 +0,0 @@ -;;; mm-calc.el --- Emacs configurations for ‘calc-mode’ -*- lexical-binding: t; -*- - -(use-package calc - ;; TODO: Can this be done in :custom? - :init - (setopt - calc-display-trail nil - calc-group-digits t - ;; Optimize for Europeans - calc-point-char "," - calc-group-char ".")) - -(provide 'mm-calc) \ No newline at end of file diff --git a/.config/emacs/modules/mm-completion.el b/.config/emacs/modules/mm-completion.el deleted file mode 100644 index 3367aa1..0000000 --- a/.config/emacs/modules/mm-completion.el +++ /dev/null @@ -1,256 +0,0 @@ -;;; mm-completion.el --- Configuration for Emacs completion -*- lexical-binding: t; -*- - - -;;; Vertical Completions - -(use-package vertico - :ensure t - :hook after-init - :custom - (vertico-cycle t) - :config - (require 'hl-line) - ;; When working with ‘file-name-shadow-mode’ enabled, if I shadow old - ;; input (i.e.) by typing ‘~/’ after ‘foo/bar’ Vertico will clear the - ;; old path to keep only the current input (the old path is hidden by - ;; ‘rfn-shadow’ anyways). - (with-eval-after-load 'rfn-shadow - (add-hook 'rfn-shadow-update-overlay-hook #'vertico-directory-tidy))) - - -;;; Annotate Completions - -(use-package marginalia - :ensure t - :hook after-init - :config - (with-eval-after-load 'magit - (defvar mm-marginalia--magit-cache nil) - (add-hook 'minibuffer-setup-hook - (lambda () (setq mm-marginalia--magit-cache nil))) - - (defvar-local mm-marginalia-magit-base-branch "master") - - (defface mm-diffstat-counter-added - '((t :inherit magit-diffstat-added)) - "TODO") - (defface mm-diffstat-counter-removed - '((t :inherit magit-diffstat-removed)) - "TODO") - - (defun mm-marginalia-populate-magit-cache () - "Batch-fetch all Git branch descriptions and stats into the cache." - (setq mm-marginalia--magit-cache (make-hash-table :test #'equal)) - (when-let ((default-directory (magit-toplevel))) - (dolist (line (magit-git-lines "config" "list")) - (when (string-match "^branch\\.\\(.*?\\)\\.description=\\(.*\\)$" line) - (puthash (match-string 1 line) - (list :desc (match-string 2 line) :stats "") - mm-marginalia--magit-cache))) - (dolist (line (magit-git-lines - "for-each-ref" - (format - "--format=%%(refname:short)\x1F%%(ahead-behind:%s)" - mm-marginalia-magit-base-branch) - "refs/heads/")) - (when (string-match (rx bol (group (1+ (not #x1F))) - #x1F (group (1+ digit)) - " " (group (1+ digit)) eol) - line) - (let* ((branch (match-string 1 line)) - (ahead (+ (string-to-number (match-string 2 line)))) - (behind (- (string-to-number (match-string 3 line)))) - (ahead-str (if (zerop ahead) - "" - (propertize (format "%+d" ahead) - 'face 'mm-diffstat-counter-added))) - (behind-str (if (zerop behind) - "" - (propertize (format "%+d" behind) - 'face 'mm-diffstat-counter-removed))) - (stats-str (format "%5s %5s" ahead-str behind-str)) - (existing (gethash branch mm-marginalia--magit-cache - (list :desc "" :stats "")))) - (puthash branch (plist-put existing :stats stats-str) - mm-marginalia--magit-cache)))))) - - (defun mm-marginalia-annotate-magit-branch (cand) - "Annotate Git branch CAND with ahead/behind stats and description." - (unless mm-marginalia--magit-cache - (mm-marginalia-populate-magit-cache)) - (let* ((data (gethash cand mm-marginalia--magit-cache '(:desc "" :stats ""))) - (desc (or (plist-get data :desc) "")) - (stats (or (plist-get data :stats) ""))) - (marginalia--fields - (stats :width 10) - (desc :truncate 1.0 :face 'marginalia-documentation)))) - - (add-to-list 'marginalia-annotators - '(magit-branch mm-marginalia-annotate-magit-branch builtin none)) - (dolist (cmd '(magit-branch-and-checkout - magit-branch-checkout - magit-branch-delete - magit-checkout - magit-merge - magit-rebase-branch)) - (add-to-list 'marginalia-command-categories (cons cmd 'magit-branch)))) - :custom - (marginalia-field-width 50) - (marginalia-max-relative-age 0)) - - -;;; Minibuffer Completion Styles - -(use-package minibuffer - :bind ( :map minibuffer-local-completion-map - ("SPC" . nil) - ("?" . nil)) - :custom - (completion-styles '(basic substring orderless)) - (completion-category-defaults nil) ; Avoid needing to override things - (completion-category-overrides - '((file (styles . (basic partial-completion orderless))) - (bookmark (styles . (basic substring))) - (library (styles . (basic substring))) - (imenu (styles . (basic substring orderless))) - (consult-location (styles . (basic substring orderless))) - (kill-ring (styles . (basic substring orderless))))) - (completion-ignore-case t) - (read-buffer-completion-ignore-case t) - (read-file-name-completion-ignore-case t)) - -(use-package orderless - :ensure t - :after minibuffer - :custom - (orderless-matching-styles '(orderless-prefixes orderless-regexp))) - - -;;; Disable Minibuffer Recursion Level - -(use-package mb-depth - :hook (after-init . minibuffer-depth-indicate-mode) - :custom - (enable-recursive-minibuffers t)) - - -;;; Don’t Show Defaults After Typing - -;; Usually if a minibuffer prompt has a default value you can access by -;; hitting RET, the prompt will remain even if you begin typing (meaning -;; the default will no longer take effect on RET). Enabling this mode -;; disables that behaviour. - -(use-package minibuf-eldef - :hook (after-init . minibuffer-electric-default-mode) - :custom - (minibuffer-default-prompt-format " [%s]")) - - -;;; Hide Shadowed Filepaths - -(use-package rfn-eshadow - :hook (after-init . file-name-shadow-mode) - :custom - (file-name-shadow-properties '(invisible t intangilble t))) - - -;;; Completion Popups - -(mm-comment - (use-package corfu - :ensure t - :hook prog-mode - :bind ( :map corfu-map - ("C-" . newline)) - :custom - (corfu-auto t) - (corfu-cycle t) - (corfu-auto-prefix 1) - (corfu-auto-delay .1) - (corfu-min-width 20) - :config - ;; I complete with RET and this interferes with ‘tempel-next’ - (keymap-unset corfu-map "TAB" :remove) - (with-eval-after-load 'savehist - (corfu-history-mode) - (add-to-list 'savehist-additional-variables 'corfu-history)) - (with-eval-after-load 'multiple-cursors - (add-to-list 'mc/unsupported-minor-modes #'corfu-mode)))) - - -;;; Save Minibuffer History - -(use-package savehist-mode - :hook (after-init . savehist-mode) - :custom - (history-length 200) - (history-delete-duplicates t) - :config - (add-to-list 'savehist-additional-variables 'kill-ring)) - - -;;; Enhanced Replacements for Builtins - -;; TODO: Investigate other commands -(use-package consult - :ensure t - :hook (completion-list-mode . consult-preview-at-point-mode) - :bind ( ([remap switch-to-buffer] . consult-buffer) - ([remap imenu] . consult-imenu) - ([remap goto-line] . consult-goto-line) - ("M-F" . consult-focus-lines) - :map project-prefix-map - ("b" . consult-project-buffer) - :map consult-narrow-map - ("?" . consult-narrow-help)) - :custom - (consult-find-args - (string-join - '("find . -not (" - " -path '*/.git*' -prune" - " -or -path '*/vendor/*' -prune" - ")") - " "))) - - -;;; Dynamic Abbreviations - -(use-package dabbrev - :commands (dabbrev-completion dabbrev-expand) - :custom - (dabbrev-upcase-means-case-search t)) - - -;;; Finding Things - -(use-package find-func - :custom - (find-library-include-other-files nil)) - - -;;; Completion at Point Functions - -(defun mm-cape-file--not-dot-path-p (cand) - (declare (ftype (function (string) boolean)) - (pure t) (side-effect-free t)) - (not (or (string= cand "./") - (string= cand "../")))) - -(use-package cape - :ensure t - :init - (add-hook 'completion-at-point-functions - (cape-capf-predicate #'cape-file #'mm-cape-file--not-dot-path-p)) - (add-hook 'completion-at-point-functions - (cape-capf-prefix-length #'cape-dabbrev 3))) - - -;;; Completion at Point Live Completions - -(use-package completion-preview - :hook (after-init . global-completion-preview-mode) - :custom - (completion-preview-minimum-symbol-length 1)) - -(provide 'mm-completion) diff --git a/.config/emacs/modules/mm-darwin.el b/.config/emacs/modules/mm-darwin.el deleted file mode 100644 index 90dbedd..0000000 --- a/.config/emacs/modules/mm-darwin.el +++ /dev/null @@ -1,30 +0,0 @@ -;;; mm-darwin.el --- MacOS Configuration -*- lexical-binding: t; -*- - -(unless (featurep 'ns) - (error "'NS not available. Something has gone horribly wrong.")) - - -;;; Launch Emacs Properly - -(defun mm-ns-raise-emacs () - (ns-do-applescript "tell application \"Emacs\" to activate")) - -(add-hook - 'after-make-frame-functions - (defun mm-ns-raise-emacs-with-frame (frame) - (when (display-graphic-p) - (with-selected-frame frame - (mm-ns-raise-emacs))))) - -(when (display-graphic-p) - (mm-ns-raise-emacs)) - - -;;; Set Modifier Keys - -(setopt mac-option-key-is-meta nil - mac-command-key-is-meta t) -(setopt mac-option-modifier 'none - mac-command-modifier 'meta) - -(provide 'mm-darwin) diff --git a/.config/emacs/modules/mm-dired.el b/.config/emacs/modules/mm-dired.el deleted file mode 100644 index 9e78466..0000000 --- a/.config/emacs/modules/mm-dired.el +++ /dev/null @@ -1,24 +0,0 @@ -;;; mm-dired.el --- Configure the directory editor -*- lexical-binding: t; -*- - -(use-package dired - :hook ((dired-mode . dired-omit-mode) - (dired-mode . dired-hide-details-mode)) - :bind ( :map dired-mode-map - ("f" . find-file)) - :custom - (dired-auto-revert-buffer #'dired-directory-changed-p) - (dired-dwim-target t) - (dired-free-space nil) - (dired-recursive-copies 'always) - (dired-recursive-deletes 'always) - (dired-listing-switches - (combine-and-quote-strings - '("-AFGhlv" "--group-directories-first" "--time-style=+%d %b %Y %T")))) - -(use-package dired-aux - :custom - (dired-create-destination-dirs 'ask) - (dired-create-destination-dirs-on-trailing-dirsep t) - (dired-isearch-filenames 'dwim)) - -(provide 'mm-dired) \ No newline at end of file diff --git a/.config/emacs/modules/mm-documentation.el b/.config/emacs/modules/mm-documentation.el deleted file mode 100644 index 1bd94da..0000000 --- a/.config/emacs/modules/mm-documentation.el +++ /dev/null @@ -1,44 +0,0 @@ -;;; mm-documentation.el --- Configuration related to documentation -*- lexical-binding: t; -*- - -;;; Enhance Describe Commands - -(use-package helpful - :ensure t - :bind (([remap describe-command] . helpful-command) - ([remap describe-function] . helpful-callable) - ([remap describe-key] . helpful-key) - ([remap describe-symbol] . helpful-symbol) - ([remap describe-variable] . helpful-variable) - (("C-h C-p" . helpful-at-point)))) - - -;;; Open Manpage for Symbol - -(defun mm-documentation-man-at-point () - "Open a UNIX manual page for the symbol at point." - (declare (modes (c-mode c++-mode c-ts-mode c++-ts-mode))) - (interactive) - (if-let ((symbol - (pcase major-mode - ((or 'c-mode 'c++-mode) - (thing-at-point 'symbol :no-properties)) - ((or 'c-ts-mode 'c++-ts-mode) - (when-let ((node (treesit-thing-at-point "identifier" 'nested))) - (treesit-node-text node :no-properties)))))) - (man symbol) - (message "No symbol at point."))) - - -;;; Browse RFC Pages - -(use-package rfc-mode - :ensure t - :custom - (rfc-mode-directory (expand-file-name "rfc" (xdg-user-dir "DOCUMENTS"))) - :config - (unless (featurep 'consult) - (keymap-set rfc-mode-map "g" #'imenu)) - (with-eval-after-load 'consult - (keymap-set rfc-mode-map "g" #'consult-imenu))) - -(provide 'mm-documentation) \ No newline at end of file diff --git a/.config/emacs/modules/mm-editing.el b/.config/emacs/modules/mm-editing.el deleted file mode 100644 index 24aa7ea..0000000 --- a/.config/emacs/modules/mm-editing.el +++ /dev/null @@ -1,449 +0,0 @@ -;;; mm-editing.el --- Text editing configuation -*- lexical-binding: t; -*- - -;;; Delete Region When Typing - -(use-package delsel - :hook (after-init . delete-selection-mode)) - - -;;; Capitalize ‘ß’ into ‘ẞ’ - -;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2024-11/msg00030.html -(set-case-syntax-pair ?ẞ ?ß (standard-case-table)) -(put-char-code-property ?ß 'special-uppercase nil) - - -;;; Force Spaces For Alignment - -(defun mm-editing-force-space-indentation (function &rest arguments) - "Call FUNCTION with ARGUMENTS in an environment in which -`indent-tabs-mode' is nil." - (let (indent-tabs-mode) - (apply function arguments))) - -(dolist (command #'(align-region - c-backslash-region - comment-dwim - makefile-backslash-region - sh-backslash-region)) - (advice-add command :around #'mm-editing-force-space-indentation)) - - -;;; Recenter The Screen When Jumping - -(mm-comment - (dolist (command #'(backward-page - backward-paragraph - forward-page - forward-paragraph - pop-global-mark)) - (advice-add command :around #'mm-do-and-center))) - - -;;; Indentation Settings - -(setq-default - tab-width 4 - indent-tabs-mode (not mm-humanwave-p)) - -(defvar mm-editing-indentation-settings-alist - '((awk-ts-mode . (:extras awk-ts-mode-indent-level)) - (c-mode . (:extras c-basic-offset)) - (c-ts-mode . (:extras c-ts-mode-indent-offset)) - (css-mode . (:extras css-indent-offset)) - (elixir-ts-mode . (:width 2 :extras elixir-ts-indent-offset)) - (emacs-lisp-mode . (:width 8 :spaces t)) ; GNU code uses 8-column tabs - (go-mod-ts-mode . (:extras go-ts-mode-indent-offset)) - (go-ts-mode . (:extras go-ts-mode-indent-offset)) - (gsp-ts-mode . (:width 2 :extras gsp-ts-mode-indent-rules)) - (helpful-mode . (:width 8)) ; GNU code uses 8-column tabs - (json-ts-mode . (:extras json-ts-mode-indent-offset)) - (latex-mode . (:width 2)) - (lisp-data-mode . (:spaces t)) - (lisp-interaction-mode . (:spaces t)) - (lisp-mode . (:spaces t)) - (mhtml-mode . (:extras sgml-basic-offset)) - (org-mode . (:width 8 :spaces t)) - (python-mode . (:extras python-indent-offset)) - (python-ts-mode . (:extras python-indent-offset)) - (sgml-mode . (:extras sgml-basic-offset)) - (sh-mode . (:extras sh-basic-offset)) - (sql-mode . (:extras sqlind-basic-offset)) - (tex-mode . (:width 2)) - (typescript-ts-mode . (:extras typescript-ts-mode-indent-offset)) - (vimscript-ts-mode . (:extras vimscript-ts-mode-indent-level)) - (vue-ts-mode . (:extras (typescript-ts-mode-indent-offset - vue-ts-mode-indent-offset)))) - "Alist of indentation settings. -Each pair in this alist is of the form (MODE . SETTINGS) where MODE -specifies the mode for which the given SETTINGS should apply. - -SETTINGS is a plist of one-or-more of the following keys: - - `:spaces' -- If nil force tabs for indentation, if non-nil for spaces - for indentation. If this key is not provided then the - value of `indent-tabs-mode' is used. - `:width' -- Specifies a non-negative number to be used as the tab - width and indentation offset. If this key is not - provided then the default value of `tab-width' is used. - `:extras' -- A list of mode-specific variables which control - indentation settings that need to be set for - configurations to properly be applied.") - -(defun mm-editing-set-indentation-settings () - "Set indentation settings for the current major mode. -The indentation settings are set based on the configured values in -`mm-editing-indentation-settings-alist'." - (let* ((plist (alist-get major-mode mm-editing-indentation-settings-alist)) - (spaces (plist-member plist :spaces)) - (width (plist-member plist :width)) - (extras (plist-member plist :extras))) - ;; Some modes like ‘python-mode’ explicitly set ‘tab-width’ and - ;; ‘indent-tabs-mode’ so we must override them explicitly. - (setq-local indent-tabs-mode (if spaces (not (cadr spaces)) - (default-value 'indent-tabs-mode)) - tab-width (or (cadr width) (default-value 'tab-width))) - (when extras - (setq extras (cadr extras)) - (when (symbolp extras) - (setq extras (list extras))) - (dolist (extra extras) - (set extra tab-width))))) - -(add-hook 'after-change-major-mode-hook #'mm-editing-set-indentation-settings) - -(defun mm-editing-set-tabsize () - "Set the tabsize for the current buffer. -If the current buffer’s major mode requires setting additional variables, -those should be listed in `mm-editing-indentation-settings'." - (interactive) - (let* ((prompt-default (default-value 'tab-width)) - (prompt (format-prompt "Tabsize" prompt-default)) - (tabsize (mm-as-number (read-string prompt nil nil prompt-default)))) - (setq-local tab-width tabsize) - (when-let* ((plist (alist-get major-mode mm-editing-indentation-settings)) - (extras (plist-get plist :extras))) - (dolist (extra (if (symbolp extras) - (list extras) - extras)) - (set (make-local-variable extra) tabsize))))) - -(use-package sh-mode - :custom - (sh-indent-for-case-label 0) - (sh-indent-for-case-alt #'+)) - - -;;; Code Commenting - -(defun mm-newcomment-c-config () - (setq-local comment-continue " ")) - -(defun mm-newcomment-html-config () - (setq-local comment-continue " ")) - -(defun mm-newcomment-rust-config () - (setq-local comment-start "/* " - comment-end " */" - comment-continue " * " ; rustfmt doesn’t play nice - comment-quote-nested nil)) - -(use-package newcomment - :custom - (comment-style 'multi-line) - :config - (dolist (mode '(c-mode c++-mode)) - (add-hook (mm-mode-to-hook mode) #'mm-newcomment-c-config) - (when-let ((ts-mode (mm-mode-to-ts-mode mode)) - ((fboundp ts-mode))) - (add-hook (mm-mode-to-hook ts-mode) #'mm-newcomment-c-config))) - (add-hook 'mhtml-mode-hook #'mm-newcomment-html-config) - (add-hook 'rust-ts-mode-hook #'mm-newcomment-rust-config)) - - -;;; Multiple Cursors - -(defmacro mm--define-mc-marking-command (name search-function noun) - (let ((noun-symbol (intern noun))) - `(defun ,name (beg end ,noun-symbol) - ,(format "Mark all occurances of %s between BEG and END. -If called interactively with an active region then all matches in the -region are marked, otherwise all matches in the buffer are marked." - (upcase noun)) - (interactive - (list (or (use-region-beginning) (point-min)) - (or (use-region-end) (point-max)) - (read-string - (format-prompt ,(concat "Match " noun) nil)))) - (if (string-empty-p ,noun-symbol) - (message "Command aborted") - (catch 'mm--no-match - (mc/remove-fake-cursors) - (goto-char beg) - (let (did-match-p) - (while (,search-function ,noun-symbol end :noerror) - (setq did-match-p t) - (push-mark (match-beginning 0)) - (exchange-point-and-mark) - (mc/create-fake-cursor-at-point) - (goto-char (mark))) - (unless did-match-p - (message "No match for `%s'" ,noun-symbol) - (throw 'mm--no-match nil))) - (when-let ((first (mc/furthest-cursor-before-point))) - (mc/pop-state-from-overlay first)) - (if (> (mc/num-cursors) 1) - (multiple-cursors-mode 1) - (multiple-cursors-mode 0))))))) - -(mm--define-mc-marking-command - mm-mark-all-in-region search-forward "string") -(mm--define-mc-marking-command - mm-mark-all-in-region-regexp re-search-forward "regexp") - -(mm-comment - (defun mm-silent-mc-load (args) - "Advice to `load' to force it to be silent. -The `multiple-cursors' package loads an `.mc-lists.el' file without -passing `:nomessage' which causes messages to be sent in the minibuffer -and *Messages* buffer. This forces that to not happen." - (when (and (boundp 'mc/list-file) - (string= (file-truename (car args)) - (file-truename mc/list-file))) - (pcase (length args) - (1 (setq args (list (car args) nil :nomessage))) - (2 (add-to-list 'args :nomessage :append)) - (_ (setf (caddr args) :nomessage))) - (advice-remove #'load #'mm-silent-mc-load)) - args)) - -(use-package multiple-cursors - :ensure t - :demand t - :bind (("C->" . #'mc/mark-next-like-this) - ("C-<" . #'mc/mark-previous-like-this) - ("C-M-<" . #'mc/mark-all-like-this-dwim) - ("C-M->" . #'mc/edit-lines) - :map search-map - ("$" . #'mm-mark-all-in-region) - ("M-$" . #'mm-mark-all-in-region-regexp)) - :commands ( mm-mark-all-in-region mm-mark-all-in-region-regexp - mm-add-cursor-to-next-thing mm-transpose-cursor-regions) - :init - (mm-comment - (advice-add #'load :filter-args #'mm-silent-mc-load) - (with-eval-after-load 'multiple-cursors-core - (dolist (command #'(backward-delete-char - capitalize-dwim - delete-backward-char - delete-forward-char - downcase-dwim - upcase-dwim)) - (add-to-list 'mc/cmds-to-run-for-all command)) - (dolist (command #'(helpful-callable - helpful-key - helpful-symbol - helpful-variable)) - (add-to-list 'mc/cmds-to-run-once command)))) - (with-eval-after-load 'multiple-cursors-core - (keymap-unset mc/keymap "" :remove))) - - -;;; Increment Numbers - -(use-package increment - :bind (("C-c i i" . #'increment-number-at-point) - ("C-c i d" . #'decrement-number-at-point)) - :commands (increment-number-at-point decrement-number-at-point)) - - -;;; Move Line or Region - -(defun mm-move-text-indent (&rest _) - (let ((deactivate deactivate-mark)) - (if (region-active-p) - (indent-region (region-beginning) (region-end)) - (indent-region (line-beginning-position) (line-end-position))) - (setq deactivate-mark deactivate))) - -(use-package move-text - :ensure t - :bind (("M-n" . move-text-down) - ("M-p" . move-text-up)) - :config - (dolist (command #'(move-text-up move-text-down)) - (advice-add command :after #'mm-move-text-indent))) - - -;;; Surround With Delimeters - -(defun mm-editing-surround-with-spaces (char) - "Surrounds region or current symbol with a pair defined by CHAR. -This is the same as `surround-insert' except it pads the contents of the -surround with spaces." - (interactive - (list (char-to-string (read-char "Character: ")))) - (let* ((pair (surround--make-pair char)) - (left (car pair)) - (right (cdr pair)) - (bounds (surround--infer-bounds t))) - (save-excursion - (goto-char (cdr bounds)) - (insert " " right) - (goto-char (car bounds)) - (insert left " ")) - (when (eq (car bounds) (point)) - (forward-char)))) - -;; TODO: Implement this manually -(use-package surround - :ensure t - :bind-keymap ("M-'" . surround-keymap) - :bind (:map surround-keymap - ("S" . #'mm-editing-surround-with-spaces)) - :config - (dolist (pair '(("‘" . "’") - ("“" . "”") - ("»" . "«") - ("⟮" . "⟯"))) - (push pair surround-pairs)) - (make-variable-buffer-local 'surround-pairs) - (add-hook 'emacs-lisp-mode-hook - (defun mm-editing-add-elisp-quotes-pair () - (push '("`" . "'") surround-pairs)))) - - -;;; Insert Webpage Contents - -(defun mm-insert-from-url (url) - "Insert the contents of URL at point." - (interactive - (let ((url-at-point (thing-at-point 'url))) - (list (read-string - (format-prompt "URL" url-at-point) - nil nil url-at-point)))) - (call-process "curl" nil '(t nil) nil url)) - - -;;; Emmet Mode - -(defun mm-editing-emmet-dwim (arg) - "Do-What-I-Mean Emmet expansion. -If the region is active then the region will be surrounded by an emmet -expansion read from the minibuffer. Otherwise the emmet expression -before point is expanded. When provided a prefix argument the behaviour -is as described by `emmet-expand-line'." - (interactive "P") - (if (region-active-p) - (call-interactively #'emmet-wrap-with-markup) - (emmet-expand-line arg))) - -(use-package emmet-mode - :ensure t - :bind ("C-," . mm-editing-emmet-dwim) - :custom - (emmet-self-closing-tag-style "")) - - -;;; JQ Manipulation in JSON Mode - -(defun mm-jq-filter (query &optional beg end) - "TODO" - (interactive - (list - (read-string (format-prompt "Query" nil)) - (when (use-region-p) (region-beginning)) - (when (use-region-p) (region-end)))) - (let* ((beg (or beg (point-min))) - (end (or end (point-max))) - (temp-buffer (generate-new-buffer "* jq temp*")) - (exit-code (call-process-region beg end "jq" nil temp-buffer nil - "--tab" query)) - (output (with-current-buffer temp-buffer (buffer-string)))) - (if (zerop exit-code) - (atomic-change-group - (delete-region beg end) - (insert output) - (indent-region beg (point))) - (message "%s" output)) - (kill-buffer temp-buffer))) - -(use-package json-ts-mode - :bind ( :map json-ts-mode-map - ("C-|" . #'mm-jq-filter)) - :config - (require 'live-jq)) - - -;;; Number Formatting - -(use-package number-format-mode - :commands ( number-format-buffer number-format-region - number-unformat-buffer number-unformat-region - number-format-mode)) - - -;;; Additional Major Modes - -(use-package awk-ts-mode :ensure t) -(use-package cmake-mode :ensure t) -(use-package git-modes :ensure t) -(use-package kdl-mode :ensure t) -(use-package po-mode :ensure t) -(use-package sed-mode :ensure t) - -(use-package csv-mode - :ensure t - :custom - (csv-align-style 'auto) - (csv-align-padding 2)) - -(use-package xcompose-mode - :vc ( :url "https://git.thomasvoss.com/xcompose-mode" - :branch "master" - :rev :newest - :vc-backend Git) - :ensure t) - -(use-package yaml-pro - :hook ((yaml-mode . yaml-pro-mode) - (yaml-ts-mode . yaml-pro-ts-mode))) - - -;;; Mode-Specific Configurations - -(use-package make-mode - :custom - (makefile-backslash-column 80)) - -(use-package python-mode - :custom - (python-indent-def-block-scale 1) - (python-indent-guess-indent-offset-verbose nil)) - - -;;; Add Missing Extensions - -(dolist (pattern '("\\.tmac\\'" "\\.mom\\'")) - (add-to-list 'auto-mode-alist (cons pattern #'nroff-mode))) - - -;;; Subword Navigation - -(use-package subword - :hook prog-mode) - - -;;; Edit Files via Doas/Sudo - -(defvar mm-root-editing-program - (if (string= (system-name) "mangobox") "doas" "sudo")) - -(defun mm-edit-root-protected-file-buffer () - (interactive) - (when (and buffer-file-name (not (file-writable-p buffer-file-name))) - (find-alternate-file (format "/%s:root@localhost:%s" - mm-root-editing-program - buffer-file-name)))) - -(provide 'mm-editing) diff --git a/.config/emacs/modules/mm-humanwave.el b/.config/emacs/modules/mm-humanwave.el deleted file mode 100644 index d52546e..0000000 --- a/.config/emacs/modules/mm-humanwave.el +++ /dev/null @@ -1,254 +0,0 @@ -;;; mm-humanwave.el --- Humanwave extras -*- lexical-binding: t; -*- - - -;;; Query the Backend - -(defvar mm--humanwave-query-history nil - "History for endpoints given to `mm-humanwave-query'.") - -(defun mm-humanwave-query (endpoint &optional method) - "Query and display the result of an HTTP reqiest on ENDPOINT. -If METHOD is nil, a GET request is performed." - (interactive - (let* ((query (read-string (format-prompt "Query" nil) - (car-safe mm--humanwave-query-history) - 'mm--humanwave-query-history)) - (parts (string-split (string-trim query) " " :omit-nulls))) - (when (length> parts 2) - (user-error "Queries must be of the form `METHOD ENDPOINT' or `ENDPOINT'.")) - (nreverse parts))) - (let* ((project-root (project-root (project-current :maybe-prompt))) - (qry-path (expand-file-name "qry" project-root)) - extras) - (unless (file-executable-p qry-path) - (user-error "No `qry' executable found in the project root")) - (let ((output-buffer (get-buffer-create "*Query Response*"))) - (with-current-buffer output-buffer - (delete-region (point-min) (point-max)) - (call-process qry-path nil t nil - (string-trim endpoint) "-X" (or method "GET")) - (unless (eq major-mode 'json-ts-mode) - (json-ts-mode)) - (goto-char (point-min))) - (display-buffer output-buffer)))) - - -;;; IMenu Support for Handlers - -(require 'imenu) -(require 'which-func) - -(defvar mm-humanwave-handler--regexp - (rx bol - (* blank) - (or "if" "elif") - (* blank) - (or "dialog" "topic" "schedule") - (* blank) - "==" - (* blank) - (or ?\' ?\") - (group (+ (not (or ?\' ?\")))) - (or ?\' ?\") - (* blank) - ?: - (* blank) - eol)) - -(defun mm-humanwave-handler--insert-entry (topic-index function-parts route pos) - (if (null function-parts) - (cons (cons (format "%s (route)" route) pos) topic-index) - (let* ((current-group (car function-parts)) - (rest-parts (cdr function-parts)) - (existing-sublist (assoc current-group topic-index))) - (if existing-sublist - (progn - (setcdr existing-sublist - (mm-humanwave-handler--insert-entry - (cdr existing-sublist) rest-parts route pos)) - topic-index) - (cons (cons current-group - (mm-humanwave-handler--insert-entry - nil rest-parts route pos)) - topic-index))))) - -(defun mm-humanwave-handler-topic-imenu-index () - (let ((case-fold-search nil) - (tree-index (python-imenu-treesit-create-index)) - (topic-index '())) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward mm-humanwave-handler--regexp nil :noerror) - (let ((route (match-string-no-properties 1)) - (pos (match-beginning 0)) - (function-parts (split-string (which-function) "\\."))) - (setq topic-index (mm-humanwave-handler--insert-entry - topic-index function-parts route pos))))) - (append (nreverse topic-index) tree-index))) - -(defun mm-humanwave-handler-topic-imenu-setup () - "Setup custom imenu index for `python-ts-mode'." - (when (and (string-match-p "/handlers?/" (or (buffer-file-name) "")) - (derived-mode-p #'python-ts-mode)) - (setq-local imenu-create-index-function - #'mm-humanwave-handler-topic-imenu-index))) - -(add-hook 'after-change-major-mode-hook - #'mm-humanwave-handler-topic-imenu-setup) - - -;;; Insert Imports in Vue - -(defun mm-humanwave-insert-vue-import-path (base-directory target-file) - "Insert an import directive at POINT. -The import directive imports TARGET-FILE relative from BASE-DIRECTORY. -When called interactively BASE-DIRECTORY is the directory of the current -open Vue file and TARGET-FILE is a file in the current project that is -queried interactively. - -When called interactively the prefix argument can be used to emulate the -behaviour of the INCLUDE-ALL-P argument to `mm-project-read-file-name'." - (interactive - (list - default-directory - (mm-humanwave-project-read-file-name current-prefix-arg))) - (let ((path (file-name-sans-extension - (file-relative-name target-file base-directory)))) - (unless (string-match-p "/" path) - (setq path (concat "./" path))) - (insert "import ") - (save-excursion - (insert (thread-last - (file-name-base path) - (mm-string-split "-") - (mapconcat #'capitalize))) - (push-mark (point)) - (insert (format " from '%s';" path))))) - -(defun mm-humanwave-project-read-file-name (&optional include-all-p) - "Prompt for a project file. -This function is similar to `project-find-file', but it returns the path -to the selected file instead of opening it. - -When called interactively the selected file is printed to the minibuffer, -otherwise it is returned. - -The prefix argument INCLUDE-ALL-P is the same as the INCLUDE-ALL argument -to the `project-find-file' command." - (interactive "P") - (let* ((project (project-current :maybe-prompt)) - (root (project-root project)) - (files (if include-all-p - (let ((vc-ignores (mapcar - (lambda (dir) (concat dir "/")) - vc-directory-exclusion-list))) - (project--files-in-directory root vc-ignores)) - (project-files project))) - (canditates (mapcar (lambda (f) (file-relative-name f root)) - files)) - (table (lambda (string predicate action) - (if (eq action 'metadata) - '(metadata (category . file)) - (complete-with-action action canditates string predicate)))) - (default-directory root) - (choice (completing-read (format-prompt "Find project file" nil) - table nil :require-match))) - (let ((path (expand-file-name choice root))) - (if (called-interactively-p 'any) - (message "%s" path) - path)))) - -(defun mm-humanwave-insert-last-commit-message () - "TODO" - (interactive) - (insert - (with-temp-buffer - (call-process "git" nil t nil "log" "-1" "--pretty=%s") - (goto-char (point-min)) - (replace-regexp "\\`HW-[0-9]+ " "") - (string-trim (buffer-string))))) - - -;;; Jira Integration - -(use-package jira - :ensure t - :custom - (jira-api-version 3) - (jira-base-url "https://humanwave.atlassian.net") - (jira-detail-show-announcements nil) - (jira-issues-max-results 100) - (jira-issues-table-fields '(:key :status-name :assignee-name :summary)) - (jira-token-is-personal-access-token nil)) - - -;;; Icon Autocompletion - -(defvar mm-humanwave-icon-component-file "web/src/components/icon.vue" - "Path to the component definition.") - -(defun mm-humanwave--find-icon-map () - (let* ((project (project-current :maybe-prompt)) - (path (expand-file-name mm-humanwave-icon-component-file - (project-root project)))) - (unless (file-exists-p path) - (user-error "File `%s' does not exist." path)) - (with-current-buffer (find-file-noselect path) - (let* ((parser (treesit-parser-create 'typescript)) - (root-node (treesit-parser-root-node parser)) - (query `((((lexical_declaration - (variable_declarator - name: (identifier) @name)) @the_catch) - (:equal @name "ICON_MAP")) - (((variable_declaration - (variable_declarator - name: (identifier) @name)) @the_catch) - (:equal @name "ICON_MAP")))) - (captures (treesit-query-capture root-node query)) - (found-node (alist-get 'the_catch captures))) - found-node)))) - -(defun mm-humanwave--icon-list (found-node) - (let ((captures (treesit-query-capture found-node '((pair) @the_pair))) - (pairs nil)) - (when captures - (dolist (capture captures) - (let* ((pair-node (cdr capture)) - (key-node (treesit-node-child-by-field-name pair-node "key")) - (val-node (treesit-node-child-by-field-name pair-node "value"))) - (when (and key-node val-node) - (push (cons (mm-camel-to-lisp - (treesit-node-text key-node :no-property)) - (treesit-node-text val-node :no-property)) - pairs)))) - (sort pairs :key #'car :lessp #'string<)))) - -(defun mm-humanwave-insert-icon-component () - "Insert an icon at point with completion. - -This command provides completion for the available props that can be -given to the component. The parser searches for the `ICON_MAP' -definition in the file specified by `mm-humanwave-icon-component-file'." - (interactive "" vue-ts-mode) - (if-let* ((node (mm-humanwave--find-icon-map)) - (alist (mm-humanwave--icon-list node))) - (let* ((max-key-width - (thread-last - alist - (mapcar (lambda (pair) (length (car pair)))) - (apply #'max) - (+ 4))) - (completion-extra-properties - `(:annotation-function - ,(lambda (key) - (concat - (propertize " " - 'display `(space :align-to ,max-key-width)) - (propertize (cdr (assoc key alist)) - 'face 'font-lock-string-face))))) - (prompt (format-prompt "Icon" nil)) - (icon (completing-read prompt alist nil :require-match))) - (insert (format "" icon))) - (error "Unable to find ICON_MAP definitions"))) - -(provide 'mm-humanwave) diff --git a/.config/emacs/modules/mm-keybindings.el b/.config/emacs/modules/mm-keybindings.el deleted file mode 100644 index 1480451..0000000 --- a/.config/emacs/modules/mm-keybindings.el +++ /dev/null @@ -1,188 +0,0 @@ -;;; mm-keybindings.el --- Emacs keybindings -*- lexical-binding: t; -*- - -(require 'editing) - -;; The following keys are either unbound and are free to populate, or are -;; bound to functions I don’t care for: -;; ‘C-i’, ‘C-j’, ‘C-o’, ‘C-{’, ‘C-}’, ‘C-|’, ‘C-/’, ‘C-\;’, ‘C-:’ - - -;;; Helper Macros - -(defmacro mm-keymap-set (keymap &rest definitions) - (declare (indent 1)) - (unless (cl-evenp (length definitions)) - (user-error "Expected an even-number of elements in DEFINITIONS.")) - `(cl-loop for (from to) on (list ,@definitions) by #'cddr - do (keymap-set ,keymap from to))) - -(defmacro mm-keymap-set-repeating (keymap &rest definitions) - (declare (indent 1)) - (unless (cl-evenp (length definitions)) - (user-error "Expected an even-number of elements in DEFINITIONS.")) - (let ((keymap-gen (gensym "mm-keybindings--repeat-map-"))) - `(progn - (defvar-keymap ,keymap-gen) - (cl-loop for (from to) on (list ,@definitions) by #'cddr - do (progn - (keymap-set ,keymap-gen from to) - (put to 'repeat-map ',keymap-gen)))))) - -(defmacro mm-keymap-remap (keymap &rest commands) - "Define command remappings for a given KEYMAP. -COMMANDS is a sequence of unquoted commands. For each pair of COMMANDS -the first command is remapped to the second command." - (declare (indent 1)) - (unless (cl-evenp (length commands)) - (user-error "Expected an even-number of elements in COMMANDS.")) - (macroexp-progn - (cl-loop for (from to) in (seq-partition commands 2) - collect `(keymap-set - ,keymap - ,(concat " <" (symbol-name from) ">") - #',to)))) - - -;;; Support the Kitty Keyboard Protocol - -(use-package kkp - :ensure t - :unless (or (display-graphic-p) mm-humanwave-p) - :hook (tty-setup . global-kkp-mode)) - - -;;; Support QMK Hyper - -(defun mm-qmk-hyper-as-hyper (args) - (let ((chord (cadr args))) - (when (string-prefix-p "H-" chord) - (setf (cadr args) (concat "C-M-S-s" (substring chord 1))))) - args) - -;; Both ‘keymap-global-set’ and ‘keymap-local-set’ call ‘keymap-set’ -;; internally, so this advice covers all cases -(advice-add #'keymap-set :filter-args #'mm-qmk-hyper-as-hyper) - - -;;; Disable ESC as Meta - -(keymap-global-set "" #'ignore) - - -;;; Enable Repeat Bindings - -(defun mm-enable-repeat-mode () - "Enable `repeat-mode' without polluting the echo area." - (mm-with-suppressed-output - (repeat-mode))) - -(use-package repeat - :hook (after-init . mm-enable-repeat-mode) - :custom - (repeat-exit-timeout 5)) - - -;;; Remap Existing Bindings - -(mm-keymap-remap global-map - backward-delete-char-untabify backward-delete-char - - capitalize-word capitalize-dwim - downcase-word downcase-dwim - upcase-word upcase-dwim - - delete-indentation e/join-current-and-next-line - kill-ring-save e/kill-ring-save-dwim - mark-sexp e/mark-entire-sexp - mark-word e/mark-entire-word - open-line e/open-line - yank e/yank) - -(with-eval-after-load 'cc-vars - (setopt c-backspace-function #'backward-delete-char)) - - -;;; Remove Unwanted Bindings - -(keymap-global-unset "C-x C-c" :remove) ; ‘capitalize-region’ -(keymap-global-unset "C-x C-l" :remove) ; ‘downcase-region’ -(keymap-global-unset "C-x C-u" :remove) ; ‘upcase-region’ - -;; The following conflict with ‘ace-window’ -(with-eval-after-load 'mhtml-mode - (keymap-unset html-mode-map "M-o" :remove)) - - -;;; Bind Commands Globally - -(mm-keymap-set global-map - ;; "" #'e/scroll-up - ;; "" #'e/scroll-down - "C-" #'forward-page - "C-" #'backward-page - - "C-." #'repeat - "C-^" #'e/split-line - "C-/" #'e/mark-line-dwim - - "C-]" #'mm-search-forward-char - "M-]" #'mm-search-backward-char - - "M-\\" #'cycle-spacing - - "C-M-@" #'mm-add-cursor-to-next-word - - "C-c c a" #'mc/vertical-align-with-space - "C-c c i" #'mc/insert-numbers - "C-c c t" #'mm-transpose-cursor-regions - "C-c d" #'duplicate-dwim - "C-c t a" #'e/align-regexp - "C-c t f" #'fill-paragraph - "C-c t s" #'e/sort-dwim) - -(mm-keymap-set-repeating global-map - "j" #'e/join-current-and-next-line - "J" #'join-line) - -(mm-keymap-set-repeating global-map - "n" #'next-error - "p" #'previous-error) - -(with-eval-after-load 'increment - (mm-keymap-set-repeating global-map - "d" #'decrement-number-at-point - "i" #'increment-number-at-point)) - - -;;; Other Bindings - -(with-eval-after-load 'project - (mm-keymap-set project-prefix-map - "g" #'mm-project-find-regexp - "G" #'project-git-grab) - - (when mm-humanwave-p - (mm-keymap-set project-prefix-map - "q" #'mm-humanwave-query))) - -(with-eval-after-load 'eat - (with-eval-after-load 'ace-window - (mm-keymap-set eat-semi-char-mode-map - "M-o" #'ace-window))) - -(with-eval-after-load 'minibuffer - (when mm-humanwave-p - (mm-keymap-set minibuffer-mode-map - "C-c m" #'mm-humanwave-insert-last-commit-message))) - - -;;; Display Available Keybindings - -(use-package which-key - :hook after-init - :custom - (which-key-dont-use-unicode nil) - (which-key-ellipsis "…") - (wihch-key-idle-delay .5)) - -(provide 'mm-keybindings) diff --git a/.config/emacs/modules/mm-lsp.el b/.config/emacs/modules/mm-lsp.el deleted file mode 100644 index 3a64f49..0000000 --- a/.config/emacs/modules/mm-lsp.el +++ /dev/null @@ -1,45 +0,0 @@ -;;; mm-lsp.el --- Language Server Protocol configuration -*- lexical-binding: t; -*- - -;;; Configure LSP - -(defun mm-lsp-eglot-no-inlay-hints () - "Disable inlay hints when `eglot' is enabled." - (eglot-inlay-hints-mode -1)) - -(use-package eglot - :hook (((c-mode c-ts-mode - c++-mode c++-ts-mode - go-ts-mode - js-mode js-ts-mode) - . eglot-ensure) - (eglot-managed-mode . mm-lsp-eglot-no-inlay-hints)) - :init - (fset #'jsonrpc--log-event #'ignore) - :custom - (eglot-events-buffer 0) - (eglot-extend-to-xref t) - :config - (add-to-list 'eglot-stay-out-of 'flymake) - (add-to-list 'eglot-server-programs - '((c-mode c-ts-mode c++-mode c++-ts-mode) - . ("clangd" "--header-insertion=never")))) - -(use-package eglot-booster - :after eglot - :config - (eglot-booster-mode)) - - -;;; Use Tempel for Snippets - -(defun mm-lsp-eglot-tempel-enable () - "Enable `eglot-tempel-mode'. -If `eglot-tempel-mode' is already enabled this function does nothing." - (unless (default-value eglot-tempel-mode) - (eglot-tempel-mode))) - -(use-package eglot-tempel - :after eglot - :hook (eglot-managed-mode . mm-lsp-eglot-tempel-enable)) - -(provide 'mm-lsp) \ No newline at end of file diff --git a/.config/emacs/modules/mm-modeline.el b/.config/emacs/modules/mm-modeline.el deleted file mode 100644 index 9a35d04..0000000 --- a/.config/emacs/modules/mm-modeline.el +++ /dev/null @@ -1,147 +0,0 @@ -;;; mm-modeline.el --- Pluggable modeline components -*- lexical-binding: t; -*- - -(defmacro mm-modeline--define-component (name &rest forms) - (declare (indent 1)) - `(progn - (defface ,(intern (format "%s-face" name)) - '((t)) - ,(format "Face for the `%s' component." name)) - (defvar-local ,name '(:eval (or ,(macroexp-progn forms) ""))) - (put ',name 'risky-local-variable t))) - - -;;; Support Icons - -(use-package all-the-icons - :ensure t - :init - (defvar mm-all-the-icons-cookie - (expand-file-name ".all-the-icons-installed-p" mm-cache-directory)) - (unless (file-exists-p mm-all-the-icons-cookie) - (all-the-icons-install-fonts) - (make-empty-file mm-all-the-icons-cookie :parents)) - (set-char-table-range char-width-table #xE907 2)) - - -;;; Modeline Components - -(mm-modeline--define-component mm-modeline-overwrite - (when overwrite-mode - (propertize " OVERWRITE" 'face 'mm-modeline-overwrite-face))) - -(mm-modeline--define-component mm-modeline-readonly - (when buffer-read-only - (propertize " READONLY" 'face 'mm-modeline-readonly-face))) - -(mm-modeline--define-component mm-modeline-buffer-name - (propertize "%b" 'face 'mm-modeline-buffer-name-face)) - -(mm-modeline--define-component mm-modeline-buffer-modified - (when (and (buffer-modified-p) - (buffer-file-name)) - (propertize " (modified)" 'face 'mm-modeline-buffer-modified-face))) - -(defconst mm-modeline-mode-acronyms - '("css" "csv" "gsp" "html" "json" "mhtml" "rfc" "scss" "sql" "toml" "tsv" - "url" "yaml") - "List of acronyms in major mode names that should be capitalized.") - -(defconst mm-modeline-remap-alist - '(("Bmenu" . "BMenu") - ("Bsdmake" . "BSD Make") - ("Gitattributes" . "Git Attributes") - ("Gitconfig" . "Git Config") - ("Gitignore" . "Git Ignore") - ("Gmake" . "GMake") - ("Imake" . "IMake") - ("Js" . "JavaScript") - ("Ts Mode" . "Tree-Sitter Mode") - ("Wdired" . "WDired") - ("Xcompose" . "XCompose")) - "Alist of substrings in major mode names that should be remapped. -Some major modes have substrings that would be better displayed in -another manner. For example expanding an abbreviation such as ‘Js’ to -its expanded form ‘JavaScript’, or fixing the casing of words with a -prefix such as ‘Gmake’ to ‘GMake’. This alist maps the original text to -the text it should be mapped to.") - -(mm-modeline--define-component mm-modeline-major-mode-name - (propertize - (let ((string (thread-last - major-mode - (symbol-name) - (capitalize) - (string-replace "-" " "))) - (case-fold-search nil)) - (save-match-data - (dolist (pair mm-modeline-remap-alist) - (setq string - (replace-regexp-in-string - (format "\\<%s\\>" (regexp-quote (car pair))) - (cdr pair) string))) - (setq case-fold-search t) - (if (string-match (regexp-opt mm-modeline-mode-acronyms 'words) string) - (concat - (substring string 0 (match-beginning 0)) - (upcase (substring string (match-beginning 0) (match-end 0))) - (substring string (match-end 0) (length string))) - string))) - 'face 'mm-modeline-major-mode-name-face)) - -(mm-modeline--define-component mm-modeline-major-mode-symbol - (propertize - (cond - ((derived-mode-p 'comint-mode) "$ ") - ((derived-mode-p 'conf-mode) "# ") - ((derived-mode-p 'prog-mode) "λ ") - ((derived-mode-p 'special-mode) "★ ") - ((derived-mode-p 'text-mode) "§ ") - (:default "")) - 'face 'mm-modeline-major-mode-symbol-face)) - -(mm-modeline--define-component mm-modeline-narrow - (when (buffer-narrowed-p) - (propertize - " NARROW " - 'face 'mm-modeline-narrow-face))) - -(mm-modeline--define-component mm-modeline-git-branch - (when-let ((branch (car (and (featurep 'vc-git) - (vc-git-branches))))) - (concat - (propertize "\uE907" 'display '(raise 0)) - " " - (propertize branch 'face 'mm-modeline-git-branch-face) - " │ "))) - - -;;; Padding Between Left and Right - -(mm-modeline--define-component mm-modeline-left-right-padding - (let ((length (string-width (format-mode-line mm-modeline-right)))) - (propertize " " 'display `(space :align-to (- right ,length))))) - - -;;; Configure Modeline - -(setopt mode-line-format-right-align 'right-margin) - -(setq - mm-modeline-left (list mm-modeline-narrow - mm-modeline-overwrite - mm-modeline-readonly - " " - mm-modeline-buffer-name - mm-modeline-buffer-modified - " │ " - mm-modeline-major-mode-symbol - mm-modeline-major-mode-name - mm-modeline-left-right-padding - mode-line-end-spaces) - mm-modeline-right (list mm-modeline-git-branch - "%l:%c ")) - -(setq-default - mode-line-format - (list mm-modeline-left mm-modeline-left-right-padding mm-modeline-right)) -(provide 'mm-modeline) diff --git a/.config/emacs/modules/mm-org.el b/.config/emacs/modules/mm-org.el deleted file mode 100644 index b4d0f31..0000000 --- a/.config/emacs/modules/mm-org.el +++ /dev/null @@ -1,6 +0,0 @@ -;;; mm-org.el --- Org-Mode configuration -*- lexical-binding: t; -*- - -(use-package org - :hook (org-mode . org-indent-mode)) - -(provide 'mm-org) \ No newline at end of file diff --git a/.config/emacs/modules/mm-projects.el b/.config/emacs/modules/mm-projects.el deleted file mode 100644 index 02d7af4..0000000 --- a/.config/emacs/modules/mm-projects.el +++ /dev/null @@ -1,114 +0,0 @@ -;;; mm-projects.el --- Configuration for project management -*- lexical-binding: t; -*- - -;;; Project Configuration - -(defun mm-projects-project-magit-status () - "Open a Git status buffer for the current project. -This is intended to be called interactively via - `project-switch-commands'." - (interactive) - (thread-last - (project-current t) - (project-root) - (magit-status-setup-buffer))) - -(use-package project - :custom - (project-switch-commands - '((project-dired "Dired" ?d) - (project-find-file "Find File" ?f) - (mm-projects-project-magit-status "Git Status" ?s))) - :config - (unless mm-humanwave-p - (if-let ((repo-directory (getenv "REPODIR"))) - (let* ((list-dir - (lambda (path) - (directory-files path :full "\\`[^.]"))) - (directories - (cl-loop for author in (funcall list-dir (getenv "REPODIR")) - append (cl-loop for path in (funcall list-dir author) - collect (list (concat path "/")))))) - (with-temp-buffer - (prin1 directories (current-buffer)) - (write-file project-list-file)) - (project--read-project-list)) - (warn "The REPODIR environment variable is not set.")))) - - -;;; Emacs VC - -(use-package vc-hooks - :custom - (vc-follow-symlinks t) - (vc-handled-backends '(Git))) - - -;;; Git Client - -(use-package magit - :ensure t - :bind (("C-c b" . magit-blame-addition) - :map magit-status-mode-map - ("[" . magit-section-backward-sibling) - ("]" . magit-section-forward-sibling)) - :custom - (git-commit-style-convention-checks - '(non-empty-second-line overlong-summary-line)) - (git-commit-summary-max-length 50) - (magit-diff-refine-hunk t) - (magit-display-buffer-function - #'magit-display-buffer-same-window-except-diff-v1) - (transient-default-level 7) - :config - (transient-define-suffix mm-projects-magit-push-current-to-all-remotes (args) - "Push the current branch to all remotes." - :if #'magit-get-current-branch - (interactive (list (magit-push-arguments))) - (run-hooks 'magit-credential-hook) - (let ((branch (magit-get-current-branch))) - (dolist (remote (magit-list-remotes)) - (magit-run-git-async - "push" "-v" args remote - (format "refs/heads/%s:refs/heads/%s" branch branch))))) - (transient-append-suffix #'magit-push '(1 -1) - '("a" "all remotes" mm-projects-magit-push-current-to-all-remotes)) - (add-to-list 'magit-blame-styles - '(margin - (show-lines . t) - (margin-format . (" %C %a" " %s%f" " ")) - (margin-width . 73) - (margin-face . magit-blame-margin) - (margin-body-face . (magit-blame-dimmed))))) - -(use-package magit-repos - :ensure nil ; Part of ‘magit’ - :if (not mm-humanwave-p) - :commands (magit-list-repositories) - :init - (if-let ((directory (getenv "REPODIR"))) - (setopt magit-repository-directories `((,directory . 2))) - (warn "The REPODIR environment variable is not set."))) - -(use-package magit-todos - :ensure t - :after magit - :hook magit-mode - :custom - (magit-todos-exclude-globs '("vendor/"))) - - -;; Project Compilation - -(use-package compile - :config - (require 'ansi-color) - (add-hook 'compilation-filter-hook #'ansi-color-compilation-filter)) - - -;;; GitHub Pull Requests - -(require 'gh) -(keymap-global-set "C-c p c" #'gh-create-pr) -(keymap-global-set "C-c p o" #'gh-open-previous-pr) - -(provide 'mm-projects) diff --git a/.config/emacs/modules/mm-search.el b/.config/emacs/modules/mm-search.el deleted file mode 100644 index c89b9d0..0000000 --- a/.config/emacs/modules/mm-search.el +++ /dev/null @@ -1,57 +0,0 @@ -;;; mm-search.el --- Emacs text searching -*- lexical-binding: t; -*- - -;;; Classic Emacs text search - -(use-package isearch - :demand t - :bind ( :map isearch-mode-map - ("M-/" . isearch-complete) - :map minibuffer-local-isearch-map - ("M-/" . isearch-complete-edit)) - :custom - (search-whitespace-regexp ".*?") - (isearch-lax-whitespace t) - (isearch-regexp-lax-whitespace nil) - (isearch-lazy-count t) - (lazy-highlight-initial-delay 0) - (lazy-count-prefix-format "(%s/%s) ") - (isearch-repeat-on-direction-change t)) - -(defun mm--project-find-wrapper (command regexp) - (let (csf) - (cond ((string-suffix-p "/i" regexp) - (setq regexp (string-remove-suffix "/i" regexp) - csf t)) - ((string-suffix-p "/I" regexp) - (setq regexp (string-remove-suffix "/I" regexp) - csf nil)) - (:else - (setq csf case-fold-search))) - (let ((case-fold-search csf)) - (funcall-interactively command regexp)))) - -(defun mm-project-find-regexp (regexp) - "Find all matches for REGEXP in the current project’s roots. -This is a thin wrapper around `project-find-regexp' that supports the -`/i' and `/I' suffixes to enable and disable case-sensitive matching -respectively." - (interactive (list (project--read-regexp))) - (mm--project-find-wrapper #'project-find-regexp regexp)) - -(defun mm-project-or-external-find-regexp (regexp) - "Find all matches for REGEXP in the project roots or external roots. -This is a thin wrapper around `project-or-external-find-regexp' that -supports the `/i' and `/I' suffixes to enable and disable case-sensitive -matching respectively." - (interactive (list (project--read-regexp))) - (mm--project-find-wrapper #'project-or-external-find-regexp regexp)) - - -;;; Grab Integration - -(use-package grab - :commands (grab git-grab project-grab project-git-grab) - :custom - (grab-default-pattern '("x/^.*?$/ g// h//" . 12))) - -(provide 'mm-search) diff --git a/.config/emacs/modules/mm-spellcheck.el b/.config/emacs/modules/mm-spellcheck.el deleted file mode 100644 index 95db7ac..0000000 --- a/.config/emacs/modules/mm-spellcheck.el +++ /dev/null @@ -1,24 +0,0 @@ -;;; mm-spellcheck.el --- Spell checking configuration -*- lexical-binding: t; -*- - -;;; ISpell Spell Checking - -(use-package ispell - :hook (flyspell-mode . ispell-minor-mode) - :custom - (ispell-program-name "hunspell") - (ispell-local-dictionary "en_US") - (ispell-local-dictionary-alist - '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[’']" - nil ("-d" "en_US") nil utf-8))) - (ispell-hunspell-dictionary-alist ispell-local-dictionary-alist)) - - -;;; On-The-Fly Spell Checking - -(use-package flyspell - :defer t - :config - ;; I use ‘C-,’ for ‘emmet-expand-line’ - (keymap-unset flyspell-mode-map "C-," :remove)) - -(provide 'mm-spellcheck) diff --git a/.config/emacs/modules/mm-tetris.el b/.config/emacs/modules/mm-tetris.el deleted file mode 100644 index 06fae58..0000000 --- a/.config/emacs/modules/mm-tetris.el +++ /dev/null @@ -1,20 +0,0 @@ -;;; mm-tetris.el --- Emacs configurations for ‘tetris’ -*- lexical-binding: t; -*- - -(defun mm-tetris-rotate-mirror () - "Rotate the current piece by 180°." - (declare (modes tetris-mode)) - (interactive) - (tetris-rotate-next) - (tetris-rotate-next)) - -(use-package tetris - :bind (:map tetris-mode-map - ("a" . tetris-move-left) - ("d" . tetris-move-right) - ("k" . tetris-rotate-next) - (";" . tetris-rotate-prev) - ("l" . tetris-move-down) - ("o" . mm-tetris-rotate-mirror) - ("SPC" . tetris-move-bottom))) - -(provide 'mm-tetris) diff --git a/.config/emacs/modules/mm-theme.el b/.config/emacs/modules/mm-theme.el deleted file mode 100644 index 89cdffd..0000000 --- a/.config/emacs/modules/mm-theme.el +++ /dev/null @@ -1,246 +0,0 @@ -;;; mm-theme.el --- Emacs theme settings -*- lexical-binding: t; -*- - - -;;; Custom Theme - -(load-theme 'mango :no-confirm) - - -;;; Fonts - -(defvar mm-theme-monospace-font `(,(if mm-humanwave-p - "Iosevka Custom" - "Iosevka Smooth") - :weight regular - :height 162) - "The default monospace font. -This is a plist containing a font name, -weight, and -height.") - -(defvar mm-theme-proportional-font - `(,(if mm-darwin-p "Microsoft Sans Serif" "Source Sans 3 Medium") - :weight regular :height 162) - "The default proportional font. -This is a plist containing a font name, -weight, and -height.") - -(defun mm-theme-set-fonts (&optional _frame) - "Set frame font settings. -Sets the frame font settings according to the fonts specified by -`mm-theme-monospace-font' and `mm-theme-proportional-font'. - -This function can be used as a hook in `after-make-frame-functions' and -_FRAME is ignored." - (interactive) - (let* ((mono-family (car mm-theme-monospace-font)) - (mono-props (cdr mm-theme-monospace-font)) - (prop-family (car mm-theme-proportional-font)) - (prop-props (cdr mm-theme-proportional-font)) - (mono-weight (plist-get mono-props :weight)) - (mono-height (plist-get mono-props :height)) - (prop-weight (plist-get prop-props :weight)) - (prop-height (plist-get prop-props :height))) - ;; Some characters in this font are larger than usual - (when (string= mono-family "Iosevka Smooth") - (dolist (rune '(?․ ?‥ ?… ?— ?← ?→ ?⇐ ?⇒ ?⇔)) - (set-char-table-range char-width-table rune 2))) - (set-face-attribute 'default nil - :font mono-family - :weight mono-weight - :height mono-height) - (set-face-attribute 'fixed-pitch nil - :font mono-family - :weight mono-weight - :height mono-height) - (set-face-attribute 'variable-pitch nil - :font prop-family - :weight prop-weight - :height prop-height))) - -(if (daemonp) - (add-hook 'after-make-frame-functions #'mm-theme-set-fonts) - (mm-theme-set-fonts)) - -;; Ligature Settings - -(defvar mm-theme-ligatures-alist - `(((c-mode c-ts-mode c++-mode c++-ts-mode) - . ("->")) - ((c++-mode c++-ts-mode) - . ("::")) - ((js-mode js-ts-mode typescript-ts-mode vue-ts-mode) - . (("=" ,(rx (or ?> (** 1 2 ?=)))) - ("!" ,(rx (** 1 2 ?=))))) - (go-ts-mode - . (":=" "<-")) - ((python-mode python-ts-mode) - . (":=" "->")) - ((mhtml-mode html-mode html-ts-mode vue-ts-mode) - . ("" "/>")) - (prog-mode - . ("<<=" "<=" ">=" "==" "!=" "*=" "__"))) - "Ligatures to enable in specific modes. -Elements of this alist are of the form: - - (SPEC . LIGATURES) - -Where LIGATURES is a list of ligatures to enable for the set of modes -described by SPEC. - -SPEC can be either a symbol, or a list of symbols. These symbols should -correspond to modes for which the associated LIGATURES should be enabled. - -A mode may also be specified in multiple entries. To configure -`go-ts-mode' to have its set of ligatures be a super-set of the -ligatures for `c-ts-mode', the following two entries could be added: - - \\='((c-ts-mode go-ts-mode) . (\">=\" \"<=\" \"!=\" \"==\")) - \\='(go-ts-mode . (\":=\"))") - -(defun mm-theme-update-ligatures () - "Update the ligature composition tables. -After running this function you may need to restart `ligature-mode'. - -Also see `mm-theme-ligatures-alist'." - (interactive) - (setopt ligature-composition-table nil) - (cl-loop for (spec . ligatures) in mm-theme-ligatures-alist - do (ligature-set-ligatures spec ligatures))) - -(use-package ligature - :ensure t - :if (or mm-darwin-p - (seq-contains-p (split-string system-configuration-features) - "HARFBUZZ")) - :hook prog-mode - :config - (mm-theme-update-ligatures)) - - -;;; Background Opacity - -(defvar mm-theme-background-opacity 100 - "Opacity of the graphical Emacs frame. -A value of 0 is fully transparent while 100 is fully opaque.") - -(defun mm-theme-background-opacity (opacity) - "Set the current frames' background opacity. -See also the `mm-theme-background-opacity' variable." - (interactive - (list (mm-as-number - (read-string - (format-prompt "Background opacity" - (default-value 'mm-theme-background-opacity)) - nil nil mm-theme-background-opacity)))) - (set-frame-parameter nil 'alpha-background opacity)) - -(add-to-list - 'default-frame-alist (cons 'alpha-background mm-theme-background-opacity)) - - -;;; Divider Between Windows - -(use-package frame - :hook (after-init . window-divider-mode)) - - -;;; Pulse Line on Jump - -(use-package pulsar - :ensure t - :hook (after-init . pulsar-global-mode) - :custom - (pulsar-pulse t) - (pulsar-delay .05) - (pulsar-iterations 10) - (pulsar-face 'hl-line) - :config - (dolist (command #'(backward-paragraph - e/scroll-down - e/scroll-up - forward-paragraph - jump-to-register - pop-global-mark)) - (add-to-list 'pulsar-pulse-functions command)) - ;; Integrate with ‘compilation-mode’ - (add-hook 'next-error-hook #'pulsar-pulse-line) - :bind - (("C-c h l" . pulsar-highlight-dwim))) - - -;;; In-buffer highlighting - -(require 'hi-lock) ; For extra face definitions -(use-package highlighter - :bind (("C-c h m" . #'highlighter-mark) - ("C-c h u" . #'highlighter-unmark) - ("C-c h U" . #'highlighter-unmark-buffer)) - :commands (highlighter-mark highlighter-unmark highlighter-unmark-buffer)) - - -;;; Add Padding - -(use-package spacious-padding - :ensure t - :hook after-init) - - -;;; Pretty Page Boundaries - -(use-package page-break-lines - :ensure t - :hook (after-init . global-page-break-lines-mode) - :config - (dolist (mode '(c-mode c++-mode gsp-ts-mode)) - (add-to-list 'page-break-lines-modes mode) - (let ((ts-mode (mm-mode-to-ts-mode mode))) - (when (fboundp ts-mode) - (add-to-list 'page-break-lines-modes ts-mode)))) - (add-hook - 'change-major-mode-hook - (defun mm-theme--set-page-break-max-width () - (setopt page-break-lines-max-width fill-column))) - ;; Since the ‘^L’ character is replaced by a horizontal rule, the - ;; cursor should appear below the horizontal rule. When moving - ;; backwards we need to account for the fact that the cursor is - ;; actually one character ahead of hte page break and adjust - ;; accordingly. - (advice-add - #'forward-page :after - (defun mm-theme--forward-char (&rest _) - (forward-char))) - (advice-add - #'backward-page :before - (defun mm-theme--backward-char (&rest _) - (backward-char)))) - - -;;; More Intuiative UI for Certain Modes - -(defun mm-disable-line-selection-mode () - (line-selection-mode -1)) - -(use-package line-selection-mode - :hook ((bookmark-bmenu-mode dired-mode ibuffer-mode magit-repolist-mode) - . line-selection-mode) - :config - (add-hook 'wdired-mode-hook #'mm-disable-line-selection-mode)) - - -;;; Line Highlighting - -(use-package hl-line - :custom - (hl-line-sticky-flag nil)) - - -;;; Indent Guides - -(when mm-humanwave-p - (use-package highlight-indent-guides - :ensure t - :hook ((jinja2-mode vue-ts-mode mhtml-mode) . highlight-indent-guides-mode) - :custom - (highlight-indent-guides-method 'fill) - (highlight-indent-guides-auto-even-face-perc 30) - (highlight-indent-guides-auto-odd-face-perc 0))) - -(provide 'mm-theme) diff --git a/.config/emacs/modules/mm-treesit.el b/.config/emacs/modules/mm-treesit.el deleted file mode 100644 index 81d0801..0000000 --- a/.config/emacs/modules/mm-treesit.el +++ /dev/null @@ -1,240 +0,0 @@ -;;; mm-treesit.el --- Tree-Sitter configuration -*- lexical-binding: t; -*- - -(unless (treesit-available-p) - (error "Tree-Sitter is not available.")) - - -;;; Tree-Sitter Variables - -(defvar mm-treesit-language-remap-alist - '((cpp . c++) - (gomod . go-mod) - (javascript . js) - (vim . vimscript)) - "TODO") - -(setopt treesit-font-lock-level 4) -(setopt treesit-language-source-alist - '((awk - "https://github.com/Beaglefoot/tree-sitter-awk") - (c - "https://github.com/tree-sitter/tree-sitter-c") - (cpp - "https://github.com/tree-sitter/tree-sitter-cpp") - (css - "https://github.com/tree-sitter/tree-sitter-css") - (dockerfile - "https://github.com/camdencheek/tree-sitter-dockerfile") - (elixir - "https://github.com/elixir-lang/tree-sitter-elixir") - (go - "https://github.com/tree-sitter/tree-sitter-go") - (gomod - "https://github.com/camdencheek/tree-sitter-go-mod") - (gsp - "git://git.thomasvoss.com/tree-sitter-gsp.git") - (heex - "https://github.com/phoenixframework/tree-sitter-heex") - (html - "https://github.com/tree-sitter/tree-sitter-html") - (java - "https://github.com/tree-sitter/tree-sitter-java") - (javascript - "https://github.com/tree-sitter/tree-sitter-javascript") - (json - "https://github.com/tree-sitter/tree-sitter-json") - (markdown - "https://github.com/tree-sitter-grammars/tree-sitter-markdown" - "split_parser" "tree-sitter-markdown/src") - (markdown-inline - "https://github.com/tree-sitter-grammars/tree-sitter-markdown" - "split_parser" "tree-sitter-markdown-inline/src") - (python - "https://github.com/tree-sitter/tree-sitter-python") - (rust - "https://github.com/tree-sitter/tree-sitter-rust") - (tsx - "https://github.com/tree-sitter/tree-sitter-typescript" - "master" "tsx/src") - (typescript - "https://github.com/tree-sitter/tree-sitter-typescript" - "master" "typescript/src") - (vim - "https://github.com/tree-sitter-grammars/tree-sitter-vim") - (vue - "https://github.com/ikatyang/tree-sitter-vue") - (yaml - "https://github.com/tree-sitter-grammars/tree-sitter-yaml"))) - - -;;; Install Missing Parsers - -(defun mm-treesit-install-all () - "Install all Tree-Sitter parsers. -This is like `mm-treesit-install-missing' but also reinstalls parsers -that are already installed." - (interactive) - (cl-loop for (lang) in treesit-language-source-alist - do (treesit-install-language-grammar lang))) - -(defun mm-treesit-install-missing () - "Install missing Tree-Sitter parsers. -The parsers are taken from `treesit-language-source-alist'." - (interactive) - (cl-loop for (lang) in treesit-language-source-alist - unless (treesit-language-available-p lang) - do (treesit-install-language-grammar lang))) - -(mm-treesit-install-missing) - - -;;; Install Additional TS Modes - -(use-package gsp-ts-mode - :vc (:url "https://git.thomasvoss.com/gsp-ts-mode" - :branch "master" - :rev :newest - :vc-backend Git) - :ensure t) - -;; NOTE: This package doesn’t autoload its ‘auto-mode-alist’ entries -(use-package vimscript-ts-mode - :ensure t - :mode (rx (or (seq (? (or ?. ?_)) (? ?g) "vimrc") - ".vim" - ".exrc") - eos)) - -;; NOTE: This package doesn’t autoload its ‘auto-mode-alist’ entries -(use-package vue-ts-mode - :vc ( :url "https://github.com/8uff3r/vue-ts-mode.git" - :branch "main" - :rev :newest - :vc-backend Git) - :ensure t - :mode "\\.vue\\'") - -;; NOTE: This package doesn’t autoload its ‘auto-mode-alist’ entries -(use-package markdown-ts-mode - :ensure t - :mode "\\.md\\'") - - -;;; Prefer Tree-Sitter Modes - -;; NOTE: ‘go-ts-mode’ already adds itself to ‘auto-mode-alist’ but it -;; isn’t autoloaded as of 2024-09-29 so we need to do it ourselves -;; anyway. Same goes for ‘typescript-ts-mode’. -(defvar mm-treesit-language-file-name-alist - '((dockerfile . "/[Dd]ockerfile\\'") - (elixir . "\\.exs?\\'") - (go . "\\.go\\'") - (gomod . "/go\\.mod\\'") - (heex . "\\.heex\\'") - (json . "\\.json\\'") - (rust . "\\.rs\\'") - (tsx . "\\.tsx\\'") - (typescript . "\\.ts\\'") - (yaml . "\\.ya?ml\\'")) - "Alist mapping languages to their associated file-names. -This alist is a set of pairs of the form (LANG . REGEXP) where LANG is -the symbol corresponding to a major mode with the `-ts-mode' suffix -removed. REGEXP is a regular expression matching filenames for which -the associated language’s major-mode should be enabled. - -This alist is used to configure `auto-mode-alist'.") - -(defvar mm-treesit-dont-have-modes - '(markdown-inline) - "List of languages that don't have modes. -Some languages may come with multiple parsers, (e.g. `markdown' and -`markdown-inline') and as a result one-or-more of the parsers won't be -associated with a mode. To avoid breaking the configuration, these -languages should be listed here.") - -(dolist (spec treesit-language-source-alist) - (let* ((lang (car spec)) - (lang-remap (alist-get lang mm-treesit-language-remap-alist lang)) - (name-mode (intern (format "%s-mode" lang-remap))) - (name-ts-mode (intern (format "%s-ts-mode" lang-remap)))) - ;; If ‘name-ts-mode’ is already in ‘auto-mode-alist’ then we don’t - ;; need to do anything, however if that’s not the case then if - ;; ‘name-ts-mode’ and ‘name-mode’ are both bound we do a simple - ;; remap. If the above is not true then we lookup the extensions in - ;; ‘mm-treesit-language-file-name-alist’. - (cond - ((memq lang mm-treesit-dont-have-modes) - nil) - ((not (fboundp name-ts-mode)) - (warn "`%s' is missing." name-ts-mode)) - ((rassq name-ts-mode auto-mode-alist) - nil) - ((fboundp name-mode) - (add-to-list 'major-mode-remap-alist (cons name-mode name-ts-mode))) - (t ; (and (fboundp name-ts-mode) (not (fboundp name-mode))) - (if-let ((file-regexp - (alist-get lang mm-treesit-language-file-name-alist))) - (add-to-list 'auto-mode-alist (cons file-regexp name-ts-mode)) - (warn "Unable to determine the extension for `%s'." name-ts-mode)))))) - -;; JavaScript being difficult as usual -(add-to-list 'major-mode-remap-alist '(javascript-mode . js-ts-mode)) - - -;;; Hack For C23 - -(advice-add #'c-ts-mode--keywords :filter-return - (defun mm-c-ts-mode-add-constexpr (keywords) - ;; NOTE: We can’t add ‘typeof’ until it’s added to the TS grammar - ;; https://github.com/tree-sitter/tree-sitter-c/issues/236 - (append keywords '("constexpr")))) - - -;;; Highlight Predefined Variables - -(with-eval-after-load 'treesit - (defvar mm-c-font-lock-rules - (treesit-font-lock-rules - :language 'c - :feature 'constant - :override t - `(((identifier) @font-lock-constant-face - (:match ,(rx bos (or "__func__" "__FUNCTION__") eos) - @font-lock-constant-face)))))) - -(add-hook 'c-ts-mode-hook - (defun mm-c-apply-font-lock-extras () - (setq treesit-font-lock-settings - (append treesit-font-lock-settings mm-c-font-lock-rules)))) - - -;;; Region Expansion - -(defun mm-expreg-expand (n) - "Expand to N syntactic units." - (interactive "p") - (dotimes (_ n) - (expreg-expand))) - -(defun mm-expreg-expand-dwim () - "Do-What-I-Mean `expreg-expand' to start with symbol or word. -If over a real symbol, mark that directly, else start with a word. Fall -back to regular `expreg-expand'." - (interactive) - (if (region-active-p) - (expreg-expand) - (let ((symbol (bounds-of-thing-at-point 'symbol))) - (cond - ((equal (bounds-of-thing-at-point 'word) symbol) - (mm-expreg-expand 1)) - (symbol - (mm-expreg-expand 2)) - (:else - (expreg-expand)))))) - -(use-package expreg - :ensure t - :commands (mm-expreg-expand mm-expreg-expand-dwim) - :bind ("M-SPC" . mm-expreg-expand-dwim)) - -(provide 'mm-treesit) diff --git a/.config/emacs/modules/mm-window.el b/.config/emacs/modules/mm-window.el deleted file mode 100644 index 0ce77c7..0000000 --- a/.config/emacs/modules/mm-window.el +++ /dev/null @@ -1,72 +0,0 @@ -;;; mm-window.el --- Window configurations -*- lexical-binding: t; -*- - - -;;; Unique Buffer Names - -(use-package uniquify - :custom - (uniquify-buffer-name-style 'forward)) - - -;;; Highlight Whitespace - -(use-package whitespace - :bind (("" . whitespace-mode) - ("C-c z" . delete-trailing-whitespace)) - :custom - (whitespace-style - '( face trailing spaces tabs space-mark tab-mark empty indentation - space-after-tab space-before-tab)) - (whitespace-display-mappings - '((space-mark 32 [?·] [?.]) ; Space - (space-mark 160 [?␣] [?_]) ; Non-Breaking Space - (tab-mark 9 [?» ?\t] [?> ?\t])))) - - -;;; Line Numbers - -(use-package display-line-numbers - :bind ("" . display-line-numbers-mode) - :custom - (display-line-numbers-grow-only t) - (display-line-numbers-type 'relative) - (display-line-numbers-width-start 99)) - - -;;; Select Help Windows - -(use-package help - :custom - (help-window-select t)) - - -;;; Window Scrolling - -(use-package window - :custom - (scroll-conservatively 101) ; (info "(Emacs)Auto Scrolling") - (scroll-error-top-bottom t) - (scroll-margin 10) - :config - (setq-default truncate-partial-width-windows nil)) - - -;;; Smoother Scrolling - -(mm-comment - (use-package pixel-scroll - :init - (pixel-scroll-precision-mode) - :config - ;; Make it easier to use custom scroll functions - (dolist (binding '("" "")) - (keymap-unset pixel-scroll-precision-mode-map binding :remove)))) - - -;;; Ace Window - -(use-package ace-window - :ensure t - :bind ("M-o" . ace-window)) - -(provide 'mm-window) \ No newline at end of file diff --git a/.config/emacs/site-lisp/emmet.el b/.config/emacs/site-lisp/emmet.el deleted file mode 100644 index eefb4ba..0000000 --- a/.config/emacs/site-lisp/emmet.el +++ /dev/null @@ -1,349 +0,0 @@ -;;; tree-exp-mode.el --- Minor mode for expanding tree-like syntax -*- lexical-binding: t; -*- - -(eval-when-compile - (require 'cl-macs) - (require 'tempo)) - -(defgroup tree-exp nil - "Customization group for `emmet-mode'." - :group 'convenience) - -(defcustom tree-exp-html-self-closing-style "" - "Self-closing tag style for HTML. -This setting specifies how `tree-exp' should generate self-closing tags -when expanding to HTML. When generating a self-closing tag the value of -`tree-exp-html-self-closing-style' is inserted verbatim between the end -of the element attributes and the closing angle-bracket. - -Note that the variable of this setting has no bearing on the validity of -the generated HTML; infact the HTML standard instructs parsers to ignore -a trailing slash." - :type '(choice (const :tag "") - (const :tag "/") - (const :tag " /")) - :package-version '(tree-exp . "1.0.0") - :group 'tree-exp) - -(defcustom tree-exp-set-marks t - "TODO" - :type 'boolean - :package-version '(tree-exp . "1.0.0") - :group 'tree-exp) - -(defvar-keymap tree-exp-mode-map - :doc "TODO") - -(defvar tree-exp-expand-functions - '(((html-mode mhtml-mode html-ts-mode) . tree-exp-expand-html) - (gsp-ts-mode . tree-exp-expand-gsp)) - "TODO") - -(defvar tree-exp-operator-alist-alist - '(((html-mode mhtml-mode html-ts-mode gsp-ts-mode) - . ((?+ . sibling) - (?^ . parent) - (?> . child) - (?. . extra) - (?# . extra) - (?@ . extra) - (?* . repeat)))) - "TODO") - -(defvar tree-exp-after-expansion-hook nil - "TODO") - - -;; Private Variables - -(defvar-local tree-exp--mark-index 0) - -(defconst tree-exp--html-void-elements - #s(hash-table size 13 - test equal - purecopy t - data ("area" t - "base" t - "br" t - "col" t - "embed" t - "hr" t - "img" t - "input" t - "link" t - "meta" t - "source" t - "track" t - "wbr" t))) - - -;; Parsing - -(defun tree-exp--pattern-start () - (max (save-excursion - (skip-syntax-backward "^ ") - (point)) - (pos-bol))) - -(defun tree-exp--pattern-bounds () - (if (use-region-p) - (progn - (when (region-noncontiguous-p) - (error "Noncontiguous regions are not supported yet.")) - (car (region-bounds))) - (cons (tree-exp--pattern-start) (point)))) - -(defun tree-exp--symbol-end (operator-alist) - (while (and (memq (car (syntax-after (point))) '(2 3)) - (not (assq (char-after (point)) operator-alist))) - (goto-char (1+ (point)))) - (point)) - -(defun tree-exp--set-children-of-leaves (tree values) - (dolist (node tree) - (if-let ((children (nth 2 node))) - (tree-exp--set-children-of-leaves children values) - (setf (nth 2 node) values))) - tree) - -(defun tree-exp--append-extra-to-leaves (tree value) - (dolist (node tree) - (if-let ((children (nth 2 node))) - (tree-exp--append-extra-to-leaves children value) - (setf - (nth 1 node) - (append (nth 1 node) (cons value nil))))) - tree) - -(defun tree-exp--parse-count () - (let* ((start (point)) - (end (+ start (skip-chars-forward "0-9"))) - (num (string-to-number - (buffer-substring-no-properties start end) - 10))) - (unless (zerop num) - num))) - -(defun tree-exp--parse-atom (operator-alist) - (let ((start (point)) - (end (tree-exp--symbol-end operator-alist))) - (if (= start end) - (when (= ?\( (char-after end)) - (goto-char (1+ end)) - (let ((tree (tree-exp--parse-expr operator-alist)) - (char (char-after (point)))) - (if (eq ?\) char) - (progn - (goto-char (1+ (point))) - tree) - (message (if char - (format "Invalid operator `%c'" char) - "Missing closing parenthesis")) - nil))) - (list (list (buffer-substring-no-properties start end) nil nil))))) - -(defun tree-exp--parse-term (operator-alist) - (let ((terms (tree-exp--parse-atom operator-alist))) - (catch 'loop - (while t - (let* ((operator (assq (char-after (point)) operator-alist)) - (op-char (car-safe operator)) - (op-type (cdr-safe operator)) - start end) - (unless (eq op-type 'extra) - (throw 'loop terms)) - (setq - start (goto-char (1+ (point))) - end (tree-exp--symbol-end operator-alist)) - (when (= start end) - (message "Operator `%c' missing right-hand side" op-char) - (throw 'loop nil)) - (tree-exp--append-extra-to-leaves - terms (cons op-char (buffer-substring-no-properties start end)))))))) - -;; Gross hack -(defun tree-exp--parse-expr-with-lhs (operator-alist lhs) - (let* ((op-char (char-after (point))) - (op-type (alist-get op-char operator-alist)) - rhs) - (cond - ((not lhs) - nil) - ((or (not op-char) - (not op-type)) - lhs) - (t - (goto-char (1+ (point))) - (setq rhs (if (eq op-type 'repeat) - (tree-exp--parse-count) - (tree-exp--parse-expr operator-alist))) - (when rhs - (pcase op-type - ('child (tree-exp--set-children-of-leaves lhs rhs)) - ('parent (tree-exp--set-children-of-leaves rhs lhs)) - ('sibling (append lhs rhs)) - ('repeat (tree-exp--parse-expr-with-lhs - operator-alist - ;; FIXME: We need to call ‘copy-tree’ or else the - ;; generated AST has cycles in it… why is that? How - ;; can we fix it? - (cl-loop for _ from 1 to rhs append (copy-tree lhs)))))))))) - -(defun tree-exp--parse-expr (operator-alist) - (tree-exp--parse-expr-with-lhs - operator-alist - (tree-exp--parse-term operator-alist))) - -(defun tree-exp--build-ast (bounds) - (save-excursion - (with-restriction (car bounds) (cdr bounds) - (goto-char 1) - (when-let* ((operator-alist (tree-exp--alist-get - major-mode tree-exp-operator-alist-alist)) - (tree (tree-exp--parse-expr operator-alist))) - (if (= (point) (point-max)) - tree - (message "Superfluous character `%c'" (char-after (point))) - nil))))) - - -;; Expansion - -(defun tree-exp--alist-get (key alist) - (cdr (or (assq key alist) - (catch 'tree-exp--break - (dolist (pair alist) - (when (and (listp (car pair)) - (memq key (car pair))) - (throw 'tree-exp--break pair))))))) - -(defun tree-exp--ast-siblings-p (ast) - (cond ((not ast) nil) - ((length> ast 1) t) - (t (tree-exp--ast-siblings-p (caddar ast))))) - -(defun tree-exp-expand-html--format-attr (attr) - (declare ((pure t) (side-effect-free t))) - (let* ((parts (string-split attr "=")) - (name (car parts)) - (value-parts (cdr parts))) - (if value-parts - (format "%s=\"%s\"" name (string-join value-parts "=")) - name))) - -(defun tree-exp-expand-html--helper (ast indentp) - (dolist (node ast) - (let* ((name (nth 0 node)) - (attrs (nth 1 node)) - (children (nth 2 node)) - (classes (cl-loop for (op . attr) in attrs - if (= ?. op) - collect attr))) - (insert (format "<%s" name)) - (when classes - (insert (format " class=\"%s\"" (string-join classes " ")))) - (cl-loop for (op . attr) in attrs - if (= ?# op) - do (insert (format " id=\"%s\"" attr)) - else if (= ?@ op) - do (thread-last - attr - (tree-exp-expand-html--format-attr) - (concat " ") - (insert))) - (if (and (not children) - (gethash name tree-exp--html-void-elements)) - (insert (format "%s>" tree-exp-html-self-closing-style)) - (insert ?>) - (if children - (progn - (when indentp - (insert ?\n)) - (tree-exp-expand-html--helper children indentp)) - (when tree-exp-set-marks - (insert #x1B))) - (insert (format "" name)))) - (when indentp - (insert ?\n)))) - -(defun tree-exp-expand-html (ast) - "TODO" - (tree-exp-expand-html--helper ast (tree-exp--ast-siblings-p ast)) - (when (= ?\n (char-before (point-max))) - (delete-region (1- (point-max)) (point-max))) - (when tree-exp-set-marks - (insert #x1B))) - -;; (defun tree-exp-expand-gsp--helper (ast indentp) -;; (dolist (node ast) -;; (let ((name (nth 0 node)) -;; (attrs (nth 1 node)) -;; (children (nth 2 node))) - - -;; ;; (insert (format "<%s" name)) -;; ;; (dolist (attr attrs) -;; ;; (insert (format " %s" (cdr attr)))) -;; ;; (if (and (not children) -;; ;; (gethash name tree-exp--html-void-elements)) -;; ;; (insert (format "%s>" tree-exp-html-self-closing-style)) -;; ;; (insert ?>) -;; ;; (if children -;; ;; (progn -;; ;; (when indentp -;; ;; (insert ?\n)) -;; ;; (tree-exp-expand-html--helper children indentp)) -;; ;; (when tree-exp-set-marks -;; ;; (insert #x1B))) -;; ;; (insert (format "" name))) -;; ) -;; (when indentp -;; (insert ?\n)))) - -(defun tree-exp-expand-gsp (ast) - "TODO" - (tree-exp-expand-gsp--helper ast (tree-exp--ast-siblings-p ast)) - (when (= ?\n (char-before (point-max))) - (delete-region (1- (point-max)) (point-max))) - (when tree-exp-set-marks - (insert #x1B))) - -;;;###autoload -(defun tree-exp-expand () - "TODO" - (interactive) - (when-let* ((current-buffer (current-buffer)) - (bounds (tree-exp--pattern-bounds)) - (ast (tree-exp--build-ast bounds)) - (expander (tree-exp--alist-get - major-mode tree-exp-expand-functions))) - (delete-region (car bounds) (cdr bounds)) - (with-temp-buffer - (funcall expander ast) - (insert-into-buffer current-buffer)) - (let ((start-pos (car bounds)) - (end-pos (point-marker)) - (delete-active-region nil) ; For ‘delete-backward-char’ - marks) - (when tree-exp-set-marks - (save-excursion - (goto-char start-pos) - (while (search-forward "\x1B" end-pos :noerror) - (delete-backward-char 1) - (push (point-marker) marks))) - (push (point-marker) marks) - (setq marks (nreverse marks)) - (goto-char (car marks)) - (mapc #'tempo-insert-mark marks)) - ;; Set the start of the region to the start bound - (unless (region-active-p) - (set-mark start-pos)) - (indent-region start-pos end-pos) - (run-hooks tree-exp-after-expansion-hook)))) - -;;;###autoload -(define-minor-mode tree-exp-mode - "TODO" - :lighter " Tree-Expand" - :keymap tree-exp-mode-map) - -(provide 'tree-exp) diff --git a/.config/emacs/site-lisp/gh.el b/.config/emacs/site-lisp/gh.el deleted file mode 100644 index 39dc339..0000000 --- a/.config/emacs/site-lisp/gh.el +++ /dev/null @@ -1,62 +0,0 @@ -;;; gh.el --- GitHub integration for Emacs -*- lexical-binding: t; -*- - -(defun gh-get-labels () - "Return a list of labels in the current GitHub repository." - (with-temp-buffer - (call-process "gh" nil t nil "label" "list" - "--sort" "name" "--json" "name" "--limit" "1000000") - (goto-char (point-min)) - (seq-map (lambda (x) (gethash "name" x)) - (json-parse-buffer)))) - -;; TODO: Set title and body in a buffer like Magit -(defun gh-create-pr (title &optional labels draftp) - "Create a GitHub pull request. -If DRAFTP is non-nil, the PR will be created as a draft. - -LABELS is a list of labels. A list of available labels can be fetched -via `gh-get-labels'." - (interactive - (list - (read-string (format-prompt "PR Title" nil)) - (completing-read-multiple (format-prompt "PR Labels" nil) - (gh-get-labels)) - (y-or-n-p "Create PR as a draft? "))) - (let* ((project (project-name (project-current))) - (flags `("--fill-verbose" "--assignee" "@me")) - (label-string (mapconcat #'identity labels ","))) - ;; TODO: Remove this - (when (string= project "blixem") - (setq title (format "%s %s" (car (vc-git-branches)) title)) - (when (member "Patch" labels) - (setq flags (append flags '("--base" "release"))))) - (setq flags (append flags `("--title" ,title))) - (when draftp - (setq flags (append flags '("--draft")))) - (when labels - (setq flags (append flags `("--label" ,label-string)))) - (with-temp-buffer - (apply #'call-process "gh" nil t nil "pr" "create" flags) - (message (buffer-string))))) - -(defvar gh-pr-regexp - "\\`https://\\(?:www\\.\\)?github\\.com/[^/]+/[^/]+/pull/[[:digit:]]+\\'") - -(defun gh--pr-link-p (s) - (declare (pure t) (side-effect-free t)) - (string-match-p gh-pr-regexp s)) - -(defun gh-open-previous-pr () - "Open the previous GitHub pull request. -Opens the previous pull request created by `gh-create-pr' by searching -for the echoed URL in the `*Messages*' buffer." - (interactive) - (with-current-buffer "*Messages*" - (goto-char (point-max)) - (while (not (gh--pr-link-p (buffer-substring-no-properties - (pos-bol) (pos-eol)))) - (unless (line-move -1 :noerror) - (user-error "No previous pull request found."))) - (browse-url-at-point))) - -(provide 'gh) diff --git a/.config/emacs/site-lisp/grab.el b/.config/emacs/site-lisp/grab.el deleted file mode 100644 index 2482d5d..0000000 --- a/.config/emacs/site-lisp/grab.el +++ /dev/null @@ -1,215 +0,0 @@ -;;; grab.el --- Emacs integration for grab -*- lexical-binding: t; -*- - -;; Author: Thomas Voss -;; Description: TODO -;; Keywords: matching, tools - -;;; Commentary: - -;; TODO - -;;; Code: - -(require 'ansi-color) -(require 'dired) -(require 'project) -(require 'rx) -(require 'xref) - -(defgroup grab nil - "Settings for `grab'." - :group 'tools) - -(defcustom grab-command "grab" - "The base executable for the Grab tool." - :type 'string) - -(defcustom git-grab-command "git-grab" - "The base executable for the Git Grab tool." - :type 'string) - -(defcustom grab-command-arguments '("-c" "-Hmulti") - "Arguments to pass to `grab-command'." - :type '(repeat string)) - -(defcustom git-grab-command-arguments grab-command-arguments - "Arguments to pass to `git-grab-command'." - :type '(repeat string)) - -(defcustom grab-default-pattern '("x// h//" . 3) - "The default pattern in Grab prompts" - :type '(choice (cons string natnum) - (string))) - -(defvar grab-history nil - "Minibuffer history for Grab search patterns.") - - -;;; Xref Location Class - -(cl-defstruct grab-location - "A location in a file specified by a byte offset." - file offset) - -(cl-defmethod xref-location-marker ((loc grab-location)) - "Return a marker for the grab location LOC." - (let* ((file (grab-location-file loc)) - (offset (grab-location-offset loc)) - (buf (find-file-noselect file))) - (with-current-buffer buf - (save-restriction - (widen) - (goto-char (byte-to-position (1+ offset))) - (point-marker))))) - -(cl-defmethod xref-location-group ((loc grab-location)) - "Group matches by their file name in the xref buffer." - (grab-location-file loc)) - -(cl-defmethod xref-location-line ((loc grab-location)) - "Return the position of the match. - -`xref' internally performs a log on this value, so we need to handle the -0 case." - (max 1 (grab-location-offset loc))) - - -;;; Process Management & Parsing - -(defvar grab--header-regexp - (rx-let ((ansi-escape (seq "\e[" (* (any "0-9;")) "m")) - (highlighted (thing) - (seq (* ansi-escape) - thing - (* ansi-escape)))) - (rx line-start - (highlighted (group (+ (not (any ?: ?\e ?\n))))) - (highlighted ?:) - (highlighted (group (+ digit))) - (highlighted ?:))) - "Regular expression matching the grab output header.") - -(defun grab--format-summary (summary) - (let* ((summary (ansi-color-apply (string-trim-right summary))) - (pos 0) - (len (length summary))) - (while (< pos len) - (let ((next (next-property-change pos summary len))) - (when (or (get-text-property pos 'font-lock-face summary) - (get-text-property pos 'face summary)) - (put-text-property pos next 'font-lock-face 'xref-match summary) - (remove-list-of-text-properties pos next '(face) summary)) - (setq pos next))) - summary)) - -(defun grab--parse-output (dir) - (let (xrefs file offset match-start) - (goto-char (point-min)) - (while (re-search-forward grab--header-regexp nil :noerror) - (let ((next-file (match-string-no-properties 1)) - (next-offset (string-to-number (match-string-no-properties 2))) - (next-start (point))) - (when file - (let* ((summary (buffer-substring-no-properties - match-start (match-beginning 0))) - (summary (grab--format-summary summary)) - (full-path (expand-file-name file dir)) - (loc (make-grab-location :file full-path :offset offset))) - (push (xref-make summary loc) xrefs))) - (setq file next-file - offset next-offset - match-start next-start))) - (when file - (let* ((summary (buffer-substring-no-properties - match-start (point-max))) - (summary (grab--format-summary summary)) - (full-path (expand-file-name file dir)) - (loc (make-grab-location :file full-path :offset offset))) - (push (xref-make summary loc) xrefs))) - (unless xrefs - (user-error "No matches found for grab pattern")) - (nreverse xrefs))) - -(defun grab--directory (cmd args pattern dir) - (grab--files cmd args pattern dir - (directory-files-recursively dir "." nil t))) - -(defun grab--files (cmd args pattern dir files) - (lambda () - (let ((default-directory dir)) - (with-temp-buffer - (apply #'call-process cmd nil t nil - (flatten-tree (list args "--" pattern files))) - (grab--parse-output dir))))) - -(defun grab--read-pattern () - (read-string (format-prompt "Grab Pattern" nil) - grab-default-pattern - 'grab-history)) - - -;;; Interactive Commands - -;;;###autoload -(defun grab (pattern) - "Run grab with PATTERN in the current directory." - (interactive (list (grab--read-pattern))) - (xref-show-xrefs - (grab--directory grab-command - grab-command-arguments - pattern - default-directory) - nil)) - -;;;###autoload -(defun git-grab (pattern) - "Run git grab with PATTERN in the current directory." - (interactive (list (grab--read-pattern))) - (xref-show-xrefs - (grab--files git-grab-command - git-grab-command-arguments - pattern - default-directory - nil) - nil)) - -;;;###autoload -(defun project-grab (pattern) - "Run grab with PATTERN at the project root." - (interactive (list (grab--read-pattern))) - (let* ((project (project-current t)) - (default-directory (project-root project))) - (xref-show-xrefs - (grab--directory grab-command - grab-command-arguments - pattern - default-directory) - nil))) - -;;;###autoload -(defun project-git-grab (pattern) - "Run git grab with PATTERN at the project root." - (interactive (list (grab--read-pattern))) - (let* ((project (project-current t)) - (default-directory (project-root project))) - (xref-show-xrefs - (grab--files git-grab-command - git-grab-command-arguments - pattern - default-directory - nil) - nil))) - -;;;###autoload -(defun dired-grab-marked-files (pattern) - "TODO" - (interactive (list (grab--read-pattern))) - (let* ((project (project-current t)) - (default-directory (project-root project))) - (xref-show-xrefs - (grab--files grab-command grab-command-arguments pattern - default-directory (dired-get-marked-files)) - nil))) - -(provide 'grab) -;;; grab.el ends here diff --git a/.config/emacs/site-lisp/highlighter.el b/.config/emacs/site-lisp/highlighter.el deleted file mode 100644 index ce67ac8..0000000 --- a/.config/emacs/site-lisp/highlighter.el +++ /dev/null @@ -1,128 +0,0 @@ -;;; highlighter.el --- In-buffer highlighting commands -*- lexical-binding: t; -*- - -(require 'seq) - -(defgroup highlighter nil - "Customization group for `highlighter'." - :group 'convenience) - -(defcustom highlighter-default-face 'match - "The default face used by `highlighter-mark'." - :type 'face - :package-version '(highlighter . "1.0.0") - :group 'highlighter) - -(defun highlighter-mark (arg) - "Highlight text in the buffer. -Highlight the current line or region if it is active. Text is -highlighted using the face specified by `highlighter-default-face'. - -With ARG, interactively pick a face to highlight with." - (declare (interactive-only t)) - (interactive "P") - (let ((bounds (if (use-region-p) - (region-bounds) - `((,(pos-bol) . ,(pos-eol))))) - (face (when arg - (highlighter--read-face-name "Highlight with face" #'facep)))) - (highlighter-mark-region bounds face)) - (when (region-active-p) - (deactivate-mark))) - -(defun highlighter-unmark (arg) - "Remove highlights in the buffer. - -Remove highlights from the current line or region if it is active. - -With ARG, interactively pick a face. Only highlights using the chosen -face will be removed." - (declare (interactive-only t)) - (interactive "P") - (let ((bounds (if (use-region-p) - (region-bounds) - `((,(pos-bol) . ,(pos-eol))))) - (face (when arg - (highlighter--read-face-name - "Clear highlights using face" - #'highlighter--used-face-p)))) - (highlighter-unmark-region bounds face)) - (when (region-active-p) - (deactivate-mark))) - -(defun highlighter-mark-region (bounds &optional face) - "Highlight text in the buffer within BOUNDS. -BOUNDS uses the same format as returned by `region-bounds'. - -Text is highlighted using the face specified by `highlighter-default-face'. - -If FACE is nil or omitted, `highlighter-default-face' is used." - (dolist (x bounds) (highlighter--mark-region (car x) (cdr x) face))) - -(defun highlighter-unmark-region (bounds &optional face) - "Remove highlights in the buffer within BOUNDS. -BOUNDS uses the same format as returned by `region-bounds'. - -If FACE is non-nil, only remove highlights using FACE." - (dolist (x bounds) (highlighter--unmark-region (car x) (cdr x) face))) - -(defun highlighter--mark-region (beg end &optional face) - (let ((ov (make-overlay beg end nil :front-advance)) - (face (or face highlighter-default-face 'match))) - (overlay-put ov 'priority 1) - (overlay-put ov 'face face) - (overlay-put ov 'evaporate t) - (overlay-put ov 'highlighter--mark-p t) - (overlay-put ov 'highlighter--face face))) - -(defun highlighter--unmark-region (beg end &optional face) - (if face - (remove-overlays beg end 'highlighter--face face) - (remove-overlays beg end 'highlighter--mark-p t))) - -(defun highlighter-unmark-buffer (arg) - "Remove highlights in the buffer. - -With ARG, interactively pick a face. Only highlights using the chosen -face will be removed." - (declare (interactive-only t)) - (interactive "P") - (let ((face (when arg - (highlighter--read-face-name - "Clear highlights using face" - #'highlighter--used-face-p)))) - (highlighter--unmark-region (point-min) (point-max) face))) - -(defun highlighter--read-face-name (prompt face-predicate) - (let (default defaults) - (let ((prompt (format "%s: " prompt)) - (completion-extra-properties - `(:affixation-function - ,(lambda (faces) - (mapcar - (lambda (face) - (list face - (concat (propertize read-face-name-sample-text - 'face face) - "\t") - "")) - faces)))) - aliasfaces nonaliasfaces faces) - ;; Build up the completion tables. - (mapatoms (lambda (s) - (when (apply face-predicate s nil) - (if (get s 'face-alias) - (push (symbol-name s) aliasfaces) - (push (symbol-name s) nonaliasfaces))))) - (let ((face (completing-read - prompt - (completion-table-in-turn nonaliasfaces aliasfaces) - nil t nil 'face-name-history defaults))) - (when (facep face) (if (stringp face) - (intern face) - face)))))) - -(defun highlighter--used-face-p (face) - (seq-filter (lambda (ov) (eq face (overlay-get ov 'highlighter--face))) - (overlays-in (point-min) (point-max)))) - -(provide 'highlighter) diff --git a/.config/emacs/site-lisp/html-escape.el b/.config/emacs/site-lisp/html-escape.el deleted file mode 100644 index afdbb4d..0000000 --- a/.config/emacs/site-lisp/html-escape.el +++ /dev/null @@ -1,55 +0,0 @@ -;;; html-escape.el --- HTML escaping functions -*- lexical-binding: t; -*- - -(defgroup html-escape nil - "Customization group for `html-escape'." - :group 'convenience) - -(defvar html-escape-table - (let ((table (make-hash-table :test #'eq))) - (puthash ?& "&" table) - (puthash ?< "<" table) - (puthash ?> ">" table) - (puthash ?\" """ table) - (puthash ?' "'" table) - table) - "Hash table mapping character codes to their HTML entity equivalents.") - -;;;###autoload -(defun html-escape () - "HTML escape text in the current buffer. - -Perform HTML escaping on the text in the current buffer. If the region -is active then only escape the contents of the active region." - (declare (interactive-only t)) - (interactive) - (if (use-region-p) - (html-escape-region (region-bounds)) - (html-escape-region-1 (pos-bol) (pos-eol))) - (when (region-active-p) - (deactivate-mark))) - -(defun html-escape-region (bounds) - "HTML escape text in the current buffer within BOUNDS. - -BOUNDS takes the same form as the return value of `region-bounds'. This -function is prefered as it supports noncontiguous regions, but there also -exists `html-escape-region-1' with a simpler bounds interface." - (dolist (x bounds) (html-escape-region-1 (car x) (cdr x)))) - -(defun html-escape-region-1 (beg end) - "HTML escape text in the current buffer within BEG and END. - -This function is the same as the prefered `html-escape-region', but takes -BEG and END parameters instead of a BOUNDS parameter. For noncontiguous -region support use `html-escape-region'." - (save-restriction - (narrow-to-region beg end) - (save-excursion - (goto-char (point-min)) - (save-match-data - (while (re-search-forward "[&<>\"']" nil :noerror) - (let* ((char (char-after (match-beginning 0))) - (replacement (gethash char html-escape-table))) - (replace-match replacement))))))) - -(provide 'html-escape) diff --git a/.config/emacs/site-lisp/increment.el b/.config/emacs/site-lisp/increment.el deleted file mode 100644 index b5bea53..0000000 --- a/.config/emacs/site-lisp/increment.el +++ /dev/null @@ -1,132 +0,0 @@ -;;; increment.el -- Increment numbers at point -*- lexical-binding: t; -*- - -(require 'cl-macs) -(require 'rx) - -(defvar increment--binary-number-regexp - (rx (group (or ?- word-start)) - "0b" - (group (* ?0)) - (group (+ (any "01"))) - word-end)) - -(defvar increment--octal-number-regexp - (rx (group (or ?- word-start)) - "0o" - (group (* ?0)) - (group (+ (any "0-7"))) - word-end)) - -(defvar increment--decimal-number-regexp - (rx (group (? ?-)) - (group (* ?0)) - (group (+ (any digit))))) - -(defvar increment--hexadecimal-number-regexp - (rx (group (or ?- word-start)) - "0x" - (group (* ?0)) - (group (+ (any hex-digit))) - word-end)) - -(defvar increment--hexadecimal-lower-number-regexp - (rx (group (or ?- word-start)) - "0o" - (group (* ?0)) - (group (+ (any "0-9a-f"))) - word-end)) - -(defvar increment--number-regexp - (rx (or (seq (or ?- word-start) - (or (seq "0b" (+ (any "01"))) - (seq "0o" (+ (any "0-7"))) - (seq "0x" (+ (any hex-digit)))) - word-end) - (seq (? ?-) (+ (any digit)))))) - -(defun increment--number-to-binary-string (number) - (nreverse - (cl-loop for x = number then (ash x -1) - while (not (= x 0)) - concat (if (= 0 (logand x 1)) "0" "1")))) - -(defun increment--format-number-with-base - (number base leading-zeros buffer-substr hex-style) - (let* ((neg (> 0 number)) - (number (abs number)) - (number-string - (pcase base - (2 (increment--number-to-binary-string number)) - (8 (format "%o" number)) - (10 (number-to-string number)) - (16 (format (if (eq hex-style 'lower) "%x" "%X") number)))) - (length-diff (- (length buffer-substr) - (length number-string))) - (leading-zeros (if (> leading-zeros 0) - (+ leading-zeros length-diff) - 0))) - (concat - (when neg - "-") - (pcase base - (2 "0b") - (8 "0o") - (16 "0x")) - (when (> leading-zeros 0) - (make-string leading-zeros ?0)) - number-string))) - -(defun increment--match-number-at-point () - (cond ((thing-at-point-looking-at - increment--binary-number-regexp) - (cons 2 nil)) - ((thing-at-point-looking-at - increment--octal-number-regexp) - (cons 8 nil)) - ((thing-at-point-looking-at - increment--hexadecimal-number-regexp) - (cons 16 nil)) - ((thing-at-point-looking-at - increment--hexadecimal-lower-number-regexp) - (cons 16 'lower)) - ((thing-at-point-looking-at - increment--decimal-number-regexp) - (cons 10 nil)))) - -;;;###autoload -(cl-defun increment-number-at-point (&optional arg) - "Increment the number at point by ARG or 1 if ARG is nil. If called -interactively, the universal argument can be used to specify ARG. If -the number at point has leading zeros then the width of the number is -preserved." - (interactive "*p") - (save-match-data - (let (case-fold-search - (match-pair (increment--match-number-at-point))) - (unless match-pair - (let ((save-point (point))) - (unless (re-search-forward - increment--number-regexp - (line-end-position) :noerror) - (goto-char save-point) - (cl-return-from increment-number-at-point)) - (setq match-pair (increment--match-number-at-point)))) - (let* ((base (car match-pair)) - (hex-style (cdr match-pair)) - (substr (buffer-substring-no-properties - (match-beginning 3) (match-end 3))) - (sign (if (= (match-beginning 1) (match-end 1)) +1 -1)) - (result (+ (* (string-to-number substr base) sign) - (or arg 1)))) - (replace-match - (increment--format-number-with-base - result base (- (match-end 2) (match-beginning 2)) - substr hex-style)))))) - -;;;###autoload -(defun decrement-number-at-point (&optional arg) - "The same as `increment-number-at-point', but ARG is negated." - (interactive "*p") - (increment-number-at-point (- (or arg 1)))) - -(provide 'increment) diff --git a/.config/emacs/site-lisp/line-selection-mode.el b/.config/emacs/site-lisp/line-selection-mode.el deleted file mode 100644 index 83da013..0000000 --- a/.config/emacs/site-lisp/line-selection-mode.el +++ /dev/null @@ -1,18 +0,0 @@ -;;; line-selection-mode.el --- Minor mode for selection by lines -*- lexical-binding: t; -*- - -(defvar-local line-selection-mode--cursor-type nil) - -;;;###autoload -(define-minor-mode line-selection-mode - "Enable `hl-line-mode' and hide the current cursor." - :global nil - :init-value nil - (if line-selection-mode - (progn - (hl-line-mode) - (setq line-selection-mode--cursor-type cursor-type) - (setq-local cursor-type nil)) - (hl-line-mode -1) - (setq-local cursor-type line-selection-mode--cursor-type))) - -(provide 'line-selection-mode) diff --git a/.config/emacs/site-lisp/live-jq.el b/.config/emacs/site-lisp/live-jq.el deleted file mode 100644 index f8a0a7f..0000000 --- a/.config/emacs/site-lisp/live-jq.el +++ /dev/null @@ -1,101 +0,0 @@ -;; TODO: ‘defcustom’ this -(defvar live-jq-major-mode - (cond ((fboundp #'json-ts-mode) #'json-ts-mode) - ((fboundp #'json-mode) #'json-mode)) - "TODO") - -(defvar live-jq--input-buffer nil - "The buffer containing the original JSON data.") - -(defvar live-jq--preview-buffer "*JQ Preview*" - "The buffer showing the live jq results.") - -(defvar live-jq--last-query "") - -(defun live-jq--get-json-input () - "Return the contents of the input buffer as a string." - (with-current-buffer live-jq--input-buffer - (buffer-substring-no-properties (point-min) (point-max)))) - -(defun live-jq--run-jq (query) - "Run jq QUERY on the input buffer's content and return result string or nil on error." - (let ((json-input (live-jq--get-json-input))) - (with-temp-buffer - (insert json-input) - (let ((exit-code (call-process-region - (point-min) (point-max) - "jq" :delete t nil "--tab" query))) - (when (zerop exit-code) - (buffer-string)))))) - -(defun live-jq--render-jq-preview (query) - "Update preview buffer with the result or error of jq QUERY." - (let* ((preview-buffer (get-buffer-create live-jq--preview-buffer)) - (json-input (live-jq--get-json-input)) - (inhibit-read-only t)) - (with-current-buffer preview-buffer - (erase-buffer) - (condition-case err - (with-temp-buffer - (insert json-input) - (let ((exit-code (call-process-region - (point-min) (point-max) - "jq" nil preview-buffer nil "--tab" query))) - (when (not (zerop exit-code)) - (erase-buffer) - (insert "%s\n%s" - (propertize (format "jq error (exit %d): %s" exit-code query) - 'face 'error) - json-input)))) - (error - (insert "%s\n%s" - (propertize (format "Error: %s" err) 'face 'error) - input-json))) - (goto-char (point-min)) - (when live-jq-major-mode - (funcall live-jq-major-mode)))) - (display-buffer live-jq--preview-buffer)) - -(defun live-jq--minibuffer-update () - "Update preview as user types." - (let ((query (minibuffer-contents))) - (unless (equal query live-jq--last-query) - (setq live-jq--last-query query) - (live-jq--render-jq-preview query)))) - -;;;###autoload -(defun live-jq () - "Prompt for a jq query, show live results, and replace buffer on confirmation." - (interactive) - (unless (executable-find "jq") - (user-error "`jq' not found in PATH.")) - - (setq live-jq--input-buffer (current-buffer)) - (setq live-jq--last-query "") - - ;; Clean up preview buffer if user cancels with C-g - (let ((minibuffer-setup-hook - (list (lambda () - ;; Add post-command-hook for live preview - (add-hook 'post-command-hook #'live-jq--minibuffer-update nil t) - ;; Add abort cleanup - (add-hook 'minibuffer-exit-hook - (lambda () - (when (get-buffer live-jq--preview-buffer) - (kill-buffer live-jq--preview-buffer))) - nil t))))) - (let ((query (read-from-minibuffer (format-prompt "Query" nil)))) - (unwind-protect - (let ((result (live-jq--run-jq query))) - (if result - (with-current-buffer live-jq--input-buffer - (let ((inhibit-read-only t)) - (erase-buffer) - (insert result)) - (message "jq applied.")) - (user-error "Invalid jq query: see *jq-preview* for details"))) - ;; Cleanup preview buffer after any outcome - (when (get-buffer live-jq--preview-buffer) - (kill-buffer live-jq--preview-buffer)))))) - -(provide 'live-jq) diff --git a/.config/emacs/site-lisp/number-format-mode.el b/.config/emacs/site-lisp/number-format-mode.el deleted file mode 100644 index cbc5937..0000000 --- a/.config/emacs/site-lisp/number-format-mode.el +++ /dev/null @@ -1,129 +0,0 @@ -;;; number-format-mode.el --- Format numbers in the current buffer -*- lexical-binding: t; -*- - -(eval-when-compile - (require 'cl-macs) - (require 'seq)) - -(defgroup number-format nil - "Customization group for `number-format'." - :group 'convenience) ; TODO: Is this the right group? - -(defcustom number-format-separator "." - "Thousands separator to use in numeric literals." - :type 'string - :package-version '(number-format-mode . "1.0.0") - :group 'number-format) - -(defcustom number-format-predicate nil - "Function determining if a number should be formatted. -When formatting a number, this function is called with the START and END -range of the number in the buffer. If this function returns non-nil the -number is formatted. - -If this function is nil then all numbers are formatted." - :type 'function - :package-version '(number-format-mode . "1.0.0") - :group 'number-format) - -(defvar-local number-format--overlays (make-hash-table :test 'eq)) -(defconst number-format--regexp "\\b[0-9]\\{4,\\}\\b") - -(defun number-format--add-separators (s) - (while (string-match "\\(.*[0-9]\\)\\([0-9][0-9][0-9].*\\)" s) - (setq s (concat (match-string 1 s) - number-format-separator - (match-string 2 s)))) - s) - -(defun number-format--adjust-overlays (ov _1 beg end &optional _2) - (let* ((ov-beg (overlay-start ov)) - (ov-end (overlay-end ov)) - (overlays (overlays-in ov-beg ov-end))) - (mapcar #'delete-overlay (gethash ov number-format--overlays)) - (save-excursion - (goto-char ov-beg) - (if (looking-at number-format--regexp :inhibit-modify) - (puthash ov (number-format--at-range ov-beg ov-end) - number-format--overlays) - (delete-overlay ov) - (remhash ov number-format--overlays))))) - -(defun number-format--at-range (beg end) - (when (or (null number-format-predicate) - (funcall number-format-predicate beg end)) - (let* ((offsets [3 1 2]) - (len (- end beg)) - (off (aref offsets (mod len 3)))) - (goto-char (+ beg off))) - (let (overlays) - (while (< (point) end) - (let* ((group-end (+ (point) 3)) - (ov (make-overlay (point) group-end))) - (overlay-put ov 'before-string ".") - (overlay-put ov 'evaporate t) - (push ov overlays) - (goto-char group-end))) - overlays))) - -(defun number-format--jit-lock (beg end) - (let ((line-beg (save-excursion (goto-char beg) (line-beginning-position))) - (line-end (save-excursion (goto-char end) (line-end-position)))) - (number-unformat-region line-beg line-end) - (number-format-region line-beg line-end))) - -;;;###autoload -(defun number-format-region (beg end) - "Format numbers between BEG and END. -When called interactively, format numbers in the active region." - (interactive "r") - (save-excursion - (goto-char beg) - (save-restriction - (narrow-to-region beg end) - (number-unformat-region beg end) - (while (re-search-forward number-format--regexp nil :noerror) - (save-excursion - (cl-destructuring-bind (beg end) (match-data) - (let ((ov (make-overlay beg end nil nil :rear-advance))) - (overlay-put ov 'evaporate t) - (dolist (sym '(insert-behind-hooks - insert-in-front-hooks - modification-hooks)) - (overlay-put ov sym '(number-format--adjust-overlays))) - (puthash ov (number-format--at-range beg end) - number-format--overlays)))))))) - -;;;###autoload -(defun number-unformat-region (beg end) - "Unformat numbers between BEG and END. -When called interactively, unformat numbers in the active region." - (interactive "r") - (dolist (ov (overlays-in beg end)) - (when-let ((overlays (gethash ov number-format--overlays))) - (mapcar #'delete-overlay overlays) - (remhash ov number-format--overlays) - (delete-overlay ov)))) - -;;;###autoload -(defun number-format-buffer () - "Format numbers in the current buffer." - (interactive) - (number-format-region (point-min) (point-max))) - -;;;###autoload -(defun number-unformat-buffer () - "Unformat numbers in the current buffer." - (interactive) - (number-unformat-region (point-min) (point-max))) - -;;;###autoload -(define-minor-mode number-format-mode - "TODO" - :lighter " Number-Format" - :group 'number-format - (number-unformat-buffer) - (if number-format-mode - (jit-lock-register #'number-format--jit-lock) - (jit-lock-unregister #'number-format--jit-lock))) - -(provide 'number-format) \ No newline at end of file diff --git a/.config/emacs/site-lisp/surround.el b/.config/emacs/site-lisp/surround.el deleted file mode 100644 index b5f679d..0000000 --- a/.config/emacs/site-lisp/surround.el +++ /dev/null @@ -1,122 +0,0 @@ -;;; surround.el --- Surround a region with delimeters -*- lexical-binding: t; -*- - -(require 'cl-macs) - -(defgroup surround nil - "Customization group for `surround'." - :group 'convenience) - -(defcustom surround-with-paired-bracket-p t - "Surround text with paired brackets. -If non-nil surrounding text with a character (assuming that character is -not configured in `surround-pairs-alist') will attempt to surround the -text with the supplied character and its paired bracket. - -As an example, if `surround-with-paired-bracket-p' is non-nil and the -user attempts to surround the word “foo” with the character “「” the -result would be “「foo」”. - -Whether or not an opening- or closing bracket is provided is not -important; the opening bracket will always be placed at the front of the -region and the closing bracket at the end of the region (assuming -left-to-right writing). - -In more technical terms this function surrounds text with both the -provided character and the characters corresponding Bidi_Paired_Bracket -Unicode property." - :type 'boolean - :package-version '(surround . "1.0.0") - :group 'surround) - -(defcustom surround-with-mirror-p t - "Surround text with mirrored characters. -If non-nil surrounding text with a character (assuming that character is -not configured in `surround-pairs-alist') will attempt to surround the -text with the supplied character and its mirror. - -As an example, if `surround-with-mirror-p' is non-nil and the user -attempts to surround the word “foo” with the character “«” the result -would be “«foo»”. - -Note that unlike `surround-with-paired-bracket-p', because there is no -concept of an “opening” or “closing” bracket — because this option -doesn't work in terms of brackets — ordering matters. This means that -surrounding “Ελλάδα” with “«” will result in “«Ελλάδα»” while -surrounding “Österreich” with “»” will result in “»Österreich«”. - -In more technical terms this function surrounds text with both the -provided character and the characters corresponding Bidi_Mirroring_Glyph -Unicode property." - :type 'boolean - :package-version '(surround . "1.0.0") - :group 'surround) - -(defvar surround-pairs-alist '((emacs-lisp-mode - . ((?` ("`" . "'"))))) - "TODO") - -(defun surround--get-pair-from-alist (char) - (declare (ftype (function (char) (cons string string))) - (side-effect-free t)) - (catch 'surround--break - (let ((char-as-string (char-to-string char))) - (dolist (pair surround-pairs-alist) - (let ((mode-or-t (car pair)) - (pairs (cdr pair))) - (when (or (derived-mode-p mode-or-t) - (eq t mode-or-t)) - (dolist (pair pairs) - (let ((open-or-trigger (car pair)) - (closing-or-pair (cdr pair))) - (if (numberp open-or-trigger) ; Implies trigger - (when (= char open-or-trigger) - (throw 'surround--break (car closing-or-pair))) - (when (string= char-as-string open-or-trigger) - (throw 'surround--break pair))))))))))) - -(defun surround--get-pair (char) - (declare (ftype (function (char) (cons string string))) - (side-effect-free t)) - (or (surround--get-pair-from-alist char) - (let ((char (char-to-string char)) - (other (char-to-string - (or (when surround-with-paired-bracket-p - (get-char-code-property char 'paired-bracket)) - (when surround-with-mirror-p - (get-char-code-property char 'mirroring)) - char))) - (bracket-type (get-char-code-property char 'bracket-type))) - (pcase bracket-type - ((or 'c 'n) (cons other char)) - ('o (cons char other)))))) - -(defun surround--region (pair beginning end) - (save-excursion - (goto-char beginning) - (insert (car pair)) - (goto-char end) - (insert (cdr pair)))) - -(defun surround-region (char) - (interactive - (list (read-char-from-minibuffer - (format-prompt "Surround with" nil)))) - (when-let ((pair (surround--get-pair char))) - (dolist (bounds (cl-loop for (beginning . end) in (region-bounds) - collect (cons (set-marker (make-marker) beginning) - (set-marker (make-marker) end)))) - (surround--region pair (car bounds) (cdr bounds))))) - -(defun surround-padded-region (char) - (interactive - (list (read-char-from-minibuffer - (format-prompt "Surround with" nil)))) - (when-let ((pair (surround--get-pair char)) - (pair (cons (concat (car pair) " ") - (concat " " (cdr pair))))) - (dolist (bounds (cl-loop for (beginning . end) in (region-bounds) - collect (cons (set-marker (make-marker) beginning) - (set-marker (make-marker) end)))) - (surround--region pair (car bounds) (cdr bounds))))) - -(provide 'surround) diff --git a/.config/emacs/templates b/.config/emacs/templates deleted file mode 100644 index ad4e97a..0000000 --- a/.config/emacs/templates +++ /dev/null @@ -1,38 +0,0 @@ -;; NOTE: https://github.com/minad/tempel/issues/23 - -c-mode c-ts-mode c++-mode c++-ts-mode - -(guard - "#ifndef " - (p - (thread-last - (file-name-base (or (buffer-file-name) - (buffer-name))) - (concat (when-let ((project (project-current))) - (concat (project-name project) "_"))) - (upcase) - (string-replace "-" "_") - (replace-regexp-in-string "^[0-9]+" "_\\&") - (replace-regexp-in-string "[^A-Z0-9_]+" "") - (format "%s_H")) - header) - n - "#define " header n n r n n - "#endif /* !" header " */") - -emacs-lisp-mode - -(header - ";;; " (file-name-nondirectory (or (buffer-file-name) - (buffer-name))) - " --- " p " -*- lexical-binding: t; -*-" n n q) - -(section "\f" n ";;; " p n n q) - -vue-ts-mode - -(fcrow - > "
" - n> "" - n> q - n> "
") \ No newline at end of file -- cgit v1.2.3