diff --git a/config.el b/config.el index 3380c02..5b8f398 100644 --- a/config.el +++ b/config.el @@ -1,165 +1,259 @@ -;;; config.el -*- lexical-binding: t; -*- +;; config.el -*- lexical-binding: t; -*- ;; ============================================================ ;; Custom & Packages Loading ;; ============================================================ (let ((custom-dir (expand-file-name "custom/" user-emacs-directory))) (when (file-directory-p custom-dir) - (mapc #'load (directory-files custom-dir t "\\.el$")))) - -;; (let ((pkg-dir (expand-file-name "packages/" user-emacs-directory))) -;; (when (file-directory-p pkg-dir) -;; (mapc #'load (directory-files pkg-dir t "\\.el$")))) + (dolist (file (directory-files custom-dir nil "\\.el$")) + (load (expand-file-name (file-name-sans-extension file) custom-dir))))) (add-to-list 'load-path (expand-file-name "packages/" user-emacs-directory)) -;;(add-to-list 'load-path (expand-file-name "custom/" user-emacs-directory)) (add-to-list 'custom-theme-load-path (expand-file-name "themes/" user-emacs-directory)) -(require 'visuals-packages) ;;ui, eye candy -(require 'editing-packages) ;;text editing -(require 'system-packages) ;; emacs itself -(require 'tutilities-packages) ;; tertiary utilities -(require 'completion-packages) ;; ui, functional +(add-hook + 'after-init-hook + (lambda () + (require 'visuals-packages) ; ui, eye candy + (require 'editing-packages) ; text editing + (require 'system-packages) ; emacs itself + (require 'tutilities-packages) ; tertiary utilities + (require 'completion-packages) ; ui, functional + (require 'dev-packages) ; lsp, treesitter + ) + ) +;; ============================================================ +;; Keybindings +;; ============================================================ (use-package general :config - (general-def - :keymaps 'global - "C-S-c" #'my/system-copy - "C-S-x" #'my/system-cut - "C-S-v" #'my/system-paste - "C-z" #'undo - "C-S-z" #'undo-redo - "C-k" #'avy-kill-whole-line - "C-r" #'recenter-top-bottom - "C-b" #'scroll-down-command - "C-" #'my/delete-word-backward - - "M-w" #'clipetty-kill-ring-save - ) - (general-def - :keymaps 'override - "M-g g" #'avy-goto-line - "C-s C-f" #'avy-goto-char-timer - "C-s C-s C-f" #'my/avy-char-region - "C-s C-S-s" #'my/avy-line-region - "C-s w" #'my/vterm-sync-here - "C-x C-b" #'buffer-table - "C-s C-l" #'consult-line - "C-s C-e" #'expreg-expand - ) (general-define-key :keymaps 'global - "C-w" #'delete-window)) + "C-l" nil ; recenter + "C-n" nil ; next line + "C-p" nil ; previous line + "C-f" nil ; forward chard + "C-o" nil ; idk + "C-t" nil ; transpose + ;"C-m" nil can't be rebound because is same as ret + "C->" nil ;end of buffer + "C-<" nil ;start of buffer + ) + + (general-def + :keymaps 'global + "C-S-c" #'my/system-copy + "C-S-x" #'my/system-cut + "C-S-v" #'my/system-paste + "C-z" #'undo + "C-M-z" #'undo-redo + "C-k" #'avy-kill-whole-line + "C-r" #'recenter-top-bottom + "C-b" #'scroll-down-command + "C-" #'my/delete-word-backward + "M-" #'my/delete-word-backward + "M-s M-s" #'scroll-lock-mode + "C-w" #'delete-window + + "C-x m" #'switch-to-minibuffer + + "M-w" #'clipetty-kill-ring-save + ; "C-x S-v" #'shrink-window + ; "C-x v" #'enlarge-window + ) + (general-def + :keymaps 'override + "C-s C-s C-f" #'my/avy-char-region ; search select find + "C-s C-s C-l" #'my/avy-line-region ; search select line + "C-s C-e" #'expreg-expand ; selection expand + "C-s C-c" #'expreg-contract ; selection contract + + "C-s f" #'kirigami-toggle-fold ; fold + ) + + (general-def + :keymaps 'override + + "C-f C-r" #'buffer-table ; recent buffer + "C-f C-f" #'avy-goto-char-timer ; find + "C-f C-l" #'consult-line ; line + "C-f g" #'avy-goto-line ; goto + + ) + + (general-def + :keymaps 'override + "C-s s" #'shell-pop ; shell + ) + ) + +;; 1. Make single ';' trigger Control for the very next keypress +(define-key key-translation-map (kbd ";") 'event-apply-control-modifier) + +;; 2. Bind C-; to insert a literal semicolon directly +(global-set-key (kbd "C-;") (lambda () (interactive) (insert ";"))) + ;; ============================================================ -;; Core Settings & UI +;; 2. Native Emacs & System Configuration ;; ============================================================ -(setq kill-ring-max 1 - select-enable-clipboard nil - select-enable-primary nil - save-interprogram-paste-before-kill nil - ;;xterm-extra-capabilities '(getSelection setSelection modifyOtherKeys) - mouse-drag-copy-region nil - tab-width 4 - truncate-lines nil - display-line-numbers-type t - cursor-type 'bar - savehist-additional-variables '(kill-ring search-ring) - recentf-max-saved-items 75 - - global-auto-revert-non-file-buffers t - - undo-limit 60000000 - undo-strong-limit 90000000 - undo-outer-limit 120000000 - ) - - -(setq-default - tab-width 4 - js-indent-level 4 - typescript-indent-level 4 - typescript-ts-mode-indent-offset 4 - typescript-ts-mode-indent-offset 4) - -;; Modes -(global-hl-line-mode t ) -(global-display-line-numbers-mode 1) -(hl-line-mode 1) -(savehist-mode 1) -(global-clipetty-mode) -(global-auto-revert-mode) -(yas-global-mode t) - -;; Fonts -(set-face-attribute 'default nil :family "Noto Sans Mono" :height 120) -(set-face-attribute 'variable-pitch nil :family "Noto Sans" :height 140) - -;; Apply variable pitch to specific modes -(dolist (hook '(markdown-mode-hook org-mode-hook json-mode-hook)) - (add-hook hook (lambda () (buffer-face-set '(:family "Noto Sans" :height 140))))) - -(add-to-list 'auto-mode-alist '("\\.qd$" . markdown-mode)) -(add-to-list 'auto-mode-alist '("\\.ino$" . c++-mode)) -(add-to-list 'term-file-aliases '("xterm-256" . "xterm")) - -;; Recentf cleanup -(with-eval-after-load 'recentf - (run-at-time nil 600 #'recentf-cleanup) - (setq recentf-exclude '(".*/$"))) - -;; ============================================================ -;; Native Emacs Configuration -;; ============================================================ (use-package emacs :ensure nil :custom - (mason-setup) - (tab-always-indent 'complete) + ;; --- Completion & Search --- (completion-ignore-case t) (read-file-name-completion-ignore-case t) (read-buffer-completion-ignore-case t) (text-mode-ispell-word-completion nil) + + ;; --- Backup & Auto-save --- + ;; Centralize all backup files to a single directory to avoid cluttering projects (backup-directory-alist '(("." . "~/MyEmacsBackups"))) + (auto-save-list-file-prefix "~/MyEmacsBackups") (backup-by-copying t) + (create-lockfiles nil) + (make-backup-files nil) + + ;; --- Miscellaneous --- + (tab-always-indent 'complete) + + :hook + (prog-mode . hs-minor-mode) ) -;; Tree-sitter & LSP tweaks (Core transformative changes) -(with-eval-after-load 'treesit - (setq treesit-font-lock-level 4)) -;; (with-eval-after-load 'typescript-ts-mode -;; (setq typescript-ts-mode-indent-offset 2) -;; (defvaralias 'typescript-indent-level 'typescript-ts-mode-indent-offset)) +;; ============================================================ +;; 3. Core Settings & UI +;; ============================================================ -(use-package mason - :config - (mason-setup)) +(setq + ;; --- Clipboard & Interprogram --- + ;; Disable automatic clipboard integration to maintain a manual 'copy-paste' workflow + kill-ring-max 1 + select-enable-clipboard nil + select-enable-primary nil + save-interprogram-paste-before-kill nil + mouse-drag-copy-region nil + selection-coding-system 'utf-8 -(use-package lsp-mode - :hook ((prog-mode . lsp-deferred) ;try to automatically start lsp-mode when prog-mode - (typescript-ts-mode . lsp-deferred) - (js-ts-mode . lsp-deferred) - (tsx-ts-mode . lsp-deferred) - (arduino-mode . lsp-deferred) - (lsp-mode . lsp-enable-which-key-integration)) - :commands lsp - :config - (add-to-list 'lsp-language-id-configuration '(arduino-mode . "cpp")) - (lsp-register-client - (make-lsp-client - :new-connection (lsp-stdio-connection '("clangd" "--header-insertion=never")) - :activation-fn (lsp-activate-on "arduino") - :server-id 'lsp-arduino-clangd - ))) + ;; --- Visuals & UI --- + cursor-type 'bar + display-line-numbers-type t + truncate-lines nil ; Enable line wrapping + fast-but-imprecise-scrolling t + ring-bell-function 'ignore ; Silence the system bell + + + ;; --- File & Buffer Handling --- + find-file-visit-truename t + vc-follow-symlinks t + recentf-max-saved-items 100 + history-length 300 + savehist-additional-variables '(kill-ring search-ring) + + ;; --- Undo System --- + ;; Expand undo limits for large files/sessions + undo-limit 60000000 + undo-strong-limit 90000000 + undo-outer-limit 120000000 + + ;; --- Dired Settings --- + dired-listing-switches "-lha" ; Show hidden files and detailed info + dired-dwim-target t + dired-create-destination-dirs 'ask + dired-clean-up-buffers-too nil + dired-auto-revert-buffer t + + ;; --- Other --- + delete-by-moving-to-trash (not noninteractive) + remote-file-name-inhibit-delete-by-moving-to-trash t + package-quickstart t + diff-font-lock-prettify t + ) + +(setq-default + ;; Standardize indentation across major modes + tab-width 4 + js-indent-level 4 + typescript-indent-level 4 + typescript-ts-mode-indent-offset 4 + selection-coding-system 'utf-8 + cursor-type 'bar + ) ;; ============================================================ -;; Theming +;; 5. Hooks, Modes & Theming ;; ============================================================ -(my/apply-theme (selected-frame)) -;;(add-hook 'window-setup-hook (lambda () (my/apply-theme (selected-frame)))) -(add-hook 'after-make-frame-functions 'my/apply-theme) + +(add-hook + 'after-init-hook + (lambda () + ;; --- Modes --- + (recentf-mode t) ; save/load recent files + (global-display-line-numbers-mode 1) ; always display line numbers + (global-hl-line-mode 0) (hl-line-mode 0) ; handled by god mode toggle + (savehist-mode 1) + (global-clipetty-mode t) ; copy-paste in terminal + (global-auto-revert-mode t) ; automatically refresh buffer + (yas-global-mode t) ; yasnippets + (repeat-mode 1) ; repeat key without modifier + (electric-pair-mode t) ; automatically handle pairs + (jit-spell-mode t) ; spellcheck + (fringe-mode '(0 . 8)) ; fringe only on right edge + (delete-selection-mode 1) + (auto-revert-mode t) + + ;; --- Special UI Settings --- + (setq ispell-program-name "hunspell" + ispell-dictionary "en_US,nl_NL") + + ;; Ensure help opens in a side window rather than replacing current buffer + (setq display-buffer-alist + (cons '("Help" . (display-buffer-in-side-window + :side 'bottom + :style 'overriding + :window-height 0.3)) + display-buffer-alist)) + + (setq minibuffer-prompt-properties + '(read-only t intangible t cursor-intangible t face minibuffer-prompt)) + ) + ) + +;; Dired Customization +(with-eval-after-load 'dired + (add-hook 'dired-mode-hook + (lambda () + (define-key dired-mode-map (kbd "a") 'dired-up-directory) + (define-key dired-mode-map (kbd "v") 'dirvish-move)))) + +;; Recentf Maintenance +(with-eval-after-load 'recentf + (run-at-time nil 600 #'recentf-cleanup) + (setq recentf-exclude '(".*/$"))) + +;; General Hooks +(add-hook 'find-file-hook #'recentf-save-list) +(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) + +;; Mode-specific fonts +(dolist (hook '(markdown-mode-hook org-mode-hook json-mode-hook)) + (add-hook hook (lambda () (buffer-face-set '(:family "Noto Sans" :height 140))))) + +;; File Associations +(add-to-list 'auto-mode-alist '("\\.qd$" . markdown-mode)) +(add-to-list 'auto-mode-alist '("\\.ino$" . c++-mode)) +(add-to-list 'auto-mode-alist '("\\.ts$" . typescript-ts-mode)) +(add-to-list 'term-file-aliases '("xterm-256" . "xterm")) + +;; Visual Finalization +(add-hook + 'window-setup-hook + (lambda () + (set-face-attribute 'default nil :family "Noto Sans Mono" :height 120) + (set-face-attribute 'variable-pitch nil :family "Noto Sans" :height 140) + (my/apply-theme (selected-frame)))) (setq nerd-icons-font-family "Symbols Nerd Font Mono") diff --git a/custom/avy-region.el b/custom/avy-region.el index afef4f8..07067f1 100644 --- a/custom/avy-region.el +++ b/custom/avy-region.el @@ -27,3 +27,13 @@ When INCLUSIVE is non-nil, include the character at the end point." (interactive) (my/avy-region 'avy-goto-line) (forward-line 1)) + +(defun my/another-select-exact-string (str) + "Prompt for a string and select its exact match using avy." + (interactive "sSelect target: ") + (avy-with my/select-exact-string + (avy-jump (regexp-quote str) + :action (lambda (pt) + (goto-char pt) + (set-mark pt) + (forward-char (length str)))))) diff --git a/custom/buffer-table.el b/custom/buffer-table.el index 786d28a..da6274a 100644 --- a/custom/buffer-table.el +++ b/custom/buffer-table.el @@ -10,7 +10,7 @@ ;; Faces for distinction (defface buffer-table-open '((t :inherit font-lock-keyword-face :bold t)) "Face for open files.") (defface buffer-table-recent '((t :inherit shadow)) "Face for recent closed files.") -(defface buffer-table-special '((t :inherit font-lock-comment-face)) "Face for internal buffers.") +(defface buffer-table-special '((t :inherit font-lock-string-face)) "Face for internal buffers.") (defface buffer-table-modified '((t :inherit error :bold t)) "Face for modified flag.") (defface buffer-table-marked '((t :inherit warning :bold t)) "Face for marked entries.") diff --git a/custom/buffer-table.elc b/custom/buffer-table.elc new file mode 100644 index 0000000..d2e2cd4 Binary files /dev/null and b/custom/buffer-table.elc differ diff --git a/custom/meow.el b/custom/meow.el deleted file mode 100644 index a93431c..0000000 --- a/custom/meow.el +++ /dev/null @@ -1,130 +0,0 @@ -;;; ../../lyfi/configs/apps/doom/custom/meow.el -*- lexical-binding: t; -*- -;;Custom Meow Cheatsheet Renderer - -(defvar my-meow-board-grid - '(("1" "2" "3" "4" "5" "6" "7" "8" "9" "0") - ("q" "w" "e" "r" "t" "y" "u" "i" "o" "p") - ("a" "s" "d" "f" "g" "h" "j" "k" "l" ";") - ("z" "x" "c" "v" "b" "n" "m" "," "." "/" "'")) - "The physical layout of the board as a 2D array.") - -(defun my-meow-get-cmd-name (key) - "Helper to get the short name of a command for a given key, or a placeholder." - (let ((cmd (key-binding key))) - (if cmd - (meow--short-command-name cmd) - (if (member key '("TAB" "SFT" "CTL" "CAPS" "GUI" "ALT" "MO1" "SPC" "ENT" "BKSL" "LMB" "RMB" "UP" "DN" "N2")) - key - "")))) - -(defun my-meow-render-grid () - "Generates a clean table of Meow commands with base and shift layers." - (let ((output "")) - (dolist (row my-meow-board-grid) - (let ((row-lower "") - (row-upper "")) - (dolist (key row) - (let* ((low-name (my-meow-get-cmd-name key)) - (up-key (upcase key)) - (up-name (my-meow-get-cmd-name up-key))) - ;; Build the lower layer string - (setq row-lower (concat row-lower - (format "[%s = %-12s] " key low-name))) - ;; Build the upper layer string - (setq row-upper (concat row-upper - (format "[%s = %-12s] " up-key up-name))))) - ;; Append both layers, then a newline for a gap between physical rows - (setq output (concat output row-lower "\n" row-upper "\n\n")))) - output)) - -(defun my-meow-cheatsheet () - "Custom cheatsheet that uses a grid instead of fragile ASCII art." - (interactive) - (let ((buf (get-buffer-create "*Meow Cheatsheet*"))) - (with-current-buffer buf - (text-mode) - (setq buffer-read-only nil) - (erase-buffer) - (insert "Meow Custom Layout Cheatsheet\n") - (insert "====================================================================================================\n\n") - (insert (my-meow-render-grid)) - (insert "\n====================================================================================================\n") - (insert meow--cheatsheet-note) - (insert (meow--render-cheatsheet-thing-table)) - (add-face-text-property (point-min) (point-max) 'meow-cheatsheet-command) - (setq buffer-read-only t)) - (switch-to-buffer buf))) - -(defun meow-setup () - ;; We no longer need the physical-layout strings because we use my-meow-board-grid - (meow-motion-overwrite-define-key - '("j" . meow-next) - '("k" . meow-prev) - '("" . mode-line-other-buffer)) - - (meow-leader-define-key - '("/" . meow-keypad-describe-key) - '("?" . my-meow-cheatsheet)) ;; Use our new custom renderer here - - (meow-normal-define-key - '("0" . meow-expand-0) - '("9" . meow-expand-9) - '("8" . meow-expand-8) - '("7" . meow-expand-7) - '("6" . meow-expand-6) - '("5" . meow-expand-5) - '("4" . meow-expand-4) - '("3" . meow-expand-3) - '("2" . meow-expand-2) - '("1" . meow-expand-1) - '("-" . negative-argument) - '(";" . meow-reverse) - '("," . meow-inner-of-thing) - '("." . meow-bounds-of-thing) - '("[" . meow-beginning-of-thing) - '("]" . meow-end-of-thing) - '("a" . meow-append) - '("A" . meow-open-below) - '("b" . meow-back-word) - '("B" . meow-back-symbol) - '("c" . meow-change) - '("d" . meow-delete) - '("D" . meow-backward-delete) - '("e" . meow-next-word) - '("E" . meow-next-symbol) - '("f" . meow-find) - '("g" . meow-cancel-selection) - '("G" . meow-grab) - '("h" . meow-left) - '("H" . meow-left-expand) - '("i" . meow-insert) - '("I" . meow-open-above) - '("j" . meow-next) - '("J" . meow-next-expand) - '("k" . meow-prev) - '("K" . meow-prev-expand) - '("l" . meow-right) - '("L" . meow-right-expand) - '("m" . meow-join) - '("n" . meow-search) - '("o" . meow-block) - '("O" . meow-to-block) - '("p" . meow-yank) - ;;'("q" . meow-quit) - '("Q" . meow-goto-line) - '("r" . meow-replace) - '("R" . meow-swap-grab) - '("k" . meow-kill) - '("t" . meow-till) - '("u" . meow-undo) - '("U" . meow-undo-in-selection) - '("v" . meow-visit) - '("w" . meow-mark-word) - '("W" . meow-mark-symbol) - '("x" . meow-line) - '("X" . meow-goto-line) - '("y" . meow-save) - '("Y" . meow-sync-grab) - '("z" . meow-pop-selection) - '("'" . repeat))) - diff --git a/custom/mydenotefuncs.el b/custom/mydenotefuncs.el new file mode 100644 index 0000000..508ac72 --- /dev/null +++ b/custom/mydenotefuncs.el @@ -0,0 +1,69 @@ +;"Generate an aligned, fontified buffer of all Denote files using fd." + +(defvar denote-browser-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") 'denote-browser-open-file) + map) + "Keymap for the custom Denote browser.") + +(defface denote-browser-dir '((t :inherit font-lock-comment-face)) "Face for subdirs.") +(defface denote-browser-id '((t :inherit font-lock-constant-face)) "Face for IDs.") +(defface denote-browser-title '((t :inherit font-lock-keyword-face :weight bold)) "Face for titles.") +(defface denote-browser-tags '((t :inherit font-lock-type-face)) "Face for tags.") + +(defun denote-browser-open-file () + "Open the file on the current line." + (interactive) + (if (get-text-property (point) 'denote-path) + (find-file (get-text-property (point) 'denote-path)) + (message "No file on this line."))) + +(defun list-denote-files () + "Generate an aligned, fontified buffer of all Denote files using fd." + (interactive) + (let* ((default-directory (expand-file-name "~/lyrinv/SOR/Notes/")) + (raw-output (shell-command-to-string "fd -t f")) + (lines (split-string raw-output "\n" t)) + (buf (get-buffer-create "*Denote Browser*"))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (erase-buffer) + (use-local-map denote-browser-map) + (setq-local buffer-read-only t) + + (dolist (line lines) + ;; Regex to break down: Subdir/ + ID + Title + Keywords + (if (string-match "^\\(.*\\/\\)?\\([0-9A-Za-z]+\\)--\\([^\n__]+\\)\\(__.*\\)?\\.\\([a-z]+\\)$" line) + (let* ((dir (or (match-string 1 line) "")) + (id (or (match-string 2 line) "")) + (title (or (match-string 3 line) "")) + (tags (or (match-string 4 line) "")) + (full-path (expand-file-name line default-directory)) + (start (point))) + + ;; Clean up trailing slash and tag underscores for legibility + (setq dir (if (string-empty-p dir) "." (directory-file-name dir))) + (setq tags (if (string-empty-p tags) "" (replace-regexp-in-string "__" " " tags))) + + ;; Insert padded, aligned string components + (insert (propertize (format "%-20s " dir) 'face 'denote-browser-dir)) + (insert (propertize (format "%-16s " id) 'face 'denote-browser-id)) + (insert (propertize (format "%-45s " title) 'face 'denote-browser-title)) + (insert (propertize tags 'face 'denote-browser-tags)) + (insert "\n") + + ;; Attach the raw file path to the entire line for RET to use + (add-text-properties start (point) (list 'denote-path full-path))) + + ;; Fallback layout for non-standard files (e.g., gereedschap.ods) + (let* ((dir (or (file-name-directory line) ".")) + (file (file-name-nondirectory line)) + (full-path (expand-file-name line default-directory)) + (start (point))) + (insert (propertize (format "%-20s " (directory-file-name dir)) 'face 'denote-browser-dir)) + (insert (propertize (format "%-16s " "No-ID") 'face 'denote-browser-id)) + (insert (propertize file 'face 'denote-browser-title)) + (insert "\n") + (add-text-properties start (point) (list 'denote-path full-path))))))) + + (pop-to-buffer buf))) diff --git a/custom/system.el b/custom/system.el index e609923..6a56990 100644 --- a/custom/system.el +++ b/custom/system.el @@ -28,11 +28,9 @@ Absolutely zero interaction with the Emacs kill ring." 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 ((text (or (gui-get-selection 'CLIPBOARD) + (gui-get-selection 'PRIMARY) + (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 @@ -41,13 +39,103 @@ Never falls back to or checks the Emacs kill ring." ;; 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." +(defun my/system-paste-via-yank () + "Pure paste: Overwrites the kill ring with clipboard data and triggers local yank." (interactive) - (let ((cwd default-directory)) - (vterm-toggle) - (vterm-send-string (format "cd %s" (shell-quote-argument cwd))) - (vterm-send-return))) + (let ((text (or (gui-get-selection 'CLIPBOARD) + (gui-get-selection 'PRIMARY) + (when (executable-find "wl-paste") + (when (executable-find "wl-paste") + (let ((val (shell-command-to-string "wl-paste -n -t text/plain"))) + (unless (string-empty-p val) val)))) + nil))) + (if text + (progn + ;; Forcibly stage to the kill ring. With kill-ring-max=1, this replaces everything. + (kill-new text) + ;; Resolve the context-aware yank command (handles terminal wrappers automatically) + (let ((local-yank (key-binding (kbd "C-y")))) + (if (commandp local-yank) + (call-interactively local-yank) + (call-interactively 'yank)))) + (user-error "System clipboard is empty")))) + +(defun my/sync-clipboard-to-kill-ring () + "Explicitly pull the system clipboard into the Emacs kill ring without pasting." + (interactive) + (let ((text (or (gui-get-selection 'CLIPBOARD) + (gui-get-selection 'PRIMARY) + (when (executable-find "wl-paste") + (when (executable-find "wl-paste") + (let ((val (shell-command-to-string "wl-paste -n -t text/plain"))) + (unless (string-empty-p val) val)))) + nil))) + (if text + (progn + (kill-new text) + (message "System clipboard staged to kill ring.")) + (user-error "System clipboard is empty")))) + +(defun dired-wayland-copy-marked-files () + "Copy marked files in Dired to the Wayland clipboard as text/uri-list." + (interactive) + (let* ((files (dired-get-marked-files)) + ;; Convert paths to file:// URIs and join with newlines + (uri-list (mapconcat (lambda (file) (concat "file://" file)) files "\n"))) + (when files + (let ((process-connection-type nil)) + (let ((proc (start-process "wl-copy-uri" nil "wl-copy" "-t" "text/uri-list"))) + (process-send-string proc uri-list) + (process-send-eof proc))) + (message "Copied %d file(s) to Wayland clipboard." (length files))))) + +(defun dired-wayland-paste-files () + "Paste files from the Wayland clipboard (text/uri-list) into the current Dired directory." + (interactive) + (let ((default-directory (dired-current-directory))) + (with-temp-buffer + ;; Call wl-paste to get the uri-list + (call-process "wl-paste" nil t nil "-t" "text/uri-list") + (goto-char (point-min)) + (let ((files '())) + ;; Parse file:// URIs line by line + (while (re-search-forward "^file://\\(.*\\)$" nil t) + (push (match-string 1) files)) + (if files + (progn + ;; Copy files to the current directory using dired's native copying + (dolist (file files) + (when (file-exists-p file) + (dired-copy-file file default-directory t))) + (revert-buffer) ; Refresh dired buffer + (message "Pasted %d file(s)." (length files))) + (message "No files found in Wayland clipboard.")))))) + +;; Bind keys in dired-mode +(with-eval-after-load 'dired + (define-key dired-mode-map (kbd "Y") #'dired-wayland-copy-marked-files) + (define-key dired-mode-map (kbd "P") #'dired-wayland-paste-files)) + +(defun my/mc-copy-regions-as-block () + "Copy all active multiple-cursors regions joined by newlines into the kill ring." + (interactive) + (if (and (bound-and-true-p multiple-cursors-mode) + (use-region-p)) + (let ((strings (mapcar (lambda (cursor) + (let ((beg (mc/cursor-beg cursor)) + (end (mc/cursor-end cursor))) + (buffer-substring-no-properties beg end))) + (mc/all-fake-cursors)))) + ;; Add the main cursor's region as well + (push (buffer-substring-no-properties (region-beginning) (region-end)) strings) + ;; Sort by position so they match document order + (setq strings (mapcar #'cdr + (sort (cl-mapcar #'cons + (cons (point) (mapcar #'mc/cursor-beg (mc/all-fake-cursors))) + strings) + (lambda (a b) (< (car a) (car b)))))) + (kill-new (string-join strings "\n")) + (message "Copied %d cursor regions as a block." (length strings))) + (message "No active multiple-cursors regions to copy."))) (provide 'system) -;;unqualified-search-registries = ["docker.io"] diff --git a/custom/ui.el b/custom/ui.el index 7047d05..521505b 100644 --- a/custom/ui.el +++ b/custom/ui.el @@ -1,18 +1,22 @@ ;;; ../../lyfi/configs/apps/doom/custom/ui.el -*- lexical-binding: t; -*- +(defun my-set-buffer-font () + "Set a specific font for the current buffer only." + (buffer-face-set '(:family "Noto Sans" :height 140))) + (defun my/apply-theme (frame) "Apply a specific theme and update package colors based on whether the FRAME is graphic or TUI." (select-frame frame) (if (display-graphic-p frame) (progn (mapc #'disable-theme custom-enabled-themes) - (load-theme 'cutarv41 t) + (load-theme 'cutarv42 t) ;; Update rainbow-delimiters colors for Light theme (setq rainbow-delimiters-rainbow-colors '("#007cbf" "#cf3f29" "#2374de" "#c75e10" "#b05197" "#429e66" "#129cc9" "#a64dd6"))) (progn (mapc #'disable-theme custom-enabled-themes) - (load-theme 'cutarv41 t) + (load-theme 'cutarv42 t) ;; Update rainbow-delimiters colors for Dark theme ;; (setq rainbow-delimiters-rainbow-colors ;; '("#4da6ff" "#ff6b6b" "#6da6ff" "#ffb347" "#d18ecb" "#8fbc8f" "#80daeb" "#c8a0f2")) diff --git a/custom/unifiedlist.el b/custom/unifiedlist.el deleted file mode 100644 index 2d8d182..0000000 --- a/custom/unifiedlist.el +++ /dev/null @@ -1,28 +0,0 @@ -;;; ../../lyfi/configs/apps/doom/custom/unifiedlist.el -*- lexical-binding: t; -*- - -(defun my/get-unified-list () - "Combine buffers and recentf into a list for tabulated-list-mode." - (let ((items '())) - ;; Add Live Buffers - (dolist (buf (buffer-list)) - (with-current-buffer buf - (push (list buf (vector (buffer-name) "Live" (format-mode-line mode-name) (or (buffer-file-name) ""))) items))) - ;; Add Recent Files (if not already open) - (dolist (file recentf-list) - (unless (get-file-buffer file) - (push (list file (vector (file-name-nondirectory file) "Recent" "File" file)) items))) - (nreverse items))) - -(define-derived-mode my-unified-list-mode tabulated-list-mode "Unified-List" - (setq tabulated-list-format [("Name" 30 t) - ("Status" 10 t) - ("Mode" 15 t) - ("Path" 0 t)]) - (setq tabulated-list-entries #'my/get-unified-list) - (tabulated-list-init-header)) - -(defun my/open-unified-list () - (interactive) - (pop-to-buffer "*Unified Switcher*") - (my-unified-list-mode) - (tabulated-list-print)) diff --git a/custom/utils.el b/custom/utils.el index 5890705..d08f1ea 100644 --- a/custom/utils.el +++ b/custom/utils.el @@ -39,10 +39,6 @@ Blocks are defined by: whitespace, alphanumerics, or groups of symbols." (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 @@ -60,17 +56,6 @@ Blocks are defined by: whitespace, alphanumerics, or groups of symbols." (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`, @@ -81,7 +66,7 @@ it ensures exactly one space of separation." (target-col (if (and (boundp 'comment-column) (numberp comment-column)) comment-column - 40)) + 80)) (start (region-beginning)) (end (region-end))) diff --git a/early-init.el b/early-init.el index 2e0fc0a..357ff6f 100644 --- a/early-init.el +++ b/early-init.el @@ -1,21 +1,505 @@ -;;; early-init.el -*- lexical-binding: t; -*- +;;; early-init.el --- Early Init -*- lexical-binding: t; -*- -;; Prevent package.el from loading at startup (elpaca handles it) -(setq package-enable-at-startup nil) +;; Author: James Cherti +;; URL: https://github.com/jamescherti/minimal-emacs.d +;; Package-Requires: ((emacs "29.1")) +;; Keywords: maint +;; Version: 1.5.1 +;; SPDX-License-Identifier: GPL-3.0-or-later -;; Disable UI elements early for faster frame rendering -(setq inhibit-startup-screen t - inhibit-startup-echo-area-message user-login-name - initial-scratch-message nil - initial-major-mode 'fundamental-mode - frame-inhibit-implied-resize t - garbage-collection-messages t) +;;; Commentary: +;; The minimal-emacs.d project is a lightweight and optimized Emacs base +;; (init.el and early-init.el) that gives you full control over your +;; configuration. It provides better defaults, an optimized startup, and a clean +;; foundation for building your own vanilla Emacs setup. +;; +;; Building the minimal-emacs.d init.el and early-init.el was the result of +;; extensive research and testing to fine-tune the best parameters and +;; optimizations for an Emacs configuration. +;; +;; Do not modify this file; instead, modify pre-early-init.el or +;; post-early-init.el. -;; Temporarily raise GC threshold during startup -(setq gc-cons-threshold 8000000000 - gc-cons-percentage 0.6) -(add-hook 'after-init-hook (lambda () (setq gc-cons-threshold 80000000))) +;;; Code: -;; Disable UI chrome -(dolist (mode '(menu-bar-mode tool-bar-mode scroll-bar-mode)) - (when (fboundp mode) (funcall mode -1))) +;;; Internal variables + +;; Backup of `gc-cons-threshold' and `gc-cons-percentage' before startup. +(defvar minimal-emacs--backup-gc-cons-threshold gc-cons-threshold) +(defvar minimal-emacs--backup-gc-cons-percentage gc-cons-percentage) + +;; Temporarily raise the garbage collection threshold to its maximum value. +;; It will be restored later to controlled values. +(if noninteractive + (setq gc-cons-threshold 268435456) ; 256 Mb + (setq gc-cons-threshold most-positive-fixnum)) +(setq gc-cons-percentage 1.0) + +;;; Variables + +(defvar minimal-emacs-ui-features '() + "List of user interface features to enable in minimal Emacs setup. +This variable holds a list of Emacs UI features that can be enabled: +- context-menu (Enables the context menu in graphical environments.) +- tool-bar (Enables the tool bar in graphical environments.) +- menu-bar (Enables the menu bar in graphical environments.) +- dialogs (Enables both file dialogs and dialog boxes.) +- tooltips (Enables tooltips.)") + +(defvar minimal-emacs-frame-title-format "%b – Emacs" + "Template for displaying the title bar of visible and iconified frame.") + +(defvar minimal-emacs-debug (bound-and-true-p init-file-debug) + "Non-nil to enable debug.") + +(defvar minimal-emacs-optimize-startup-gc t + "If non-nil, increase `gc-cons-threshold' during startup to reduce pauses. +After Emacs finishes loading, `gc-cons-threshold' is restored to the value +stored in `minimal-emacs-gc-cons-threshold'.") + +(defvar minimal-emacs-gc-cons-threshold (* 32 1024 1024) + "Value to which `gc-cons-threshold' is set after Emacs startup. +Ignored if `minimal-emacs-optimize-startup-gc' is nil.") + +(defvar minimal-emacs-gc-cons-percentage gc-cons-percentage + "Value to which `gc-cons-percentage' is set after Emacs startup. +Ignored if `minimal-emacs-optimize-startup-gc' is nil.") + +(defvar minimal-emacs-gc-cons-threshold-restore-delay nil + "Number of seconds to wait before restoring `gc-cons-threshold'.") + +(defvar minimal-emacs-optimize-file-name-handler-alist t + "Enable optimization of `file-name-handler-alist'. +When non-nil, this variable activates optimizations to reduce file name handler +lookups during Emacs startup.") + +(defvar minimal-emacs-disable-mode-line-during-startup t + "Disable the mode line during startup. +This reduces visual clutter and slightly enhances startup performance. The +tradeoff is that the mode line is hidden during the startup phase.") + +(defvar minimal-emacs-package-initialize-and-refresh nil + "Whether to automatically initialize and refresh packages. +When set to non-nil, Emacs will automatically call `package-initialize' and +`package-refresh-contents' to set up and update the package system.") + +(defvar minimal-emacs-inhibit-redisplay-during-startup nil + "Suppress redisplay during startup to improve performance. +This prevents visual updates while Emacs initializes. The tradeoff is that you +won't see the progress or activities during the startup process.") + +(defvar minimal-emacs-inhibit-message-during-startup nil + "Suppress startup messages for a cleaner experience. +This slightly enhances performance. The tradeoff is that you won't be informed +of the progress or any relevant activities during startup.") + +(defvar minimal-emacs-user-directory user-emacs-directory + "Directory beneath minimal-emacs.d files are placed. +Note that this should end with a directory separator.") + +(defvar minimal-emacs-load-pre-early-init t + "If non-nil, attempt to load `pre-early-init.el`.") + +(defvar minimal-emacs-load-post-early-init t + "If non-nil, attempt to load `post-early-init.el`.") + +(defvar minimal-emacs-load-pre-init t + "If non-nil, attempt to load `pre-init.el`.") + +(defvar minimal-emacs-load-post-init t + "If non-nil, attempt to load `post-init.el`.") + +;;; Load pre-early-init.el + +;; Prefer loading newer compiled files +(setq load-prefer-newer t) +(when minimal-emacs-debug + (setq debug-on-error minimal-emacs-debug)) + +(defvar minimal-emacs--success nil) +(defun minimal-emacs--check-success () + "Verify that the Emacs configuration has loaded successfully." + (unless minimal-emacs--success + (cond + ((or (file-exists-p (expand-file-name "~/.emacs.el")) + (file-exists-p (expand-file-name "~/.emacs"))) + (error "Emacs ignored loading 'init.el'. Please ensure that files such as ~/.emacs or ~/.emacs.el do not exist, as they may be preventing Emacs from loading the 'init.el' file")) + + (t + (error "Configuration error. Debug by starting Emacs with: --debug-init"))))) + +(unless noninteractive + (add-hook 'emacs-startup-hook #'minimal-emacs--check-success 102)) + +(defvar minimal-emacs-load-compiled-init-files nil + "If non-nil, attempt to load byte-compiled .elc for init files. +This will enable minimal-emacs to load byte-compiled or possibly native-compiled +init files for the following initialization files: pre-init.el, post-init.el, +pre-early-init.el, and post-early-init.el.") + +(defun minimal-emacs--remove-el-file-suffix (filename) + "Remove the Elisp file suffix from FILENAME and return it (.el, .el.gz...)." + (let ((suffixes (mapcar (lambda (ext) (concat ".el" ext)) + load-file-rep-suffixes))) + (catch 'done + (dolist (suffix suffixes filename) + (when (string-suffix-p suffix filename) + (setq filename (substring filename 0 (- (length suffix)))) + (throw 'done t)))) + filename)) + +(defun minimal-emacs-load-user-init (filename) + "Execute a file of Lisp code named FILENAME." + (let ((init-file (expand-file-name filename + minimal-emacs-user-directory))) + (if (not minimal-emacs-load-compiled-init-files) + (load init-file :no-error (not minimal-emacs-debug) :nosuffix) + ;; Remove the file suffix (.el, .el.gz, etc.) to let the `load' function + ;; select between .el and .elc files. + (setq init-file (minimal-emacs--remove-el-file-suffix init-file)) + (load init-file :no-error (not minimal-emacs-debug))))) + +(when minimal-emacs-load-pre-early-init + (minimal-emacs-load-user-init "pre-early-init.el")) + +(setq custom-theme-directory + (expand-file-name "themes/" minimal-emacs-user-directory)) + +(setq custom-file (expand-file-name "custom.el" minimal-emacs-user-directory)) + +;;; Garbage collection +;; Garbage collection significantly affects startup times. This setting delays +;; garbage collection during startup but will be reset later. + +(defun minimal-emacs--restore-gc-values () + "Restore garbage collection values to minimal-emacs.d values." + (setq gc-cons-threshold minimal-emacs-gc-cons-threshold) + (setq gc-cons-percentage minimal-emacs-gc-cons-percentage)) + +(defun minimal-emacs--restore-gc () + "Restore garbage collection settings." + (if (and (bound-and-true-p minimal-emacs-gc-cons-threshold-restore-delay) + ;; In noninteractive mode, the event loop does not run + (not noninteractive)) + ;; Defer garbage collection during initialization to avoid 2 collections. + (run-with-timer minimal-emacs-gc-cons-threshold-restore-delay nil + #'minimal-emacs--restore-gc-values) + (minimal-emacs--restore-gc-values))) + +(if minimal-emacs-optimize-startup-gc + ;; `gc-cons-threshold' is managed by minimal-emacs.d + (add-hook 'emacs-startup-hook #'minimal-emacs--restore-gc 105) + ;; gc-cons-threshold is not managed by minimal-emacs.d. + (when (= gc-cons-threshold most-positive-fixnum) + (setq gc-cons-threshold minimal-emacs--backup-gc-cons-threshold) + (setq gc-cons-percentage minimal-emacs--backup-gc-cons-percentage))) + +;;; Native compilation and Byte compilation + +(unless (and (featurep 'native-compile) + (fboundp 'native-comp-available-p) + (native-comp-available-p)) + ;; Deactivate the `native-compile' feature if it is not available + (setq native-comp-jit-compilation nil) + (setq features (delq 'native-compile features))) + +(setq native-comp-warning-on-missing-source minimal-emacs-debug + native-comp-async-report-warnings-errors (or minimal-emacs-debug 'silent)) + +(setq jka-compr-verbose minimal-emacs-debug) +(setq byte-compile-warnings minimal-emacs-debug + byte-compile-verbose minimal-emacs-debug) + +;;; Miscellaneous + +(set-language-environment "UTF-8") + +;; Increase how much is read from processes in a single chunk +(setq read-process-output-max (* 4 1024 1024)) ; 4096kb + +(setq process-adaptive-read-buffering nil) + +;; Don't ping things that look like domain names. +(setq ffap-machine-p-known 'reject) + +(setq warning-minimum-level (if minimal-emacs-debug :warning :error)) + +;; Establish a strict baseline for suppressed warnings. +;; - defvaralias: Emacs emits warnings when an alias is defined for a variable +;; that already exists. In modern, lazy-loaded configurations, this occurs +;; frequently and is almost always benign. +;; - lexical-binding: Emacs warns about third-party packages that lack +;; lexical-binding. Because end users cannot easily fix upstream source code, +;; these warnings create noise without providing actionable value. +(setq warning-suppress-types '((defvaralias) (lexical-binding))) +(setq warning-inhibit-types '((files missing-lexbind-cookie))) + +(when minimal-emacs-debug + (setq message-log-max 16384)) + +;; Disable warnings from the legacy advice API. They aren't useful. +(setq ad-redefinition-action 'accept) + +;;; Performance: Miscellaneous options + +;; A second, case-insensitive pass over `auto-mode-alist' is time wasted. +;; No second pass of case-insensitive search over auto-mode-alist. +(setq auto-mode-case-fold nil) + +(unless minimal-emacs-debug + ;; Unset command line options irrelevant to the current OS. These options + ;; are still processed by `command-line-1` but have no effect. + (unless (eq system-type 'darwin) + (setq command-line-ns-option-alist nil)) + (unless (memq initial-window-system '(x pgtk)) + (setq command-line-x-option-alist nil))) + +(unless noninteractive + ;; In PGTK, this timeout introduces latency. Reducing it from the default 0.1 + ;; improves responsiveness of childframes and related packages. + (when (boundp 'pgtk-wait-for-event-timeout) + (setq pgtk-wait-for-event-timeout 0.001)) + + ;; Font compacting can be very resource-intensive, especially when rendering + ;; icon fonts on Windows. This will increase memory usage. + (setq inhibit-compacting-font-caches t) + + ;; Resizing the Emacs frame can be costly when changing the font. Disable this + ;; to improve startup times with fonts larger than the system default. + (setq frame-resize-pixelwise t) + + ;; Without this, Emacs will try to resize itself to a specific column size + (setq frame-inhibit-implied-resize t) + + ;; Reduce *Message* noise at startup. An empty scratch buffer (or the + ;; dashboard) is more than enough, and faster to display. + (setq inhibit-startup-screen t + inhibit-startup-echo-area-message user-login-name) + (setq initial-buffer-choice nil + inhibit-startup-buffer-menu t + inhibit-x-resources t) + + ;; Disable startup screens and messages + (setq inhibit-splash-screen t) + + ;; Disable bidirectional text scanning for a modest performance boost. + (setq-default bidi-display-reordering 'left-to-right + bidi-paragraph-direction 'left-to-right) + + ;; Give up some bidirectional functionality for slightly faster re-display. + (setq bidi-inhibit-bpa t) + + ;; Remove "For information about GNU Emacs..." message at startup + (advice-add 'display-startup-echo-area-message :override #'ignore) + + ;; Suppress the vanilla startup screen completely. We've disabled it with + ;; `inhibit-startup-screen', but it would still initialize anyway. + (advice-add 'display-startup-screen :override #'ignore)) + +;;; Performance: File-name-handler-alist + +(defvar minimal-emacs--old-file-name-handler-alist (default-toplevel-value + 'file-name-handler-alist)) + +(defun minimal-emacs--respect-file-handlers (fn args-left) + "Respect file handlers. +FN is the function and ARGS-LEFT is the same argument as `command-line-1'. +Emacs processes command-line files very early in startup. These files may +include special paths like TRAMP paths, so restore `file-name-handler-alist' for +this stage of initialization." + (let ((file-name-handler-alist (if args-left + minimal-emacs--old-file-name-handler-alist + file-name-handler-alist))) + (funcall fn args-left))) + +(defun minimal-emacs--restore-file-name-handler-alist () + "Restore `file-name-handler-alist'." + (set-default-toplevel-value + 'file-name-handler-alist + ;; Merge instead of overwrite to preserve any changes made since startup. + (delete-dups (append file-name-handler-alist + minimal-emacs--old-file-name-handler-alist)))) + +(when (and minimal-emacs-optimize-file-name-handler-alist + (not minimal-emacs-debug) + (not noninteractive)) + ;; Determine the state of bundled libraries using calc-loaddefs.el. If + ;; compressed, retain the gzip handler in `file-name-handler-alist`. If + ;; compiled or neither, omit the gzip handler during startup for improved + ;; startup and package load time. + (set-default-toplevel-value + 'file-name-handler-alist + (if (locate-file-internal "calc-loaddefs.el" load-path) + nil + (list (rassq 'jka-compr-handler + minimal-emacs--old-file-name-handler-alist)))) + + ;; Ensure the new value persists through any current let-binding. + (put 'file-name-handler-alist 'initial-value + minimal-emacs--old-file-name-handler-alist) + + ;; Emacs processes command-line files very early in startup. These files may + ;; include special paths TRAMP. Restore `file-name-handler-alist'. + (advice-add 'command-line-1 :around #'minimal-emacs--respect-file-handlers) + + (add-hook 'emacs-startup-hook #'minimal-emacs--restore-file-name-handler-alist + 101)) + +;;; Performance: Inhibit redisplay + +(defun minimal-emacs--reset-inhibit-redisplay () + "Reset inhibit redisplay." + (setq-default inhibit-redisplay nil) + (remove-hook 'post-command-hook #'minimal-emacs--reset-inhibit-redisplay)) + +(when (and minimal-emacs-inhibit-redisplay-during-startup + (not noninteractive) + (not minimal-emacs-debug)) + ;; Suppress redisplay and redraw during startup to avoid delays and + ;; prevent flashing an unstyled Emacs frame. + (setq-default inhibit-redisplay t) + (add-hook 'post-command-hook #'minimal-emacs--reset-inhibit-redisplay -100)) + +;;; Performance: Inhibit message + +(defun minimal-emacs--reset-inhibit-message () + "Reset inhibit message." + (setq-default inhibit-message nil) + (remove-hook 'post-command-hook #'minimal-emacs--reset-inhibit-message)) + +(when (and minimal-emacs-inhibit-message-during-startup + (not noninteractive) + (not minimal-emacs-debug)) + (setq-default inhibit-message t) + (add-hook 'post-command-hook #'minimal-emacs--reset-inhibit-message -100)) + +;;; Performance: Disable mode-line during startup + +(defvar-local minimal-emacs--hidden-mode-line nil + "Store the buffer-local value of `mode-line-format' during startup.") + +(when (and minimal-emacs-disable-mode-line-during-startup + (not noninteractive) + (not minimal-emacs-debug)) + (put 'mode-line-format + 'initial-value (default-toplevel-value 'mode-line-format)) + (setq-default mode-line-format nil) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (local-variable-p 'mode-line-format) + (setq minimal-emacs--hidden-mode-line mode-line-format) + (setq mode-line-format nil))))) + +;;; Restore values + +(defun minimal-emacs--startup-load-user-init-file (fn &rest args) + "Advice to reset `mode-line-format'. FN and ARGS are the function and args." + (unwind-protect + ;; Start up as normal + (apply fn args) + ;; If we don't undo inhibit-{message, redisplay} and there's an error, we'll + ;; see nothing but a blank Emacs frame. + (when minimal-emacs-inhibit-message-during-startup + (setq-default inhibit-message nil)) + (when minimal-emacs-inhibit-redisplay-during-startup + (setq-default inhibit-redisplay nil)) + ;; Restore the mode-line + (when minimal-emacs-disable-mode-line-during-startup + (unless (default-toplevel-value 'mode-line-format) + (setq-default mode-line-format (get 'mode-line-format + 'initial-value))) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (local-variable-p 'minimal-emacs--hidden-mode-line) + (setq mode-line-format minimal-emacs--hidden-mode-line) + (kill-local-variable 'minimal-emacs--hidden-mode-line))))))) + +(advice-add 'startup--load-user-init-file :around + #'minimal-emacs--startup-load-user-init-file) + +;;; UI elements + +(defun minimal-emacs--setup-toolbar (&rest _) + "Setup the toolbar." + (when (fboundp 'tool-bar-setup) + (advice-remove 'tool-bar-setup #'ignore) + (when (bound-and-true-p tool-bar-mode) + (funcall 'tool-bar-setup)))) + +(unless noninteractive + (setq frame-title-format minimal-emacs-frame-title-format + icon-title-format minimal-emacs-frame-title-format) + + ;; I intentionally avoid calling `menu-bar-mode', `tool-bar-mode', and + ;; `scroll-bar-mode' because manipulating frame parameters can trigger or queue + ;; a superfluous and potentially expensive frame redraw at startup, depending + ;; on the window system. The variables must also be set to `nil' so users don't + ;; have to call the functions twice to re-enable them. + (unless (memq 'menu-bar minimal-emacs-ui-features) + (push '(menu-bar-lines . 0) default-frame-alist) + (unless (memq window-system '(mac ns)) + (setq menu-bar-mode nil))) + + (when (fboundp 'tool-bar-setup) + ;; Temporarily override the tool-bar-setup function to prevent it from + ;; running during the initial stages of startup + (advice-add 'tool-bar-setup :override #'ignore) + + (advice-add 'startup--load-user-init-file :after + #'minimal-emacs--setup-toolbar)) + + (unless (memq 'tool-bar minimal-emacs-ui-features) + (push '(tool-bar-lines . 0) default-frame-alist) + (setq tool-bar-mode nil)) + + (setq default-frame-scroll-bars 'right) + (push '(vertical-scroll-bars) default-frame-alist) + (push '(horizontal-scroll-bars) default-frame-alist) + (setq scroll-bar-mode nil) + + (unless (memq 'tooltips minimal-emacs-ui-features) + (when (bound-and-true-p tooltip-mode) + (tooltip-mode -1))) + + ;; Disable GUIs because they are inconsistent across systems, desktop + ;; environments, and themes, and they don't match the look of Emacs. + (unless (memq 'dialogs minimal-emacs-ui-features) + (setq use-file-dialog nil) + (setq use-dialog-box nil))) + +;;; Security +(setq gnutls-verify-error t) ; Prompts if there are cert issues +(setq tls-checktrust gnutls-verify-error) ; Ensure SSL/TLS connections checks +(setq gnutls-min-prime-bits 3072) ; Stronger GnuTLS encryption + +;; This results in a more compact output that emphasizes performance +(setq use-package-expand-minimally t) + +;; (setq use-package-minimum-reported-time (if minimal-emacs-debug 0 0.1)) +;; (setq use-package-verbose minimal-emacs-debug) +;; (setq use-package-always-ensure (not noninteractive)) +;; (setq use-package-enable-imenu-support t) + +;; package.el +(setq package-enable-at-startup nil) ; Let the init.el file handle this +;; (setq package-quickstart-file +;; (expand-file-name "package-quickstart.el" user-emacs-directory)) +;; (setq package-archives '(("melpa" . "https://melpa.org/packages/") +;; ("gnu" . "https://elpa.gnu.org/packages/") +;; ("nongnu" . "https://elpa.nongnu.org/nongnu/") +;; ("melpa-stable" . "https://stable.melpa.org/packages/"))) +;; (setq package-archive-priorities '(("gnu" . 99) +;; ("nongnu" . 80) +;; ("melpa" . 70) +;; ("melpa-stable" . 50))) + +;;; Load post-early-init.el + +(when minimal-emacs-load-post-early-init + (minimal-emacs-load-user-init "post-early-init.el")) + +;; Local variables: +;; byte-compile-warnings: (not obsolete free-vars) +;; End: + +;;; early-init.el ends here diff --git a/init.el b/init.el index 5b8cf28..8b409cc 100644 --- a/init.el +++ b/init.el @@ -38,10 +38,8 @@ (let ((load-source-file-function nil)) (load "./elpaca-autoloads")))) (add-hook 'after-init-hook #'elpaca-process-queues) (elpaca `(,@elpaca-order)) -;;(elpaca-wait) (elpaca benchmark-init) (elpaca-wait) - (benchmark-init/activate) ;; emacs 30 fix @@ -53,12 +51,13 @@ (elpaca compat) (elpaca general) ;Keybindings -(elpaca vertico) ;Vertical completion +(elpaca vertico) ;vertical minibuffer +(elpaca vertico-posframe) ;hover (elpaca orderless) ;Filtering for Consult/Vertico (elpaca marginalia) ;Annotations in the minibuffer (elpaca corfu) ;In-buffer completion -(elpaca corfu-terminal) ;necessary for popup on emacs <31 -(elpaca-wait) ;Ensure UI is ready before loading tools +;;(elpaca corfu-terminal) ;necessary for popup on emacs <31 ; codeberg not cooperating. +;;(elpaca-wait) ;Ensure UI is ready before loading tools (elpaca nerd-icons) (elpaca nerd-icons-completion) (elpaca nerd-icons-dired) @@ -70,34 +69,37 @@ ;; EDITING & NAVIGATION ;; ============================================================================== -(elpaca meow) ; Modal editing +;;(elpaca meow) ; Modal editing +(elpaca god-mode) ; psuedo modal editing +(elpaca multiple-cursors) (elpaca avy) ; Fast jumping -(elpaca smartparens) -;;(elpaca expand-region) ; replaced by expreg -(elpaca expreg) ;expand selection +(elpaca surround) ; utilties around surround selection +(elpaca expreg) ; expand selection (elpaca undo-fu) (elpaca vundo) ; Visual undo tree (elpaca xclip) -(elpaca clipetty) +(elpaca clipetty) ; clipboard stuff TUI-GUI-Wayland (elpaca embark) ; Contextual actions (elpaca embark-consult) -(elpaca lsp-embark) -(elpaca kirigami) ; Selection/Editing -(elpaca jinx) ; Fast duplicate lines - +(elpaca wgrep) ; allow writeable grep buffers +;(elpaca lsp-embark) +(elpaca kirigami) ; folding meta utility +(elpaca pcre2el) ; fix regex ;; ============================================================================== ;; CODE ANALYSIS & VISUALS ;; ============================================================================== -(elpaca treesit-auto) -(elpaca treesit-fold) -(elpaca highlight-quoted) -(elpaca highlight-defined) -(elpaca color-identifiers-mode) -(elpaca rainbow-delimiters) -(elpaca indent-bars) -(elpaca outline-indent) - +(elpaca treesit-auto) ; automatically install treesitter grammars +(elpaca treesit-fold) ; folding based on treesit +(elpaca highlight-quoted) ; emacs +(elpaca highlight-defined) ; emacs +(elpaca color-identifiers-mode) ; emacs +(elpaca highlight-parentheses) ; delimiters around point +(elpaca rainbow-delimiters) ; rainbow colours for pairs +(elpaca indent-bars) ; show indentation bars +(elpaca outline-indent) ; +(elpaca (svg-margin :repo "chiply/svg-margin" + :host github)) ;; ============================================================================== ;; LSP & DEVELOPMENT ;; ============================================================================== @@ -105,8 +107,9 @@ (elpaca mason) ; LSP server manager (elpaca lsp-mode) (elpaca lsp-ui) -(elpaca consult-lsp) (elpaca flycheck) +(elpaca consult-lsp) +(elpaca consult-flycheck) (elpaca yasnippet) (elpaca yasnippet-snippets) @@ -118,19 +121,24 @@ (elpaca csv-mode) (elpaca arduino-mode) (elpaca nix-mode) +(elpaca web-mode) ;; ============================================================================== ;; UTILITIES ;; ============================================================================== (elpaca consult) ; Enhanced search/navigation -(elpaca vterm) -(elpaca vterm-toggle) -(elpaca colorful-mode) +(elpaca ghostel) ; terminal +(elpaca shell-pop) +(elpaca colorful-mode) ; colourise color codes (elpaca (dirvish :repo "latiagertrutis/dirvish" - :host github)) ; broken on emacs 30, fixed by using fork -(elpaca transient) -(elpaca magit) -(elpaca transpose-frame) + :host github)) ; broken on emacs 30, fixed by using fork +(elpaca (dired-clipboard :repo "kn66/dired-clipboard.el" ;system clipboard in dired + :host github)) +(elpaca transient) ; bindings in modes +(elpaca magit) ; git client +(elpaca transpose-frame) ; edit frame layout +(elpaca jit-spell) ; spellcheck +(elpaca sudo-edit) ; sudo util ;; ============================================================================== ;; KNOWLEDGE MANAGEMENT (ZK/DENOTE) ;; ============================================================================== @@ -141,6 +149,8 @@ (elpaca zk) (elpaca zk-index) + + ;; ============================================================================== ;; ELPACA CONFIGURATION ;; ============================================================================== @@ -157,21 +167,16 @@ ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(custom-safe-themes - '("c9afaac8aedf1bb721d21053a79a65969fd8f44314d22ff29c8981709ee4245f" - "0672d7fbe7fa24344bbe98461a8db26cb52a074354f9a4529cea4ba1af456044" - "664111db1521fe3351061dc87aea95fa98b3f244f4b830fbc048d39c3a8bc125" - "df7b90a88131500ce9e5a911c815ce96eb7855d88747830f298c6914d80be48e" - "4fa3b7b09062f707a4770804dda9dda4807aa5c86623076b9741897df2e7acdd" - "5bfc7c010e3ee71396e421c2e8a5a561c305da812eba9e0e48742896d8e45d97" - "48cebeaf733cae05b5265eceafea44c042f2fc65906ccd999f652d230be25b6f" - "1b4f5bebc7f47257997a8d56e797e2e8d85581bbd824a275bb1ebc7aea7c1399" - "a7dab7ccf5c97be13a1d957e8847cfda7cf768554595429a43f6b6393459c45e" - "ca223796522e77b1813111ad2994b8e579df1000d1e3c34b604fe0a18ad45dec" - default))) + '("312bc908e53b07c97cbe1e09521e44c560d457c34399fe19f2dbf5a052104207"))) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. - '(meow-insert-cursor ((t (:inherit unspecified :background "#c75e10")))) - '(meow-normal-cursor ((t (:foreground "#7cc9f2" :background "#f8f8ff"))))) + ) + + +(setq minimal-emacs--success t) + +(setq initial-major-mode 'fundamental-mode + initial-scratch-message nil) diff --git a/packages/completion-packages.el b/packages/completion-packages.el index 75c1c18..04b44a8 100644 --- a/packages/completion-packages.el +++ b/packages/completion-packages.el @@ -12,9 +12,59 @@ (corfu-auto-prefix 2) (corfu-popupinfo-delay '(0.5 . 0.3))) +;; (use-package corfu-terminal +;; :after corfu +;; :init +;; (unless (display-graphic-p) +;; (corfu-terminal-mode +1))) + (use-package vertico :init - (vertico-mode)) + (vertico-mode) + :config + (vertico-multiform-mode t) + + (setq vertico-multiform-commands + '( + (consult-imenu posframe indexed) + (consult-completion-in-region grid))) + ) + +;; Configure directory extension. +(use-package vertico-directory + :after vertico + :ensure nil + ;; More convenient directory navigation commands + :bind (:map vertico-map + ("RET" . vertico-directory-enter) + ("DEL" . vertico-directory-delete-char) + ("M-DEL" . vertico-directory-delete-word)) + ;; Tidy shadowed file names + :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) + +(use-package vertico-posframe + :after vertico + :config + (vertico-posframe-mode t) + + (setq vertico-posframe-width 150 + vertico-posframe-min-width 90 + vertico-posframe-border-width 3 + vertico-count 15 + vertico-scroll-margin 4) + ) + +;use consult + vertico instead of corfu if in terminal +(use-package consult + :defer t + :init + (setq completion-in-region-function #'consult-completion-in-region + consult-fd-args '("fd" "--color=never" "--hidden" )) + :config + (add-hook 'after-change-major-mode-hook + (lambda () + (setq completion-in-region-function #'consult-completion-in-regionc))) + ) (use-package marginalia :init @@ -23,7 +73,6 @@ (use-package orderless :custom (completion-styles '(orderless basic)) - (completion-category-overrides '((file (styles partial-completion)))) (completion-pcm-leading-wildcard t)) (provide 'completion-packages) diff --git a/packages/dev-packages.el b/packages/dev-packages.el new file mode 100644 index 0000000..449a2a0 --- /dev/null +++ b/packages/dev-packages.el @@ -0,0 +1,125 @@ +;; Tree-sitter & LSP tweaks (Core transformative changes) + +(use-package treesit-auto + :functions global-treesit-auto-mode + :config + (treesit-auto-add-to-auto-mode-alist 'all) + :hook (after-init . global-treesit-auto-mode) + :custom + (treesit-auto-install 'prompt) + ) + +(use-package treesit-fold + :defer t + :commands (treesit-fold-close + treesit-fold-close-all + treesit-fold-open + treesit-fold-toggle + treesit-fold-open-all + treesit-fold-mode + global-treesit-fold-mode + treesit-fold-open-recursively + treesit-fold-line-comment-mode) + :custom + (treesit-fold-line-count-show t) + (treesit-fold-line-count-format "--▼--") + :config + (set-face-attribute 'treesit-fold-replacement-face nil + :foreground "#808080" + :box nil + :weight 'bold)) + +;; Tree-sitter hooks +(dolist (hook '(c-ts-mode-hook c++-ts-mode-hook java-ts-mode-hook rust-ts-mode-hook + go-ts-mode-hook ruby-ts-mode-hook js-ts-mode-hook typescript-ts-mode-hook + tsx-ts-mode-hook css-ts-mode-hook html-ts-mode-hook bash-ts-mode-hook + cmake-ts-mode-hook dockerfile-ts-mode-hook json-ts-mode-hook toml-ts-mode-hook yaml-ts-mode-hook)) + (add-hook hook #'treesit-fold-mode)) + +(with-eval-after-load 'treesit + (setq treesit-font-lock-level 4)) + +(use-package mason + :defer t + :config + (mason-setup)) + +(use-package lsp-mode + :defer t + :hook ((c-mode . lsp-deferred) + (c++-mode . lsp-deferred) + (c-ts-mode . lsp-deferred) + (c++-ts-mode . lsp-deferred) + (typescript-ts-mode . lsp-deferred) + (js-ts-mode . lsp-deferred) + (tsx-ts-mode . lsp-deferred) + (arduino-mode . lsp-deferred) + (toml-ts-mode . lsp-deferred) + (json-ts-mode . lsp-deferred) + (lsp-mode . lsp-enable-which-key-integration)) + :commands lsp + :init + (setq lsp-keymap-prefix "C-l") + :config + (setq lsp-clients-clangd-executable "clangd" + lsp-clangd-binary-path "/usr/bin/clangd" + lsp-clients--clangd-default-executable "/usr/bind/clangd" + lsp-completion-provider :none + lsp-clients-clangd-args '("--header-insertion=iwyu" "--fallback-style=LLVM") + ) + + (with-eval-after-load 'lsp-mode + (define-key lsp-command-map (kbd "a") #'lsp-execute-code-action) + (define-key lsp-command-map (kbd "d") #'lsp-ui-doc-glance) + (define-key lsp-command-map (kbd "r") #'lsp-rename) + + ;; Safe Capability Filter: Handles both association list (alist) and hash-table formats + (advice-add 'lsp--client-capabilities :filter-return + (lambda (caps) + (cond + ;; If it's a hash table + ((hash-table-p caps) + (when-let ((text-doc (gethash "textDocument" caps))) + (if (hash-table-p text-doc) + (remhash "inlineCompletion" text-doc) + (setcdr (assoc "inlineCompletion" text-doc) nil)))) + ;; If it's an association list (alist) + ((listp caps) + (when-let ((text-doc (cdr (assoc 'textDocument caps)))) + (setcdr (assoc 'textDocument caps) + (assq-delete-all 'inlineCompletion text-doc))))) + caps)) + + ;; Set up arduino-mode safely after lsp-mode is loaded + (add-to-list 'lsp-language-id-configuration '(arduino-mode . "cpp")) + (lsp-register-client + (make-lsp-client + :new-connection (lsp-stdio-connection '("clangd" "--header-insertion=never")) + :activation-fn (lsp-activate-on "arduino") + :server-id 'lsp-arduino-clangd + )))) + +(use-package lsp-ui + :defer t + :after lsp-mode + :commands lsp-ui-mode + :init + (setq lsp-ui-sideline-show-symbol t + lsp-ui-side-show-code-actions t + lsp-ui-sideline-show-hover t + + lsp-ui-doc-enable t + lsp-ui-doc-delay 1 + lsp-ui-doc-position 'at-point + lsp-ui-sideline-show-hover t + lsp-ui-sideline-show-diagnostics t + lsp-ui-side-show-code-actions t + lsp-ui-sideline-delay 0.25 + + ) + ) + +(with-eval-after-load 'lsp-mode + (add-to-list 'lsp-disabled-clients 'tailwindcss)) + +(provide 'dev-packages) diff --git a/packages/editing-packages.el b/packages/editing-packages.el index 343e4ac..dc47533 100644 --- a/packages/editing-packages.el +++ b/packages/editing-packages.el @@ -1,27 +1,37 @@ ;;; editing-packages.el --- Editing and navigation configuration -*- lexical-binding: t; -*- -(use-package meow - :config - (setq meow-use-clipboard nil - meow--kbd-kill-region "C-S-x") - (meow-setup) - (meow-global-mode 1) - ) - (use-package avy + :defer t :config (setq avy-timeout-seconds 0.25 avy-style 'at-full - avy-keys (number-sequence ?a ?z))) + avy-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l ?A ?S ?D ?F ?G ?H ?J ?K ?L) + avy-orders-alist nil) + ) -(use-package smartparens - :config - (smartparens-global-mode 1)) +(use-package surround + :defer t + :bind-keymap ("M-'" . surround-keymap)) ; Or bind to a prefix in general-def (use-package kirigami + :defer t :commands (kirigami-open-fold kirigami-open-fold-rec kirigami-close-fold kirigami-toggle-fold kirigami-open-folds kirigami-close-folds-except-current kirigami-close-folds)) +(use-package embark + :defer t + :bind + (("M-m" . embark-act) + ("C-h B" . embark-bindings) + ) + :config + (add-to-list 'display-buffer-alist + '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" + nil + (window-parameters (mode-line-format . none)))) + ) + + (provide 'editing-packages) diff --git a/packages/system-packages.el b/packages/system-packages.el index d085f10..0733d72 100644 --- a/packages/system-packages.el +++ b/packages/system-packages.el @@ -3,25 +3,37 @@ (use-package clipetty :hook (after-init . global-clipetty-mode)) - (use-package dirvish - :defer t :config (dirvish-peek-mode) (dirvish-side-follow-mode) - (add-hook 'dirvish-directory-view-mode 'diredfl-mode)) + (add-hook 'dirvish-directory-view-mode 'diredfl-mode) + (with-eval-after-load 'dirvish + (define-key dirvish-mode-map (kbd "a") #'dirvish-setup-menu) + (define-key dirvish-mode-map (kbd "v") #'dirvish-move)) + ) -(use-package embark - - :bind - (("C-." . embark-act) - ("C-h B" . embark-bindings) - ) +(use-package shell-pop + :defer t + :custom + ;(shell-pop-universal-key "C-s s") + (shell-pop-window-position "bottom") + (shell-pop-term-shell shell-file-name) + (shell-pop-window-size 50) + ) + +(with-eval-after-load 'shell-pop + (setopt shell-pop-shell-type '("ghostel" "*ghostel*" + (lambda () + (when (fboundp 'ghostel) + (let ((ghostel-shell shell-pop-term-shell)) + (ghostel))))))) + +(use-package dired-clipboard + :hook (dired-mode . dired-clipboard-mode) :config - (add-to-list 'display-buffer-alist - '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" - nil - (window-parameters (mode-line-format . none)))) + (setq dired-clipboard-use-wl-copy t + dired-clipboard-wayland-target 'uri-list) ) (use-package benchmark-init diff --git a/packages/tutilities-packages.el b/packages/tutilities-packages.el index bed135a..03d0ab1 100644 --- a/packages/tutilities-packages.el +++ b/packages/tutilities-packages.el @@ -1,12 +1,10 @@ (use-package denote + :defer t :config - (setq denote-directory (list (expand-file-name "~/lyfi/SOR/Notes/")) + (setq denote-directory (list (expand-file-name "~/lyrinv/SOR/Notes/")) denote-file-type 'markdown-yaml - denote-prompts '(title subdirectory keywords))) - -(use-package jinx - :hook (emacs-startup . global-jinx-mode) - :custom (jinx-languages "en_US nl_NL")) + denote-prompts '(title subdirectory keywords)) + ) (provide 'tutilities-packages) diff --git a/packages/visuals-packages.el b/packages/visuals-packages.el index dc03ba6..b086428 100644 --- a/packages/visuals-packages.el +++ b/packages/visuals-packages.el @@ -1,40 +1,5 @@ ;;; visuals-packages.el --- Visual and structural configuration -*- lexical-binding: t; -*- - -(use-package treesit-auto - :functions global-treesit-auto-mode - :config - (treesit-auto-add-to-auto-mode-alist 'all) - :hook (after-init . global-treesit-auto-mode) - :custom - (treesit-auto-install 'prompt) - ) - -(use-package treesit-fold - :commands (treesit-fold-close - treesit-fold-close-all - treesit-fold-open - treesit-fold-toggle - treesit-fold-open-all - treesit-fold-mode - global-treesit-fold-mode - treesit-fold-open-recursively - treesit-fold-line-comment-mode) - :custom - (treesit-fold-line-count-show t) - (treesit-fold-line-count-format "--▼--") - :config - (set-face-attribute 'treesit-fold-replacement-face nil - :foreground "#808080" - :box nil - :weight 'bold)) - -;; Tree-sitter hooks -(dolist (hook '(c-ts-mode-hook c++-ts-mode-hook java-ts-mode-hook rust-ts-mode-hook - go-ts-mode-hook ruby-ts-mode-hook js-ts-mode-hook typescript-ts-mode-hook - tsx-ts-mode-hook css-ts-mode-hook html-ts-mode-hook bash-ts-mode-hook - cmake-ts-mode-hook dockerfile-ts-mode-hook json-ts-mode-hook toml-ts-mode-hook)) - (add-hook hook #'treesit-fold-mode)) - +t (use-package highlight-quoted :hook (emacs-lisp-mode . highlight-quoted-mode)) @@ -49,6 +14,17 @@ (prog-mode . rainbow-delimiters-mode) (inferior-ess-mode . rainbow-delimiters-mode)) +(use-package highlight-parentheses + :hook (prog-mode . highlight-parentheses-mode) + :config + (setq highlight-parentheses-colors + '("grey95" "#111" "#333" "#666") + highlight-parentheses-background-colors + '("#111" "blue" "green" "red") + ) + ) + + (use-package indent-bars :config (setq indent-bars-prefer-character ?. @@ -57,11 +33,12 @@ indent-bars-pad-frac 0.2 indent-bars-color-by-depth '(:regexp "outline-\\([0-9]+\\)" :blend 0.9) indent-bars-highlight-current-depth '(:face default :blend 0.4)) - (add-hook 'prog-mode-hook #'indent-bars-mode) + ;(add-hook 'prog-mode-hook #'indent-bars-mode) :hook (prog-mode . indent-bars-mode)) (use-package colorful-mode + :defer t :config (setq colorful-allow-mouse-clicks nil)) (use-package doom-modeline @@ -71,7 +48,9 @@ :config (setq doom-modeline-minor-modes t - doom-modeline-indent-info t) + doom-modeline-indent-info t + doom-modeline-column-zero-based t + doom-modeline-position-column-line-format '("%l:%c")) ) ;;--- @@ -79,17 +58,20 @@ ;;--- (use-package nerd-icons-completion + :defer t :after marginalia :config (nerd-icons-completion-mode) (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup)) (use-package nerd-icons-corfu + :defer t :after corfu :config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) (use-package nerd-icons-dired + :defer t :config (nerd-icons-dired-mode) (add-hook 'dired-mode-hook #'nerd-icons-dired-mode)) diff --git a/themes/cutarv42-theme.el b/themes/cutarv42-theme.el new file mode 100644 index 0000000..6fd641f --- /dev/null +++ b/themes/cutarv42-theme.el @@ -0,0 +1,180 @@ +;;; cutarv42-theme.el --- A high-contrast light theme with blue/pink accents -*- lexical-binding: t; no-byte-compile: t; -*- + +(deftheme cutarv42 + "A high-contrast light theme with blue/pink accents, optimized for clarity and syntax highlighting.") + +(let* (;; --- 1. Primitive Palette (Raw Colors) --- + (pure-white "#f8f8ff") + (pure-black "#010101") + (deep-blue "#007cbf") + (mid-blue "#2374de") + (soft-pink "#ef89df") + (deep-purple "#a64dd6") + (raw-magenta "#b05197") + (burnt-amber "#e58e40") + (duck-blue "#007a94") + (forest-green "#429e66") + (bright-green "#2cd45c") + (crimson-red "#cf3f29") + (soft-red "#f07b69") + (deep-orange "#ee7722") + (light-blue "#7cc9f2") + (light-grey "#f9f9f9") + (mid-grey "#888888") + (dark-grey "#444444") + (faint-purple "#eeccee") + + ;; --- 2. Semantic Palette (Functional Roles) --- + ;; Base UI + (bg-main pure-white) + (fg-main pure-black) + (ui-accent soft-pink) + (ui-hl-line faint-purple) + (ui-selection light-blue) + (ui-border raw-magenta) + (ui-muted mid-grey) + + ;; Syntax Roles + (syntax-keyword duck-blue) + (syntax-string forest-green) + (syntax-variable mid-blue) + (syntax-type deep-purple) + (syntax-constant burnt-amber) + (syntax-builtin deep-orange) + (syntax-comment "#666666") ;; Standard grey for comments + (syntax-comment-d bright-green) ;; Delimiter color + (syntax-function deep-blue) + + ;; Status / Feedback + (status-error crimson-red) + (status-warning soft-red) + (status-info deep-orange) + (status-success bright-green) + (status-highlight deep-blue) + + ;; Theme Class + (class '((class color) (min-colors 256)))) + + (custom-theme-set-faces + 'cutarv42 + + ;; --- Core UI --- + `(default ((,class (:background ,bg-main :foreground ,fg-main)))) + `(cursor ((,class (:background ,bg-main :foreground ,bg-main)))) + `(fringe ((,class (:background ,bg-main :foreground ,status-highlight)))) + `(region ((,class (:background ,ui-accent)))) + `(highlight ((,class (:background ,ui-selection :foreground ,bg-main)))) + `(hl-line ((,class (:background ,ui-hl-line :extend t)))) + `(link ((,class (:foreground ,syntax-keyword :underline t)))) + `(link-visited ((,class (:foreground ,syntax-type :underline t)))) + `(minibuffer-prompt ((,class (:foreground ,status-highlight :weight bold)))) + `(vertical-border ((,class (:foreground ,ui-border)))) + + ;; --- Syntax Highlighting (Font Lock) --- + `(font-lock-comment-face ((,class (:foreground ,syntax-comment :slant italic)))) + `(font-lock-doc-face ((,class (:inherit font-lock-comment-face)))) + `(font-lock-comment-delimiter-face ((,class (:foreground ,syntax-comment-d :slant italic)))) + `(font-lock-string-face ((,class (:foreground ,syntax-string)))) + `(font-lock-type-face ((,class (:foreground ,syntax-type)))) + `(font-lock-keyword-face ((,class (:foreground ,syntax-keyword :weight bold)))) + `(font-lock-function-name-face ((,class (:foreground ,syntax-function :weight bold)))) + `(font-lock-variable-name-face ((,class (:foreground ,syntax-variable)))) + `(font-lock-constant-face ((,class (:foreground ,syntax-constant)))) + `(font-lock-builtin-face ((,class (:foreground ,syntax-builtin)))) + `(font-lock-warning-face ((,class (:foreground ,status-warning :weight bold)))) + `(font-lock-negation-char-face ((,class (:foreground ,status-error)))) + `(font-lock-regexp-grouping-backslash ((,class (:foreground ,status-info)))) + `(font-lock-regexp-grouping-construct ((,class (:inherit font-lock-constant-face)))) + + ;; --- Mode-line --- + `(mode-line ((,class (:background ,ui-accent :foreground ,bg-main)))) + `(mode-line-inactive ((,class (:background ,ui-selection :foreground ,fg-main)))) + ;:box (:line-width 1 :color ,syntax-keyword) + + ;; --- Search & Isearch --- + `(isearch ((,class (:inherit hl-line)))) + `(isearch-fail ((,class (:inherit show-paren-mismatch)))) + `(lazy-highlight ((,class (:background ,status-info :foreground ,bg-main)))) + + ;; --- Line Numbers --- + `(line-number ((,class (:foreground ,fg-main :background ,ui-selection)))) + `(line-number-current-line ((,class (:inherit mode-line :weight bold)))) + + ;; --- Package Specifics --- + ;; Doom Modeline + `(doom-modeline-bar ((,class (:background ,ui-accent :foreground ,fg-main)))) + `(doom-modeline-buffer-file ((,class (:foreground ,fg-main :weight bold)))) + `(doom-modeline-buffer-path ((,class (:foreground ,fg-main :weight bold)))) + `(doom-modeline-buffer-modified ((,class (:foreground ,status-info :weight bold)))) + `(doom-modeline-debug ((,class (:inherit font-lock-warning-face)))) + `(doom-modeline-info ((,class (:inherit font-lock-delimiter-face)))) + `(doom-modeline-warning ((,class (:inherit font-lock-warning-face)))) + `(doom-modeline-error ((,class (:inherit error)))) + + ;; Vertico / Marginalia + `(vertico-current ((,class (:inherit line-number-current-line)))) + `(marginalia-documentation ((,class (:inherit font-lock-comment-face)))) + + ;; Magit + `(magit-branch-local ((,class (:foreground ,syntax-function :weight bold)))) + `(magit-branch-remote ((,class (:foreground ,syntax-string :weight bold)))) + `(magit-hash ((,class (:foreground ,status-highlight)))) + `(magit-item-highlight ((,class (:background ,ui-selection)))) + `(magit-diff-added ((,class (:foreground ,status-success :background unspecified)))) + `(magit-diff-removed ((,class (:foreground ,status-error :background unspecified)))) + `(magit-diff-context-highlight ((,class (:background ,status-highlight :foreground ,fg-main)))) + `(magit-section-heading ((,class (:foreground ,ui-selection :weight bold :underline t)))) + + ;; Tree-sitter + `(tree-sitter-hl-face:function.call ((,class (:foreground ,ui-accent)))) + `(tree-sitter-hl-face:method.call ((,class (:foreground ,ui-accent)))) + `(tree-sitter-hl-face:type ((,class (:foreground ,syntax-function)))) + `(tree-sitter-hl-face:property ((,class (:foreground ,ui-selection)))) + `(tree-sitter-hl-face:parameter ((,class (:foreground ,status-info)))) + `(tree-sitter-hl-face:escape ((,class (:foreground ,status-warning)))) + + ;; Flycheck / LSP + `(flycheck-error ((,class (:underline (:style wave :color ,status-error))))) + `(flycheck-warning ((,class (:underline (:style wave :color ,status-info))))) + `(flycheck-info ((,class (:underline (:style wave :color ,syntax-keyword))))) + `(lsp-face-highlight-textual ((,class (:background ,ui-selection)))) + + ;; Misc + `(show-paren-match ((,class (:background ,syntax-keyword :foreground ,bg-main :weight bold)))) + `(show-paren-mismatch ((,class (:background ,status-error :foreground ,fg-main :weight bold)))) + `(success ((,class (:foreground ,status-success)))) + `(error ((,class (:foreground ,status-error :weight bold)))) + `(warning ((,class (:foreground ,status-warning)))) + `(header-line ((,class (:background ,status-highlight :foreground ,fg-main)))) + + ;; Whitespace mode + `(whitespace-indentation ((,class (:background ,ui-muted :foreground ,status-warning )))) + `(whitespace-tab ((,class (:background ,light-grey :foreground ,syntax-constant)))) + `(whitespace-space ((,class (:background ,light-grey :foreground ,status-info)))) + `(whitespace-trailing ((,class (:background ,status-error :foreground ,status-info)))) + `(whitespace-line ((,class (:background ,light-grey)))) + + ;; Org Mode + `(org-level-1 ((,class (:foreground ,ui-accent :weight bold :height 1.2)))) + `(org-level-2 ((,class (:foreground ,syntax-keyword :weight bold :height 1.1)))) + `(org-level-3 ((,class (:foreground ,status-success :weight bold)))) + `(org-level-4 ((,class (:foreground ,ui-selection :weight bold)))) + `(org-level-5 ((,class (:foreground ,syntax-type :weight bold)))) + `(org-todo ((,class (:foreground ,status-warning :weight bold :box t)))) + `(org-done ((,class (:foreground ,status-success :weight bold :box t)))) + `(org-date ((,class (:foreground ,syntax-keyword)))) + `(org-link ((,class (:foreground ,syntax-type :underline t)))) + `(org-code ((,class (:foreground ,status-info :background ,bg-main)))) + `(org-block ((,class (:background ,bg-main :foreground ,fg-main :extend t)))) + `(org-block-begin-line ((,class (:foreground ,status-highlight :background ,bg-main :extend t)))) + )) + +;;;###autoload +(and load-file-name + (boundp 'custom-theme-load-path) + (add-to-list 'custom-theme-load-path + (file-name-as-directory (file-name-directory load-file-name)))) + +(provide-theme 'cutarv42) + +;;; cutarv41-theme.el ends here