This commit is contained in:
2026-05-26 03:17:52 +02:00
parent f3cb5a6e26
commit 102a3357c3
4 changed files with 248 additions and 6 deletions
+3 -2
View File
@@ -110,11 +110,11 @@
'("o" . meow-block) '("o" . meow-block)
'("O" . meow-to-block) '("O" . meow-to-block)
'("p" . meow-yank) '("p" . meow-yank)
'("q" . meow-quit) ;;'("q" . meow-quit)
'("Q" . meow-goto-line) '("Q" . meow-goto-line)
'("r" . meow-replace) '("r" . meow-replace)
'("R" . meow-swap-grab) '("R" . meow-swap-grab)
'("s" . meow-kill) '("k" . meow-kill)
'("t" . meow-till) '("t" . meow-till)
'("u" . meow-undo) '("u" . meow-undo)
'("U" . meow-undo-in-selection) '("U" . meow-undo-in-selection)
@@ -127,3 +127,4 @@
'("Y" . meow-sync-grab) '("Y" . meow-sync-grab)
'("z" . meow-pop-selection) '("z" . meow-pop-selection)
'("'" . repeat))) '("'" . repeat)))
+53
View File
@@ -0,0 +1,53 @@
;;; system.el --- System integration functions -*- lexical-binding: t; -*-
(defun my/system-cut (beg end)
"Cut region directly to system clipboard, bypassing the kill ring."
(interactive "r")
(my/system-copy beg end)
;; delete-region deletes without adding to the kill ring
(delete-region beg end))
(defun my/system-copy (beg end)
"Pure copy: Sends the active region directly to the system clipboard.
Absolutely zero interaction with the Emacs kill ring."
(interactive "r")
(unless (region-active-p)
(user-error "No active region to copy"))
(let ((text (buffer-substring-no-properties beg end)))
(if (display-graphic-p)
;; Low-level GUI primitive: talks directly to the OS clipboard manager
(gui-backend-set-selection 'CLIPBOARD text)
;; TUI Fallback via Clipetty
(if (fboundp 'clipetty-set-selection)
(clipetty-set-selection text)
(error "Clipetty not loaded")))
(deactivate-mark)
(message "Copied to system clipboard (pure)")))
(defun my/system-paste ()
"Pure paste: Inserts text directly from the system clipboard.
Never falls back to or checks the Emacs kill ring."
(interactive)
(if (display-graphic-p)
(let ((text (or (gui-backend-get-selection 'CLIPBOARD 'STRING)
(gui-backend-get-selection 'CLIPBOARD 'UTF8_STRING)
(gui-backend-get-selection 'PRIMARY 'STRING)
;; Wayland/Dolphin fallback from previous fix
(when (executable-find "wl-paste")
(let ((val (shell-command-to-string "wl-paste -n -t text/plain")))
(unless (string-empty-p val) val))))))
(if text
(insert text)
(user-error "System clipboard is empty")))
;; TUI Fallback
(message "In a terminal, use your terminal emulator's native paste shortcut (e.g., Ctrl-Shift-V).")))
(defun my/vterm-sync-here ()
"Switch to vterm and instantly 'cd' to the current buffer's directory."
(interactive)
(let ((cwd default-directory))
(vterm-toggle)
(vterm-send-string (format "cd %s" (shell-quote-argument cwd)))
(vterm-send-return)))
(provide 'system)
;;unqualified-search-registries = ["docker.io"]
+18 -4
View File
@@ -1,13 +1,27 @@
;;; ../../lyfi/configs/apps/doom/custom/ui.el -*- lexical-binding: t; -*- ;;; ../../lyfi/configs/apps/doom/custom/ui.el -*- lexical-binding: t; -*-
(defun my/apply-theme (frame) (defun my/apply-theme (frame)
"Apply a specific theme based on whether the FRAME is graphic or TUI." "Apply a specific theme and update package colors based on whether the FRAME is graphic or TUI."
(select-frame frame) (select-frame frame)
(if (display-graphic-p frame) (if (display-graphic-p frame)
(progn (progn
(mapc #'disable-theme custom-enabled-themes) (mapc #'disable-theme custom-enabled-themes)
(load-theme 'cutarv32 t)) ;; Your GUI theme (load-theme 'cutarv41 t)
;; Update rainbow-delimiters colors for Light theme
(setq rainbow-delimiters-rainbow-colors
'("#007cbf" "#cf3f29" "#2374de" "#c75e10" "#b05197" "#429e66" "#129cc9" "#a64dd6")))
(progn (progn
(mapc #'disable-theme custom-enabled-themes) (mapc #'disable-theme custom-enabled-themes)
(load-theme 'cutarv32_dark t)))) ;; Your TUI theme (load-theme 'cutarv41 t)
;; Update rainbow-delimiters colors for Dark theme
;; (setq rainbow-delimiters-rainbow-colors
;; '("#4da6ff" "#ff6b6b" "#6da6ff" "#ffb347" "#d18ecb" "#8fbc8f" "#80daeb" "#c8a0f2"))
))
(custom-set-faces
`(meow-insert-cursor ((t (:inherit unspecified :background ,(face-attribute 'font-lock-builtin-face :foreground)))))
`(meow-normal-cursor ((t (:foreground ,(face-attribute 'mode-line-inactive :background), :background ,(face-attribute 'mode-line :foreground)))))
)
)
(provide 'ui)
+174
View File
@@ -0,0 +1,174 @@
;;; utils.el --- General utility functions -*- lexical-binding: t; -*-
(defun dired-follow-symlink ()
"In dired, visit the file or directory at point by its true physical path."
(interactive)
(let ((filename (dired-get-file-for-visit)))
(if filename
(find-file (file-truename filename))
(message "No file at point"))))
(defun my/delete-word-backward ()
"Delete the previous 'block' of characters without killing them.
Blocks are defined by: whitespace, alphanumerics, or groups of symbols."
(interactive)
(if (use-region-p)
(delete-region (region-beginning) (region-end))
(let ((end (point)))
(save-excursion
(cond
;; Case 1: Multiple spaces or tabs (but not a newline)
((looking-back "[ \t]+" 1)
(re-search-backward "[^ \t]" nil t)
(forward-char 1))
;; Case 2: Newlines
((looking-back "\n+" 1)
(re-search-backward "[^\n]" nil t)
(forward-char 1))
;; Case 3: Alphanumerics (Words)
((looking-back "[[:alnum:]]+" 1)
(re-search-backward "[^[:alnum:]]" nil t)
(forward-char 1))
;; Case 4: Special Characters (Symbols)
(t
(re-search-backward "[[:alnum:][:space:]]" nil t)
(forward-char 1)))
(delete-region (point) end)))))
(defun my-set-buffer-font ()
"Set a specific font for the current buffer only."
(buffer-face-set '(:family "Noto Sans" :height 140)))
(defun my/toggle-quote-wrap-all-in-region (beg end)
"Toggle wrapping all items in region with double quotes."
;;https://xenodium.com/emacs-quote-wrap-all-in-region
(interactive (list (mark) (point)))
(unless (region-active-p)
(user-error "no region to wrap"))
(let ((deactivate-mark nil)
(replacement (string-join
(mapcar (lambda (item)
(if (string-match-p "^\".*\"$" item)
(string-trim item "\"" "\"")
(format "\"%s\"" item)))
(split-string (buffer-substring beg end)))
" ")))
(delete-region beg end)
(insert replacement)))
(defun my/meow-wrap-arbitrary (s e)
"Wrap the current meow selection with arbitrary strings."
(interactive "r")
(let ((start-str (read-string "Start: "))
(end-str (read-string "End: ")))
(save-excursion
(goto-char e)
(insert end-str)
(goto-char s)
(insert start-str))))
(defun my/column-align-regexp ()
"Aligns the matched regexp to `comment-column`.
If the text preceding the regexp is already past `comment-column`,
it ensures exactly one space of separation."
(interactive)
(let* ((regexp (read-string "Align on regexp: "))
;; Use comment-column if set, otherwise default to 40
(target-col (if (and (boundp 'comment-column)
(numberp comment-column))
comment-column
40))
(start (region-beginning))
(end (region-end)))
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(let* ((match-start (match-beginning 0))
(match-end (match-end 0)))
;; 1. Find the end of the actual content before the match
;; We move back from the match start and skip all whitespace
(save-excursion
(goto-char match-start)
(skip-chars-backward " \t")
(let ((content-end-pos (point))
(content-end-col (current-column)))
;; Delete the whitespace between the content and the match
(delete-region content-end-pos match-start)
;; Calculate how much space we need
(if (< content-end-col target-col)
(let ((num-spaces (- target-col content-end-col)))
(insert (make-string num-spaces ?\s)))
;; If content is already past the target, just insert one space
(insert " "))))
;; Move point to the end of the match to continue searching
(goto-char match-end)))))))
;; Optional: Bind it to a key for easier access
;; (global-set-key (kbd "C-c a l") 'my/column-align-regexp)
(defun diff-buffers (buffer-a buffer-b)
"Generate a diff between BUFFER-A and BUFFER-B using standard diff.
Prompts for the two buffers, defaulting to the current buffer and the
most recently active one."
(interactive
(let* ((current (current-buffer))
(other (other-buffer current t))
(buf-a (read-buffer "New buffer (to diff): " current t))
(buf-b (read-buffer "Old buffer (against): " other t)))
(list (get-buffer buf-a) (get-buffer buf-b))))
(let ((name-a (buffer-name buffer-a))
(name-b (buffer-name buffer-b)))
(diff buffer-b buffer-a nil t)
;; Rename the diff output buffer to make it clear what was diffed
(when (get-buffer "*Diff*")
(with-current-buffer "*Diff*"
(rename-buffer (format "*Diff: %s vs %s*" name-b name-a) t)))))
(defun my/list-no-prefix-bindings (keymap &optional map-name)
"Extract and display all single-key (no-prefix) bindings from KEYMAP.
Outputs a clean list into a dedicated buffer."
(interactive (list global-map "global-map"))
(let ((buf (get-buffer-create "*No-Prefix Bindings*"))
(bindings '()))
(cl-labels ((map-extract (map)
(map-keymap
(lambda (event binding)
(cond
;; Skip nested/prefix keymaps entirely
((keymapp binding) nil)
;; Handle standard events (symbols or characters)
((or (symbolp event) (integerp event))
(let ((key-str (single-key-description event)))
;; Filter for simple keys (no spaces, meaning no multi-key sequences)
(unless (string-match-p " " key-str)
(push (cons key-str binding) bindings))))))
map)))
(map-extract keymap)
;; Sort logically by key description
;; Print the results cleanly
(with-current-buffer buf
(text-mode)
(setq buffer-read-only nil)
(erase-buffer)
(insert (format "No-Prefix Bindings for: %s\n" (or map-name "Selected Map")))
(insert "==================================================\n\n")
(dolist (b bindings)
(insert (format "%-15s -> %s\n" (car b) (cdr b))))
(setq buffer-read-only t))
(pop-to-buffer buf))))
(provide 'utils)