emac update

This commit is contained in:
2025-12-29 12:12:55 -05:00
parent 3594439b47
commit 14577b8e17
2 changed files with 187 additions and 60 deletions

View File

@@ -135,14 +135,18 @@
;;; FLYMAKE & DIAGNOSTICS ;;; FLYMAKE & DIAGNOSTICS
;;; ============================================================================ ;;; ============================================================================
;; hide squiggly underlines
(set-face-attribute 'flymake-error nil :underline nil)
(set-face-attribute 'flymake-warning nil :underline nil)
(set-face-attribute 'flymake-note nil :underline nil)
;; hide fringe indicators ;; hide fringe indicators
(setq flymake-fringe-indicator-position nil) (setq flymake-fringe-indicator-position nil)
;; hide squiggly underlines (must be set after flymake loads)
(with-eval-after-load 'flymake
(set-face-attribute 'flymake-error nil :underline nil)
(set-face-attribute 'flymake-warning nil :underline nil)
(set-face-attribute 'flymake-note nil :underline nil))
;; disable eglot inlay hints
(add-to-list 'eglot-ignored-server-capabilities :inlayHintProvider)
(defun my-flymake-show-project-errors-warnings () (defun my-flymake-show-project-errors-warnings ()
"Show project diagnostics, filtering out notes (only errors and warnings)." "Show project diagnostics, filtering out notes (only errors and warnings)."
(interactive) (interactive)
@@ -248,9 +252,6 @@
;; editing behavior ;; editing behavior
(show-paren-mode 1) (show-paren-mode 1)
(delete-selection-mode 1) (delete-selection-mode 1)
(cua-mode t)
(setq cua-auto-tabify-rectangles nil)
(setq cua-keep-region-after-copy nil)
(transient-mark-mode 1) (transient-mark-mode 1)
(electric-pair-mode -1) (electric-pair-mode -1)
(electric-indent-mode 0) (electric-indent-mode 0)
@@ -404,12 +405,20 @@
(setq mac-command-modifier 'control) (setq mac-command-modifier 'control)
(setq mac-control-modifier 'command) (setq mac-control-modifier 'command)
;; Remap C-c and C-x prefixes to C-k so we can use them for copy/cut
(global-unset-key (kbd "C-k")) ; unbind kill-line so C-k can be a prefix
(define-prefix-command 'my-ck-prefix)
(global-set-key (kbd "C-k") 'my-ck-prefix)
(define-key my-ck-prefix (kbd "C-c") mode-specific-map)
(define-key my-ck-prefix (kbd "C-x") ctl-x-map)
;; isearch settings ;; isearch settings
(setq isearch-wrap-pause 'no) (setq isearch-wrap-pause 'no)
;; --- File & Buffer Operations --- ;; --- File & Buffer Operations ---
(global-set-key (kbd "C-s") 'save-buffer) (global-set-key (kbd "C-s") 'save-buffer)
(global-set-key (kbd "C-n") (lambda () (interactive) (switch-to-buffer (generate-new-buffer "untitled")))) (global-set-key (kbd "C-n") (lambda () (interactive) (switch-to-buffer (generate-new-buffer "untitled"))))
(global-set-key (kbd "C-o") 'find-file)
(global-set-key (kbd "C-p") 'project-find-file) (global-set-key (kbd "C-p") 'project-find-file)
(global-set-key (kbd "C-3") 'switch-to-buffer) (global-set-key (kbd "C-3") 'switch-to-buffer)
(global-set-key (kbd "C-4") 'find-file) (global-set-key (kbd "C-4") 'find-file)
@@ -420,7 +429,8 @@
(global-set-key (kbd "C-w") 'delete-window) (global-set-key (kbd "C-w") 'delete-window)
(global-set-key (kbd "C-\\") 'split-window-below) (global-set-key (kbd "C-\\") 'split-window-below)
(global-set-key (kbd "C-|") 'split-window-right) (global-set-key (kbd "C-|") 'split-window-right)
(global-set-key (kbd "C-o") 'next-multiframe-window) (global-set-key (kbd "C-<prior>") 'previous-multiframe-window)
(global-set-key (kbd "C-<next>") 'next-multiframe-window)
(global-set-key (kbd "C-1") 'my-select-left-pane) (global-set-key (kbd "C-1") 'my-select-left-pane)
(global-set-key (kbd "C-2") 'my-select-right-pane) (global-set-key (kbd "C-2") 'my-select-right-pane)
(global-set-key (kbd "<f11>") 'toggle-frame-maximized) (global-set-key (kbd "<f11>") 'toggle-frame-maximized)
@@ -430,14 +440,14 @@
(global-set-key (kbd "C-l") 'my-select-line) (global-set-key (kbd "C-l") 'my-select-line)
(global-set-key (kbd "C-/") 'my-toggle-comment) (global-set-key (kbd "C-/") 'my-toggle-comment)
(global-set-key (kbd "M-j") 'my-duplicate-line) (global-set-key (kbd "M-j") 'my-duplicate-line)
(global-unset-key (kbd "C-x C-SPC")) (global-set-key (kbd "C-k C-x C-SPC") 'rectangle-mark-mode)
(global-set-key (kbd "C-x C-SPC") 'rectangle-mark-mode)
(global-set-key (kbd "S-<down-mouse-1>") #'my-mouse-start-rectangle) (global-set-key (kbd "S-<down-mouse-1>") #'my-mouse-start-rectangle)
;; --- Clipboard & Kill Ring --- ;; --- Clipboard & Kill Ring (CUA-style) ---
(global-set-key [?\C-z] 'undo) (global-set-key (kbd "C-z") 'undo)
(global-set-key (kbd "C-y") 'clipboard-yank) (global-set-key (kbd "C-v") 'clipboard-yank)
(global-set-key (kbd "M-w") 'clipboard-kill-ring-save) (global-set-key (kbd "C-c") 'my-copy)
(global-set-key (kbd "C-x") 'my-cut)
;; --- Navigation --- ;; --- Navigation ---
(global-set-key (kbd "<home>") 'my-smart-home) (global-set-key (kbd "<home>") 'my-smart-home)
@@ -458,6 +468,7 @@
(global-set-key (kbd "C-*") 'search-current-word) (global-set-key (kbd "C-*") 'search-current-word)
(global-set-key (kbd "C-S-f") 'my-project-find-text) (global-set-key (kbd "C-S-f") 'my-project-find-text)
(global-set-key (kbd "C-S-h") 'my-find-replace) (global-set-key (kbd "C-S-h") 'my-find-replace)
(global-set-key (kbd "C-r") 'my-configure-search-settings)
;; --- Code Navigation (xref/LSP) --- ;; --- Code Navigation (xref/LSP) ---
(global-set-key (kbd "<f12>") 'my-xref-find-definitions-same-pane) (global-set-key (kbd "<f12>") 'my-xref-find-definitions-same-pane)
@@ -499,9 +510,6 @@
(global-set-key (kbd "C-=") 'my-global-zoom-in) (global-set-key (kbd "C-=") 'my-global-zoom-in)
(global-set-key (kbd "C--") 'my-global-zoom-out) (global-set-key (kbd "C--") 'my-global-zoom-out)
(global-set-key (kbd "C-0") 'my-global-zoom-reset) (global-set-key (kbd "C-0") 'my-global-zoom-reset)
(global-unset-key (kbd "C-x C-="))
(global-unset-key (kbd "C-x C--"))
(global-unset-key (kbd "C-x C-0"))
(global-set-key (kbd "C-<wheel-up>") 'ignore) (global-set-key (kbd "C-<wheel-up>") 'ignore)
(global-set-key (kbd "C-<wheel-down>") 'ignore) (global-set-key (kbd "C-<wheel-down>") 'ignore)
@@ -548,7 +556,9 @@
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map (kbd "M-p") 'backward-paragraph) (define-key map (kbd "M-p") 'backward-paragraph)
(define-key map (kbd "M-n") 'forward-paragraph) (define-key map (kbd "M-n") 'forward-paragraph)
(define-key map (kbd "C-o") 'next-multiframe-window) (define-key map (kbd "C-o") 'find-file)
(define-key map (kbd "C-<prior>") 'previous-multiframe-window)
(define-key map (kbd "C-<next>") 'next-multiframe-window)
(define-key map (kbd "C-1") 'my-select-left-pane) (define-key map (kbd "C-1") 'my-select-left-pane)
(define-key map (kbd "C-2") 'my-select-right-pane) (define-key map (kbd "C-2") 'my-select-right-pane)
(define-key map (kbd "C-3") 'switch-to-buffer) (define-key map (kbd "C-3") 'switch-to-buffer)
@@ -557,6 +567,9 @@
(define-key map (kbd "C-d") 'my-mc-mark-next-like-this) (define-key map (kbd "C-d") 'my-mc-mark-next-like-this)
(define-key map (kbd "C-S-d") 'mc/mark-previous-like-this-word) (define-key map (kbd "C-S-d") 'mc/mark-previous-like-this-word)
(define-key map (kbd "C-S-a") 'mc/mark-all-like-this) (define-key map (kbd "C-S-a") 'mc/mark-all-like-this)
(define-key map (kbd "C-c") 'my-copy)
(define-key map (kbd "C-x") 'my-cut)
(define-key map (kbd "C-v") 'clipboard-yank)
map) map)
"my-keys-minor-mode keymap.") "my-keys-minor-mode keymap.")
@@ -641,17 +654,92 @@ Falls back to dumb-jump if xref fails."
;;; CUSTOM FUNCTIONS - Search & Replace ;;; CUSTOM FUNCTIONS - Search & Replace
;;; ============================================================================ ;;; ============================================================================
(defun my-isearch-forward () (defvar my-search-use-regexp nil
"Start isearch, using selected text if region is active." "When non-nil, search functions use regexp mode instead of literal text.")
(defvar my-search-whole-word nil
"When non-nil, search functions match whole words only.")
(defvar my-search-case-sensitive nil
"When non-nil, search functions are case-sensitive. When nil, uses smart case.")
(defun my-search-settings-status ()
"Return a string showing current search settings."
(format "Search :: Regexp: %s | Whole-word: %s | Case-sensitive: %s"
(if my-search-use-regexp "on" "off")
(if my-search-whole-word "on" "off")
(if my-search-case-sensitive "on" "off")))
(defun my-configure-search-settings ()
"Prompt user to configure search settings: regexp, whole-word, case-sensitivity."
(interactive) (interactive)
(if (use-region-p) (let* ((regexp-choice (completing-read
(let ((text (buffer-substring-no-properties (region-beginning) (region-end)))) (format "Search :: Regexp [current: %s]: " (if my-search-use-regexp "on" "off"))
(deactivate-mark) (if my-search-use-regexp '("on" "off") '("off" "on")) nil t))
(isearch-forward nil 1) (word-choice (completing-read
(setq isearch-string text (format "Search :: Whole word [current: %s]: " (if my-search-whole-word "on" "off"))
isearch-message text) (if my-search-whole-word '("on" "off") '("off" "on")) nil t))
(isearch-update)) (case-choice (completing-read
(isearch-forward))) (format "Search :: Case sensitive [current: %s]: " (if my-search-case-sensitive "on" "off"))
(if my-search-case-sensitive '("on" "off") '("off" "on")) nil t)))
(setq my-search-use-regexp (string= regexp-choice "on"))
(setq my-search-whole-word (string= word-choice "on"))
(setq my-search-case-sensitive (string= case-choice "on"))
(message (my-search-settings-status))))
(defun my-search-transform-pattern (text)
"Transform TEXT according to current search settings.
Applies regexp-quote if not in regexp, and word boundaries if whole-word mode."
(let ((pattern (if my-search-use-regexp text (regexp-quote text))))
(if my-search-whole-word
(concat "\\_<" pattern "\\_>")
pattern)))
(defvar my-isearch-apply-settings nil
"When non-nil, apply custom search settings to isearch on next start.")
(defun my-isearch-apply-custom-settings ()
"Apply custom search settings when isearch starts via my-isearch-forward."
(when my-isearch-apply-settings
(setq isearch-case-fold-search (not my-search-case-sensitive))
(setq my-isearch-apply-settings nil)))
(add-hook 'isearch-mode-hook #'my-isearch-apply-custom-settings)
(defun my-isearch-forward ()
"Start isearch, using selected text if region is active.
Respects search settings: regexp, whole-word, case-sensitivity."
(interactive)
(setq my-isearch-apply-settings t)
(cond
;; Region active: use selected text as search string
((use-region-p)
(let* ((raw-text (buffer-substring-no-properties (region-beginning) (region-end)))
(use-regexp (or my-search-use-regexp my-search-whole-word))
(text (cond
((and my-search-whole-word my-search-use-regexp)
(concat "\\_<" raw-text "\\_>"))
(my-search-whole-word
(concat "\\_<" (regexp-quote raw-text) "\\_>"))
(my-search-use-regexp
raw-text)
(t raw-text))))
(deactivate-mark)
(if use-regexp
(isearch-forward-regexp nil 1)
(isearch-forward nil 1))
(setq isearch-string text
isearch-message (if use-regexp text raw-text))
(isearch-update)))
;; Whole word mode without selection: use isearch-forward-word
(my-search-whole-word
(isearch-forward-word))
;; Regexp mode
(my-search-use-regexp
(isearch-forward-regexp))
;; Normal literal search
(t
(isearch-forward))))
(defun my-isearch-cancel-or-exit () (defun my-isearch-cancel-or-exit ()
"Cancel isearch if search string is empty, otherwise exit at current position." "Cancel isearch if search string is empty, otherwise exit at current position."
@@ -679,12 +767,22 @@ Falls back to dumb-jump if xref fails."
(isearch-yank-string (buffer-substring-no-properties $p1 $p2)))) (isearch-yank-string (buffer-substring-no-properties $p1 $p2))))
(defun my-project-find-text () (defun my-project-find-text ()
"Search for literal text in project." "Search for text in project.
Respects search settings: regexp, whole-word, case-sensitivity."
(interactive) (interactive)
(let* ((initial (when (use-region-p) (let* ((initial (when (use-region-p)
(buffer-substring-no-properties (region-beginning) (region-end)))) (buffer-substring-no-properties (region-beginning) (region-end))))
(text (read-string "Search in project: " initial))) (settings-hint (concat
(project-find-regexp (regexp-quote text)))) (if my-search-use-regexp "regex" "")
(if my-search-whole-word (if my-search-use-regexp ",word" "word") "")
(if my-search-case-sensitive
(if (or my-search-use-regexp my-search-whole-word) ",case" "case") "")))
(prompt (if (string= settings-hint "")
"Search in project: "
(format "Search in project [%s]: " settings-hint)))
(text (read-string prompt initial))
(case-fold-search (not my-search-case-sensitive)))
(project-find-regexp (my-search-transform-pattern text))))
(defun my-project-find-word-at-point () (defun my-project-find-word-at-point ()
"Search for word under cursor in project." "Search for word under cursor in project."
@@ -702,22 +800,59 @@ Falls back to dumb-jump if xref fails."
(project-find-regexp (regexp-quote word))))) (project-find-regexp (regexp-quote word)))))
(defun my-find-replace () (defun my-find-replace ()
"Find and replace with mode selection: project, file, or selection." "Find and replace. If region is active, replace in region. Otherwise prompt for file or project.
Respects search settings: regexp, whole-word, case-sensitivity."
(interactive) (interactive)
(let* ((mode (completing-read "Replace in: " '("file" "project" "selection") nil t)) (let* ((settings-hint (concat
(search (read-string "Find: ")) (if my-search-use-regexp "regex" "")
(replace (read-string (format "Replace '%s' with: " search)))) (if my-search-whole-word (if my-search-use-regexp ",word" "word") "")
(cond (if my-search-case-sensitive
((string= mode "project") (if (or my-search-use-regexp my-search-whole-word) ",case" "case") "")))
(project-query-replace-regexp (regexp-quote search) replace)) (find-prompt (if (string= settings-hint "")
((string= mode "file") "Find: "
(save-excursion (format "Find [%s]: " settings-hint)))
(goto-char (point-min)) (case-fold-search (not my-search-case-sensitive))
(query-replace search replace))) (use-regexp (or my-search-use-regexp my-search-whole-word)))
((string= mode "selection") (if (use-region-p)
(if (use-region-p) (let* ((beg (region-beginning))
(query-replace search replace nil (region-beginning) (region-end)) (end (region-end))
(message "No region selected.")))))) (search (read-string find-prompt))
(pattern (my-search-transform-pattern search))
(replace (read-string (format "Replace '%s' with: " search))))
(if use-regexp
(query-replace-regexp pattern replace nil beg end)
(query-replace search replace nil beg end)))
(let* ((mode (completing-read "Replace in: " '("file" "project") nil t))
(search (read-string find-prompt))
(pattern (my-search-transform-pattern search))
(replace (read-string (format "Replace '%s' with: " search))))
(cond
((string= mode "project")
(project-query-replace-regexp pattern replace))
((string= mode "file")
(save-excursion
(goto-char (point-min))
(if use-regexp
(query-replace-regexp pattern replace)
(query-replace search replace)))))))))
;;; ============================================================================
;;; CUSTOM FUNCTIONS - Clipboard (CUA-style)
;;; ============================================================================
(defun my-copy ()
"Copy region to clipboard. If no region is active, copy the current line."
(interactive)
(if (use-region-p)
(clipboard-kill-ring-save (region-beginning) (region-end))
(clipboard-kill-ring-save (line-beginning-position) (line-beginning-position 2))))
(defun my-cut ()
"Cut region to clipboard. If no region is active, cut the current line."
(interactive)
(if (use-region-p)
(clipboard-kill-region (region-beginning) (region-end))
(clipboard-kill-region (line-beginning-position) (line-beginning-position 2))))
;;; ============================================================================ ;;; ============================================================================
;;; CUSTOM FUNCTIONS - Line Operations ;;; CUSTOM FUNCTIONS - Line Operations
@@ -926,7 +1061,7 @@ Does not copy to kill ring."
(defun my-select-theme () (defun my-select-theme ()
"Select and load a theme from all available themes." "Select and load a theme from all available themes."
(interactive) (interactive)
(let* ((themes (append '("default" "default-dark") (mapcar #'symbol-name (custom-available-themes)))) (let* ((themes (append '("default" "default-dark" "xah") (mapcar #'symbol-name (custom-available-themes))))
(choice (completing-read "Theme: " themes nil t))) (choice (completing-read "Theme: " themes nil t)))
(when my-current-theme (when my-current-theme
(disable-theme my-current-theme)) (disable-theme my-current-theme))
@@ -939,6 +1074,10 @@ Does not copy to kill ring."
(set-foreground-color "white") (set-foreground-color "white")
(set-background-color "black") (set-background-color "black")
(setq my-current-theme nil)) (setq my-current-theme nil))
((string= choice "xah")
(set-foreground-color "black")
(set-background-color "honeydew")
(setq my-current-theme nil))
(t (t
(setq my-current-theme (intern choice)) (setq my-current-theme (intern choice))
(load-theme my-current-theme t))))) (load-theme my-current-theme t)))))

View File

@@ -77,15 +77,6 @@
'(compilation-mode-line-exit ((t (:foreground "#51b04f")))) '(compilation-mode-line-exit ((t (:foreground "#51b04f"))))
'(compilation-mode-line-fail ((t (:foreground "#ff6f6f")))) '(compilation-mode-line-fail ((t (:foreground "#ff6f6f"))))
;; Flymake
'(flymake-error ((t (:underline (:style wave :color "#ff6f6f")))))
'(flymake-warning ((t (:underline (:style wave :color "#d09950")))))
'(flymake-note ((t (:underline (:style wave :color "#8f8886")))))
;; Flyspell
'(flyspell-incorrect ((t (:underline (:style wave :color "#ff6f6f")))))
'(flyspell-duplicate ((t (:underline (:style wave :color "#d09950")))))
;; Vertico ;; Vertico
'(vertico-current ((t (:background "#503240" :foreground "#efd5c5")))) '(vertico-current ((t (:background "#503240" :foreground "#efd5c5"))))
'(vertico-group-title ((t (:foreground "#8fcfd0")))) '(vertico-group-title ((t (:foreground "#8fcfd0"))))
@@ -117,9 +108,6 @@
'(ediff-fine-diff-B ((t (:background "#2f6767")))) '(ediff-fine-diff-B ((t (:background "#2f6767"))))
'(ediff-fine-diff-C ((t (:background "#64651f")))) '(ediff-fine-diff-C ((t (:background "#64651f"))))
;; Eglot
'(eglot-highlight-symbol-face ((t (:background "#412f4f"))))
;; Link ;; Link
'(link ((t (:foreground "#57b0ff" :underline t)))) '(link ((t (:foreground "#57b0ff" :underline t))))
'(link-visited ((t (:foreground "#d0b0ff" :underline t)))) '(link-visited ((t (:foreground "#d0b0ff" :underline t))))