;; config.el -*- lexical-binding: t; -*- ;; ============================================================ ;; Custom & Packages Loading ;; ============================================================ (let ((custom-dir (expand-file-name "custom/" user-emacs-directory))) (when (file-directory-p custom-dir) (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 'custom-theme-load-path (expand-file-name "themes/" user-emacs-directory)) (add-hook 'after-init-hook (lambda () (with-demoted-errors "Error in after-init-hook: %S" (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-define-key :keymaps 'global "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 "C-" nil "C-" nil ) (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 ";"))) ;; ============================================================ ;; 2. Native Emacs & System Configuration ;; ============================================================ (use-package emacs :ensure nil :custom ;; --- 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) (completion-category-overrides '((point (styles orderless basic)))) ;; --- 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) ) ;; ============================================================ ;; 3. Core Settings & UI ;; ============================================================ (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 ;; --- 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 150 history-length 500 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 2 js-indent-level 2 typescript-indent-level 2 typescript-ts-mode-indent-offset 2 selection-coding-system 'utf-8 cursor-type 'bar ) ;; ============================================================ ;; 5. Hooks, Modes & Theming ;; ============================================================ (add-hook 'text-mode-hook #'jit-spell-mode) (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 (fringe-mode '(0 . 8)) ; fringe only on right edge (delete-selection-mode 1) ;; --- 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 'term-file-aliases '("xterm-256" . "xterm")) (use-package markdown-mode :mode "\\.qd$") (use-package typescript-ts-mode :mode "\\.ts$") (use-package js-ts-mode :mode "\\.json$") (setq major-mode-remap-alist '((c-mode . c-ts-mode) (c++-mode . c++-ts-mode) (cmake-mode . cmake-ts-mode) (css-mode . css-ts-mode) (java-mode . java-ts-mode) (javascript-mode . js-ts-mode) (js-mode . js-ts-mode) (js2-mode . js-ts-mode) (json-mode . json-ts-mode) (python-mode . python-ts-mode) (ruby-mode . ruby-ts-mode) (rust-mode . rust-ts-mode) (sh-mode . bash-ts-mode) (typescript-mode . typescript-ts-mode) (yaml-mode . yaml-ts-mode))) ;; Visual Finalization (add-hook 'window-setup-hook (lambda () (set-face-attribute 'default nil :family "Noto Sans Mono" :height 110) (set-face-attribute 'variable-pitch nil :family "Noto Sans" :height 120) (load-theme 'cutarv42 t) ) ) (setq nerd-icons-font-family "Symbols Nerd Font Mono")