From 883f8047f683afee6821eaddb31ae002ee316381 Mon Sep 17 00:00:00 2001 From: Max Amundsen Date: Fri, 26 Dec 2025 18:06:16 -0500 Subject: [PATCH] refactor init.el (emac) --- .emacs.d/init.el | 1120 ++++++++++++++++++++++++++-------------------- 1 file changed, 639 insertions(+), 481 deletions(-) diff --git a/.emacs.d/init.el b/.emacs.d/init.el index 51250fc..c248b0d 100755 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -1,49 +1,87 @@ ;; Max's init.el -*- lexical-binding: t; -*- -;; General Configuration +;;; ============================================================================ +;;; PACKAGE LOADING & LOAD PATHS +;;; ============================================================================ -;; set load paths for lisp evaluation (add-to-list 'load-path "~/.emacs.d/lisp/") (let ((default-directory "~/.emacs.d/lisp/")) (normal-top-level-add-subdirs-to-load-path)) -(require 'yaml-mode) -(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) -(require 'dockerfile-mode) -(require 'go-mode) -(add-to-list 'auto-mode-alist '("\\.go\\'" . go-mode)) -(require 'jai-mode) -(add-to-list 'auto-mode-alist '("\\.jai\\'" . jai-mode)) -(require 'stupid-indent-mode) -(require 'xah-find) -(require 'multiple-cursors) -(require 'ivy) -(require 'counsel) +;; Core libraries (require 's) (require 'dash) (require 'popup) + +;; Completion framework +(require 'ivy) +(require 'counsel) + +;; Language modes +(require 'yaml-mode) +(require 'dockerfile-mode) +(require 'go-mode) +(require 'jai-mode) (require 'simpc-mode) -;; Automatically enabling simpc-mode on files with extensions like .h, .c, .cpp, .hpp -(add-to-list 'auto-mode-alist '("\\.[hc]\\(pp\\)?\\'" . simpc-mode)) -;; ctags for xref, with dumb-jump as fallback + +;; Editing enhancements +(require 'stupid-indent-mode) +(require 'multiple-cursors) +(require 'vundo) + +;; Navigation (require 'dumb-jump) +(require 'eglot) + +;; Search +(require 'xah-find) + +;;; ============================================================================ +;;; MODE ASSOCIATIONS +;;; ============================================================================ + +(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) +(add-to-list 'auto-mode-alist '("\\.go\\'" . go-mode)) +(add-to-list 'auto-mode-alist '("\\.jai\\'" . jai-mode)) +(add-to-list 'auto-mode-alist '("\\.[hc]\\(pp\\)?\\'" . simpc-mode)) + +;;; ============================================================================ +;;; IVY & COMPLETION FRAMEWORK +;;; ============================================================================ + +(ivy-mode 1) +(setq ivy-use-virtual-buffers t) +(setq ivy-count-format "(%d/%d) ") +(setq ivy-wrap t) + +;;; ============================================================================ +;;; XREF, CTAGS & NAVIGATION +;;; ============================================================================ + +;; dumb-jump as fallback for xref (setq dumb-jump-force-searcher 'grep) (setq dumb-jump-selector 'ivy) (setq xref-show-definitions-function #'xref-show-definitions-completing-read) (setq tags-revert-without-query t) (add-hook 'xref-backend-functions #'dumb-jump-xref-activate 100) -;; eglot LSP client +;;; ============================================================================ +;;; EGLOT (LSP) CONFIGURATION +;;; ============================================================================ + ;; When eglot is active, xref commands (F12, M-f12) automatically use LSP ;; instead of CTAGS. Eglot registers itself as a higher-priority xref backend. -(require 'eglot) + (setq eglot-autoshutdown t) ; shutdown server when last buffer is closed (setq eglot-confirm-server-initiated-edits nil) ; don't ask for confirmation on renames ;; disable LSP visual indicators but keep diagnostics available (add-to-list 'eglot-ignored-server-capabilities :documentHighlightProvider) +;; Go: auto-start eglot (requires gopls: go install golang.org/x/tools/gopls@latest) +(add-hook 'go-mode-hook 'eglot-ensure) + ;; auto-confirm "modified buffer" prompts when jumping from diagnostics (defun my-auto-confirm-modified-buffer (orig-fun prompt) "Auto-confirm prompts about modified buffers having wrong location." @@ -51,44 +89,6 @@ t (funcall orig-fun prompt))) (advice-add 'y-or-n-p :around #'my-auto-confirm-modified-buffer) -;; 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 -(setq flymake-fringe-indicator-position nil) - -;; Go: auto-start eglot (requires gopls: go install golang.org/x/tools/gopls@latest) -(add-hook 'go-mode-hook 'eglot-ensure) - -(global-set-key (kbd "") 'eglot-rename) -(global-set-key (kbd "C-S-m") 'my-flymake-show-project-errors-warnings) -(global-set-key (kbd "") 'eglot-reconnect) -(global-set-key (kbd "C-t") 'my-lsp-find-workspace-symbol) - -(defun my-flymake-show-project-errors-warnings () - "Show project diagnostics, filtering out notes (only errors and warnings)." - (interactive) - ;; Kill existing diagnostics buffer to force refresh - (when-let ((buf (get-buffer "*Flymake diagnostics*"))) - (kill-buffer buf)) - ;; Refresh flymake on all project buffers - (dolist (buf (buffer-list)) - (with-current-buffer buf - (when (and (bound-and-true-p flymake-mode) - (buffer-file-name)) - (flymake-start)))) - (flymake-show-project-diagnostics) - (run-at-time 0.1 nil - (lambda () - (when-let ((buf (get-buffer "*Flymake diagnostics*"))) - (with-current-buffer buf - (let ((inhibit-read-only t)) - (goto-char (point-min)) - (while (not (eobp)) - (if (looking-at ".*\\bnote\\b.*$") - (delete-region (line-beginning-position) (1+ (line-end-position))) - (forward-line 1))))))))) (defun my-lsp-find-workspace-symbol () "Interactively search for symbols in workspace using LSP." @@ -129,27 +129,62 @@ (forward-line (1- (get-text-property 0 'line candidate))))))) (call-interactively 'xref-find-apropos))) -;; vundo for visual undo tree -(require 'vundo) -(ivy-mode 1) -(setq ivy-use-virtual-buffers t) -(setq ivy-count-format "(%d/%d) ") -(setq ivy-wrap t) +;;; ============================================================================ +;;; FLYMAKE & DIAGNOSTICS +;;; ============================================================================ -;; dired: mouse click opens in same window -(add-hook 'dired-mode-hook - (lambda () - (define-key dired-mode-map [mouse-2] 'dired-find-file))) +;; 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) -;; default indentation settings +;; hide fringe indicators +(setq flymake-fringe-indicator-position nil) + +(defun my-flymake-show-project-errors-warnings () + "Show project diagnostics, filtering out notes (only errors and warnings)." + (interactive) + ;; Kill existing diagnostics buffer to force refresh + (when-let ((buf (get-buffer "*Flymake diagnostics*"))) + (kill-buffer buf)) + ;; Refresh flymake on all project buffers + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (and (bound-and-true-p flymake-mode) + (buffer-file-name)) + (flymake-start)))) + (flymake-show-project-diagnostics) + (run-at-time 0.1 nil + (lambda () + (when-let ((buf (get-buffer "*Flymake diagnostics*"))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (goto-char (point-min)) + (while (not (eobp)) + (if (looking-at ".*\\bnote\\b.*$") + (delete-region (line-beginning-position) (1+ (line-end-position))) + (forward-line 1))))))))) + +;;; ============================================================================ +;;; MULTIPLE CURSORS +;;; ============================================================================ + +(setq mc/always-run-for-all t) +(define-key mc/keymap (kbd "") 'mc/keyboard-quit) +(define-key mc/keymap (kbd "") nil) + +;;; ============================================================================ +;;; INDENTATION SETTINGS +;;; ============================================================================ + +;; default indentation (setq-default indent-tabs-mode t) (setq-default tab-width 4) (setq-default stupid-indent-level 4) (add-hook 'text-mode-hook 'stupid-indent-mode) (add-hook 'prog-mode-hook 'stupid-indent-mode) -;; per-language indentation settings -;; (indent-tabs-mode: t = tabs, nil = spaces) +;; per-language indentation (indent-tabs-mode: t = tabs, nil = spaces) (add-hook 'go-mode-hook (lambda () (setq-local indent-tabs-mode t) (setq-local tab-width 4) @@ -180,14 +215,78 @@ (setq-local tab-width 2) (setq-local stupid-indent-level 2))) -;; general settings -(setq-default inhibit-startup-screen t) +;;; ============================================================================ +;;; GENERAL SETTINGS & UI +;;; ============================================================================ + +;; startup +(setq-default inhibit-startup-screen t) +(setq initial-major-mode 'text-mode) +(setq initial-scratch-message "Just give him some food, water, and a funny hat." ) + +;; frame & window +(add-to-list 'default-frame-alist '(fullscreen . maximized)) +(setq ns-pop-up-frames nil) +(setq use-dialog-box nil) +(setq frame-inhibit-implied-resize t) + +;; UI chrome +(menu-bar-mode -1) +(scroll-bar-mode -1) +(tool-bar-mode -1) +(context-menu-mode -1) +(tooltip-mode -1) +(blink-cursor-mode 0) + +;; editing behavior +(show-paren-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) +(electric-pair-mode -1) +(electric-indent-mode 0) +(global-auto-revert-mode t) +(global-so-long-mode 1) +(global-hl-line-mode -1) + +;; display +(setq-default truncate-lines 1) +(setq column-number-mode t) +(column-number-mode 1) +(global-font-lock-mode 1) + +;; clipboard +(setq-default select-enable-clipboard t) +(setq-default x-select-enable-clipboard t) + +;; misc behavior +(setq-default backward-delete-char-untabify-method nil) +(setq ring-bell-function 'ignore) +(setq-default require-final-newline t) +(setq ediff-split-window-function 'split-window-horizontally) +(setq dired-dnd-protocol-alist nil) +(setq custom-file "~/.emacs.d/custom.el") + +;; mouse - disable right-click context menu +(global-set-key [mouse-3] 'ignore) +(global-set-key [down-mouse-3] 'ignore) +(global-set-key [C-down-mouse-1] 'ignore) +(global-set-key [C-down-mouse-3] 'ignore) + +;; dired: mouse click opens in same window +(add-hook 'dired-mode-hook + (lambda () + (define-key dired-mode-map [mouse-2] 'dired-find-file))) + +;;; ============================================================================ +;;; BOTTOM PANEL / COMPILATION WINDOW +;;; ============================================================================ -;; bottom panel settings (compilation, xref, etc.) (setq compilation-scroll-output -1) (setq compilation-save-buffers-predicate 'ignore) -;; bottom panel buffer patterns (defvar my-bottom-panel-buffers '("\\*compilation\\*" "\\*xref\\*" "\\*Flymake diagnostics.*\\*") "List of buffer name patterns for bottom panel.") @@ -196,7 +295,6 @@ (seq-some (lambda (pat) (string-match-p pat (buffer-name buf))) my-bottom-panel-buffers)) -;; find existing bottom panel window (defun my-get-bottom-panel-window () "Get existing bottom panel window if any." (seq-find (lambda (w) @@ -204,7 +302,6 @@ (my-bottom-panel-buffer-p (window-buffer w)))) (window-list))) -;; display function that reuses bottom panel (defun my-display-in-bottom-panel (buffer alist) "Display BUFFER in bottom panel, reusing existing panel window." (let ((window (my-get-bottom-panel-window))) @@ -218,7 +315,6 @@ (set-window-parameter new-window 'window-height 0.25))) new-window)))) -;; use our custom display function for panel buffers (add-to-list 'display-buffer-alist '("\\*compilation\\*" (my-display-in-bottom-panel) (window-height . 0.25))) (add-to-list 'display-buffer-alist @@ -226,7 +322,6 @@ (add-to-list 'display-buffer-alist '("\\*Flymake diagnostics.*\\*" (my-display-in-bottom-panel) (window-height . 0.25))) - (defun my-bottom-panel-toggle () "Toggle the bottom panel. Close if visible, open if hidden." (interactive) @@ -242,56 +337,26 @@ (my-display-in-bottom-panel (car matching-buffers) '((window-height . 0.25))) (message "No bottom panel buffers open.")))))) -(add-to-list 'default-frame-alist '(fullscreen . maximized)) -(show-paren-mode 1) -(delete-selection-mode 1) -(setq cua-auto-tabify-rectangles nil) ;; Don't tabify after rectangle commands -(transient-mark-mode 1) ;; No region when it is not highlighted -(setq cua-keep-region-after-copy nil) ;; don't reselect after copy -(menu-bar-mode -1) -(scroll-bar-mode -1) -(tool-bar-mode -1) -(context-menu-mode -1) -(global-set-key [mouse-3] 'ignore) -(global-set-key [down-mouse-3] 'ignore) -(global-set-key [C-down-mouse-1] 'ignore) -(global-set-key [C-down-mouse-3] 'ignore) -(global-auto-revert-mode t) -(electric-pair-mode -1) -(setq ns-pop-up-frames nil) -(setq initial-major-mode 'text-mode) -(setq initial-scratch-message "Just give him some food, water, and a funny hat." ) -(setq ediff-split-window-function 'split-window-horizontally) -(setq-default truncate-lines 1) -(setq column-number-mode t) -(setq dired-dnd-protocol-alist nil) -(global-so-long-mode 1) -(column-number-mode 1) -(blink-cursor-mode 0) -(setq use-dialog-box nil) -(electric-indent-mode 0) -(tooltip-mode -1) -(setq-default select-enable-clipboard t) -(setq-default x-select-enable-clipboard t) -(setq-default backward-delete-char-untabify-method nil) -(setq ring-bell-function 'ignore) -(setq custom-file "~/.emacs.d/custom.el") ;; place custom in a separate file -(setq-default require-final-newline t) -(cua-mode t) -(global-hl-line-mode -1) +;;; ============================================================================ +;;; BACKUP & AUTOSAVE SETTINGS +;;; ============================================================================ -;; backup and autosave settings -(setq backup-by-copying t ; don't clobber symlinks - backup-directory-alist '(("." . "~/.emacs.d/saves/")) ; don't litter my fs tree +(setq backup-by-copying t + backup-directory-alist '(("." . "~/.emacs.d/saves/")) delete-old-versions t kept-new-versions 6 kept-old-versions 2 - version-control t) ; use versioned backups + version-control t) + (setq auto-save-file-name-transforms `((".*" "~/.emacs.d/saves/" t))) + (setq create-lockfiles nil) -;; Recursively kill process and all descendants +;;; ============================================================================ +;;; PROCESS MANAGEMENT +;;; ============================================================================ + (defun my-kill-process-tree (pid) "Kill PID and all its descendant processes." (let ((children (split-string @@ -303,7 +368,7 @@ (my-kill-process-tree (string-to-number child))))) (ignore-errors (call-process "kill" nil nil nil "-9" (number-to-string pid)))) -;; Ensure all subprocesses (including grandchildren like DLV) are killed when Emacs exits +;; Ensure all subprocesses are killed when Emacs exits (add-hook 'kill-emacs-hook (lambda () (dolist (proc (process-list)) @@ -314,38 +379,6 @@ (set-process-query-on-exit-flag proc t) (ignore-errors (delete-process proc)))))) -;; Keybindings / Keybinds -;; global -(global-set-key (kbd "C-a") 'mark-whole-buffer) -(global-set-key (kbd "C-n") (lambda () (interactive) (switch-to-buffer (generate-new-buffer "untitled")))) -(global-set-key (kbd "S-") #'my-mouse-start-rectangle) -(global-set-key (kbd "") 'my-compile-last) -(global-set-key (kbd "") 'my-compile-custom) -(global-set-key (kbd "") 'my-bottom-panel-toggle) -(global-set-key (kbd "") 'my-file-manager-command) -(global-set-key (kbd "") 'project-switch-project) -(global-set-key (kbd "") 'my-terminal-emulator-command) -(global-set-key [f8] 'goto-line) -(global-set-key (kbd "C-\\") 'split-window-below) -(global-set-key (kbd "C-|") 'split-window-right) -(global-unset-key (kbd "C-x C-SPC")) -(global-set-key (kbd "C-x C-SPC") 'rectangle-mark-mode) -(global-set-key [?\C-z] 'undo) -(global-set-key (kbd "C-*") 'search-current-word) -(global-set-key (kbd "C-/") 'my-toggle-comment) -(global-set-key (kbd "M-") 'save-buffers-kill-terminal) ;; windows thing -(global-set-key (kbd "C-y") 'clipboard-yank) ;; fix killring messing with system clipboard -(global-set-key (kbd "C-w") 'delete-window) -(global-set-key (kbd "M-w") 'clipboard-kill-ring-save) -(global-set-key (kbd "M-j") 'my-duplicate-line) -(global-set-key (kbd "") 'bookmark-jump) -(global-set-key (kbd "") 'bookmark-set) -(global-set-key (kbd "") 'toggle-frame-maximized) -(global-set-key (kbd "") 'my-smart-home) -(global-set-key (kbd "") 'move-end-of-line) -(setq mac-command-modifier 'control) -(setq mac-control-modifier 'command) - ;; Kill terminal buffer when process exits (defun my-term-handle-exit (&optional process-name msg) "Kill terminal buffer when process exits." @@ -353,28 +386,141 @@ (kill-buffer (current-buffer)))) (advice-add 'term-handle-exit :after #'my-term-handle-exit) + +;;; ============================================================================ +;;; KEYBINDINGS +;;; ============================================================================ + +;; Mac-specific modifier keys +(setq mac-command-modifier 'control) +(setq mac-control-modifier 'command) + +;; isearch settings +(setq isearch-wrap-pause 'no) + +;; --- File & Buffer Operations --- +(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-p") 'project-find-file) +(global-set-key (kbd "C-3") 'switch-to-buffer) +(global-set-key (kbd "C-4") 'find-file) +(global-set-key (kbd "C-q") 'save-buffers-kill-terminal) +(global-set-key (kbd "M-") 'save-buffers-kill-terminal) + +;; --- Window & Pane Management --- +(global-set-key (kbd "C-w") 'delete-window) +(global-set-key (kbd "C-\\") 'split-window-below) +(global-set-key (kbd "C-|") 'split-window-right) +(global-set-key (kbd "C-o") 'next-multiframe-window) +(global-set-key (kbd "C-1") 'my-select-left-pane) +(global-set-key (kbd "C-2") 'my-select-right-pane) +(global-set-key (kbd "") 'toggle-frame-maximized) + +;; --- Selection & Editing --- +(global-set-key (kbd "C-a") 'mark-whole-buffer) +(global-set-key (kbd "C-l") 'my-select-line) +(global-set-key (kbd "C-/") 'my-toggle-comment) +(global-set-key (kbd "M-j") 'my-duplicate-line) +(global-unset-key (kbd "C-x C-SPC")) +(global-set-key (kbd "C-x C-SPC") 'rectangle-mark-mode) +(global-set-key (kbd "S-") #'my-mouse-start-rectangle) + +;; --- Clipboard & Kill Ring --- +(global-set-key [?\C-z] 'undo) +(global-set-key (kbd "C-y") 'clipboard-yank) +(global-set-key (kbd "M-w") 'clipboard-kill-ring-save) + +;; --- Navigation --- +(global-set-key (kbd "") 'my-smart-home) +(global-set-key (kbd "") 'move-end-of-line) +(global-set-key (kbd "M-p") 'backward-paragraph) +(global-set-key (kbd "M-n") 'forward-paragraph) +(global-set-key [f8] 'goto-line) (when (eq system-type 'darwin) (global-set-key (kbd "C-") 'my-smart-home) (global-set-key (kbd "C-") 'move-end-of-line)) + +;; --- Line Movement --- +(global-set-key (kbd "M-") 'my-move-line-up) +(global-set-key (kbd "M-") 'my-move-line-down) + +;; --- Search & Replace --- (global-set-key (kbd "C-f") 'my-isearch-forward) +(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-h") 'my-find-replace) -(global-set-key (kbd "C-S-p") 'counsel-M-x) -(global-set-key (kbd "C-p") 'project-find-file) -(global-set-key (kbd "C-s") 'save-buffer) -(global-set-key (kbd "") 'my-select-theme) -(global-set-key (kbd "C-") 'my-xref-find-definitions-at-click) -(global-set-key (kbd "C-S-") 'my-xref-find-references-at-click) + +;; --- Code Navigation (xref/LSP) --- (global-set-key (kbd "") 'my-xref-find-definitions-same-pane) (global-set-key (kbd "C-") 'xref-find-references) (global-set-key (kbd "C-{") 'xref-go-back) (global-set-key (kbd "C-}") 'xref-go-forward) (global-set-key (kbd "") 'xref-go-back) (global-set-key (kbd "") 'xref-go-forward) -(global-set-key (kbd "C-q") 'save-buffers-kill-terminal) -(global-set-key (kbd "C-l") 'my-select-line) +(global-set-key (kbd "C-") 'my-xref-find-definitions-at-click) +(global-set-key (kbd "C-S-") 'my-xref-find-references-at-click) +(global-set-key (kbd "C-t") 'my-lsp-find-workspace-symbol) + +;; --- LSP / Eglot --- +(global-set-key (kbd "") 'eglot-rename) +(global-set-key (kbd "") 'eglot-reconnect) +(global-set-key (kbd "C-S-m") 'my-flymake-show-project-errors-warnings) + +;; --- Compilation & Build --- +(global-set-key (kbd "") 'my-bottom-panel-toggle) +(global-set-key (kbd "") 'my-compile-last) +(global-set-key (kbd "") 'my-compile-custom) + +;; --- External Tools --- +(global-set-key (kbd "") 'my-file-manager-command) +(global-set-key (kbd "") 'my-terminal-emulator-command) + +;; --- Project Management --- +(global-set-key (kbd "") 'project-switch-project) +(global-set-key (kbd "C-S-p") 'counsel-M-x) + +;; --- Bookmarks --- +(global-set-key (kbd "") 'bookmark-jump) +(global-set-key (kbd "") 'bookmark-set) + +;; --- Themes --- +(global-set-key (kbd "") 'my-select-theme) + +;; --- Zoom --- +(global-set-key (kbd "C-=") 'my-global-zoom-in) +(global-set-key (kbd "C--") 'my-global-zoom-out) +(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-") 'ignore) +(global-set-key (kbd "C-") 'ignore) + +;; --- Completion (dabbrev) --- +(global-set-key (kbd "C-j") 'dabbrev-expand) + +;; --- Multiple Cursors --- +(global-set-key (kbd "C-d") 'mc/mark-next-like-this-word) +(global-set-key (kbd "C-S-d") 'mc/mark-previous-like-this-word) +(global-set-key (kbd "C-S-a") 'mc/mark-all-like-this) +(global-set-key (kbd "M-") 'ignore) +(global-set-key (kbd "M-") 'mc/add-cursor-on-click) +(global-set-key (kbd "C-M-") (lambda () (interactive) (mc/mark-previous-lines 1))) +(global-set-key (kbd "C-M-") (lambda () (interactive) (mc/mark-next-lines 1))) + +;; --- Word Deletion (without kill ring) --- +(global-set-key (kbd "M-") 'my-backward-delete-word) +(global-set-key (kbd "M-d") 'my-delete-word) +(global-set-key (kbd "M-") 'my-delete-word) +(global-set-key (kbd "C-") 'my-backward-delete-word) + +;; --- Misc --- (global-set-key (kbd "C-e") 'my-copy-path-with-line) + +;; --- Minibuffer Keybindings --- (define-key minibuffer-local-filename-completion-map (kbd "C-2") 'my-find-file-right-pane) + +;; --- Isearch Keybindings --- (define-key isearch-mode-map (kbd "") 'isearch-repeat-forward) (define-key isearch-mode-map (kbd "S-") 'isearch-repeat-backward) (define-key isearch-mode-map (kbd "") 'isearch-del-char) @@ -382,6 +528,119 @@ (define-key isearch-mode-map (kbd "") 'my-isearch-cancel-or-exit) (define-key isearch-mode-map (kbd "C-g") 'my-isearch-cancel-or-exit) +;;; ============================================================================ +;;; CUSTOM MINOR MODE (for keybinding overrides) +;;; ============================================================================ + +(defvar my-keys-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "M-p") 'backward-paragraph) + (define-key map (kbd "M-n") 'forward-paragraph) + (define-key map (kbd "C-o") 'next-multiframe-window) + (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-3") 'switch-to-buffer) + (define-key map (kbd "C-4") 'find-file) + (define-key map (kbd "C-j") 'dabbrev-expand) + (define-key map (kbd "C-d") 'mc/mark-next-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) + map) + "my-keys-minor-mode keymap.") + +(define-minor-mode my-keys-minor-mode + "A minor mode so that my key settings override annoying major modes." + :init-value t + :lighter "") + +;; don't enable override keymap in minibuffer +(defun my-minibuffer-setup-hook () + (my-keys-minor-mode 0)) +(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook) + +(my-keys-minor-mode 1) + +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Navigation +;;; ============================================================================ + +(defun my-smart-home () + "Move to first non-whitespace char, or beginning of line if already there." + (interactive "^") + (let ((orig-point (point))) + (back-to-indentation) + (when (= orig-point (point)) + (move-beginning-of-line 1)))) + +(defun my-get-top-windows () + "Get windows in the top portion of the frame (not bottom compilation)." + (let ((windows '())) + (walk-windows + (lambda (w) + (when (window-at-side-p w 'top) + (push w windows)))) + (sort windows (lambda (a b) (< (car (window-edges a)) (car (window-edges b))))))) + +(defun my-select-left-pane () + "Select the left pane of the top split." + (interactive) + (let ((top-windows (my-get-top-windows))) + (when top-windows + (select-window (car top-windows))))) + +(defun my-select-right-pane () + "Select the right pane of the top split, creating it if needed." + (interactive) + (let ((top-windows (my-get-top-windows))) + (if (>= (length top-windows) 2) + (select-window (cadr top-windows)) + (when top-windows + (select-window (car top-windows)) + (split-window-right) + (other-window 1))))) + +(defun my-xref-find-definitions-same-pane () + "Find definition and show it in the same pane. +Falls back to dumb-jump if xref fails." + (interactive) + (let ((identifier (thing-at-point 'symbol t))) + (if (null identifier) + (message "No symbol at point") + (condition-case nil + (let ((xrefs (xref-backend-definitions (xref-find-backend) identifier))) + (if xrefs + (xref-find-definitions identifier) + (dumb-jump-go))) + (error (dumb-jump-go)))))) + +(defun my-xref-find-definitions-at-click (event) + "Find definition of the symbol clicked on." + (interactive "e") + (mouse-set-point event) + (my-xref-find-definitions-same-pane)) + +(defun my-xref-find-references-at-click (event) + "Find references of the symbol clicked on." + (interactive "e") + (mouse-set-point event) + (xref-find-references (thing-at-point 'symbol t))) + +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Search & Replace +;;; ============================================================================ + +(defun my-isearch-forward () + "Start isearch, using selected text if region is active." + (interactive) + (if (use-region-p) + (let ((text (buffer-substring-no-properties (region-beginning) (region-end)))) + (deactivate-mark) + (isearch-forward nil 1) + (setq isearch-string text + isearch-message text) + (isearch-update)) + (isearch-forward))) + (defun my-isearch-cancel-or-exit () "Cancel isearch if search string is empty, otherwise exit at current position." (interactive) @@ -389,6 +648,109 @@ (isearch-cancel) (isearch-exit))) +(defun search-current-word () + (interactive) + (let ($p1 $p2) + (if (region-active-p) + (setq $p1 (region-beginning) $p2 (region-end)) + (save-excursion + + (skip-chars-backward "-_A-Za-z0-9") + (setq $p1 (point)) + (right-char) + (skip-chars-forward "-_A-Za-z0-9") + (setq $p2 (point)))) + (setq mark-active nil) + (when (< $p1 (point)) + (goto-char $p1)) + (isearch-mode t) + (isearch-yank-string (buffer-substring-no-properties $p1 $p2)))) + +(defun my-project-find-text () + "Search for literal text in project." + (interactive) + (let* ((initial (when (use-region-p) + (buffer-substring-no-properties (region-beginning) (region-end)))) + (text (read-string "Search in project: " initial))) + (project-find-regexp (regexp-quote text)))) + +(defun my-project-find-word-at-point () + "Search for word under cursor in project." + (interactive) + (let ($p1 $p2 word) + (if (region-active-p) + (setq $p1 (region-beginning) $p2 (region-end)) + (save-excursion + (skip-chars-backward "-_A-Za-z0-9") + (setq $p1 (point)) + (skip-chars-forward "-_A-Za-z0-9") + (setq $p2 (point)))) + (setq word (buffer-substring-no-properties $p1 $p2)) + (when (> (length word) 0) + (project-find-regexp (regexp-quote word))))) + +(defun my-find-replace () + "Find and replace with mode selection: project, file, or selection." + (interactive) + (let* ((mode (completing-read "Replace in: " '("file" "project" "selection") nil t)) + (search (read-string "Find: ")) + (replace (read-string (format "Replace '%s' with: " search)))) + (cond + ((string= mode "project") + (project-query-replace-regexp (regexp-quote search) replace)) + ((string= mode "file") + (save-excursion + (goto-char (point-min)) + (query-replace search replace))) + ((string= mode "selection") + (if (use-region-p) + (query-replace search replace nil (region-beginning) (region-end)) + (message "No region selected.")))))) + +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Line Operations +;;; ============================================================================ + +(defun my-select-line () + "Select the current line. Repeat to select subsequent lines." + (interactive) + (if (and (use-region-p) (eq last-command 'my-select-line)) + (forward-line 1) + (move-beginning-of-line 1) + (set-mark (point)) + (forward-line 1))) + +(defun my-toggle-comment () + "Toggle comment on line or region without moving point." + (interactive) + (let* ((region-active (use-region-p)) + (start (if region-active (region-beginning) (line-beginning-position))) + (end (if region-active (region-end) (line-end-position)))) + (comment-or-uncomment-region start end) + (when region-active + (setq deactivate-mark nil)))) + +(defun my-duplicate-line (arg) + "Duplicate current line, leaving point in lower line." + (interactive "*p") + (setq buffer-undo-list (cons (point) buffer-undo-list)) + (let ((bol (save-excursion (beginning-of-line) (point))) + eol) + (save-excursion + (end-of-line) + (setq eol (point)) + (let ((line (buffer-substring bol eol)) + (buffer-undo-list t) + (count arg)) + (while (> count 0) + (newline) + (insert line) + (setq count (1- count))) + ) + (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))) + ) + (next-line arg)) + (defun my-move-line-up () "Move current line or region up one line." (interactive) @@ -443,151 +805,28 @@ (goto-char (+ new-beg offset-from-beg region-len)) (setq deactivate-mark nil)))) -(global-set-key (kbd "M-") 'my-move-line-up) -(global-set-key (kbd "M-") 'my-move-line-down) -(setq isearch-wrap-pause 'no) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Word Deletion +;;; ============================================================================ -;; multiple cursors (vscode-style) -(setq mc/always-run-for-all t) -(global-set-key (kbd "M-") 'ignore) -(global-set-key (kbd "M-") 'mc/add-cursor-on-click) -(global-set-key (kbd "C-M-") (lambda () (interactive) (mc/mark-previous-lines 1))) -(global-set-key (kbd "C-M-") (lambda () (interactive) (mc/mark-next-lines 1))) -(define-key mc/keymap (kbd "") 'mc/keyboard-quit) -(define-key mc/keymap (kbd "") nil) +(defun my-delete-word (arg) + "Delete characters forward until encountering the end of a word. +With argument ARG, do this that many times. +Does not copy to kill ring." + (interactive "p") + (delete-region (point) (progn (forward-word arg) (point)))) -;; functions to get top panes (ignoring bottom compilation window) -(defun my-get-top-windows () - "Get windows in the top portion of the frame (not bottom compilation)." - (let ((windows '())) - (walk-windows - (lambda (w) - (when (window-at-side-p w 'top) - (push w windows)))) - (sort windows (lambda (a b) (< (car (window-edges a)) (car (window-edges b))))))) +(defun my-backward-delete-word (arg) + "Delete characters backward until encountering the beginning of a word. +With argument ARG, do this that many times. +Does not copy to kill ring." + (interactive "p") + (my-delete-word (- arg))) -(defun my-select-left-pane () - "Select the left pane of the top split." - (interactive) - (let ((top-windows (my-get-top-windows))) - (when top-windows - (select-window (car top-windows))))) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Compile Commands +;;; ============================================================================ -(defun my-select-right-pane () - "Select the right pane of the top split, creating it if needed." - (interactive) - (let ((top-windows (my-get-top-windows))) - (if (>= (length top-windows) 2) - (select-window (cadr top-windows)) - (when top-windows - (select-window (car top-windows)) - (split-window-right) - (other-window 1))))) - -(defun my-xref-find-definitions-same-pane () - "Find definition and show it in the same pane. -Falls back to dumb-jump if xref fails." - (interactive) - (let ((identifier (thing-at-point 'symbol t))) - (if (null identifier) - (message "No symbol at point") - (condition-case nil - (let ((xrefs (xref-backend-definitions (xref-find-backend) identifier))) - (if xrefs - (xref-find-definitions identifier) - (dumb-jump-go))) - (error (dumb-jump-go)))))) - -(defun my-xref-find-definitions-at-click (event) - "Find definition of the symbol clicked on." - (interactive "e") - (mouse-set-point event) - (my-xref-find-definitions-same-pane)) - -(defun my-xref-find-references-at-click (event) - "Find references of the symbol clicked on." - (interactive "e") - (mouse-set-point event) - (xref-find-references (thing-at-point 'symbol t))) - -;; custom bind minor mode -;; this allows binding keys that override all other modes -(defvar my-keys-minor-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "M-p") 'backward-paragraph) - (define-key map (kbd "M-n") 'forward-paragraph) - (define-key map (kbd "C-o") 'next-multiframe-window) - (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-3") 'switch-to-buffer) - (define-key map (kbd "C-4") 'find-file) - (define-key map (kbd "C-j") 'dabbrev-expand) - ;; multiple cursors (override major modes) - (define-key map (kbd "C-d") 'mc/mark-next-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) - map) - "my-keys-minor-mode keymap.") - -(define-minor-mode my-keys-minor-mode - "A minor mode so that my key settings override annoying major modes." - :init-value t - :lighter "") - -;; don't enable override keymap in minibuffer -(defun my-minibuffer-setup-hook () - (my-keys-minor-mode 0)) -(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook) - -(my-keys-minor-mode 1) - -;; Custom Functions - -;; toggle comment (vscode-style) -(defun my-toggle-comment () - "Toggle comment on line or region without moving point." - (interactive) - (let* ((region-active (use-region-p)) - (start (if region-active (region-beginning) (line-beginning-position))) - (end (if region-active (region-end) (line-end-position)))) - (comment-or-uncomment-region start end) - (when region-active - (setq deactivate-mark nil)))) - -;; smart home (vscode-style) -(defun my-smart-home () - "Move to first non-whitespace char, or beginning of line if already there." - (interactive "^") - (let ((orig-point (point))) - (back-to-indentation) - (when (= orig-point (point)) - (move-beginning-of-line 1)))) - -;; project find text (literal search) -(defun my-project-find-text () - "Search for literal text in project." - (interactive) - (let* ((initial (when (use-region-p) - (buffer-substring-no-properties (region-beginning) (region-end)))) - (text (read-string "Search in project: " initial))) - (project-find-regexp (regexp-quote text)))) - -(defun my-project-find-word-at-point () - "Search for word under cursor in project." - (interactive) - (let ($p1 $p2 word) - (if (region-active-p) - (setq $p1 (region-beginning) $p2 (region-end)) - (save-excursion - (skip-chars-backward "-_A-Za-z0-9") - (setq $p1 (point)) - (skip-chars-forward "-_A-Za-z0-9") - (setq $p2 (point)))) - (setq word (buffer-substring-no-properties $p1 $p2)) - (when (> (length word) 0) - (project-find-regexp (regexp-quote word))))) - -;; compile custom command (persisted per-project) (defvar my-project-data-dir "~/.emacs.d/project-data/" "Directory to store per-project data.") (defun my-project-data-file (filename) @@ -631,7 +870,10 @@ Falls back to dumb-jump if xref fails." (compile cmd) (my-compile-custom)))) -;; ctags (persisted per-project) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - CTAGS +;;; ============================================================================ + (defun my-tags-get-saved () "Get saved TAGS file path for current project." (when (project-current) @@ -669,49 +911,10 @@ Falls back to dumb-jump if xref fails." (visit-tags-table tags-path) (message "TAGS generated and saved: %s" tags-path))) -;; find and replace with modes -(defun my-find-replace () - "Find and replace with mode selection: project, file, or selection." - (interactive) - (let* ((mode (completing-read "Replace in: " '("file" "project" "selection") nil t)) - (search (read-string "Find: ")) - (replace (read-string (format "Replace '%s' with: " search)))) - (cond - ((string= mode "project") - (project-query-replace-regexp (regexp-quote search) replace)) - ((string= mode "file") - (save-excursion - (goto-char (point-min)) - (query-replace search replace))) - ((string= mode "selection") - (if (use-region-p) - (query-replace search replace nil (region-beginning) (region-end)) - (message "No region selected.")))))) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - File Operations +;;; ============================================================================ -;; isearch with selection (vscode-style) -(defun my-isearch-forward () - "Start isearch, using selected text if region is active." - (interactive) - (if (use-region-p) - (let ((text (buffer-substring-no-properties (region-beginning) (region-end)))) - (deactivate-mark) - (isearch-forward nil 1) - (setq isearch-string text - isearch-message text) - (isearch-update)) - (isearch-forward))) - -;; select whole line (vscode-style) -(defun my-select-line () - "Select the current line. Repeat to select subsequent lines." - (interactive) - (if (and (use-region-p) (eq last-command 'my-select-line)) - (forward-line 1) - (move-beginning-of-line 1) - (set-mark (point)) - (forward-line 1))) - -;; open file in right pane from minibuffer (defvar my--find-file-right-pane nil) (defun my-find-file-right-pane () @@ -732,7 +935,19 @@ Falls back to dumb-jump if xref fails." (add-hook 'minibuffer-exit-hook 'my-find-file-right-pane-after) -;; theme selection +(defun my-copy-path-with-line () + "Copy the current file path with line number to clipboard." + (interactive) + (if buffer-file-name + (let ((path-with-line (format "%s:%d" buffer-file-name (line-number-at-pos)))) + (kill-new path-with-line) + (message "Copied: %s" path-with-line)) + (message "Buffer has no file."))) + +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Theme Selection +;;; ============================================================================ + (add-to-list 'custom-theme-load-path "~/.emacs.d/themes/") (defvar my-current-theme 'bedroom "Currently active theme.") @@ -756,8 +971,10 @@ Falls back to dumb-jump if xref fails." (setq my-current-theme (intern choice)) (load-theme my-current-theme t))))) -;; global zoom (without resizing window) -(setq frame-inhibit-implied-resize t) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Zoom +;;; ============================================================================ + (defvar my-default-font-height (face-attribute 'default :height)) (defun my-global-zoom-in () @@ -772,56 +989,10 @@ Falls back to dumb-jump if xref fails." (interactive) (set-face-attribute 'default nil :height my-default-font-height)) -(global-set-key (kbd "C-=") 'my-global-zoom-in) -(global-set-key (kbd "C--") 'my-global-zoom-out) -(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-") 'ignore) -(global-set-key (kbd "C-") 'ignore) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Buffer Management +;;; ============================================================================ -;; reload emacs config -(defun reload-emacs-config () - "Reload the Emacs configuration file." - (interactive) - (load-file "~/.emacs.d/init.el") - (message "Emacs config reloaded.")) - -(defun edit-emacs-config () - "Open the Emacs configuration file for editing." - (interactive) - (find-file "~/.emacs.d/init.el")) - -;; test function -(defun my-test () - (interactive) - (message "Hello world!")) - -;; duplicate line (cleanly) -;; https://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs -(defun my-duplicate-line (arg) - "Duplicate current line, leaving point in lower line." - (interactive "*p") - (setq buffer-undo-list (cons (point) buffer-undo-list)) - (let ((bol (save-excursion (beginning-of-line) (point))) - eol) - (save-excursion - (end-of-line) - (setq eol (point)) - (let ((line (buffer-substring bol eol)) - (buffer-undo-list t) - (count arg)) - (while (> count 0) - (newline) - (insert line) - (setq count (1- count))) - ) - (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))) - ) - (next-line arg)) - -;; kill all buffers except current and close other panes (defun kill-other-buffers () "Kill all buffers except the current one and close other panes." (interactive) @@ -840,69 +1011,10 @@ Falls back to dumb-jump if xref fails." (setq recentf-list nil) (delete-other-windows)) -;; delete word without copying to kill ring -(defun my-delete-word (arg) - "Delete characters forward until encountering the end of a word. -With argument ARG, do this that many times. -Does not copy to kill ring." - (interactive "p") - (delete-region (point) (progn (forward-word arg) (point)))) +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Window Management +;;; ============================================================================ -(defun my-backward-delete-word (arg) - "Delete characters backward until encountering the beginning of a word. -With argument ARG, do this that many times. -Does not copy to kill ring." - (interactive "p") - (my-delete-word (- arg))) - -(global-set-key (kbd "M-") 'my-backward-delete-word) -(global-set-key (kbd "M-d") 'my-delete-word) -(global-set-key (kbd "M-") 'my-delete-word) -(global-set-key (kbd "C-") 'my-backward-delete-word) - -;; copy current path with line number -(defun my-copy-path-with-line () - "Copy the current file path with line number to clipboard." - (interactive) - (if buffer-file-name - (let ((path-with-line (format "%s:%d" buffer-file-name (line-number-at-pos)))) - (kill-new path-with-line) - (message "Copied: %s" path-with-line)) - (message "Buffer has no file."))) - -;; select rectangle with shift+mouse -(defun my-mouse-start-rectangle (start-event) - (interactive "e") - (deactivate-mark) - (mouse-set-point start-event) - (rectangle-mark-mode +1) - (let ((drag-event)) - (track-mouse - (while (progn - (setq drag-event (read-event)) - (mouse-movement-p drag-event)) - (mouse-set-point drag-event))))) - -;; open file manager -(defun my-file-manager-command () - (interactive) - (cond ((eq system-type 'windows-nt) - (shell-command "explorer.exe .")) - ((eq system-type 'darwin) - (shell-command "open .")) - ((eq system-type 'gnu/linux) - (shell-command "setsid -f nautilus . >/dev/null 2>&1")))) - -;; open terminal or cmd prompt -(defun my-terminal-emulator-command () - (interactive) - (cond ((eq system-type 'windows-nt) - (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe"))) - (set-process-query-on-exit-flag proc nil))) - ((eq system-type 'gnu/linux) - (shell-command "setsid -f gnome-terminal . >/dev/null 2>&1")))) - -;; transpose (move) windows (defun my-transpose-windows (arg) "Transpose the buffers shown in two windows." (interactive "p") @@ -915,29 +1027,71 @@ Does not copy to kill ring." (select-window (funcall selector))) (setq arg (if (plusp arg) (1- arg) (1+ arg)))))) -;; search current word -(defun search-current-word () +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Rectangle Selection +;;; ============================================================================ + +(defun my-mouse-start-rectangle (start-event) + (interactive "e") + (deactivate-mark) + (mouse-set-point start-event) + (rectangle-mark-mode +1) + (let ((drag-event)) + (track-mouse + (while (progn + (setq drag-event (read-event)) + (mouse-movement-p drag-event)) + (mouse-set-point drag-event))))) + +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - External Tools +;;; ============================================================================ + +(defun my-file-manager-command () (interactive) - (let ($p1 $p2) - (if (region-active-p) - (setq $p1 (region-beginning) $p2 (region-end)) - (save-excursion + (cond ((eq system-type 'windows-nt) + (shell-command "explorer.exe .")) + ((eq system-type 'darwin) + (shell-command "open .")) + ((eq system-type 'gnu/linux) + (shell-command "setsid -f nautilus . >/dev/null 2>&1")))) - (skip-chars-backward "-_A-Za-z0-9") - (setq $p1 (point)) - (right-char) - (skip-chars-forward "-_A-Za-z0-9") - (setq $p2 (point)))) - (setq mark-active nil) - (when (< $p1 (point)) - (goto-char $p1)) - (isearch-mode t) - (isearch-yank-string (buffer-substring-no-properties $p1 $p2)))) +(defun my-terminal-emulator-command () + (interactive) + (cond ((eq system-type 'windows-nt) + (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe"))) + (set-process-query-on-exit-flag proc nil))) + ((eq system-type 'gnu/linux) + (shell-command "setsid -f gnome-terminal . >/dev/null 2>&1")))) -;; Tweaks / Fixes -;; Emacs sucks by default, here are some fixes. +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Emacs Config +;;; ============================================================================ -;; fix isearch +(defun reload-emacs-config () + "Reload the Emacs configuration file." + (interactive) + (load-file "~/.emacs.d/init.el") + (message "Emacs config reloaded.")) + +(defun edit-emacs-config () + "Open the Emacs configuration file for editing." + (interactive) + (find-file "~/.emacs.d/init.el")) + +;;; ============================================================================ +;;; CUSTOM FUNCTIONS - Misc +;;; ============================================================================ + +(defun my-test () + (interactive) + (message "Hello world!")) + +;;; ============================================================================ +;;; TWEAKS & FIXES +;;; ============================================================================ + +;; fix isearch wrapping behavior (defadvice isearch-search (after isearch-no-fail activate) (unless isearch-success (ad-disable-advice 'isearch-search 'after 'isearch-no-fail) @@ -946,6 +1100,7 @@ Does not copy to kill ring." (ad-enable-advice 'isearch-search 'after 'isearch-no-fail) (ad-activate 'isearch-search))) +;; go to match beginning after isearch (add-hook 'isearch-mode-end-hook #'endless/goto-match-beginning) @@ -958,8 +1113,11 @@ Use in `isearch-mode-end-hook'." (not isearch-mode-end-hook-quit)) (goto-char isearch-other-end))) -;; appearance -;; (set-face-attribute 'default nil :font "Consolas-15") +;;; ============================================================================ +;;; APPEARANCE & THEME +;;; ============================================================================ -(global-font-lock-mode 1) +;; (set-face-attribute 'default nil :font "Consolas-15") (load-theme 'bedroom t) + +;;; init.el ends here