diff options
Diffstat (limited to 'modules/modeline-config.el')
| -rw-r--r-- | modules/modeline-config.el | 223 |
1 files changed, 160 insertions, 63 deletions
diff --git a/modules/modeline-config.el b/modules/modeline-config.el index 0a247732..b1403539 100644 --- a/modules/modeline-config.el +++ b/modules/modeline-config.el @@ -3,73 +3,170 @@ ;;; Commentary: -;; Doom modeline configuration with performance optimizations. - -;; Settings prioritize speed while keeping essential information including: -;; - relative file paths from project root -;; - column number and percentage position -;; - buffer modification indicators -;; - and major mode with icon. - -;; Disabled features for performance: -;; - minor modes display -;; - word count -;; - encoding info -;; - LSP information - -;; Performance tuning includes: -;; - 0.75 second refresh rate -;; - 1MB process output chunks -;; - nerd-icons (faster than all-the-icons) -;; - simplified checker format -;; - limited VCS info length +;; Simple, minimal modeline using only built-in Emacs functionality. +;; No external packages = no buffer issues, no native-comp errors. + +;; Features: +;; - Buffer status (modified, read-only) +;; - Buffer name +;; - Major mode +;; - Version control status +;; - Line and column position +;; - Buffer percentage ;;; Code: -;; ------------------------------- Doom Modeline ------------------------------- - -(use-package doom-modeline - :hook (after-init . doom-modeline-mode) - :custom - ;; Performance optimizations - (doom-modeline-buffer-file-name-style 'relative-from-project) ;; Faster than 'file-name - (doom-modeline-icon t) - (doom-modeline-major-mode-icon t) - (doom-modeline-major-mode-color-icon t) - (doom-modeline-buffer-state-icon t) - (doom-modeline-buffer-modification-icon t) - (doom-modeline-unicode-fallback nil) - (doom-modeline-minor-modes nil) ;; Hide minor modes as requested - (doom-modeline-enable-word-count nil) ;; Faster without word count - (doom-modeline-continuous-word-count-modes nil) - (doom-modeline-buffer-encoding nil) ;; Hide encoding for speed - (doom-modeline-indent-info nil) ;; Hide indent info for speed - (doom-modeline-checker-simple-format t) ;; Simpler checker format for speed - (doom-modeline-number-limit 99) ;; Lower number limit for better performance - (doom-modeline-vcs-max-length 12) ;; Limit VCS info length for speed - (doom-modeline-persp-name nil) ;; Disable perspective name for speed - (doom-modeline-display-default-persp-name nil) - (doom-modeline-persp-icon nil) - (doom-modeline-lsp nil) ;; Disable LSP info for speed - - ;; UI Preferences - (doom-modeline-height 25) - (doom-modeline-bar-width 3) - (doom-modeline-window-width-limit 0.25) - (doom-modeline-project-detection 'projectile) ;; Use projectile if available, nil is faster - - ;; Use nerd-icons instead of all-the-icons - (doom-modeline-icon-preference 'nerd-icons) - - ;; Enable elements you specifically requested - (doom-modeline-column-number t) ;; Show column number - (doom-modeline-percent-position t) ;; Show percentage position - (doom-modeline-buffer-name t) ;; Show buffer name - (doom-modeline-buffer-file-name t) ;; Show file name - :config - (setq read-process-output-max (* 1024 1024)) ;; 1MB process read size for better performance - (setq doom-modeline-refresh-rate 0.75)) ;; Update rate in seconds +;; Use buffer status colors from user-constants +(require 'user-constants) + +;; -------------------------- Modeline Configuration -------------------------- + +;; Use Emacs 30's built-in right-alignment +(setq mode-line-right-align-edge 'right-margin) + +;; String truncation length for narrow windows +(defcustom cj/modeline-string-truncate-length 12 + "String length after which truncation happens in narrow windows." + :type 'natnum + :group 'modeline) + +;; -------------------------- Helper Functions --------------------------------- + +(defun cj/modeline-window-narrow-p () + "Return non-nil if window is narrow (less than 100 chars wide)." + (< (window-total-width) 100)) + +(defun cj/modeline-string-truncate-p (str) + "Return non-nil if STR should be truncated." + (and (stringp str) + (not (string-empty-p str)) + (cj/modeline-window-narrow-p) + (> (length str) cj/modeline-string-truncate-length) + (not (one-window-p :no-minibuffer)))) + +(defun cj/modeline-string-cut-middle (str) + "Truncate STR in the middle if appropriate, else return STR. +Example: `my-very-long-name.el' → `my-ver...me.el'" + (if (cj/modeline-string-truncate-p str) + (let ((half (floor cj/modeline-string-truncate-length 2))) + (concat (substring str 0 half) "..." (substring str (- half)))) + str)) + +;; -------------------------- Modeline Segments -------------------------------- + +(defvar-local cj/modeline-buffer-name + '(:eval (let* ((state (cond + (buffer-read-only 'read-only) + (overwrite-mode 'overwrite) + (t 'normal))) + (color (alist-get state cj/buffer-status-colors)) + (name (buffer-name)) + (truncated-name (cj/modeline-string-cut-middle name))) + (propertize truncated-name + 'face `(:foreground ,color) + 'mouse-face 'mode-line-highlight + 'help-echo (concat + name "\n" + (or (buffer-file-name) + (format "No file. Directory: %s" default-directory))) + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] 'previous-buffer) + (define-key map [mode-line mouse-3] 'next-buffer) + map)))) + "Buffer name colored by read-only/read-write status. +Green = writeable, Red = read-only, Gold = overwrite. +Truncates in narrow windows. Click to switch buffers.") + +(defvar-local cj/modeline-position + '(:eval (format "L:%d C:%d" (line-number-at-pos) (current-column))) + "Line and column position as L:line C:col.") + +(defvar cj/modeline-vc-faces + '((added . vc-locally-added-state) + (edited . vc-edited-state) + (removed . vc-removed-state) + (missing . vc-missing-state) + (conflict . vc-conflict-state) + (locked . vc-locked-state) + (up-to-date . vc-up-to-date-state)) + "VC state to face mapping.") + +(defvar-local cj/modeline-vc-branch + '(:eval (when (mode-line-window-selected-p) ; Only show in active window + (when-let* ((file (or buffer-file-name default-directory)) + (backend (vc-backend file))) + (when-let* ((branch (vc-working-revision file backend))) + ;; For Git, try to get symbolic branch name + (when (eq backend 'Git) + (require 'vc-git) + (when-let* ((symbolic (vc-git--symbolic-ref file))) + (setq branch symbolic))) + ;; Get VC state for face + (let* ((state (vc-state file backend)) + (face (alist-get state cj/modeline-vc-faces 'vc-up-to-date-state)) + (truncated-branch (cj/modeline-string-cut-middle branch))) + (concat + (propertize (char-to-string #xE0A0) 'face 'shadow) ; Git branch symbol + " " + (propertize truncated-branch + 'face face + 'mouse-face 'mode-line-highlight + 'help-echo (format "Branch: %s\nState: %s\nmouse-1: vc-diff\nmouse-3: vc-root-diff" branch state) + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] 'vc-diff) + (define-key map [mode-line mouse-3] 'vc-root-diff) + map)))))))) + "Git branch with symbol and colored by VC state. +Shows only in active window. Truncates in narrow windows. +Click to show diffs with `vc-diff' or `vc-root-diff'.") + +(defvar-local cj/modeline-major-mode + '(:eval (let ((mode-str (format-mode-line mode-name)) ; Convert to string + (mode-sym major-mode)) + (propertize mode-str + 'mouse-face 'mode-line-highlight + 'help-echo (if-let* ((parent (get mode-sym 'derived-mode-parent))) + (format "Major mode: %s\nDerived from: %s\nmouse-1: describe-mode" mode-sym parent) + (format "Major mode: %s\nmouse-1: describe-mode" mode-sym)) + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] 'describe-mode) + map)))) + "Major mode name only (no minor modes). +Click to show help with `describe-mode'.") + +(defvar-local cj/modeline-misc-info + '(:eval (when (mode-line-window-selected-p) + mode-line-misc-info)) + "Misc info (chime notifications, etc). +Shows only in active window.") + +;; -------------------------- Modeline Assembly -------------------------------- + +(setq-default mode-line-format + '("%e" ; Error message if out of memory + ;; LEFT SIDE + " " + cj/modeline-major-mode + " " + cj/modeline-buffer-name + " " + cj/modeline-position + ;; RIGHT SIDE (using Emacs 30 built-in right-align) + ;; Order: leftmost to rightmost as they appear in the list + mode-line-format-right-align + cj/modeline-vc-branch + " " + cj/modeline-misc-info + " ")) +;; Mark all segments as risky-local-variable (required for :eval forms) +(dolist (construct '(cj/modeline-buffer-name + cj/modeline-position + cj/modeline-vc-branch + cj/modeline-vc-faces + cj/modeline-major-mode + cj/modeline-misc-info)) + (put construct 'risky-local-variable t)) (provide 'modeline-config) ;;; modeline-config.el ends here |
