diff --git a/init.el b/init.el index dd29ee6..aa55579 100644 --- a/init.el +++ b/init.el @@ -23,6 +23,7 @@ (require 'init-editor) ; Basic editor enhancements (require 'init-project) ; Project management with projectile (require 'init-vcs) ; Version control (diff-hl) +(require 'init-magit) ; Magit git interface (require 'init-search) ; Search tools (require 'init-dired) ; Dired configuration (require 'init-treemacs) ; Treemacs file browser @@ -39,7 +40,7 @@ ;;; Load optional configurations ;; Development configuration - Modern version with Eglot -(let ((dev-config-modern (expand-file-name "emacs-dev-config-modern.el" user-emacs-directory))) +(let ((dev-config-modern (expand-file-name "lisp/emacs-dev-config-modern.el" user-emacs-directory))) (when (file-exists-p dev-config-modern) (load-file dev-config-modern) (add-hook 'emacs-startup-hook @@ -49,24 +50,24 @@ (message "Modern development mode available. Use M-x enable-dev-mode-modern to activate."))))))) ;; Legacy development configuration (lsp-mode) - kept for compatibility -(let ((dev-config (expand-file-name "emacs-dev-config.el" user-emacs-directory))) +(let ((dev-config (expand-file-name "lisp/emacs-dev-config.el" user-emacs-directory))) (when (file-exists-p dev-config) (load-file dev-config))) ;; SHR Configuration (for HTML rendering in mu4e, elfeed, eww) -(let ((shr-config (expand-file-name "shr-config.el" user-emacs-directory))) +(let ((shr-config (expand-file-name "lisp/shr-config.el" user-emacs-directory))) (when (file-exists-p shr-config) (load-file shr-config) (message "SHR configuration loaded."))) ;; RSS Reader Configuration (Elfeed) -(let ((elfeed-config (expand-file-name "elfeed-config.el" user-emacs-directory))) +(let ((elfeed-config (expand-file-name "lisp/elfeed-config.el" user-emacs-directory))) (when (file-exists-p elfeed-config) (load-file elfeed-config) (message "Elfeed RSS reader configuration loaded."))) ;; Email Configuration (mu4e) -(let ((mu4e-config (expand-file-name "mu4e-config.el" user-emacs-directory))) +(let ((mu4e-config (expand-file-name "lisp/mu4e-config.el" user-emacs-directory))) (when (file-exists-p mu4e-config) (condition-case err (progn @@ -76,20 +77,20 @@ (message "mu4e configuration available but mu4e not installed. Install mu4e package to enable email."))))) ;; Beancount Configuration -(let ((beancount-config (expand-file-name "beancount-config.el" user-emacs-directory))) +(let ((beancount-config (expand-file-name "lisp/beancount-config.el" user-emacs-directory))) (when (file-exists-p beancount-config) (load-file beancount-config) (message "Beancount portfolio tracking configuration loaded."))) ;; Portfolio Tracker Configuration (with-eval-after-load 'tabulated-list - (let ((portfolio-tracker (expand-file-name "portfolio-tracker-v2.el" user-emacs-directory))) + (let ((portfolio-tracker (expand-file-name "lisp/portfolio-tracker-v2.el" user-emacs-directory))) (when (file-exists-p portfolio-tracker) (load-file portfolio-tracker) (message "Portfolio tracker with live prices loaded.")))) ;; Keybinding fixes for special modes -(let ((keybinding-fix (expand-file-name "keybinding-fix.el" user-emacs-directory))) +(let ((keybinding-fix (expand-file-name "lisp/keybinding-fix.el" user-emacs-directory))) (when (file-exists-p keybinding-fix) (load-file keybinding-fix) ;; Automatically apply fixes for special modes diff --git a/bungee.el b/lisp/bungee.el similarity index 100% rename from bungee.el rename to lisp/bungee.el diff --git a/developer-dark-theme.el b/lisp/developer-dark-theme.el similarity index 100% rename from developer-dark-theme.el rename to lisp/developer-dark-theme.el diff --git a/elfeed-config.el b/lisp/elfeed-config.el similarity index 91% rename from elfeed-config.el rename to lisp/elfeed-config.el index 15a5403..368c653 100644 --- a/elfeed-config.el +++ b/lisp/elfeed-config.el @@ -51,8 +51,14 @@ (lambda () (message "Feed update complete!")))) + ;; Store timer references so we can cancel them + (defvar elfeed-update-timer-30min nil + "Timer for 30-minute elfeed updates.") + ;; Auto-update feeds every 30 minutes in the background - (run-with-timer 0 (* 30 60) #'elfeed-update-async) + ;; Delayed start to avoid impacting startup performance + (setq elfeed-update-timer-30min + (run-with-timer (* 5 60) (* 30 60) #'elfeed-update-async)) ;; Custom function for fuzzy relative timestamps (defun my-elfeed-search-format-date (date) @@ -191,8 +197,35 @@ (rmh-elfeed-org-process rmh-elfeed-org-files rmh-elfeed-org-tree-id) (message "Elfeed feeds reloaded from org files. %d feeds loaded." (length elfeed-feeds)))) +;; Store timer reference for hourly updates +(defvar elfeed-update-timer-hourly nil + "Timer for hourly elfeed updates.") + ;; Update feeds every hour -(run-at-time 0 (* 60 60) 'elfeed-update) +(setq elfeed-update-timer-hourly + (run-at-time 0 (* 60 60) 'elfeed-update)) + +;; Functions to control auto-updates +(defun elfeed-stop-auto-updates () + "Stop all automatic elfeed feed updates." + (interactive) + (when (timerp elfeed-update-timer-30min) + (cancel-timer elfeed-update-timer-30min) + (setq elfeed-update-timer-30min nil)) + (when (timerp elfeed-update-timer-hourly) + (cancel-timer elfeed-update-timer-hourly) + (setq elfeed-update-timer-hourly nil)) + (message "Elfeed auto-updates stopped.")) + +(defun elfeed-start-auto-updates () + "Start automatic elfeed feed updates." + (interactive) + (elfeed-stop-auto-updates) ; Stop any existing timers first + (setq elfeed-update-timer-30min + (run-with-timer (* 5 60) (* 30 60) #'elfeed-update-async)) + (setq elfeed-update-timer-hourly + (run-at-time 0 (* 60 60) 'elfeed-update)) + (message "Elfeed auto-updates started.")) ;; Sorting functions (defun elfeed-sort-by-date-ascending () @@ -606,6 +639,22 @@ If USE-GENERIC-P is non-nil, use eww-readable after loading." (when entry (browse-url (elfeed-entry-link entry))))) +(defun elfeed-show-open-image-at-point () + "Open image at point in external viewer (useful in terminal mode)." + (interactive) + (let ((url (or (get-text-property (point) 'image-url) + (get-text-property (point) 'shr-url) + (thing-at-point 'url)))) + (if url + (progn + (if (display-graphic-p) + ;; In GUI mode, try to display inline + (browse-url url) + ;; In terminal mode, open with external viewer + (start-process "image-viewer" nil "xdg-open" url)) + (message "Opening image: %s" url)) + (message "No image found at point")))) + ;; Create ordering/sorting keymap (defvar elfeed-ordering-map (let ((map (make-sparse-keymap))) @@ -675,14 +724,23 @@ If USE-GENERIC-P is non-nil, use eww-readable after loading." (define-key elfeed-show-mode-map (kbd "E") 'elfeed-show-eww-open) (define-key elfeed-show-mode-map (kbd "R") 'elfeed-show-readable) (define-key elfeed-show-mode-map (kbd "F") 'elfeed-show-toggle-full-article) - (define-key elfeed-show-mode-map (kbd "B") 'elfeed-open-in-browser)) + (define-key elfeed-show-mode-map (kbd "B") 'elfeed-open-in-browser) + (define-key elfeed-show-mode-map (kbd "I") 'elfeed-show-open-image-at-point)) ;; Disable line numbers in elfeed buffers and increase font size (add-hook 'elfeed-show-mode-hook (lambda () (display-line-numbers-mode -1) (setq-local display-line-numbers nil) - (text-scale-set 1))) ; Increase font size by 1 step + (text-scale-set 1) ; Increase font size by 1 step + ;; Handle images based on display type + (if (display-graphic-p) + ;; GUI mode - show images inline + (progn + (setq-local shr-inhibit-images nil) + (setq-local shr-blocked-images nil)) + ;; Terminal mode - show placeholders + (setq-local shr-inhibit-images t)))) (add-hook 'elfeed-search-mode-hook (lambda () diff --git a/emacs-dev-config-modern.el b/lisp/emacs-dev-config-modern.el similarity index 93% rename from emacs-dev-config-modern.el rename to lisp/emacs-dev-config-modern.el index 7968840..7955599 100644 --- a/emacs-dev-config-modern.el +++ b/lisp/emacs-dev-config-modern.el @@ -180,9 +180,9 @@ (global-set-key (kbd "") 'compile) (global-set-key (kbd "") 'recompile) - ;; Testing - (global-set-key (kbd "C-c t p") 'projectile-test-project) - (global-set-key (kbd "C-c t f") 'projectile-test-file) + ;; Testing - use C-c C-t prefix to avoid conflict with CUA copy + (global-set-key (kbd "C-c C-t p") 'projectile-test-project) + (global-set-key (kbd "C-c C-t f") 'projectile-test-file) ;; Navigation (global-set-key (kbd "M-.") 'xref-find-definitions) @@ -212,8 +212,11 @@ ;; Load tree-sitter if available (when (file-exists-p (expand-file-name "lisp/init-treesitter.el" user-emacs-directory)) (require 'init-treesitter)) + ;; Stop elfeed auto-updates to prevent UI lag + (when (fboundp 'elfeed-stop-auto-updates) + (elfeed-stop-auto-updates)) (setq dev-mode-modern-enabled t) - (message "Modern development mode enabled! Eglot will auto-start for supported files."))) + (message "Modern development mode enabled! Eglot will auto-start for supported files. Elfeed auto-updates disabled."))) ;;;###autoload (defun disable-dev-mode-modern () @@ -228,8 +231,11 @@ ;; Disable some modes (yas-global-mode -1) (global-flycheck-mode -1) + ;; Re-enable elfeed auto-updates + (when (fboundp 'elfeed-start-auto-updates) + (elfeed-start-auto-updates)) (setq dev-mode-modern-enabled nil) - (message "Modern development mode disabled."))) + (message "Modern development mode disabled. Elfeed auto-updates re-enabled."))) (provide 'emacs-dev-config-modern) ;;; emacs-dev-config-modern.el ends here \ No newline at end of file diff --git a/emacs-dev-config.el b/lisp/emacs-dev-config.el similarity index 94% rename from emacs-dev-config.el rename to lisp/emacs-dev-config.el index e154c11..aed9e43 100644 --- a/emacs-dev-config.el +++ b/lisp/emacs-dev-config.el @@ -478,10 +478,11 @@ (defun dev-mode-setup-keybindings () "Set up development-specific keybindings." - (global-set-key (kbd "C-c t c") 'generate-cpp-tags) - (global-set-key (kbd "C-c t p") 'generate-python-tags) - (global-set-key (kbd "C-c t a") 'generate-all-tags) - (global-set-key (kbd "C-c q") 'quick-compile-and-run) + ;; Tag generation - use C-c C-t prefix to avoid conflict with CUA copy + (global-set-key (kbd "C-c C-t c") 'generate-cpp-tags) + (global-set-key (kbd "C-c C-t p") 'generate-python-tags) + (global-set-key (kbd "C-c C-t a") 'generate-all-tags) + (global-set-key (kbd "C-c C-q") 'quick-compile-and-run) (global-set-key (kbd "M-.") 'xref-find-definitions) (global-set-key (kbd "M-,") 'xref-pop-marker-stack) (global-set-key (kbd "C-M-.") 'xref-find-references) @@ -502,19 +503,25 @@ (interactive) (with-output-to-temp-buffer "*Development Mode Help*" (princ "=== Development Mode Key Bindings ===\n\n") + (princ "EDITING (CUA MODE):\n") + (princ " C-c : Copy\n") + (princ " C-v : Paste\n") + (princ " C-x : Cut\n") + (princ " C-z : Undo\n") + (princ " C- : Rectangle selection\n\n") (princ "LSP COMMANDS:\n") (princ " C-c l : LSP prefix for all LSP commands\n") (princ " M-. : Go to definition\n") (princ " M-, : Return from definition\n") (princ " C-M-. : Find references\n\n") (princ "TAGS & NAVIGATION:\n") - (princ " C-c t c : Generate C++ TAGS file\n") - (princ " C-c t p : Generate Python TAGS file\n") - (princ " C-c t a : Generate TAGS for all files\n\n") + (princ " C-c C-t c : Generate C++ TAGS file\n") + (princ " C-c C-t p : Generate Python TAGS file\n") + (princ " C-c C-t a : Generate TAGS for all files\n\n") (princ "COMPILATION & EXECUTION:\n") (princ " C-c c : Compile current file\n") (princ " C-c r : Run (GDB for C++, Python REPL for Python)\n") - (princ " C-c q : Quick compile and run\n") + (princ " C-c C-q : Quick compile and run\n") (princ " C-c C-c : Recompile (C++) or Send buffer to Python\n\n") (princ "PROJECT MANAGEMENT:\n") (princ " C-c p : Projectile commands prefix\n\n") @@ -574,8 +581,11 @@ (add-to-list 'auto-mode-alist '("\\.qml\\'" . qml-mode)) ;; Set up help command (global-set-key (kbd "C-c h") 'show-dev-mode-help) + ;; Stop elfeed auto-updates to prevent UI lag + (when (fboundp 'elfeed-stop-auto-updates) + (elfeed-stop-auto-updates)) (setq dev-mode-enabled t) - (message "Development mode enabled! Press C-c h for help. QML files will use qml-mode."))) + (message "Development mode enabled! Press C-c h for help. QML files will use qml-mode. Elfeed auto-updates disabled."))) ;;;###autoload (defun disable-dev-mode () @@ -590,9 +600,12 @@ (yas-global-mode -1) (projectile-mode -1) (global-hl-todo-mode -1) + ;; Re-enable elfeed auto-updates + (when (fboundp 'elfeed-start-auto-updates) + (elfeed-start-auto-updates)) ;; Note: Some modes might require restarting Emacs to fully disable (setq dev-mode-enabled nil) - (message "Development mode disabled. Some features may require restarting Emacs to fully disable."))) + (message "Development mode disabled. Elfeed auto-updates re-enabled. Some features may require restarting Emacs to fully disable."))) ;;;###autoload (defun dev-mode-status () diff --git a/god-mode-config.el b/lisp/god-mode-config.el similarity index 100% rename from god-mode-config.el rename to lisp/god-mode-config.el diff --git a/init-bungee.el b/lisp/init-bungee.el similarity index 100% rename from init-bungee.el rename to lisp/init-bungee.el diff --git a/lisp/init-completion.el b/lisp/init-completion.el index c72eec2..bdbe076 100644 --- a/lisp/init-completion.el +++ b/lisp/init-completion.el @@ -167,6 +167,38 @@ (corfu-on-exact-match nil) ;; Configure handling of exact matches (corfu-scroll-margin 5) ;; Use scroll margin + :config + ;; Fix font issues with Corfu child frames + (defun corfu--fix-child-frame-font (frame) + "Ensure child frames don't inherit problematic font specs." + frame) + + ;; Override the frame parameters to avoid font issues + (setq corfu--frame-parameters + '((no-accept-focus . t) + (no-focus-on-map . t) + (min-width . t) + (min-height . t) + (border-width . 0) + (outer-border-width . 0) + (internal-border-width . 1) + (child-frame-border-width . 1) + (left-fringe . 7) + (right-fringe . 7) + (vertical-scroll-bars) + (horizontal-scroll-bars) + (menu-bar-lines . 0) + (tool-bar-lines . 0) + (tab-bar-lines . 0) + (tab-bar-lines-keep-state . t) + (no-other-frame . t) + (unsplittable . t) + (undecorated . t) + (cursor-type) + (no-special-glyphs . t) + (desktop-dont-save . t) + (inhibit-double-buffering . t))) + :init (global-corfu-mode)) @@ -194,7 +226,10 @@ (let ((root (or (projectile-project-root) default-directory))) (consult-ripgrep root))) +;; Quick access to ripgrep - C-c r for backward compatibility (global-set-key (kbd "C-c r") 'consult-ripgrep-project-root) +;; Additional quick binding for project search +(global-set-key (kbd "C-c /") 'consult-ripgrep-project-root) ;;; Make completion work nicely with Projectile (with-eval-after-load 'projectile diff --git a/lisp/init-editor.el b/lisp/init-editor.el index 9bc3ca8..73ae12f 100644 --- a/lisp/init-editor.el +++ b/lisp/init-editor.el @@ -16,17 +16,107 @@ (global-set-key (kbd "C-") 'left-word) (global-set-key (kbd "C-") 'right-word) -;; Word selection with C-Shift-left/right -(global-set-key (kbd "C-S-") 'left-word) -(global-set-key (kbd "C-S-") 'right-word) +;; Custom functions for shift-selection with word movement +(defun left-word-select () + "Move left by words, extending selection." + (interactive "^") + (left-word)) -;; Make sure shift-selection works with these commands -(put 'left-word 'CUA 'move) -(put 'right-word 'CUA 'move) +(defun right-word-select () + "Move right by words, extending selection." + (interactive "^") + (right-word)) + +;; Word selection with C-Shift-left/right +(global-set-key (kbd "C-S-") 'left-word-select) +(global-set-key (kbd "C-S-") 'right-word-select) + +;; Mark these functions as shift-selectable +(put 'left-word 'shift-selection-mode t) +(put 'right-word 'shift-selection-mode t) +(put 'left-word-select 'shift-selection-mode t) +(put 'right-word-select 'shift-selection-mode t) + +;; Additional selection keybindings for consistency +;; Shift+Home/End to select to beginning/end of line +(global-set-key (kbd "S-") 'beginning-of-line-select) +(global-set-key (kbd "S-") 'end-of-line-select) + +(defun beginning-of-line-select () + "Move to beginning of line, extending selection." + (interactive "^") + (beginning-of-line)) + +(defun end-of-line-select () + "Move to end of line, extending selection." + (interactive "^") + (end-of-line)) + +;; Ctrl+Shift+Home/End to select to beginning/end of buffer +(global-set-key (kbd "C-S-") 'beginning-of-buffer-select) +(global-set-key (kbd "C-S-") 'end-of-buffer-select) + +(defun beginning-of-buffer-select () + "Move to beginning of buffer, extending selection." + (interactive "^") + (beginning-of-buffer)) + +(defun end-of-buffer-select () + "Move to end of buffer, extending selection." + (interactive "^") + (end-of-buffer)) + +;; Ensure shift-arrow keys work for character selection +(global-set-key (kbd "S-") 'left-char-select) +(global-set-key (kbd "S-") 'right-char-select) +(global-set-key (kbd "S-") 'previous-line-select) +(global-set-key (kbd "S-") 'next-line-select) + +(defun left-char-select () + "Move left by character, extending selection." + (interactive "^") + (left-char)) + +(defun right-char-select () + "Move right by character, extending selection." + (interactive "^") + (right-char)) + +(defun previous-line-select () + "Move up by line, extending selection." + (interactive "^") + (previous-line)) + +(defun next-line-select () + "Move down by line, extending selection." + (interactive "^") + (next-line)) ;;; Text manipulation (global-set-key (kbd "C-") 'cua-set-rectangle-mark) +;; Diagnostic function for selection keybindings +(defun diagnose-selection-keys () + "Check if selection keybindings are properly configured." + (interactive) + (with-output-to-temp-buffer "*Selection Keys Diagnostics*" + (princ "=== SELECTION KEYBINDINGS DIAGNOSTICS ===\n\n") + (princ (format "Shift-select mode: %s\n" (if shift-select-mode "ENABLED" "DISABLED"))) + (princ (format "Transient mark mode: %s\n\n" (if transient-mark-mode "ENABLED" "DISABLED"))) + (princ "Word selection keys:\n") + (princ (format " C-S-: %s\n" (key-binding (kbd "C-S-")))) + (princ (format " C-S-: %s\n\n" (key-binding (kbd "C-S-")))) + (princ "Character selection keys:\n") + (princ (format " S-: %s\n" (key-binding (kbd "S-")))) + (princ (format " S-: %s\n" (key-binding (kbd "S-")))) + (princ (format " S-: %s\n" (key-binding (kbd "S-")))) + (princ (format " S-: %s\n\n" (key-binding (kbd "S-")))) + (princ "Line selection keys:\n") + (princ (format " S-: %s\n" (key-binding (kbd "S-")))) + (princ (format " S-: %s\n\n" (key-binding (kbd "S-")))) + (princ "If keys are not bound correctly, reload with:\n") + (princ " M-x reload-emacs-config\n"))) + ;;; Anzu - show match information in mode line (use-package anzu :ensure t diff --git a/lisp/init-magit.el b/lisp/init-magit.el new file mode 100644 index 0000000..145aee0 --- /dev/null +++ b/lisp/init-magit.el @@ -0,0 +1,78 @@ +;;; init-magit.el --- Magit configuration -*- lexical-binding: t -*- +;;; Commentary: +;;; Git interface configuration with Magit + +;;; Code: + +(use-package magit + :ensure t + :defer t + :bind (("C-x g" . magit-status) + ("C-x M-g" . magit-dispatch) + ("C-c g" . magit-file-dispatch)) + :config + (setq magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1) + + ;; Performance improvements + (setq magit-refresh-status-buffer nil) + (setq magit-diff-highlight-indentation nil) + (setq magit-diff-highlight-trailing nil) + + ;; Custom function to save commits as patches + (defun magit-save-commit-as-patch () + "Save the commit at point as a patch file." + (interactive) + (let* ((commit (or (magit-commit-at-point) + (error "No commit at point"))) + (default-name (format "%s.patch" + (substring commit 0 (min 8 (length commit))))) + (file (read-file-name "Save patch to file: " + default-directory + default-name + nil + default-name)) + (default-directory (magit-toplevel))) + (if (zerop (shell-command + (format "git format-patch -1 %s --stdout > %s" + (shell-quote-argument commit) + (shell-quote-argument (expand-file-name file))))) + (message "Patch saved to %s" file) + (error "Failed to save patch")))) + + ;; Bind C-c C-p in all relevant Magit modes + (define-key magit-revision-mode-map (kbd "C-c C-p") 'magit-save-commit-as-patch) + (define-key magit-log-mode-map (kbd "C-c C-p") 'magit-save-commit-as-patch) + (define-key magit-log-select-mode-map (kbd "C-c C-p") 'magit-save-commit-as-patch) + + ;; Also add to cherry mode and refs mode + (with-eval-after-load 'magit-refs + (define-key magit-refs-mode-map (kbd "C-c C-p") 'magit-save-commit-as-patch)) + (with-eval-after-load 'magit-cherry + (define-key magit-cherry-mode-map (kbd "C-c C-p") 'magit-save-commit-as-patch))) + +;; Ensure keybindings persist through hooks +(add-hook 'magit-revision-mode-hook + (lambda () (local-set-key (kbd "C-c C-p") 'magit-save-commit-as-patch))) +(add-hook 'magit-log-mode-hook + (lambda () (local-set-key (kbd "C-c C-p") 'magit-save-commit-as-patch))) +(add-hook 'magit-log-select-mode-hook + (lambda () (local-set-key (kbd "C-c C-p") 'magit-save-commit-as-patch))) +(add-hook 'magit-refs-mode-hook + (lambda () (local-set-key (kbd "C-c C-p") 'magit-save-commit-as-patch))) +(add-hook 'magit-cherry-mode-hook + (lambda () (local-set-key (kbd "C-c C-p") 'magit-save-commit-as-patch))) + +;; Optional: Magit-delta for better diffs (if delta is installed) +(when (executable-find "delta") + (use-package magit-delta + :ensure t + :defer t + :hook (magit-mode . magit-delta-mode))) + +;; Integration with diff-hl if available +(with-eval-after-load 'diff-hl + (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh) + (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh)) + +(provide 'init-magit) +;;; init-magit.el ends here \ No newline at end of file diff --git a/lisp/init-performance.el b/lisp/init-performance.el new file mode 100644 index 0000000..43ba4c1 --- /dev/null +++ b/lisp/init-performance.el @@ -0,0 +1,206 @@ +;;; init-performance.el --- Performance optimizations and fixes -*- lexical-binding: t -*- +;;; Commentary: +;;; Comprehensive performance optimizations to prevent UI freezing, lag, and other issues + +;;; Code: + +;;;; Garbage Collection Optimizations +;; Increase garbage collection threshold during startup +(setq gc-cons-threshold (* 100 1024 1024)) ; 100MB +(setq gc-cons-percentage 0.6) + +;; Reset after startup +(add-hook 'emacs-startup-hook + (lambda () + (setq gc-cons-threshold (* 16 1024 1024)) ; 16MB + (setq gc-cons-percentage 0.1))) + +;;;; File Watching and Auto-revert Optimizations +(setq auto-revert-interval 5) ; Check every 5 seconds instead of 1 +(setq auto-revert-use-notify t) ; Use file system notifications +(setq auto-revert-avoid-polling t) ; Don't poll, use notifications +(setq global-auto-revert-non-file-buffers nil) ; Don't auto-revert non-file buffers + +;;;; Display and Rendering Optimizations +(setq idle-update-delay 2.0) ; Default is 0.5 +(setq redisplay-dont-pause t) ; Never pause redisplay +(setq fast-but-imprecise-scrolling t) ; Faster scrolling +(setq inhibit-compacting-font-caches t) ; Don't compact font caches during GC + +;; Font-lock optimizations +(setq jit-lock-defer-time 0.05) ; Slightly defer font-locking +(setq jit-lock-stealth-time 5) ; Wait 5 seconds before stealth fontification +(setq jit-lock-chunk-size 1000) ; Smaller chunks +(setq jit-lock-stealth-load 20) ; Don't fontify when load is high + +;; Disable bidirectional text rendering for performance +(setq-default bidi-display-reordering nil) +(setq-default bidi-paragraph-direction 'left-to-right) + +;; Optimize long line handling +(setq-default truncate-lines t) +(setq line-move-visual nil) + +;;;; Memory and Process Optimizations +(setq undo-limit 80000) ; Default is 160000 +(setq undo-strong-limit 120000) ; Default is 240000 +(setq undo-outer-limit 12000000) ; Default is 24000000 +(setq read-process-output-max (* 1024 1024)) ; 1MB, default is 4096 + +;;;; X11 Specific Optimizations (for no-toolkit builds) +(when (and (display-graphic-p) + (not (memq window-system '(ns mac w32)))) + ;; More aggressive redrawing for X11 + (setq idle-update-delay 0.1) ; Faster idle updates + (setq redisplay-skip-fontification-on-input nil)) ; Don't skip font-lock + +;;;; Timer Management Functions +(defun clear-duplicate-idle-timers () + "Remove duplicate idle timers that may be causing performance issues." + (let ((seen-timers '())) + (dolist (timer timer-idle-list) + (let ((timer-func (timer--function timer))) + (if (member timer-func seen-timers) + (cancel-timer timer) + (push timer-func seen-timers)))))) + +(defun disable-qml-timers () + "Disable QML idle timers." + (dolist (timer timer-idle-list) + (when (and (timer--function timer) + (eq (timer--function timer) 'qml-timer-handler)) + (cancel-timer timer)))) + +;; Run timer cleanup on load +(clear-duplicate-idle-timers) +(disable-qml-timers) + +;;;; Mode-specific Performance Fixes + +;; Disable DAP mode if it's somehow enabled (causes major lag) +(when (boundp 'dap-mode) + (dap-mode -1)) +(when (boundp 'dap-ui-mode) + (dap-ui-mode -1)) +(when (boundp 'dap-auto-configure-mode) + (dap-auto-configure-mode -1)) + +;; Disable LSP-UI doc if causing issues +(when (boundp 'lsp-ui-doc-mode) + (setq lsp-ui-doc-enable nil)) + +;; Prevent QML timers from being created +(with-eval-after-load 'qml-mode + (remove-hook 'qml-mode-hook 'qml-start-timer-handler) + (fset 'qml-timer-handler 'ignore) + (fset 'qml-start-timer-handler 'ignore)) + +;; Prevent LSP from activating in QML files +(with-eval-after-load 'lsp-mode + ;; Remove QML mode from LSP's activation list + (setq lsp--major-modes-for-activate + (delete 'qml-mode lsp--major-modes-for-activate)) + ;; Advise lsp-deferred to skip QML files + (defadvice lsp-deferred (around no-lsp-for-qml activate) + "Prevent LSP from starting in QML mode." + (unless (eq major-mode 'qml-mode) + ad-do-it))) + +;;;; Large File Handling +(defun my-large-file-hook () + "Disable expensive features in large files." + (when (> (buffer-size) (* 1024 1024)) ; Files larger than 1MB + (setq-local line-number-mode nil) + (setq-local column-number-mode nil) + (setq-local show-paren-mode nil) + (setq-local font-lock-mode nil) + (setq-local bidi-display-reordering nil))) + +(defun check-large-file-performance () + "Disable expensive features in large files (512KB threshold)." + (when (> (buffer-size) (* 512 1024)) ; Files larger than 512KB + (when (bound-and-true-p rainbow-delimiters-mode) + (rainbow-delimiters-mode -1)) + (when (bound-and-true-p diff-hl-mode) + (diff-hl-mode -1)) + (when (bound-and-true-p undo-tree-mode) + (undo-tree-mode -1)))) + +(add-hook 'find-file-hook 'my-large-file-hook) +(add-hook 'find-file-hook 'check-large-file-performance) + +;; Prevent timer accumulation when killing buffers +(add-hook 'kill-buffer-hook + (lambda () + (when (derived-mode-p 'qml-mode) + (disable-qml-timers)))) + +;;;; Manual Performance Control Functions + +(defun force-redraw () + "Force a complete redraw of the frame." + (interactive) + (redraw-frame)) + +(defun force-redraw-all () + "Force redraw of all frames and windows." + (interactive) + (dolist (frame (frame-list)) + (redraw-frame frame)) + (redisplay t)) + +(defun fix-performance-now () + "Fix all known performance issues immediately." + (interactive) + ;; Disable DAP + (when (boundp 'dap-mode) (dap-mode -1)) + (when (boundp 'dap-ui-mode) (dap-ui-mode -1)) + (when (boundp 'dap-auto-configure-mode) (dap-auto-configure-mode -1)) + + ;; Clear timers + (clear-duplicate-idle-timers) + (disable-qml-timers) + + ;; Force garbage collection + (garbage-collect) + + (message "Performance fixes applied!")) + +(defun diagnose-performance () + "Show information about potential performance issues." + (interactive) + (with-current-buffer (get-buffer-create "*Performance Diagnostic*") + (erase-buffer) + (insert "=== Emacs Performance Diagnostic ===\n\n") + (insert (format "Garbage Collection Threshold: %s\n" gc-cons-threshold)) + (insert (format "Garbage Collection Percentage: %s\n" gc-cons-percentage)) + (insert (format "Auto-revert interval: %s\n" auto-revert-interval)) + (insert (format "Number of buffers: %s\n" (length (buffer-list)))) + (insert (format "Active minor modes: %s\n" + (mapconcat 'symbol-name + (delq nil (mapcar (lambda (m) (and (boundp m) (symbol-value m) m)) + minor-mode-list)) + ", "))) + (insert "\n=== Active Timers ===\n") + (dolist (timer timer-list) + (insert (format "%s\n" timer))) + (insert "\n=== Idle Timers ===\n") + (dolist (timer timer-idle-list) + (insert (format "%s\n" timer))) + (switch-to-buffer (current-buffer)))) + +;;;; Keybindings for Performance Control +(global-set-key (kbd "C-c r r") 'force-redraw) +(global-set-key (kbd "C-c r a") 'force-redraw-all) +(global-set-key (kbd "C-c p f") 'fix-performance-now) +(global-set-key (kbd "C-c p d") 'diagnose-performance) + +;;;; Window Configuration Hook +(add-hook 'window-configuration-change-hook + (lambda () + (when (and (display-graphic-p) + (not (memq window-system '(ns mac w32)))) + (redisplay)))) + +(provide 'init-performance) +;;; init-performance.el ends here \ No newline at end of file diff --git a/lisp/init-search.el b/lisp/init-search.el index 2230d81..5b751c8 100644 --- a/lisp/init-search.el +++ b/lisp/init-search.el @@ -9,7 +9,7 @@ :ensure t :defer t :commands deadgrep - :bind (("C-c r" . deadgrep))) + :bind (("C-c d g" . deadgrep))) ;;; Wgrep - editable grep buffers (use-package wgrep @@ -26,5 +26,166 @@ :defer t :commands (ripgrep-regexp)) +;;; Live search functions using consult-ripgrep +(with-eval-after-load 'consult + (defun search-project-for-symbol-at-point () + "Search project for symbol at point using consult-ripgrep." + (interactive) + (require 'projectile) + (if (use-region-p) + (consult-ripgrep (projectile-project-root) + (buffer-substring-no-properties (region-beginning) (region-end))) + (consult-ripgrep (projectile-project-root) (thing-at-point 'symbol)))) + + (defun search-project () + "Live search in project files using consult-ripgrep." + (interactive) + (require 'projectile) + (consult-ripgrep (projectile-project-root))) + + (defun search-current-directory () + "Live search in current directory using consult-ripgrep." + (interactive) + (consult-ripgrep default-directory))) + +;;; Enhanced grep with live preview +(use-package consult + :defer t + :config + ;; Configure ripgrep arguments for better results + (setq consult-ripgrep-args + "rg --null --line-buffered --color=never --max-columns=1000 --path-separator / --smart-case --no-heading --with-filename --line-number --search-zip") + + ;; Preview at point for grep commands + (consult-customize + consult-ripgrep consult-git-grep consult-grep + :preview-key '(:debounce 0.4 any))) + +;;; Set up search keymap +(define-prefix-command 'search-map) +(global-set-key (kbd "C-c s") 'search-map) + +;;; Convenient keybindings for search - using deferred loading +(define-key search-map (kbd "p") + (lambda () (interactive) + (require 'consult) + (require 'projectile) + (if (fboundp 'search-project) + (call-interactively 'search-project) + (consult-ripgrep (projectile-project-root))))) + +(define-key search-map (kbd "s") + (lambda () (interactive) + (require 'consult) + (require 'projectile) + (if (fboundp 'search-project-for-symbol-at-point) + (call-interactively 'search-project-for-symbol-at-point) + (consult-ripgrep (projectile-project-root) (thing-at-point 'symbol))))) + +(define-key search-map (kbd "d") + (lambda () (interactive) + (require 'consult) + (consult-ripgrep default-directory))) + +(define-key search-map (kbd "r") + (lambda () (interactive) + (require 'consult) + (call-interactively 'consult-ripgrep))) + +(define-key search-map (kbd "g") + (lambda () (interactive) + (require 'consult) + (call-interactively 'consult-grep))) + +(define-key search-map (kbd "G") + (lambda () (interactive) + (require 'consult) + (call-interactively 'consult-git-grep))) + +(define-key search-map (kbd "l") + (lambda () (interactive) + (require 'consult) + (call-interactively 'consult-line))) + +(define-key search-map (kbd "L") + (lambda () (interactive) + (require 'consult) + (call-interactively 'consult-line-multi))) + +(define-key search-map (kbd "o") + (lambda () (interactive) + (require 'consult) + (call-interactively 'consult-outline))) + +;;; Alternative: Helm-ag for live search (if you prefer helm) +;; Uncomment if you want to use helm-ag instead +;; (use-package helm-ag +;; :ensure t +;; :defer t +;; :config +;; (setq helm-ag-base-command "rg --vimgrep --no-heading --smart-case")) + +;;; Ag (The Silver Searcher) - alternative to ripgrep +(use-package ag + :ensure t + :defer t + :commands (ag ag-project ag-regexp) + :config + (setq ag-highlight-search t) + (setq ag-reuse-buffers t)) + +;;; Rg.el - Another ripgrep interface +(use-package rg + :ensure t + :defer t + :commands (rg rg-project rg-dwim) + :config + (rg-enable-default-bindings)) + +;;; Search and replace across project +(defun project-search-and-replace (search-string replace-string) + "Search for SEARCH-STRING and replace with REPLACE-STRING in project." + (interactive + (list (read-string "Search: " (thing-at-point 'symbol)) + (read-string "Replace: "))) + (let ((project-root (projectile-project-root))) + (rg search-string "*" project-root) + (with-current-buffer "*rg*" + (wgrep-change-to-wgrep-mode) + (goto-char (point-min)) + (while (re-search-forward search-string nil t) + (replace-match replace-string)) + (wgrep-finish-edit)))) + +(define-key search-map (kbd "R") 'project-search-and-replace) + +;;; Help function to show all search keybindings +(defun show-search-help () + "Show available search commands and keybindings." + (interactive) + (with-output-to-temp-buffer "*Search Commands Help*" + (princ "=== SEARCH COMMANDS ===\n\n") + (princ "LIVE SEARCH (with preview):\n") + (princ " C-c s p : Search in project files (live)\n") + (princ " C-c s s : Search project for symbol at point\n") + (princ " C-c s d : Search in current directory\n") + (princ " C-c s r : Consult ripgrep (specify directory)\n") + (princ " C-c s l : Search lines in current buffer\n") + (princ " C-c s L : Search lines in multiple buffers\n") + (princ " C-c s o : Search outline/headings in buffer\n\n") + (princ "OTHER SEARCH TOOLS:\n") + (princ " C-c s g : Consult grep\n") + (princ " C-c s G : Consult git-grep\n") + (princ " C-c d g : Deadgrep (ripgrep with nice UI)\n") + (princ " C-c s R : Project search and replace\n") + (princ " M-s . : isearch symbol at point\n\n") + (princ "TIPS:\n") + (princ " - In consult-ripgrep, use '#pattern' to filter results\n") + (princ " - Use C-SPC to preview different results\n") + (princ " - In deadgrep results, press 'r' to enable wgrep mode for editing\n"))) + +(define-key search-map (kbd "h") 'show-search-help) +(define-key search-map (kbd "?") 'show-search-help) + (provide 'init-search) ;;; init-search.el ends here \ No newline at end of file diff --git a/lisp/init-seq-fix.el b/lisp/init-seq-fix.el new file mode 100644 index 0000000..5dbd9b6 --- /dev/null +++ b/lisp/init-seq-fix.el @@ -0,0 +1,74 @@ +;;; init-seq-fix.el --- Fix seq library issues -*- lexical-binding: t -*- +;;; Commentary: +;;; Fix for cl-no-applicable-method errors with seq-empty-p +;;; This particularly affects Emacs 31 development versions + +;;; Code: + +;; Ensure seq library is properly loaded +(require 'seq) +(require 'cl-lib) +(require 'cl-generic) ; Needed for method dispatch in Emacs 31 + +;; Fix potential issues with seq-empty-p being called on strings +;; This can happen with input methods or certain packages +(defadvice seq-empty-p (before fix-string-input activate) + "Handle string inputs that should be converted to sequences." + (when (and (ad-get-arg 0) + (stringp (ad-get-arg 0)) + (not (sequencep (ad-get-arg 0)))) + (ad-set-arg 0 (append (ad-get-arg 0) nil)))) + +;; Alternative fix: Override seq-empty-p to handle strings properly +(with-eval-after-load 'seq + (defun seq-empty-p-fixed (orig-fun sequence) + "Fixed version of seq-empty-p that handles strings." + (cond + ((stringp sequence) (string-empty-p sequence)) + ((sequencep sequence) (funcall orig-fun sequence)) + (t (funcall orig-fun sequence)))) + + ;; Only apply if we're having issues + (when (condition-case nil + (progn (seq-empty-p "test") nil) + (error t)) + (advice-add 'seq-empty-p :around #'seq-empty-p-fixed))) + +;; Ensure proper loading order for seq-related packages +(with-eval-after-load 'company + (require 'seq)) + +(with-eval-after-load 'lsp-mode + (require 'seq)) + +;; Fix for input method issues that might trigger this error +(setq default-input-method nil) + +;; Specific fix for the "latin" string issue +;; This often comes from font or input method configurations +(with-eval-after-load 'mule + (when (and (boundp 'current-input-method) + (stringp current-input-method) + (string= current-input-method "latin")) + (setq current-input-method nil))) + +;; Prevent problematic input method activation +(defadvice activate-input-method (before check-input-method activate) + "Prevent activation of problematic input methods." + (when (and (ad-get-arg 0) + (stringp (ad-get-arg 0)) + (string= (ad-get-arg 0) "latin")) + (ad-set-arg 0 nil))) + +;; Ensure strings are properly handled in various contexts +(defun ensure-seq-compatibility () + "Ensure seq library compatibility across Emacs." + (unless (fboundp 'string-empty-p) + (defun string-empty-p (string) + "Check whether STRING is empty." + (string= string "")))) + +(ensure-seq-compatibility) + +(provide 'init-seq-fix) +;;; init-seq-fix.el ends here \ No newline at end of file diff --git a/lisp/init-ui.el b/lisp/init-ui.el index 5ebc3e6..4b198d3 100644 --- a/lisp/init-ui.el +++ b/lisp/init-ui.el @@ -15,10 +15,135 @@ (show-paren-mode 1) (setq show-paren-delay 0) -;; CUA mode for rectangles - use selection mode only to avoid conflicts -(cua-selection-mode t) ; Only rectangle selection, not full CUA bindings +;; Enable syntax highlighting globally +(global-font-lock-mode t) +(setq font-lock-maximum-decoration t) +(setq font-lock-support-mode 'jit-lock-mode) +(setq jit-lock-contextually t) +(setq jit-lock-stealth-time 5) + +;; Enable full CUA mode for standard copy/paste/cut +;; This provides C-c (copy), C-v (paste), C-x (cut), C-z (undo) +(setq cua-enable-cua-keys t) (setq cua-auto-tabify-rectangles nil) (setq cua-keep-region-after-copy t) +;; Make CUA mode work properly with other keybindings +(setq cua-prefix-override-inhibit-delay 0.001) +(cua-mode t) + +;; Function to ensure CUA bindings work properly +(defun ensure-cua-bindings () + "Ensure CUA mode bindings are properly set." + (interactive) + ;; Force CUA mode to be on + (cua-mode 1) + ;; Ensure the keybindings are active + (setq cua-enable-cua-keys t) + (message "CUA bindings reinforced: C-c (copy), C-v (paste), C-x (cut), C-z (undo)")) + +;; Run this after all init files are loaded +(add-hook 'after-init-hook 'ensure-cua-bindings) + +;; Ensure CUA works in programming modes +(add-hook 'prog-mode-hook + (lambda () + (when (not cua-mode) + (cua-mode 1)) + (local-set-key (kbd "C-c") nil) ; Clear any local C-c binding + (local-set-key (kbd "C-v") nil) ; Clear any local C-v binding + )) + +;; Function to fix syntax highlighting in current buffer +(defun fix-syntax-highlighting () + "Fix syntax highlighting in the current buffer." + (interactive) + (font-lock-mode -1) + (font-lock-mode 1) + (font-lock-fontify-buffer) + (message "Syntax highlighting refreshed")) + +;; Function to switch between tree-sitter and regular modes +(defun toggle-tree-sitter-mode () + "Toggle between tree-sitter and regular mode for current buffer." + (interactive) + (cond + ((eq major-mode 'c-ts-mode) + (c-mode) + (message "Switched to regular c-mode")) + ((eq major-mode 'c++-ts-mode) + (c++-mode) + (message "Switched to regular c++-mode")) + ((eq major-mode 'c-mode) + (if (fboundp 'c-ts-mode) + (progn (c-ts-mode) + (message "Switched to c-ts-mode")) + (message "Tree-sitter mode not available"))) + ((eq major-mode 'c++-mode) + (if (fboundp 'c++-ts-mode) + (progn (c++-ts-mode) + (message "Switched to c++-ts-mode")) + (message "Tree-sitter mode not available"))) + (t (message "Not in a C/C++ buffer")))) + +;; Function to diagnose syntax highlighting issues +(defun diagnose-syntax-highlighting () + "Diagnose syntax highlighting issues in current buffer." + (interactive) + (with-output-to-temp-buffer "*Syntax Highlighting Diagnostics*" + (princ "=== SYNTAX HIGHLIGHTING DIAGNOSTICS ===\n\n") + (princ (format "Buffer: %s\n" (buffer-name))) + (princ (format "Major mode: %s\n" major-mode)) + (princ (format "Font-lock mode: %s\n" (if font-lock-mode "ENABLED" "DISABLED"))) + (princ (format "Global font-lock mode: %s\n" (if global-font-lock-mode "ENABLED" "DISABLED"))) + (princ (format "Font-lock keywords defined: %s\n" + (if font-lock-keywords "YES" "NO"))) + (princ (format "Buffer size: %d bytes\n" (buffer-size))) + (princ (format "File size threshold check: %s\n" + (if (> (buffer-size) (* 1024 1024)) + "LARGE FILE (>1MB) - highlighting may be disabled" + "Normal size"))) + (princ "\nTo fix issues, try:\n") + (princ " M-x fix-syntax-highlighting\n") + (princ " M-x font-lock-mode (toggle off and on)\n") + (princ " M-x font-lock-fontify-buffer\n"))) + +;; Ensure font-lock works in C/C++ modes (both regular and tree-sitter) +(defun ensure-c-syntax-highlighting () + "Ensure syntax highlighting works in C/C++ modes." + (font-lock-mode 1) + (setq font-lock-keywords-case-fold-search nil) + ;; Force fontification if needed + (when (and (boundp 'font-lock-mode) (not font-lock-mode)) + (font-lock-mode 1)) + ;; For tree-sitter modes, ensure proper setup + (when (or (eq major-mode 'c-ts-mode) + (eq major-mode 'c++-ts-mode)) + (when (fboundp 'treesit-font-lock-recompute-features) + (treesit-font-lock-recompute-features)))) + +;; Apply to all C/C++ mode variants +(add-hook 'c-mode-hook 'ensure-c-syntax-highlighting) +(add-hook 'c++-mode-hook 'ensure-c-syntax-highlighting) +(add-hook 'c-ts-mode-hook 'ensure-c-syntax-highlighting) +(add-hook 'c++-ts-mode-hook 'ensure-c-syntax-highlighting) + +;; Diagnostic function for CUA mode +(defun diagnose-cua-mode () + "Diagnose CUA mode settings and keybindings." + (interactive) + (with-output-to-temp-buffer "*CUA Mode Diagnostics*" + (princ "=== CUA MODE DIAGNOSTICS ===\n\n") + (princ (format "CUA mode enabled: %s\n" (if cua-mode "YES" "NO"))) + (princ (format "CUA keys enabled: %s\n" (if cua-enable-cua-keys "YES" "NO"))) + (princ (format "CUA prefix override delay: %s\n" cua-prefix-override-inhibit-delay)) + (princ "\nKey bindings:\n") + (princ (format "C-c binding: %s\n" (key-binding (kbd "C-c")))) + (princ (format "C-v binding: %s\n" (key-binding (kbd "C-v")))) + (princ (format "C-x binding: %s\n" (key-binding (kbd "C-x")))) + (princ (format "C-z binding: %s\n" (key-binding (kbd "C-z")))) + (princ "\nTo fix issues, try:\n") + (princ " M-x ensure-cua-bindings\n") + (princ " M-x cua-mode (toggle off and on)\n"))) ;; Trailing whitespace (setq show-trailing-whitespace t) @@ -56,11 +181,13 @@ :foundry "nil" :slant 'normal :weight 'regular - :height 140 + :height 180 :width 'normal) ;; Ensure font settings apply to new frames -(add-to-list 'default-frame-alist '(font . "0xProto Nerd Font Mono-14")) +;; Use the proper font spec format +(add-to-list 'default-frame-alist + (cons 'font (font-spec :family "0xProto Nerd Font Mono" :size 18))) ;;; Diff-hl face customizations (with-eval-after-load 'diff-hl @@ -69,6 +196,10 @@ (set-face-attribute 'diff-hl-insert nil :background "green3" :foreground "green3")) ;;; Theme Management +;; Add lisp directory to theme load path +(add-to-list 'custom-theme-load-path + (expand-file-name "lisp" user-emacs-directory)) + (defvar jens-themes '(developer-dark modus-vivendi @@ -113,4 +244,4 @@ (setq which-key-popup-type 'side-window)) (provide 'init-ui) -;;; init-ui.el ends here \ No newline at end of file +;;; init-ui.el ends here diff --git a/mu4e-config.el b/lisp/mu4e-config.el similarity index 100% rename from mu4e-config.el rename to lisp/mu4e-config.el diff --git a/qml-config.el b/lisp/qml-config.el similarity index 100% rename from qml-config.el rename to lisp/qml-config.el diff --git a/shr-config.el b/lisp/shr-config.el similarity index 97% rename from shr-config.el rename to lisp/shr-config.el index f948f3b..35ec636 100644 --- a/shr-config.el +++ b/lisp/shr-config.el @@ -13,6 +13,8 @@ (setq shr-max-image-proportion 0.7) ; Limit image size (setq shr-width nil) ; Use full window width (setq shr-bullet "• ") ; Nice bullet character + (setq shr-inhibit-images nil) ; Enable image display + (setq shr-blocked-images nil) ; Don't block any images ;; Increase indentation for better structure (setq shr-indentation 2) diff --git a/symbol-finder.el b/lisp/symbol-finder.el similarity index 100% rename from symbol-finder.el rename to lisp/symbol-finder.el