- Delete emacs-dev-config.el (650 lines of legacy lsp-mode config) - Update emacs-dev-config-modern.el to use Company instead of Corfu - Remove legacy config loading from init.el and init-utils.el - Update CLAUDE.md documentation to reflect new architecture New structure: - init-eglot.el: LSP support (auto-enables for programming modes) - emacs-dev-config-modern.el: Optional extras via M-x enable-dev-mode-modern - init-completion.el: Company completion (single source of truth) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
283 lines
11 KiB
EmacsLisp
283 lines
11 KiB
EmacsLisp
;;; init-utils.el --- Utility functions and configurations -*- lexical-binding: t -*-
|
|
;;; Commentary:
|
|
;;; Custom utility functions and helper configurations
|
|
|
|
;;; Code:
|
|
|
|
;;; Custom Functions
|
|
(defun kill-current-buffer-no-confirm ()
|
|
"Kill the current buffer without confirmation, unless it has unsaved changes."
|
|
(interactive)
|
|
(kill-buffer (current-buffer)))
|
|
|
|
;; Keep original function but rename it
|
|
(defun reload-emacs-config-blocking ()
|
|
"Reload the Emacs configuration file and all dependent configs (blocking version)."
|
|
(interactive)
|
|
;; First reload the main init.el
|
|
(load-file (expand-file-name "init.el" user-emacs-directory))
|
|
|
|
;; Reload SHR config if it exists
|
|
(let ((shr-config (expand-file-name "lisp/shr-config.el" user-emacs-directory)))
|
|
(when (file-exists-p shr-config)
|
|
(load-file shr-config)))
|
|
|
|
;; Reload elfeed config if it exists
|
|
(let ((elfeed-config (expand-file-name "lisp/elfeed-config.el" user-emacs-directory)))
|
|
(when (file-exists-p elfeed-config)
|
|
(load-file elfeed-config)))
|
|
|
|
;; Reload mu4e config if it exists
|
|
(let ((mu4e-config (expand-file-name "lisp/mu4e-config.el" user-emacs-directory)))
|
|
(when (file-exists-p mu4e-config)
|
|
(condition-case err
|
|
(load-file mu4e-config)
|
|
(error
|
|
(message "mu4e config available but mu4e not installed")))))
|
|
|
|
(message "Emacs configuration fully reloaded!"))
|
|
|
|
(defvar reload-emacs-config-timer nil
|
|
"Timer for non-blocking configuration reload.")
|
|
|
|
(defvar reload-emacs-config-files nil
|
|
"List of files to reload.")
|
|
|
|
(defvar reload-emacs-config-index 0
|
|
"Current index in the reload process.")
|
|
|
|
(defun reload-emacs-config-process-next ()
|
|
"Process the next file in the reload queue."
|
|
(when (< reload-emacs-config-index (length reload-emacs-config-files))
|
|
(let ((file (nth reload-emacs-config-index reload-emacs-config-files)))
|
|
(condition-case err
|
|
(progn
|
|
(load-file file)
|
|
(message "[%d/%d] Loaded %s"
|
|
(1+ reload-emacs-config-index)
|
|
(length reload-emacs-config-files)
|
|
(file-name-nondirectory file)))
|
|
(error
|
|
(message "[%d/%d] Error loading %s: %s"
|
|
(1+ reload-emacs-config-index)
|
|
(length reload-emacs-config-files)
|
|
(file-name-nondirectory file)
|
|
err)))
|
|
(cl-incf reload-emacs-config-index)
|
|
;; Schedule next file
|
|
(setq reload-emacs-config-timer
|
|
(run-with-idle-timer 0.01 nil #'reload-emacs-config-process-next)))
|
|
;; All done
|
|
(when (>= reload-emacs-config-index (length reload-emacs-config-files))
|
|
(message "✓ Configuration reload complete!")
|
|
(setq reload-emacs-config-timer nil
|
|
reload-emacs-config-files nil
|
|
reload-emacs-config-index 0))))
|
|
|
|
(defun reload-emacs-config (&optional arg)
|
|
"Reload Emacs configuration non-blocking with incremental updates.
|
|
This version loads configuration files one by one during idle time
|
|
to prevent UI freezing. With prefix ARG, use blocking reload."
|
|
(interactive "P")
|
|
;; If prefix arg given, use blocking reload
|
|
(if arg
|
|
(reload-emacs-config-blocking)
|
|
;; Otherwise, proceed with non-blocking reload
|
|
;; Cancel any ongoing reload
|
|
(when reload-emacs-config-timer
|
|
(cancel-timer reload-emacs-config-timer)
|
|
(setq reload-emacs-config-timer nil))
|
|
|
|
;; Prepare list of files to reload
|
|
(setq reload-emacs-config-files
|
|
(cl-remove-if-not
|
|
#'file-exists-p
|
|
(list (expand-file-name "init.el" user-emacs-directory)
|
|
(expand-file-name "lisp/shr-config.el" user-emacs-directory)
|
|
(expand-file-name "lisp/elfeed-config.el" user-emacs-directory)
|
|
(expand-file-name "lisp/mu4e-config.el" user-emacs-directory))))
|
|
|
|
(setq reload-emacs-config-index 0)
|
|
|
|
(message "Starting configuration reload (%d files)..."
|
|
(length reload-emacs-config-files))
|
|
|
|
;; Start the reload process
|
|
(reload-emacs-config-process-next)))
|
|
|
|
(defun reload-emacs-config-async ()
|
|
"Reload Emacs configuration asynchronously with progress feedback."
|
|
(interactive)
|
|
(let* ((start-time (current-time))
|
|
(config-files '())
|
|
(total-files 0)
|
|
(loaded-files 0)
|
|
(progress-reporter nil))
|
|
|
|
;; Collect all config files to reload
|
|
(setq config-files
|
|
(append
|
|
;; Main init.el
|
|
(list (expand-file-name "init.el" user-emacs-directory))
|
|
;; Optional configs
|
|
(cl-remove-if-not
|
|
#'file-exists-p
|
|
(list
|
|
(expand-file-name "lisp/shr-config.el" user-emacs-directory)
|
|
(expand-file-name "lisp/elfeed-config.el" user-emacs-directory)
|
|
(expand-file-name "lisp/mu4e-config.el" user-emacs-directory)))))
|
|
|
|
(setq total-files (length config-files))
|
|
(setq progress-reporter
|
|
(make-progress-reporter "Reloading configuration..." 0 total-files))
|
|
|
|
;; Load files with progress updates
|
|
(dolist (file config-files)
|
|
(condition-case err
|
|
(progn
|
|
(load-file file)
|
|
(cl-incf loaded-files)
|
|
(progress-reporter-update progress-reporter loaded-files))
|
|
(error
|
|
(message "Error loading %s: %s" (file-name-nondirectory file) err))))
|
|
|
|
(progress-reporter-done progress-reporter)
|
|
(message "Configuration reloaded in %.2f seconds"
|
|
(float-time (time-subtract (current-time) start-time)))))
|
|
|
|
(defun reload-emacs-config-smart ()
|
|
"Smart reload that only reloads changed files since last load."
|
|
(interactive)
|
|
(let* ((lisp-dir (expand-file-name "lisp" user-emacs-directory))
|
|
(init-file (expand-file-name "init.el" user-emacs-directory))
|
|
(changed-files '())
|
|
(reload-all nil))
|
|
|
|
;; Check if init.el has changed
|
|
(when (file-newer-than-file-p init-file (current-time))
|
|
(setq reload-all t))
|
|
|
|
(if reload-all
|
|
;; If init.el changed, do full reload
|
|
(reload-emacs-config-async)
|
|
;; Otherwise, reload only changed files
|
|
(progn
|
|
;; Find changed files in lisp directory
|
|
(dolist (file (directory-files lisp-dir t "\\.el$"))
|
|
(when (and (not (string-match-p "\\.elc$" file))
|
|
(not (string-match-p "#" file))
|
|
(file-newer-than-file-p file (time-subtract (current-time) 60)))
|
|
(push file changed-files)))
|
|
|
|
(if changed-files
|
|
(progn
|
|
(message "Reloading %d changed file(s)..." (length changed-files))
|
|
(dolist (file changed-files)
|
|
(condition-case err
|
|
(progn
|
|
(load-file file)
|
|
(message "Reloaded %s" (file-name-nondirectory file)))
|
|
(error
|
|
(message "Error reloading %s: %s"
|
|
(file-name-nondirectory file) err))))
|
|
(message "Smart reload complete!"))
|
|
(message "No files changed recently. Use C-u C-c C-r for full reload."))))))
|
|
|
|
(defun reload-current-file ()
|
|
"Reload only the current file if it's an Emacs Lisp file."
|
|
(interactive)
|
|
(when (and (buffer-file-name)
|
|
(string-match-p "\\.el$" (buffer-file-name)))
|
|
(save-buffer)
|
|
(load-file (buffer-file-name))
|
|
(message "Reloaded %s" (file-name-nondirectory (buffer-file-name)))))
|
|
|
|
(defun reload-emacs-config-fast ()
|
|
"Fast reload using byte-compiled files when available.
|
|
This is the fastest reload method but requires byte-compilation."
|
|
(interactive)
|
|
(let* ((init-file (expand-file-name "init" user-emacs-directory))
|
|
(start-time (current-time)))
|
|
;; Try to load byte-compiled version first, fall back to source
|
|
(if (file-exists-p (concat init-file ".elc"))
|
|
(progn
|
|
(load init-file t t)
|
|
(message "Fast reload complete (byte-compiled) in %.2f seconds"
|
|
(float-time (time-subtract (current-time) start-time))))
|
|
;; Fall back to non-blocking reload
|
|
(reload-emacs-config))))
|
|
|
|
;;; Package management helpers
|
|
(defun package-refresh-without-proxy ()
|
|
"Temporarily disable proxy and refresh packages."
|
|
(interactive)
|
|
(let ((url-proxy-services nil))
|
|
(package-refresh-contents)
|
|
(message "Package list refreshed without proxy")))
|
|
|
|
(defun package-install-without-proxy (package)
|
|
"Install PACKAGE without using proxy."
|
|
(interactive
|
|
(list (intern (completing-read "Install package: "
|
|
(mapcar #'car package-archive-contents)))))
|
|
(let ((url-proxy-services nil))
|
|
(package-install package)
|
|
(message "Package %s installed without proxy" package)))
|
|
|
|
(defun install-dev-packages ()
|
|
"Install development packages without proxy."
|
|
(interactive)
|
|
(let ((url-proxy-services nil)
|
|
(dev-packages '(lsp-mode lsp-ui lsp-treemacs
|
|
company company-box yasnippet
|
|
flycheck magit forge)))
|
|
(package-refresh-contents)
|
|
(dolist (pkg dev-packages)
|
|
(unless (package-installed-p pkg)
|
|
(condition-case err
|
|
(progn
|
|
(package-install pkg)
|
|
(message "Installed %s" pkg))
|
|
(error
|
|
(message "Failed to install %s: %s" pkg err)))))
|
|
(message "Development packages installation complete")))
|
|
|
|
;;; Proxy management
|
|
(defvar url-proxy-services-backup nil
|
|
"Backup of proxy settings.")
|
|
|
|
(defun toggle-proxy ()
|
|
"Toggle proxy settings on/off."
|
|
(interactive)
|
|
(if url-proxy-services
|
|
(progn
|
|
(setq url-proxy-services-backup url-proxy-services)
|
|
(setq url-proxy-services nil)
|
|
(message "Proxy disabled"))
|
|
(progn
|
|
(setq url-proxy-services (or url-proxy-services-backup
|
|
'(("https" . "eudewerepo001:3128")
|
|
("http" . "eudewerepo001:3128"))))
|
|
(message "Proxy enabled: %s" (cdr (assoc "http" url-proxy-services))))))
|
|
|
|
;;; Development mode helpers
|
|
(defun show-dev-mode-info ()
|
|
"Show information about development mode."
|
|
(interactive)
|
|
(message "Development mode is available. Use M-x enable-dev-mode-modern to activate yasnippet, origami, and other development tools. LSP (Eglot) is already active for programming modes."))
|
|
|
|
;;; God-mode helpers
|
|
(defun enable-god-mode-config ()
|
|
"Enable god-mode configuration."
|
|
(interactive)
|
|
(let ((god-config (expand-file-name "lisp/god-mode-config.el" user-emacs-directory)))
|
|
(if (file-exists-p god-config)
|
|
(condition-case err
|
|
(progn
|
|
(load-file god-config)
|
|
(message "God-mode configuration loaded. Press ESC to toggle god-mode."))
|
|
(error (message "Failed to load god-mode config: %s" err)))
|
|
(message "God-mode config file not found at %s" god-config))))
|
|
|
|
(provide 'init-utils)
|
|
;;; init-utils.el ends here |