doom-modeline-segments.el (138081B)
1 ;;; doom-modeline-segments.el --- The segments for doom-modeline -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2018-2024 Vincent Zhang 4 5 ;; This file is not part of GNU Emacs. 6 7 ;; 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 ;; 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 ;; 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 20 ;; 21 22 ;;; Commentary: 23 ;; 24 ;; The segments for doom-modeline. 25 ;; Use `doom-modeline-def-segment' to create a new segment. 26 ;; 27 28 ;;; Code: 29 30 (require 'doom-modeline-core) 31 (require 'doom-modeline-env) 32 (eval-when-compile 33 (require 'cl-lib) 34 (require 'seq) 35 (require 'subr-x)) 36 37 38 ;; 39 ;; Externals 40 ;; 41 42 (defvar Info-current-file) 43 (defvar Info-current-node) 44 (defvar Info-mode-line-node-keymap) 45 (defvar anzu--cached-count) 46 (defvar anzu--current-position) 47 (defvar anzu--overflow-p) 48 (defvar anzu--state) 49 (defvar anzu--total-matched) 50 (defvar anzu-cons-mode-line-p) 51 (defvar aw-keys) 52 (defvar battery-echo-area-format) 53 (defvar battery-load-critical) 54 (defvar battery-mode-line-format) 55 (defvar battery-mode-line-limit) 56 (defvar battery-status-function) 57 (defvar boon-command-state) 58 (defvar boon-insert-state) 59 (defvar boon-off-state) 60 (defvar boon-special-state) 61 (defvar display-time-string) 62 (defvar edebug-execution-mode) 63 (defvar eglot--managed-mode) 64 (defvar eglot-menu) 65 (defvar eglot-menu-string) 66 (defvar eglot-server-menu) 67 (defvar erc-modified-channels-alist) 68 (defvar evil-ex-active-highlights-alist) 69 (defvar evil-ex-argument) 70 (defvar evil-ex-range) 71 (defvar evil-mc-frozen) 72 (defvar evil-state) 73 (defvar evil-visual-beginning) 74 (defvar evil-visual-end) 75 (defvar evil-visual-selection) 76 (defvar flycheck--automatically-enabled-checkers) 77 (defvar flycheck-current-errors) 78 (defvar flycheck-mode-menu-map) 79 (defvar flymake--mode-line-format) 80 (defvar flymake--state) 81 (defvar flymake-menu) 82 (defvar gnus-newsrc-alist) 83 (defvar gnus-newsrc-hashtb) 84 (defvar grip--process) 85 (defvar helm--mode-line-display-prefarg) 86 (defvar iedit-occurrences-overlays) 87 (defvar kele-menu-map) 88 (defvar meow--indicator) 89 (defvar minions-mode-line-lighter) 90 (defvar minions-mode-line-minor-modes-map) 91 (defvar mlscroll-right-align) 92 (defvar mu4e--modeline-item) 93 (defvar mu4e-alert-mode-line) 94 (defvar mu4e-alert-modeline-formatter) 95 (defvar mu4e-modeline-mode) 96 (defvar objed--obj-state) 97 (defvar objed--object) 98 (defvar objed-modeline-setup-func) 99 (defvar persp-nil-name) 100 (defvar phi-replace--mode-line-format) 101 (defvar phi-search--overlays) 102 (defvar phi-search--selection) 103 (defvar phi-search-mode-line-format) 104 (defvar projectile-mode-map) 105 (defvar rcirc-activity) 106 (defvar symbol-overlay-keywords-alist) 107 (defvar symbol-overlay-temp-symbol) 108 (defvar text-scale-mode-amount) 109 (defvar tracking-buffers) 110 (defvar winum-auto-setup-mode-line) 111 (defvar xah-fly-insert-state-p) 112 113 (declare-function anzu--reset-status "ext:anzu") 114 (declare-function anzu--where-is-here "ext:anzu") 115 (declare-function async-inject-variables "ext:async") 116 (declare-function async-start "ext:async") 117 (declare-function avy-traverse "ext:avy") 118 (declare-function avy-tree "ext:avy") 119 (declare-function aw-update "ext:ace-window") 120 (declare-function aw-window-list "ext:ace-window") 121 (declare-function battery-format "battery") 122 (declare-function battery-update "battery") 123 (declare-function boon-modeline-string "ext:boon") 124 (declare-function boon-state-string "ext:boon") 125 (declare-function cider--connection-info "ext:cider") 126 (declare-function cider-connected-p "ext:cider") 127 (declare-function cider-current-repl "ext:cider") 128 (declare-function cider-jack-in "ext:cider") 129 (declare-function cider-quit "ext:cider") 130 (declare-function citre-mode "ext:citre-basic-tools") 131 (declare-function compilation-goto-in-progress-buffer "compile") 132 (declare-function dap--cur-session "ext:dap-mode") 133 (declare-function dap--debug-session-name "ext:dap-mode") 134 (declare-function dap--debug-session-state "ext:dap-mode") 135 (declare-function dap--session-running "ext:dap-mode") 136 (declare-function dap-debug-recent "ext:dap-mode") 137 (declare-function dap-disconnect "ext:dap-mode") 138 (declare-function dap-hydra "ext:dap-hydra") 139 (declare-function edebug-help "edebug") 140 (declare-function edebug-next-mode "edebug") 141 (declare-function edebug-stop "edebug") 142 (declare-function eglot--major-modes "eglot") 143 (declare-function eglot--server-info "eglot" t t) 144 (declare-function eglot-current-server "eglot") 145 (declare-function eglot-managed-p "eglot") 146 (declare-function eglot-project-nickname "eglot" t t) 147 (declare-function erc-switch-to-buffer "erc") 148 (declare-function erc-track-switch-buffer "erc-track") 149 (declare-function evil-delimited-arguments "ext:evil-common") 150 (declare-function evil-emacs-state-p "ext:evil-states" t t) 151 (declare-function evil-force-normal-state "ext:evil-commands" t t) 152 (declare-function evil-insert-state-p "ext:evil-states" t t) 153 (declare-function evil-motion-state-p "ext:evil-states" t t) 154 (declare-function evil-normal-state-p "ext:evil-states" t t) 155 (declare-function evil-operator-state-p "ext:evil-states" t t) 156 (declare-function evil-replace-state-p "ext:evil-states" t t) 157 (declare-function evil-state-property "ext:evil-common") 158 (declare-function evil-visual-state-p "ext:evil-states" t t) 159 (declare-function eyebrowse--get "ext:eyebrowse") 160 (declare-function face-remap-remove-relative "face-remap") 161 (declare-function fancy-narrow-active-p "ext:fancy-narrow") 162 (declare-function flycheck-buffer "ext:flycheck") 163 (declare-function flycheck-count-errors "ext:flycheck") 164 (declare-function flycheck-error-level-compilation-level "ext:flycheck") 165 (declare-function flycheck-list-errors "ext:flycheck") 166 (declare-function flycheck-next-error "ext:flycheck") 167 (declare-function flycheck-previous-error "ext:flycheck") 168 (declare-function flymake--diag-type "flymake" t t) 169 (declare-function flymake--handle-report "flymake") 170 (declare-function flymake--lookup-type-property "flymake") 171 (declare-function flymake--state-diags "flymake" t t) 172 (declare-function flymake-disabled-backends "flymake") 173 (declare-function flymake-goto-next-error "flymake") 174 (declare-function flymake-goto-prev-error "flymake") 175 (declare-function flymake-reporting-backends "flymake") 176 (declare-function flymake-running-backends "flymake") 177 (declare-function flymake-show-buffer-diagnostics "flymake") 178 (declare-function flymake-show-buffer-diagnostics "flymake") 179 (declare-function flymake-start "flymake") 180 (declare-function follow-all-followers "follow") 181 (declare-function gnus-demon-add-handler "gnus-demon") 182 (declare-function grip--preview-url "ext:grip-mode") 183 (declare-function grip-browse-preview "ext:grip-mode") 184 (declare-function grip-restart-preview "ext:grip-mode") 185 (declare-function grip-stop-preview "ext:grip-mode") 186 (declare-function helm-candidate-number-at-point "ext:helm-core") 187 (declare-function helm-get-candidate-number "ext:helm-core") 188 (declare-function iedit-find-current-occurrence-overlay "ext:iedit-lib") 189 (declare-function iedit-prev-occurrence "ext:iedit-lib") 190 (declare-function image-get-display-property "image-mode") 191 (declare-function jsonrpc--request-continuations "jsonrpc" t t) 192 (declare-function jsonrpc-last-error "jsonrpc" t t) 193 (declare-function jsonrpc-name "jsonrpc" t t) 194 (declare-function kele-current-context-name "ext:kele") 195 (declare-function kele-current-namespace "ext:kele") 196 (declare-function lsp--workspace-print "ext:lsp-mode") 197 (declare-function lsp-describe-session "ext:lsp-mode") 198 (declare-function lsp-workspace-folders-open "ext:lsp-mode") 199 (declare-function lsp-workspace-restart "ext:lsp-mode") 200 (declare-function lsp-workspace-shutdown "ext:lsp-mode") 201 (declare-function lsp-workspaces "ext:lsp-mode") 202 (declare-function lv-message "ext:lv") 203 (declare-function mc/num-cursors "ext:multiple-cursors-core") 204 (declare-function meow--current-state "ext:meow") 205 (declare-function meow-beacon-mode-p "ext:meow") 206 (declare-function meow-insert-mode-p "ext:meow") 207 (declare-function meow-keypad-mode-p "ext:meow") 208 (declare-function meow-motion-mode-p "ext:meow") 209 (declare-function meow-normal-mode-p "ext:meow") 210 (declare-function minions--prominent-modes "ext:minions") 211 (declare-function mlscroll-mode-line "ext:mlscroll") 212 (declare-function mu4e--modeline-string "ext:mu4e-modeline") 213 (declare-function mu4e-alert-default-mode-line-formatter "ext:mu4e-alert") 214 (declare-function mu4e-alert-enable-mode-line-display "ext:mu4e-alert") 215 (declare-function nyan-create "ext:nyan-mode") 216 (declare-function org-edit-src-save "org-src") 217 (declare-function parrot-create "ext:parrot") 218 (declare-function pdf-cache-number-of-pages "ext:pdf-cache" t t) 219 (declare-function persp-add-buffer "ext:persp-mode") 220 (declare-function persp-contain-buffer-p "ext:persp-mode") 221 (declare-function persp-switch "ext:persp-mode") 222 (declare-function phi-search--initialize "ext:phi-search") 223 (declare-function poke-line-create "ext:poke-line") 224 (declare-function popup-create "ext:popup") 225 (declare-function popup-delete "ext:popup") 226 (declare-function project-name "project") 227 (declare-function projectile-project-name "ext:projectile") 228 (declare-function rcirc-next-active-buffer "rcirc") 229 (declare-function rcirc-short-buffer-name "rcirc") 230 (declare-function rcirc-switch-to-server-buffer "rcirc") 231 (declare-function rcirc-window-configuration-change "rcirc") 232 (declare-function rime--should-enable-p "ext:rime") 233 (declare-function rime--should-inline-ascii-p "ext:rime") 234 (declare-function sml-modeline-create "ext:sml-modeline") 235 (declare-function svg-circle "svg") 236 (declare-function svg-create "svg") 237 (declare-function svg-image "svg") 238 (declare-function svg-line "svg") 239 (declare-function symbol-overlay-assoc "ext:symbol-overlay") 240 (declare-function symbol-overlay-get-list "ext:symbol-overlay") 241 (declare-function symbol-overlay-get-symbol "ext:symbol-overlay") 242 (declare-function symbol-overlay-rename "ext:symbol-overlay") 243 (declare-function tab-bar--current-tab "tab-bar") 244 (declare-function tab-bar--current-tab-index "tab-bar") 245 (declare-function tracking-next-buffer "ext:tracking") 246 (declare-function tracking-previous-buffer "ext:tracking") 247 (declare-function tracking-shorten "ext:tracking") 248 (declare-function warning-numeric-level "warnings") 249 (declare-function window-numbering-clear-mode-line "ext:window-numbering") 250 (declare-function window-numbering-get-number-string "ext:window-numbering") 251 (declare-function window-numbering-install-mode-line "ext:window-numbering") 252 (declare-function winum--clear-mode-line "ext:winum") 253 (declare-function winum--install-mode-line "ext:winum") 254 (declare-function winum-get-number-string "ext:winum") 255 256 257 258 ;; 259 ;; Buffer information 260 ;; 261 262 (defvar-local doom-modeline--buffer-file-icon nil) 263 (defun doom-modeline-update-buffer-file-icon (&rest _) 264 "Update file icon in mode-line." 265 (setq doom-modeline--buffer-file-icon 266 (when (and doom-modeline-major-mode-icon 267 (doom-modeline-icon-displayable-p)) 268 (let ((icon (doom-modeline-icon-for-buffer))) 269 (propertize (if (or (null icon) (symbolp icon)) 270 (doom-modeline-icon 'faicon "nf-fa-file_o" nil nil 271 :face 'nerd-icons-dsilver) 272 (doom-modeline-propertize-icon icon)) 273 'help-echo (format "Major-mode: %s" (format-mode-line mode-name))))))) 274 (add-hook 'find-file-hook #'doom-modeline-update-buffer-file-icon) 275 (add-hook 'after-change-major-mode-hook #'doom-modeline-update-buffer-file-icon) 276 (add-hook 'clone-indirect-buffer-hook #'doom-modeline-update-buffer-file-icon) 277 278 (doom-modeline-add-variable-watcher 279 'doom-modeline-icon 280 (lambda (_sym val op _where) 281 (when (eq op 'set) 282 (setq doom-modeline-icon val) 283 (dolist (buf (buffer-list)) 284 (with-current-buffer buf 285 (doom-modeline-update-buffer-file-icon)))))) 286 287 (defun doom-modeline-buffer-file-state-icon (icon unicode text face) 288 "Displays an ICON of buffer state with FACE. 289 UNICODE and TEXT are the alternatives if it is not applicable. 290 Uses `nerd-icons-mdicon' to fetch the icon." 291 (doom-modeline-icon 'mdicon icon unicode text :face face)) 292 293 (defvar-local doom-modeline--buffer-file-state-icon nil) 294 (defun doom-modeline-update-buffer-file-state-icon (&rest _) 295 "Update the buffer or file state in mode-line." 296 (setq doom-modeline--buffer-file-state-icon 297 (when doom-modeline-buffer-state-icon 298 (ignore-errors 299 (concat 300 (cond ((not (or (and (buffer-file-name) (file-remote-p buffer-file-name)) 301 (verify-visited-file-modtime (current-buffer)))) 302 (doom-modeline-buffer-file-state-icon 303 "nf-md-reload_alert" "âŗ" "%1*" 304 'doom-modeline-warning)) 305 (buffer-read-only 306 (doom-modeline-buffer-file-state-icon 307 "nf-md-lock" "đ" "%1*" 308 'doom-modeline-warning)) 309 ((and buffer-file-name (buffer-modified-p) 310 doom-modeline-buffer-modification-icon) 311 (doom-modeline-buffer-file-state-icon 312 "nf-md-content_save_edit" "đž" "%1*" 313 'doom-modeline-warning)) 314 ((and buffer-file-name 315 ;; Avoid freezing while connection is lost 316 (not (file-remote-p buffer-file-name)) 317 (not (file-exists-p buffer-file-name))) 318 (doom-modeline-buffer-file-state-icon 319 "nf-md-cancel" "đĢ" "!" 320 'doom-modeline-urgent)) 321 (t "")) 322 (when (or (buffer-narrowed-p) 323 (and (bound-and-true-p fancy-narrow-mode) 324 (fancy-narrow-active-p)) 325 (bound-and-true-p dired-narrow-mode)) 326 (doom-modeline-buffer-file-state-icon 327 "nf-md-unfold_less_horizontal" "â" "><" 328 'doom-modeline-warning))))))) 329 330 (defvar-local doom-modeline--buffer-file-name nil) 331 (defun doom-modeline-update-buffer-file-name (&rest _) 332 "Update buffer file name in mode-line." 333 (setq doom-modeline--buffer-file-name 334 (ignore-errors 335 (save-match-data 336 (if buffer-file-name 337 (doom-modeline-buffer-file-name) 338 (propertize "%b" 339 'face 'doom-modeline-buffer-file 340 'mouse-face 'doom-modeline-highlight 341 'help-echo "Buffer name 342 mouse-1: Previous buffer\nmouse-3: Next buffer" 343 'local-map mode-line-buffer-identification-keymap)))))) 344 (add-hook 'find-file-hook #'doom-modeline-update-buffer-file-name) 345 (add-hook 'after-save-hook #'doom-modeline-update-buffer-file-name) 346 (add-hook 'clone-indirect-buffer-hook #'doom-modeline-update-buffer-file-name) 347 (add-hook 'evil-insert-state-exit-hook #'doom-modeline-update-buffer-file-name) 348 (add-hook 'Info-selection-hook #'doom-modeline-update-buffer-file-name) 349 (advice-add #'rename-buffer :after #'doom-modeline-update-buffer-file-name) 350 (advice-add #'set-visited-file-name :after #'doom-modeline-update-buffer-file-name) 351 (advice-add #'pop-to-buffer :after #'doom-modeline-update-buffer-file-name) 352 (advice-add #'popup-create :after #'doom-modeline-update-buffer-file-name) 353 (advice-add #'popup-delete :after #'doom-modeline-update-buffer-file-name) 354 ;; (advice-add #'primitive-undo :after #'doom-modeline-update-buffer-file-name) 355 ;; (advice-add #'set-buffer-modified-p :after #'doom-modeline-update-buffer-file-name) 356 357 (with-no-warnings 358 (if (boundp 'after-focus-change-function) 359 (progn 360 (advice-add #'handle-switch-frame :after #'doom-modeline-update-buffer-file-name) 361 (add-function :after after-focus-change-function #'doom-modeline-update-buffer-file-name)) 362 (progn 363 (add-hook 'focus-in-hook #'doom-modeline-update-buffer-file-name) 364 (add-hook 'focus-out-hook #'doom-modeline-update-buffer-file-name)))) 365 366 (doom-modeline-add-variable-watcher 367 'doom-modeline-buffer-file-name-style 368 (lambda (_sym val op _where) 369 (when (eq op 'set) 370 (setq doom-modeline-buffer-file-name-style val) 371 (dolist (buf (buffer-list)) 372 (with-current-buffer buf 373 (when buffer-file-name 374 (doom-modeline-update-buffer-file-name))))))) 375 376 (defsubst doom-modeline--buffer-mode-icon () 377 "The icon of the current major mode." 378 (when (and doom-modeline-icon doom-modeline-major-mode-icon) 379 (when-let* ((icon (or doom-modeline--buffer-file-icon 380 (doom-modeline-update-buffer-file-icon)))) 381 (unless (string-empty-p icon) 382 (concat 383 (if doom-modeline-major-mode-color-icon 384 (doom-modeline-display-icon icon) 385 (doom-modeline-propertize-icon 386 icon 387 (doom-modeline-face))) 388 (doom-modeline-vspc)))))) 389 390 (defsubst doom-modeline--buffer-state-icon () 391 "The icon of the current buffer state." 392 (when doom-modeline-buffer-state-icon 393 (when-let* ((icon (doom-modeline-update-buffer-file-state-icon))) 394 (unless (string-empty-p icon) 395 (concat 396 (doom-modeline-display-icon icon) 397 (doom-modeline-vspc)))))) 398 399 (defsubst doom-modeline--buffer-simple-name () 400 "The buffer simple name." 401 (propertize "%b" 402 'face (doom-modeline-face 403 (if (and doom-modeline-highlight-modified-buffer-name 404 (buffer-modified-p)) 405 'doom-modeline-buffer-modified 406 'doom-modeline-buffer-file)) 407 'mouse-face 'doom-modeline-highlight 408 'help-echo "Buffer name 409 mouse-1: Previous buffer\nmouse-3: Next buffer" 410 'local-map mode-line-buffer-identification-keymap)) 411 412 (defsubst doom-modeline--buffer-name () 413 "The current buffer name." 414 (when doom-modeline-buffer-name 415 (if (and (not (eq doom-modeline-buffer-file-name-style 'file-name)) 416 doom-modeline--limited-width-p) 417 ;; Only display the buffer name if the window is small, and doesn't 418 ;; need to respect file-name style. 419 (doom-modeline--buffer-simple-name) 420 (when-let* ((name (or doom-modeline--buffer-file-name 421 (doom-modeline-update-buffer-file-name)))) 422 ;; Check if the buffer is modified 423 (if (and doom-modeline-highlight-modified-buffer-name 424 (buffer-modified-p)) 425 (propertize name 'face (doom-modeline-face 'doom-modeline-buffer-modified)) 426 (doom-modeline-display-text name)))))) 427 428 (doom-modeline-def-segment buffer-info 429 "Combined information about the current buffer. 430 431 Including the current working directory, the file name, and its state (modified, 432 read-only or non-existent)." 433 (concat 434 (doom-modeline-spc) 435 (doom-modeline--buffer-mode-icon) 436 (doom-modeline--buffer-state-icon) 437 (doom-modeline--buffer-name))) 438 439 (doom-modeline-def-segment buffer-info-simple 440 "Display only the current buffer's name, but with fontification." 441 (concat 442 (doom-modeline-spc) 443 (doom-modeline--buffer-mode-icon) 444 (doom-modeline--buffer-state-icon) 445 (doom-modeline--buffer-simple-name))) 446 447 (doom-modeline-def-segment calc 448 "Display calculator icons and info." 449 (concat 450 (doom-modeline-spc) 451 (when-let* ((icon (doom-modeline-icon 'faicon "nf-fa-calculator" "đŠ" ""))) 452 (concat 453 (doom-modeline-display-icon icon) 454 (doom-modeline-vspc))) 455 (doom-modeline--buffer-simple-name))) 456 457 (doom-modeline-def-segment buffer-default-directory 458 "Displays `default-directory' with the icon and state. 459 460 This is for special buffers like the scratch buffer where knowing the current 461 project directory is important." 462 (let ((face (doom-modeline-face 463 (if (and buffer-file-name (buffer-modified-p)) 464 'doom-modeline-buffer-modified 465 'doom-modeline-buffer-path)))) 466 (concat 467 (doom-modeline-spc) 468 (and doom-modeline-major-mode-icon 469 (concat 470 (doom-modeline-icon 471 'octicon "nf-oct-file_directory_fill" "đŋ" "" :face face) 472 (doom-modeline-vspc))) 473 (doom-modeline--buffer-state-icon) 474 (propertize (abbreviate-file-name default-directory) 'face face)))) 475 476 (doom-modeline-def-segment buffer-default-directory-simple 477 "Displays `default-directory'. 478 479 This is for special buffers like the scratch buffer where knowing the current 480 project directory is important." 481 (let ((face (doom-modeline-face 'doom-modeline-buffer-path))) 482 (concat 483 (doom-modeline-spc) 484 (and doom-modeline-major-mode-icon 485 (concat 486 (doom-modeline-icon 487 'octicon "nf-oct-file_directory_fill" "đŋ" "" :face face) 488 (doom-modeline-vspc))) 489 (propertize (abbreviate-file-name default-directory) 'face face)))) 490 491 492 ;; 493 ;; Encoding 494 ;; 495 496 (doom-modeline-def-segment buffer-encoding 497 "Displays the eol and the encoding style of the buffer." 498 (when doom-modeline-buffer-encoding 499 (let ((sep (doom-modeline-spc)) 500 (face (doom-modeline-face)) 501 (mouse-face 'doom-modeline-highlight)) 502 (concat 503 sep 504 505 ;; eol type 506 (let ((eol (coding-system-eol-type buffer-file-coding-system))) 507 (when (or (eq doom-modeline-buffer-encoding t) 508 (and (eq doom-modeline-buffer-encoding 'nondefault) 509 (not (equal eol doom-modeline-default-eol-type)))) 510 (propertize 511 (pcase eol 512 (0 "LF ") 513 (1 "CRLF ") 514 (2 "CR ") 515 (_ "")) 516 'face face 517 'mouse-face mouse-face 518 'help-echo (format "End-of-line style: %s\nmouse-1: Cycle" 519 (pcase eol 520 (0 "Unix-style LF") 521 (1 "DOS-style CRLF") 522 (2 "Mac-style CR") 523 (_ "Undecided"))) 524 'local-map (let ((map (make-sparse-keymap))) 525 (define-key map [mode-line mouse-1] 'mode-line-change-eol) 526 map)))) 527 528 ;; coding system 529 (let* ((sys (coding-system-plist buffer-file-coding-system)) 530 (cat (plist-get sys :category)) 531 (sym (if (memq cat 532 '(coding-category-undecided coding-category-utf-8)) 533 'utf-8 534 (plist-get sys :name)))) 535 (when (or (eq doom-modeline-buffer-encoding t) 536 (and (eq doom-modeline-buffer-encoding 'nondefault) 537 (not (eq cat 'coding-category-undecided)) 538 (not (eq sym doom-modeline-default-coding-system)))) 539 (propertize 540 (upcase (symbol-name sym)) 541 'face face 542 'mouse-face mouse-face 543 'help-echo 'mode-line-mule-info-help-echo 544 'local-map mode-line-coding-system-map))) 545 546 sep)))) 547 548 549 ;; 550 ;; Indentation 551 ;; 552 553 (doom-modeline-def-segment indent-info 554 "Displays the indentation information." 555 (when doom-modeline-indent-info 556 (let ((do-propertize 557 (lambda (mode size) 558 (propertize 559 (format " %s %d " mode size) 560 'face (doom-modeline-face))))) 561 (if indent-tabs-mode 562 (funcall do-propertize "TAB" tab-width) 563 (let ((lookup-var 564 (seq-find (lambda (var) 565 (and var (boundp var) (symbol-value var))) 566 (cdr (assoc major-mode doom-modeline-indent-alist)) nil))) 567 (funcall do-propertize "SPC" 568 (if lookup-var 569 (symbol-value lookup-var) 570 tab-width))))))) 571 572 ;; 573 ;; Remote host 574 ;; 575 576 (doom-modeline-def-segment remote-host 577 "Hostname for remote buffers." 578 (when default-directory 579 (when-let* ((host (file-remote-p default-directory 'host))) 580 (propertize 581 (concat "@" host) 582 'face (doom-modeline-face 'doom-modeline-host))))) 583 584 585 ;; 586 ;; Major mode 587 ;; 588 589 (doom-modeline-def-segment major-mode 590 "The major mode, including environment and text-scale info." 591 (let ((sep (doom-modeline-spc)) 592 (face (doom-modeline-face 'doom-modeline-buffer-major-mode))) 593 (concat 594 sep 595 (propertize (concat 596 (format-mode-line 597 (or (and (boundp 'delighted-modes) 598 (cadr (assq major-mode delighted-modes))) 599 mode-name)) 600 (when (and doom-modeline-env-version doom-modeline-env--version) 601 (format " %s" doom-modeline-env--version))) 602 'help-echo "Major mode\n\ 603 mouse-1: Display major mode menu\n\ 604 mouse-2: Show help for major mode\n\ 605 mouse-3: Toggle minor modes" 606 'face face 607 'mouse-face 'doom-modeline-highlight 608 'local-map mode-line-major-mode-keymap) 609 (and (boundp 'text-scale-mode-amount) 610 (/= text-scale-mode-amount 0) 611 (propertize 612 (format 613 (if (> text-scale-mode-amount 0) " (%+d)" " (%-d)") 614 text-scale-mode-amount) 615 'face face)) 616 sep))) 617 618 619 ;; 620 ;; Process 621 ;; 622 623 (doom-modeline-def-segment process 624 "The process info." 625 (doom-modeline-display-text 626 (format-mode-line mode-line-process))) 627 628 629 ;; 630 ;; Minor modes 631 ;; 632 633 (doom-modeline-def-segment minor-modes 634 (when doom-modeline-minor-modes 635 (let ((sep (doom-modeline-spc)) 636 (face (doom-modeline-face 'doom-modeline-buffer-minor-mode)) 637 (mouse-face 'doom-modeline-highlight) 638 (help-echo "Minor mode 639 mouse-1: Display minor mode menu 640 mouse-2: Show help for minor mode 641 mouse-3: Toggle minor modes")) 642 (if (bound-and-true-p minions-mode) 643 `((:propertize ("" ,(minions--prominent-modes)) 644 face ,face 645 mouse-face ,mouse-face 646 help-echo ,help-echo 647 local-map ,mode-line-minor-mode-keymap) 648 ,sep 649 (:propertize ("" ,(doom-modeline-icon 'octicon "nf-oct-gear" "â" 650 minions-mode-line-lighter 651 :face face)) 652 mouse-face ,mouse-face 653 help-echo "Minions 654 mouse-1: Display minor modes menu" 655 local-map ,minions-mode-line-minor-modes-map) 656 ,sep) 657 `((:propertize ("" minor-mode-alist) 658 face ,face 659 mouse-face ,mouse-face 660 help-echo ,help-echo 661 local-map ,mode-line-minor-mode-keymap) 662 ,sep))))) 663 664 665 ;; 666 ;; VCS 667 ;; 668 669 (defun doom-modeline-vcs-icon (icon &optional unicode text face) 670 "Displays the vcs ICON with FACE and VOFFSET. 671 672 UNICODE and TEXT are fallbacks. 673 Uses `nerd-icons-octicon' to fetch the icon." 674 (doom-modeline-icon 'devicon (and doom-modeline-vcs-icon icon) 675 unicode text :face face)) 676 677 (defvar-local doom-modeline--vcs nil) 678 (defun doom-modeline-update-vcs (&rest _) 679 "Update vcs state in mode-line." 680 (setq doom-modeline--vcs 681 (when (and vc-mode buffer-file-name) 682 (let* ((backend (vc-backend buffer-file-name)) 683 (state (vc-state buffer-file-name backend)) 684 (icon (cond ((memq state '(edited added)) 685 (doom-modeline-vcs-icon "nf-dev-git_compare" "đ" "*" 'doom-modeline-info)) 686 ((eq state 'needs-merge) 687 (doom-modeline-vcs-icon "nf-dev-git_merge" "đ" "?" 'doom-modeline-info)) 688 ((eq state 'needs-update) 689 (doom-modeline-vcs-icon "nf-dev-git_pull_request" "âŦ" "!" 'doom-modeline-warning)) 690 ((memq state '(removed conflict unregistered)) 691 (doom-modeline-icon 'octicon "nf-oct-alert" "â " "!" :face 'doom-modeline-urgent)) 692 (t (doom-modeline-vcs-icon "nf-dev-git_branch" "î " "@" 'doom-modeline-info)))) 693 (str (or (and vc-display-status 694 (functionp doom-modeline-vcs-display-function) 695 (funcall doom-modeline-vcs-display-function)) 696 "")) 697 (face (cond ((eq state 'needs-update) 698 '(doom-modeline-warning bold)) 699 ((memq state '(removed conflict unregistered)) 700 '(doom-modeline-urgent bold)) 701 (t '(doom-modeline-info bold)))) 702 (text (propertize (if (length> str doom-modeline-vcs-max-length) 703 (concat 704 (substring str 0 (- doom-modeline-vcs-max-length 3)) 705 doom-modeline-ellipsis) 706 str) 707 'face face))) 708 `((icon . ,icon) (text . ,text)))))) 709 (add-hook 'find-file-hook #'doom-modeline-update-vcs) 710 (add-hook 'after-save-hook #'doom-modeline-update-vcs) 711 (advice-add #'vc-refresh-state :after #'doom-modeline-update-vcs) 712 713 (doom-modeline-add-variable-watcher 714 'doom-modeline-icon 715 (lambda (_sym val op _where) 716 (when (eq op 'set) 717 (setq doom-modeline-icon val) 718 (dolist (buf (buffer-list)) 719 (with-current-buffer buf 720 (doom-modeline-update-vcs)))))) 721 722 (doom-modeline-add-variable-watcher 723 'doom-modeline-unicode-fallback 724 (lambda (_sym val op _where) 725 (when (eq op 'set) 726 (setq doom-modeline-unicode-fallback val) 727 (dolist (buf (buffer-list)) 728 (with-current-buffer buf 729 (doom-modeline-update-vcs)))))) 730 731 (doom-modeline-add-variable-watcher 732 'doom-modeline-vcs-icon 733 (lambda (_sym val op _where) 734 (when (eq op 'set) 735 (setq doom-modeline-vcs-icon val) 736 (dolist (buf (buffer-list)) 737 (with-current-buffer buf 738 (doom-modeline-update-vcs)))))) 739 740 (doom-modeline-add-variable-watcher 741 'vc-display-status 742 (lambda (_sym val op _where) 743 (when (eq op 'set) 744 (setq vc-display-status val) 745 (dolist (buf (buffer-list)) 746 (with-current-buffer buf 747 (doom-modeline-update-vcs)))))) 748 749 (doom-modeline-def-segment vcs 750 "Displays the current branch, colored based on its state." 751 (when doom-modeline--vcs 752 (let-alist doom-modeline--vcs 753 (let ((sep (doom-modeline-spc)) 754 (vsep (doom-modeline-vspc))) 755 (concat sep 756 (propertize (concat 757 (doom-modeline-display-icon .icon) 758 vsep 759 (doom-modeline-display-text .text)) 760 'help-echo (get-text-property 1 'help-echo vc-mode) 761 'mouse-face 'doom-modeline-highlight 762 'local-map (get-text-property 1 'local-map vc-mode)) 763 sep))))) 764 765 766 ;; 767 ;; Check 768 ;; 769 770 (defun doom-modeline-check-icon (icon unicode text face) 771 "Displays the check ICON with FACE. 772 773 UNICODE and TEXT are fallbacks. 774 Uses `nerd-icons-mdicon' to fetch the icon." 775 (doom-modeline-icon 'mdicon (and doom-modeline-check-icon icon) 776 unicode text :face face)) 777 778 (defun doom-modeline-check-text (text &optional face) 779 "Displays the check TEXT with FACE." 780 (propertize text 'face (or face 'mode-line))) 781 782 ;; Flycheck 783 784 (defun doom-modeline--flycheck-count-errors () 785 "Count the number of ERRORS, grouped by level. 786 787 Return an alist, where each ITEM is a cons cell whose `car' is an 788 error level, and whose `cdr' is the number of errors of that 789 level." 790 (let ((info 0) (warning 0) (error 0)) 791 (mapc 792 (lambda (item) 793 (let ((count (cdr item))) 794 (pcase (flycheck-error-level-compilation-level (car item)) 795 (0 (cl-incf info count)) 796 (1 (cl-incf warning count)) 797 (2 (cl-incf error count))))) 798 (flycheck-count-errors flycheck-current-errors)) 799 `((info . ,info) (warning . ,warning) (error . ,error)))) 800 801 (defvar-local doom-modeline--flycheck nil) 802 (defun doom-modeline-update-flycheck (&optional status) 803 "Update flycheck via STATUS." 804 (setq doom-modeline--flycheck 805 (let-alist (doom-modeline--flycheck-count-errors) 806 (let* ((vsep (doom-modeline-vspc)) 807 (seg (if doom-modeline-check-simple-format 808 (let ((count (+ .error .warning .info))) 809 (pcase status 810 ('finished (if (> count 0) 811 (let ((face (if (> .error 0) 'doom-modeline-urgent 'doom-modeline-warning))) 812 (concat 813 (doom-modeline-check-icon "nf-md-alert_circle_outline" "â " "!" face) 814 vsep 815 (doom-modeline-check-text (number-to-string count) face))) 816 (doom-modeline-check-icon "nf-md-check_circle_outline" "â" "*" 'doom-modeline-info))) 817 ('running (concat 818 (doom-modeline-check-icon "nf-md-timer_sand" "âŗ" "*" 'doom-modeline-debug) 819 (when (> count 0) 820 (concat 821 vsep 822 (doom-modeline-check-text (number-to-string count) 'doom-modeline-debug))))) 823 ('no-checker (doom-modeline-check-icon "nf-md-alert_box_outline" "â " "-" 'doom-modeline-debug)) 824 ('errored (doom-modeline-check-icon "nf-md-alert_box_outline" "â " "!" 'doom-modeline-urgent)) 825 ('interrupted (doom-modeline-check-icon "nf-md-pause_circle_outline" "âĻˇ" "." 'doom-modeline-debug)) 826 ('suspicious (doom-modeline-check-icon "nf-md-file_question_outline" "â" "?" 'doom-modeline-debug)) 827 (_ ""))) 828 (concat (doom-modeline-check-icon "nf-md-close_circle_outline" "⎞" "!" 'doom-modeline-urgent) 829 vsep 830 (doom-modeline-check-text (number-to-string .error) 'doom-modeline-urgent) 831 vsep 832 (doom-modeline-check-icon "nf-md-alert_outline" "â " "!" 'doom-modeline-warning) 833 vsep 834 (doom-modeline-check-text (number-to-string .warning) 'doom-modeline-warning) 835 vsep 836 (doom-modeline-check-icon "nf-md-information_outline" "đ" "!" 'doom-modeline-info) 837 vsep 838 (doom-modeline-check-text (number-to-string .info) 'doom-modeline-info))))) 839 (propertize seg 840 'help-echo (concat "Flycheck\n" 841 (pcase status 842 ('finished (format "error: %d, warning: %d, info: %d" .error .warning .info)) 843 ('running "Checking...") 844 ('no-checker "No Checker") 845 ('errored "Error") 846 ('interrupted "Interrupted") 847 ('suspicious "Suspicious")) 848 "\nmouse-1: Display minor mode menu\nmouse-2: Show help for minor mode") 849 'mouse-face 'doom-modeline-highlight 850 'local-map (let ((map (make-sparse-keymap))) 851 (define-key map [mode-line down-mouse-1] 852 flycheck-mode-menu-map) 853 (define-key map [mode-line mouse-2] 854 (lambda () 855 (interactive) 856 (describe-function 'flycheck-mode))) 857 map)))))) 858 (add-hook 'flycheck-status-changed-functions #'doom-modeline-update-flycheck) 859 (add-hook 'flycheck-mode-hook #'doom-modeline-update-flycheck) 860 861 (doom-modeline-add-variable-watcher 862 'doom-modeline-icon 863 (lambda (_sym val op _where) 864 (when (eq op 'set) 865 (setq doom-modeline-icon val) 866 (dolist (buf (buffer-list)) 867 (with-current-buffer buf 868 (when (bound-and-true-p flycheck-mode) 869 (doom-modeline-update-flycheck))))))) 870 871 (doom-modeline-add-variable-watcher 872 'doom-modeline-check-icon 873 (lambda (_sym val op _where) 874 (when (eq op 'set) 875 (setq doom-modeline-check-icon val) 876 (dolist (buf (buffer-list)) 877 (with-current-buffer buf 878 (when (bound-and-true-p flycheck-mode) 879 (doom-modeline-update-flycheck))))))) 880 881 (doom-modeline-add-variable-watcher 882 'doom-modeline-unicode-fallback 883 (lambda (_sym val op _where) 884 (when (eq op 'set) 885 (setq doom-modeline-unicode-fallback val) 886 (dolist (buf (buffer-list)) 887 (with-current-buffer buf 888 (when (bound-and-true-p flycheck-mode) 889 (doom-modeline-update-flycheck))))))) 890 891 (doom-modeline-add-variable-watcher 892 'doom-modeline-check-simple-format 893 (lambda (_sym val op _where) 894 (when (eq op 'set) 895 (setq doom-modeline-check-simple-format val) 896 (dolist (buf (buffer-list)) 897 (with-current-buffer buf 898 (when (bound-and-true-p flycheck-mode) 899 (doom-modeline-update-flycheck))))))) 900 901 ;; Flymake 902 903 ;; Compatibility 904 ;; @see https://github.com/emacs-mirror/emacs/commit/6e100869012da9244679696634cab6b9cac96303. 905 (with-eval-after-load 'flymake 906 (unless (boundp 'flymake--state) 907 (defvaralias 'flymake--state 'flymake--backend-state)) 908 (unless (fboundp 'flymake--state-diags) 909 (defalias 'flymake--state-diags 'flymake--backend-state-diags))) 910 911 (defun doom-modeline--flymake-count-errors () 912 "Count the number of ERRORS, grouped by level." 913 (let ((warning-level (warning-numeric-level :warning)) 914 (note-level (warning-numeric-level :debug)) 915 (note 0) (warning 0) (error 0)) 916 (maphash (lambda (_b state) 917 (cl-loop 918 with diags = (flymake--state-diags state) 919 for diag in diags do 920 (let ((severity (flymake--lookup-type-property (flymake--diag-type diag) 'severity 921 (warning-numeric-level :error)))) 922 (cond ((> severity warning-level) (cl-incf error)) 923 ((> severity note-level) (cl-incf warning)) 924 (t (cl-incf note)))))) 925 flymake--state) 926 `((note . ,note) (warning . ,warning) (error . ,error)))) 927 928 (defvar-local doom-modeline--flymake nil) 929 (defun doom-modeline-update-flymake (&rest _) 930 "Update flymake." 931 (setq doom-modeline--flymake 932 (let* ((known (hash-table-keys flymake--state)) 933 (running (flymake-running-backends)) 934 (disabled (flymake-disabled-backends)) 935 (reported (flymake-reporting-backends)) 936 (all-disabled (and disabled (null running))) 937 (some-waiting (cl-set-difference running reported))) 938 (let-alist (doom-modeline--flymake-count-errors) 939 (let* ((vsep (doom-modeline-vspc)) 940 (seg (if doom-modeline-check-simple-format 941 (let ((count (+ .error .warning .note))) 942 (cond 943 (some-waiting (concat 944 (doom-modeline-check-icon "nf-md-timer_sand" "âŗ" "*" 'doom-modeline-debug) 945 (when (> count 0) 946 (concat 947 vsep 948 (doom-modeline-check-text (number-to-string count) 'doom-modeline-debug))))) 949 ((null known) (doom-modeline-check-icon "nf-md-alert_box_outline" "â " "!" 'doom-modeline-urgent)) 950 (all-disabled (doom-modeline-check-icon "nf-md-alert_box_outline" "â " "!" 'doom-modeline-warning)) 951 (t (if (> count 0) 952 (let ((face (cond ((> .error 0) 'doom-modeline-urgent) 953 ((> .warning 0) 'doom-modeline-warning) 954 (t 'doom-modeline-info)))) 955 (concat 956 (doom-modeline-check-icon "nf-md-alert_circle_outline" "â " "!" face) 957 vsep 958 (doom-modeline-check-text (number-to-string count) face))) 959 (doom-modeline-check-icon "nf-md-check_circle_outline" "â" "*" 'doom-modeline-info))))) 960 (concat 961 (doom-modeline-check-icon "nf-md-close_circle_outline" "⎞" "!" 'doom-modeline-urgent) 962 vsep 963 (doom-modeline-check-text (number-to-string .error) 'doom-modeline-urgent) 964 vsep 965 (doom-modeline-check-icon "nf-md-alert_outline" "â " "!" 'doom-modeline-warning) 966 vsep 967 (doom-modeline-check-text (number-to-string .warning) 'doom-modeline-warning) 968 vsep 969 (doom-modeline-check-icon "nf-md-information_outline" "đ" "!" 'doom-modeline-info) 970 vsep 971 (doom-modeline-check-text (number-to-string .note) 'doom-modeline-info))))) 972 (propertize 973 seg 974 'help-echo (concat 975 "Flymake\n" 976 (cond (some-waiting "Checking...") 977 ((null known) "No Checker") 978 (all-disabled "All Checkers Disabled") 979 (t (format "%d/%d backends running\nerror: %d, warning: %d, note: %d" 980 (length running) (length known) .error .warning .note))) 981 "\nmouse-1: Display minor mode menu\nmouse-2: Show help for minor mode") 982 'mouse-face 'doom-modeline-highlight 983 'local-map (let ((map (make-sparse-keymap))) 984 (define-key map [mode-line down-mouse-1] 985 flymake-menu) 986 (define-key map [mode-line mouse-2] 987 (lambda () 988 (interactive) 989 (describe-function 'flymake-mode))) 990 map))))))) 991 (advice-add #'flymake--handle-report :after #'doom-modeline-update-flymake) 992 993 (doom-modeline-add-variable-watcher 994 'doom-modeline-icon 995 (lambda (_sym val op _where) 996 (when (eq op 'set) 997 (setq doom-modeline-icon val) 998 (dolist (buf (buffer-list)) 999 (with-current-buffer buf 1000 (when (bound-and-true-p flymake-mode) 1001 (doom-modeline-update-flymake))))))) 1002 1003 (doom-modeline-add-variable-watcher 1004 'doom-modeline-check-icon 1005 (lambda (_sym val op _where) 1006 (when (eq op 'set) 1007 (setq doom-modeline-check-icon val) 1008 (dolist (buf (buffer-list)) 1009 (with-current-buffer buf 1010 (when (bound-and-true-p flymake-mode) 1011 (doom-modeline-update-flymake))))))) 1012 1013 (doom-modeline-add-variable-watcher 1014 'doom-modeline-unicode-fallback 1015 (lambda (_sym val op _where) 1016 (when (eq op 'set) 1017 (setq doom-modeline-unicode-fallback val) 1018 (dolist (buf (buffer-list)) 1019 (with-current-buffer buf 1020 (when (bound-and-true-p flymake-mode) 1021 (doom-modeline-update-flymake))))))) 1022 1023 (doom-modeline-add-variable-watcher 1024 'doom-modeline-check-simple-format 1025 (lambda (_sym val op _where) 1026 (when (eq op 'set) 1027 (setq doom-modeline-check-simple-format val) 1028 (dolist (buf (buffer-list)) 1029 (with-current-buffer buf 1030 (when (bound-and-true-p flymake-mode) 1031 (doom-modeline-update-flymake))))))) 1032 1033 (doom-modeline-def-segment check 1034 "Displays color-coded error status in the current buffer with pretty icons." 1035 (when-let* ((sep (doom-modeline-spc)) 1036 (vsep (doom-modeline-vspc)) 1037 (seg (cond 1038 ((and (bound-and-true-p flymake-mode) 1039 (bound-and-true-p flymake--state)) ; only support 26+ 1040 doom-modeline--flymake) 1041 ((and (bound-and-true-p flycheck-mode) 1042 (bound-and-true-p flycheck--automatically-enabled-checkers)) 1043 doom-modeline--flycheck)))) 1044 (concat 1045 sep 1046 (let ((str)) 1047 (dolist (s (split-string seg " ")) 1048 (setq str 1049 (concat str 1050 (if (string-match-p "^[0-9]+$" s) 1051 (concat vsep 1052 (doom-modeline-display-text s) 1053 vsep) 1054 (doom-modeline-display-icon s))))) 1055 (propertize str 1056 'help-echo (get-text-property 0 'help-echo seg) 1057 'mouse-face 'doom-modeline-highlight 1058 'local-map (get-text-property 0 'local-map seg))) 1059 sep))) 1060 1061 1062 ;; 1063 ;; Word Count 1064 ;; 1065 1066 (doom-modeline-def-segment word-count 1067 "The buffer word count. 1068 Displayed when in a major mode in `doom-modeline-continuous-word-count-modes'. 1069 Respects `doom-modeline-enable-word-count'." 1070 (when (and doom-modeline-enable-word-count 1071 (member major-mode doom-modeline-continuous-word-count-modes)) 1072 (propertize (format " %dW" (count-words (point-min) (point-max))) 1073 'face (doom-modeline-face)))) 1074 1075 1076 ;; 1077 ;; Selection 1078 ;; 1079 1080 (defsubst doom-modeline-column (pos) 1081 "Get the column of the position `POS'." 1082 (save-excursion (goto-char pos) 1083 (current-column))) 1084 1085 (doom-modeline-def-segment selection-info 1086 "Information about the current selection. 1087 1088 Such as how many characters and lines are selected, or the NxM dimensions of a 1089 block selection." 1090 (when (and (or mark-active (and (bound-and-true-p evil-local-mode) 1091 (eq evil-state 'visual))) 1092 (doom-modeline--active)) 1093 (cl-destructuring-bind (beg . end) 1094 (if (and (bound-and-true-p evil-local-mode) (eq evil-state 'visual)) 1095 (cons evil-visual-beginning evil-visual-end) 1096 (cons (region-beginning) (region-end))) 1097 (propertize 1098 (let ((lines (count-lines beg (min end (point-max))))) 1099 (concat 1100 " " 1101 (cond ((or (bound-and-true-p rectangle-mark-mode) 1102 (and (bound-and-true-p evil-visual-selection) 1103 (eq 'block evil-visual-selection))) 1104 (let ((cols (abs (- (doom-modeline-column end) 1105 (doom-modeline-column beg))))) 1106 (format "%dx%dB" lines cols))) 1107 ((and (bound-and-true-p evil-visual-selection) 1108 (eq evil-visual-selection 'line)) 1109 (format "%dL" lines)) 1110 ((> lines 1) 1111 (format "%dC %dL" (- end beg) lines)) 1112 (t 1113 (format "%dC" (- end beg)))) 1114 (when doom-modeline-enable-word-count 1115 (format " %dW" (count-words beg end))) 1116 " ")) 1117 'face 'doom-modeline-emphasis)))) 1118 1119 1120 ;; 1121 ;; Matches (macro, anzu, evil-substitute, iedit, symbol-overlay and multi-cursors) 1122 ;; 1123 1124 (defsubst doom-modeline--macro-recording () 1125 "Display current Emacs or evil macro being recorded." 1126 (when (and (doom-modeline--active) 1127 (or defining-kbd-macro executing-kbd-macro)) 1128 (let ((sep (propertize " " 'face 'doom-modeline-panel)) 1129 (vsep (propertize " " 'face 1130 '(:inherit (doom-modeline-panel variable-pitch)))) 1131 (macro-name (if (bound-and-true-p evil-this-macro) 1132 (format " @%s " 1133 (char-to-string evil-this-macro)) 1134 "Macro"))) 1135 (concat 1136 sep 1137 (if doom-modeline-always-show-macro-register 1138 (propertize macro-name 'face 'doom-modeline-panel) 1139 (concat 1140 (doom-modeline-icon 'mdicon "nf-md-record" "â" 1141 macro-name 1142 :face '(:inherit (doom-modeline-urgent doom-modeline-panel)) 1143 :v-adjust 0.15) 1144 vsep 1145 (doom-modeline-icon 'mdicon "nf-md-menu_right" "âļ" ">" 1146 :face 'doom-modeline-panel 1147 :v-adjust 0.15))) 1148 sep)))) 1149 1150 ;; `anzu' and `evil-anzu' expose current/total state that can be displayed in the 1151 ;; mode-line. 1152 (defun doom-modeline-fix-anzu-count (positions here) 1153 "Calulate anzu count via POSITIONS and HERE." 1154 (cl-loop with i = 0 1155 for (start . end) in positions 1156 do (cl-incf i) 1157 when (and (>= here start) (<= here end)) 1158 return i 1159 finally return 0)) 1160 1161 (advice-add #'anzu--where-is-here :override #'doom-modeline-fix-anzu-count) 1162 1163 (setq anzu-cons-mode-line-p nil) ; manage modeline segment ourselves 1164 ;; Ensure anzu state is cleared when searches & iedit are done 1165 (with-eval-after-load 'anzu 1166 (add-hook 'isearch-mode-end-hook #'anzu--reset-status t) 1167 (add-hook 'iedit-mode-end-hook #'anzu--reset-status) 1168 (advice-add #'evil-force-normal-state :after #'anzu--reset-status) 1169 ;; Fix matches segment mirroring across all buffers 1170 (mapc #'make-variable-buffer-local 1171 '(anzu--total-matched 1172 anzu--current-position anzu--state anzu--cached-count 1173 anzu--cached-positions anzu--last-command 1174 anzu--last-isearch-string anzu--overflow-p))) 1175 1176 (defsubst doom-modeline--anzu () 1177 "Show the match index and total number thereof. 1178 Requires `anzu', also `evil-anzu' if using `evil-mode' for compatibility with 1179 `evil-search'." 1180 (when (and (bound-and-true-p anzu--state) 1181 (not (bound-and-true-p iedit-mode))) 1182 (propertize 1183 (let ((here anzu--current-position) 1184 (total anzu--total-matched)) 1185 (cond ((eq anzu--state 'replace-query) 1186 (format " %d replace " anzu--cached-count)) 1187 ((eq anzu--state 'replace) 1188 (format " %d/%d " here total)) 1189 (anzu--overflow-p 1190 (format " %s+ " total)) 1191 (t 1192 (format " %s/%d " here total)))) 1193 'face (doom-modeline-face 'doom-modeline-panel)))) 1194 1195 (defsubst doom-modeline--evil-substitute () 1196 "Show number of matches for `evil-ex' in real time. 1197 The number of matches contains substitutions and highlightings." 1198 (when (and (bound-and-true-p evil-local-mode) 1199 (or (assq 'evil-ex-substitute evil-ex-active-highlights-alist) 1200 (assq 'evil-ex-global-match evil-ex-active-highlights-alist) 1201 (assq 'evil-ex-buffer-match evil-ex-active-highlights-alist))) 1202 (propertize 1203 (let ((range (if evil-ex-range 1204 (cons (car evil-ex-range) (cadr evil-ex-range)) 1205 (cons (line-beginning-position) (line-end-position)))) 1206 (pattern (car-safe (evil-delimited-arguments evil-ex-argument 2)))) 1207 (if pattern 1208 (format " %s matches " (how-many pattern (car range) (cdr range))) 1209 " - ")) 1210 'face (doom-modeline-face 'doom-modeline-panel)))) 1211 1212 (defun doom-modeline-themes--overlay-sort (a b) 1213 "Sort overlay A and B." 1214 (< (overlay-start a) (overlay-start b))) 1215 1216 (defsubst doom-modeline--iedit () 1217 "Show the number of iedit regions matches + what match you're on." 1218 (when (and (bound-and-true-p iedit-mode) 1219 (bound-and-true-p iedit-occurrences-overlays)) 1220 (propertize 1221 (let ((this-oc (or (let ((inhibit-message t)) 1222 (iedit-find-current-occurrence-overlay)) 1223 (save-excursion (iedit-prev-occurrence) 1224 (iedit-find-current-occurrence-overlay)))) 1225 (length (length iedit-occurrences-overlays))) 1226 (format " %s/%d " 1227 (if this-oc 1228 (- length 1229 (length (memq this-oc (sort (append iedit-occurrences-overlays nil) 1230 #'doom-modeline-themes--overlay-sort))) 1231 -1) 1232 "-") 1233 length)) 1234 'face (doom-modeline-face 'doom-modeline-panel)))) 1235 1236 (defsubst doom-modeline--symbol-overlay () 1237 "Show the number of matches for symbol overlay." 1238 (when (and (doom-modeline--active) 1239 (bound-and-true-p symbol-overlay-keywords-alist) 1240 (not (bound-and-true-p symbol-overlay-temp-symbol)) 1241 (not (bound-and-true-p iedit-mode))) 1242 (let* ((keyword (symbol-overlay-assoc (symbol-overlay-get-symbol t))) 1243 (symbol (car keyword)) 1244 (before (symbol-overlay-get-list -1 symbol)) 1245 (after (symbol-overlay-get-list 1 symbol)) 1246 (count (length before))) 1247 (if (symbol-overlay-assoc symbol) 1248 (propertize 1249 (format (concat " %d/%d " (and (cadr keyword) "in scope ")) 1250 (+ count 1) 1251 (+ count (length after))) 1252 'face (doom-modeline-face 'doom-modeline-panel)))))) 1253 1254 (defsubst doom-modeline--multiple-cursors () 1255 "Show the number of multiple cursors." 1256 (cl-destructuring-bind (count . face) 1257 (cond ((bound-and-true-p multiple-cursors-mode) 1258 (cons (mc/num-cursors) 1259 (doom-modeline-face 'doom-modeline-panel))) 1260 ((bound-and-true-p evil-mc-cursor-list) 1261 (cons (length evil-mc-cursor-list) 1262 (doom-modeline-face (if evil-mc-frozen 1263 'doom-modeline-bar 1264 'doom-modeline-panel)))) 1265 ((cons nil nil))) 1266 (when count 1267 (concat (propertize " " 'face face) 1268 (if (doom-modeline-icon-displayable-p) 1269 (doom-modeline-icon 'faicon "nf-fa-i_cursor" "" "" :face face) 1270 (propertize "I" 1271 'face `(:inherit ,face :height 1.4 :weight normal) 1272 'display '(raise -0.1))) 1273 (propertize " " 1274 'face `(:inherit (variable-pitch ,face))) 1275 (propertize (format "%d " count) 1276 'face face))))) 1277 1278 (defsubst doom-modeline--phi-search () 1279 "Show the number of matches for `phi-search' and `phi-replace'." 1280 (when (and (doom-modeline--active) 1281 (bound-and-true-p phi-search--overlays)) 1282 (let ((total (length phi-search--overlays)) 1283 (selection phi-search--selection)) 1284 (when selection 1285 (propertize 1286 (format " %d/%d " (1+ selection) total) 1287 'face (doom-modeline-face 'doom-modeline-panel)))))) 1288 1289 (defun doom-modeline--override-phi-search (orig-fun &rest args) 1290 "Override the mode-line of `phi-search' and `phi-replace'. 1291 Apply ORIG-FUN with ARGS." 1292 (if (bound-and-true-p doom-modeline-mode) 1293 (apply orig-fun mode-line-format (cdr args)) 1294 (apply orig-fun args))) 1295 (advice-add #'phi-search--initialize :around #'doom-modeline--override-phi-search) 1296 1297 (defsubst doom-modeline--buffer-size () 1298 "Show buffer size." 1299 (when size-indication-mode 1300 (let ((sep (doom-modeline-spc))) 1301 (concat sep 1302 (propertize "%I" 1303 'face (doom-modeline-face) 1304 'help-echo "Buffer size 1305 mouse-1: Display Line and Column Mode Menu" 1306 'mouse-face 'doom-modeline-highlight 1307 'local-map mode-line-column-line-number-mode-map) 1308 sep)))) 1309 1310 (doom-modeline-def-segment matches 1311 "Displays matches. 1312 1313 Including: 1314 1. the currently recording macro, 2. A current/total for the 1315 current search term (with `anzu'), 3. The number of substitutions being 1316 conducted with `evil-ex-substitute', and/or 4. The number of active `iedit' 1317 regions, 5. The current/total for the highlight term (with `symbol-overlay'), 1318 6. The number of active `multiple-cursors'." 1319 (let ((meta (concat (doom-modeline--macro-recording) 1320 (doom-modeline--anzu) 1321 (doom-modeline--phi-search) 1322 (doom-modeline--evil-substitute) 1323 (doom-modeline--iedit) 1324 (doom-modeline--symbol-overlay) 1325 (doom-modeline--multiple-cursors)))) 1326 (or (and (not (string-empty-p meta)) meta) 1327 (doom-modeline--buffer-size)))) 1328 1329 (doom-modeline-def-segment buffer-size 1330 "Display buffer size." 1331 (doom-modeline--buffer-size)) 1332 1333 ;; 1334 ;; Media 1335 ;; 1336 1337 (doom-modeline-def-segment media-info 1338 "Metadata regarding the current file, such as dimensions for images." 1339 ;; TODO: Include other information 1340 (cond ((eq major-mode 'image-mode) 1341 (cl-destructuring-bind (width . height) 1342 (when (fboundp 'image-size) 1343 (image-size (image-get-display-property) :pixels)) 1344 (format " %dx%d " width height))))) 1345 1346 1347 ;; 1348 ;; Bars 1349 ;; 1350 1351 (defvar doom-modeline--bar-active nil) 1352 (defvar doom-modeline--bar-inactive nil) 1353 1354 (defsubst doom-modeline--bar () 1355 "The default bar regulates the height of the mode-line in GUI." 1356 (unless (and doom-modeline--bar-active doom-modeline--bar-inactive) 1357 (let ((width doom-modeline-bar-width) 1358 (height (max doom-modeline-height (doom-modeline--font-height)))) 1359 (setq doom-modeline--bar-active 1360 (doom-modeline--create-bar-image 'doom-modeline-bar width height) 1361 doom-modeline--bar-inactive 1362 (doom-modeline--create-bar-image 1363 'doom-modeline-bar-inactive width height)))) 1364 (if (doom-modeline--active) 1365 doom-modeline--bar-active 1366 doom-modeline--bar-inactive)) 1367 1368 (defun doom-modeline-refresh-bars () 1369 "Refresh mode-line bars on next redraw." 1370 (setq doom-modeline--bar-active nil 1371 doom-modeline--bar-inactive nil)) 1372 1373 (cl-defstruct doom-modeline--hud-cache active inactive top-margin bottom-margin) 1374 1375 (defsubst doom-modeline--hud () 1376 "Powerline's hud segment reimplemented in the style of Doom's bar segment." 1377 (let* ((ws (window-start)) 1378 (we (window-end)) 1379 (bs (buffer-size)) 1380 (height (max doom-modeline-height (doom-modeline--font-height))) 1381 (top-margin (if (zerop bs) 1382 0 1383 (/ (* height (1- ws)) bs))) 1384 (bottom-margin (if (zerop bs) 1385 0 1386 (max 0 (/ (* height (- bs we 1)) bs)))) 1387 (cache (or (window-parameter nil 'doom-modeline--hud-cache) 1388 (set-window-parameter 1389 nil 1390 'doom-modeline--hud-cache 1391 (make-doom-modeline--hud-cache))))) 1392 (unless (and (doom-modeline--hud-cache-active cache) 1393 (doom-modeline--hud-cache-inactive cache) 1394 (= top-margin (doom-modeline--hud-cache-top-margin cache)) 1395 (= bottom-margin 1396 (doom-modeline--hud-cache-bottom-margin cache))) 1397 (setf (doom-modeline--hud-cache-active cache) 1398 (doom-modeline--create-hud-image 1399 'doom-modeline-bar 'default doom-modeline-bar-width 1400 height top-margin bottom-margin) 1401 (doom-modeline--hud-cache-inactive cache) 1402 (doom-modeline--create-hud-image 1403 'doom-modeline-bar-inactive 'default doom-modeline-bar-width 1404 height top-margin bottom-margin) 1405 (doom-modeline--hud-cache-top-margin cache) top-margin 1406 (doom-modeline--hud-cache-bottom-margin cache) bottom-margin)) 1407 (if (doom-modeline--active) 1408 (doom-modeline--hud-cache-active cache) 1409 (doom-modeline--hud-cache-inactive cache)))) 1410 1411 (defun doom-modeline-invalidate-huds () 1412 "Invalidate all cached hud images." 1413 (dolist (frame (frame-list)) 1414 (dolist (window (window-list frame)) 1415 (set-window-parameter window 'doom-modeline--hud-cache nil)))) 1416 1417 (doom-modeline-add-variable-watcher 1418 'doom-modeline-height 1419 (lambda (_sym val op _where) 1420 (when (and (eq op 'set) (integerp val)) 1421 (doom-modeline-refresh-bars) 1422 (doom-modeline-invalidate-huds)))) 1423 1424 (doom-modeline-add-variable-watcher 1425 'doom-modeline-bar-width 1426 (lambda (_sym val op _where) 1427 (when (and (eq op 'set) (integerp val)) 1428 (doom-modeline-refresh-bars) 1429 (doom-modeline-invalidate-huds)))) 1430 1431 (doom-modeline-add-variable-watcher 1432 'doom-modeline-icon 1433 (lambda (_sym _val op _where) 1434 (when (eq op 'set) 1435 (doom-modeline-refresh-bars) 1436 (doom-modeline-invalidate-huds)))) 1437 1438 (doom-modeline-add-variable-watcher 1439 'doom-modeline-unicode-fallback 1440 (lambda (_sym _val op _where) 1441 (when (eq op 'set) 1442 (doom-modeline-refresh-bars) 1443 (doom-modeline-invalidate-huds)))) 1444 1445 (add-hook 'window-configuration-change-hook #'doom-modeline-refresh-bars) 1446 (add-hook 'window-configuration-change-hook #'doom-modeline-invalidate-huds) 1447 1448 (doom-modeline-def-segment bar 1449 "The bar regulates the height of the `doom-modeline' in GUI." 1450 (when (display-graphic-p) 1451 (concat 1452 (if doom-modeline-hud 1453 (doom-modeline--hud) 1454 (doom-modeline--bar)) 1455 (doom-modeline-spc)))) 1456 1457 (doom-modeline-def-segment hud 1458 "Powerline's hud segment reimplemented in the style of bar segment." 1459 (when (display-graphic-p) 1460 (concat 1461 (doom-modeline--hud) 1462 (doom-modeline-spc)))) 1463 1464 1465 ;; 1466 ;; Window number 1467 ;; 1468 1469 ;; HACK: `ace-window-display-mode' should respect the ignore buffers. 1470 (defun doom-modeline-aw-update () 1471 "Update ace-window-path window parameter for all windows. 1472 Ensure all windows are labeled so the user can select a specific 1473 one. The ignored buffers are excluded unless `aw-ignore-on' is nil." 1474 (let ((ignore-window-parameters t)) 1475 (avy-traverse 1476 (avy-tree (aw-window-list) aw-keys) 1477 (lambda (path leaf) 1478 (set-window-parameter 1479 leaf 'ace-window-path 1480 (propertize 1481 (apply #'string (reverse path)) 1482 'face 'aw-mode-line-face)))))) 1483 (advice-add #'aw-update :override #'doom-modeline-aw-update) 1484 1485 ;; Remove original window number of `ace-window-display-mode'. 1486 (add-hook 'ace-window-display-mode-hook 1487 (lambda () 1488 (setq-default mode-line-format 1489 (assq-delete-all 'ace-window-display-mode 1490 (default-value 'mode-line-format))))) 1491 1492 (advice-add #'window-numbering-install-mode-line :override #'ignore) 1493 (advice-add #'window-numbering-clear-mode-line :override #'ignore) 1494 (advice-add #'winum--install-mode-line :override #'ignore) 1495 (advice-add #'winum--clear-mode-line :override #'ignore) 1496 1497 (doom-modeline-def-segment window-number 1498 "The current window number." 1499 (let ((num (cond 1500 ((bound-and-true-p ace-window-display-mode) 1501 (aw-update) 1502 (window-parameter (selected-window) 'ace-window-path)) 1503 ((bound-and-true-p winum-mode) 1504 (setq winum-auto-setup-mode-line nil) 1505 (winum-get-number-string)) 1506 ((bound-and-true-p window-numbering-mode) 1507 (window-numbering-get-number-string)) 1508 (t "")))) 1509 (when (and (length> num 0) 1510 (length> (cl-mapcan 1511 (lambda (frame) 1512 ;; Exclude minibuffer, tooltip and child frames 1513 (unless (or (and (fboundp 'frame-parent) (frame-parent frame)) 1514 (string= (frame-parameter frame 'name) 1515 (alist-get 'name (bound-and-true-p tooltip-frame-parameters)))) 1516 (window-list frame 'never))) 1517 (visible-frame-list)) 1518 1)) 1519 (propertize (format " %s " num) 1520 'face (doom-modeline-face 'doom-modeline-buffer-major-mode))))) 1521 1522 ;; 1523 ;; Project 1524 ;; 1525 1526 (defvar doom-modeline-project-map 1527 (cond 1528 ((and (memq doom-modeline-project-detection '(auto projectile)) 1529 (bound-and-true-p projectile-mode)) 1530 projectile-mode-map) 1531 ((and (memq doom-modeline-project-detection '(auto project)) 1532 (fboundp 'project-current)) 1533 (let ((map (make-sparse-keymap))) 1534 (define-key map [mode-line down-mouse-1] 1535 (bound-and-true-p menu-bar-project-item)) 1536 map)))) 1537 1538 (defvar-local doom-modeline--project-name nil) 1539 (defun doom-modeline-project-name () 1540 "Get the project name." 1541 (or doom-modeline--project-name 1542 (setq doom-modeline--project-name 1543 (let ((name (cond 1544 ((and (memq doom-modeline-project-detection '(auto projectile)) 1545 (bound-and-true-p projectile-mode)) 1546 (projectile-project-name)) 1547 ((and (memq doom-modeline-project-detection '(auto project)) 1548 (fboundp 'project-current)) 1549 (when-let* ((project (project-current))) 1550 (project-name project)))))) 1551 (if (and name (not (string-empty-p name))) 1552 (format " [%s] " name) 1553 ""))))) 1554 1555 (doom-modeline-add-variable-watcher 1556 'doom-modeline-project-detection 1557 (lambda (_sym val op _where) 1558 (when (eq op 'set) 1559 (setq doom-modeline-project-detection val) 1560 (dolist (buf (buffer-list)) 1561 (with-current-buffer buf 1562 (setq doom-modeline--project-name nil) 1563 (and buffer-file-name (revert-buffer t t))))))) 1564 1565 (doom-modeline-def-segment project-name 1566 "The current perspective name." 1567 (when (and doom-modeline-project-name 1568 (doom-modeline--segment-visible 'project-name)) 1569 (propertize (doom-modeline-project-name) 1570 'face (doom-modeline-face 'doom-modeline-project-name) 1571 'mouse-face 'mode-line-highlight 1572 'help-echo "mouse-1: Project menu" 1573 'local-map doom-modeline-project-map))) 1574 1575 1576 ;; 1577 ;; Workspace 1578 ;; 1579 1580 (doom-modeline-def-segment workspace-name 1581 "The current workspace name or number. 1582 Requires `eyebrowse-mode' to be enabled or `tab-bar-mode' tabs to be created." 1583 (when doom-modeline-workspace-name 1584 (when-let* 1585 ((name (cond 1586 ((and (bound-and-true-p eyebrowse-mode) 1587 (length> (eyebrowse--get 'window-configs) 1)) 1588 (setq mode-line-misc-info 1589 (assq-delete-all 'eyebrowse-mode mode-line-misc-info)) 1590 (when-let* 1591 ((num (eyebrowse--get 'current-slot)) 1592 (tag (nth 2 (assoc num (eyebrowse--get 'window-configs))))) 1593 (if (length> tag 0) tag (int-to-string num)))) 1594 ((and (fboundp 'tab-bar-mode) 1595 (length> (frame-parameter nil 'tabs) 1)) 1596 (let* ((current-tab (tab-bar--current-tab)) 1597 (tab-index (tab-bar--current-tab-index)) 1598 (explicit-name (alist-get 'explicit-name current-tab)) 1599 (tab-name (alist-get 'name current-tab))) 1600 (if explicit-name tab-name (+ 1 tab-index))))))) 1601 (unless (string-empty-p name) 1602 (propertize (format " %s " name) 1603 'face (doom-modeline-face 'doom-modeline-workspace-name)))))) 1604 1605 1606 ;; 1607 ;; Perspective 1608 ;; 1609 1610 (defvar-local doom-modeline--persp-name nil) 1611 (defun doom-modeline-update-persp-name (&rest _) 1612 "Update perspective name in mode-line." 1613 (setq doom-modeline--persp-name 1614 ;; Support `persp-mode', while not support `perspective' 1615 (when (and doom-modeline-persp-name 1616 (bound-and-true-p persp-mode) 1617 (fboundp 'safe-persp-name) 1618 (fboundp 'get-current-persp)) 1619 (let* ((persp (get-current-persp)) 1620 (name (safe-persp-name persp)) 1621 (face (if (and persp 1622 (not (persp-contain-buffer-p (current-buffer) persp))) 1623 'doom-modeline-persp-buffer-not-in-persp 1624 'doom-modeline-persp-name)) 1625 (icon (doom-modeline-icon 'octicon "nf-oct-repo" "đŋ" "#" 1626 :face `(:inherit ,face :slant normal)))) 1627 (when (or doom-modeline-display-default-persp-name 1628 (not (string-equal persp-nil-name name))) 1629 (concat " " 1630 (propertize (concat (and doom-modeline-persp-icon 1631 (concat icon (doom-modeline-vspc))) 1632 (propertize name 'face face)) 1633 'help-echo "mouse-1: Switch perspective 1634 mouse-2: Show help for minor mode" 1635 'mouse-face 'doom-modeline-highlight 1636 'local-map (let ((map (make-sparse-keymap))) 1637 (define-key map [mode-line mouse-1] 1638 #'persp-switch) 1639 (define-key map [mode-line mouse-2] 1640 (lambda () 1641 (interactive) 1642 (describe-function 'persp-mode))) 1643 map)) 1644 " ")))))) 1645 1646 (add-hook 'buffer-list-update-hook #'doom-modeline-update-persp-name) 1647 (add-hook 'find-file-hook #'doom-modeline-update-persp-name) 1648 (add-hook 'persp-activated-functions #'doom-modeline-update-persp-name) 1649 (add-hook 'persp-renamed-functions #'doom-modeline-update-persp-name) 1650 (advice-add #'lv-message :after #'doom-modeline-update-persp-name) 1651 1652 (doom-modeline-def-segment persp-name 1653 "The current perspective name." 1654 (when (doom-modeline--segment-visible 'persp-name) 1655 doom-modeline--persp-name)) 1656 1657 1658 ;; 1659 ;; Misc info 1660 ;; 1661 1662 (doom-modeline-def-segment misc-info 1663 "Mode line construct for miscellaneous information. 1664 By default, this shows the information specified by `global-mode-string'." 1665 (when (or doom-modeline-display-misc-in-all-mode-lines 1666 (doom-modeline--segment-visible 'misc-info)) 1667 (doom-modeline-display-text 1668 (string-replace "%" "%%" (format-mode-line mode-line-misc-info))))) 1669 1670 1671 ;; 1672 ;; Position 1673 ;; 1674 1675 (doom-modeline-def-segment buffer-position 1676 "The buffer position information." 1677 (let ((visible (doom-modeline--segment-visible 'buffer-position)) 1678 (sep (doom-modeline-spc)) 1679 (wsep (doom-modeline-wspc)) 1680 (face (doom-modeline-face)) 1681 (help-echo "Buffer percentage\n\ 1682 mouse-1: Display Line and Column Mode Menu") 1683 (mouse-face 'doom-modeline-highlight) 1684 (local-map mode-line-column-line-number-mode-map)) 1685 `(,wsep 1686 1687 ;; Line and column 1688 (:propertize 1689 ((line-number-mode 1690 (column-number-mode 1691 (doom-modeline-column-zero-based 1692 doom-modeline-position-column-line-format 1693 ,(string-replace 1694 "%c" "%C" (car doom-modeline-position-column-line-format))) 1695 doom-modeline-position-line-format) 1696 (column-number-mode 1697 (doom-modeline-column-zero-based 1698 doom-modeline-position-column-format 1699 ,(string-replace 1700 "%c" "%C" (car doom-modeline-position-column-format))))) 1701 (doom-modeline-total-line-number 1702 ,(and doom-modeline-total-line-number 1703 (format "/%d" (line-number-at-pos (point-max)))))) 1704 face ,face 1705 help-echo ,help-echo 1706 mouse-face ,mouse-face 1707 local-map ,local-map) 1708 1709 ((or line-number-mode column-number-mode) 1710 ,sep) 1711 1712 ;; Position 1713 (,visible 1714 ,(cond 1715 ((bound-and-true-p nyan-mode) 1716 (concat sep (nyan-create) sep)) 1717 ((bound-and-true-p poke-line-mode) 1718 (concat sep (poke-line-create) sep)) 1719 ((bound-and-true-p mlscroll-mode) 1720 (concat sep 1721 (let ((mlscroll-right-align nil)) 1722 (format-mode-line (mlscroll-mode-line))) 1723 sep)) 1724 ((bound-and-true-p sml-modeline-mode) 1725 (concat sep (sml-modeline-create) sep)) 1726 (t ""))) 1727 1728 ;; Percent position 1729 (doom-modeline-percent-position 1730 ((:propertize ("" doom-modeline-percent-position) 1731 face ,face 1732 help-echo ,help-echo 1733 mouse-face ,mouse-face 1734 local-map ,local-map) 1735 ,sep))))) 1736 1737 ;; 1738 ;; Party parrot 1739 ;; 1740 (doom-modeline-def-segment parrot 1741 "The party parrot animated icon. Requires `parrot-mode' to be enabled." 1742 (when (and (doom-modeline--segment-visible 'parrot) 1743 (bound-and-true-p parrot-mode)) 1744 (concat (doom-modeline-wspc) 1745 (parrot-create) 1746 (doom-modeline-spc)))) 1747 1748 ;; 1749 ;; Modals (evil, overwrite, god, ryo and xah-fly-keys, etc.) 1750 ;; 1751 1752 (defun doom-modeline--modal-icon (text face help-echo &optional icon unicode) 1753 "Display the model icon with FACE and HELP-ECHO. 1754 TEXT is alternative if icon is not available." 1755 (propertize (doom-modeline-icon 1756 'mdicon 1757 (and doom-modeline-modal-icon 1758 (or (and doom-modeline-modal-modern-icon icon) 1759 "nf-md-record")) 1760 (or (and doom-modeline-modal-modern-icon unicode) "â") 1761 text 1762 :face (doom-modeline-face face)) 1763 'help-echo help-echo)) 1764 1765 (defsubst doom-modeline--evil () 1766 "The current evil state. Requires `evil-mode' to be enabled." 1767 (when (bound-and-true-p evil-local-mode) 1768 (doom-modeline--modal-icon 1769 (let ((tag (evil-state-property evil-state :tag t))) 1770 (if (stringp tag) tag (funcall tag))) 1771 (cond 1772 ((evil-normal-state-p) 'doom-modeline-evil-normal-state) 1773 ((evil-emacs-state-p) 'doom-modeline-evil-emacs-state) 1774 ((evil-insert-state-p) 'doom-modeline-evil-insert-state) 1775 ((evil-motion-state-p) 'doom-modeline-evil-motion-state) 1776 ((evil-visual-state-p) 'doom-modeline-evil-visual-state) 1777 ((evil-operator-state-p) 'doom-modeline-evil-operator-state) 1778 ((evil-replace-state-p) 'doom-modeline-evil-replace-state) 1779 (t 'doom-modeline-evil-user-state)) 1780 (evil-state-property evil-state :name t) 1781 (cond 1782 ((evil-normal-state-p) "nf-md-alpha_n_circle") 1783 ((evil-emacs-state-p) "nf-md-alpha_e_circle") 1784 ((evil-insert-state-p) "nf-md-alpha_i_circle") 1785 ((evil-motion-state-p) "nf-md-alpha_m_circle") 1786 ((evil-visual-state-p) "nf-md-alpha_v_circle") 1787 ((evil-operator-state-p) "nf-md-alpha_o_circle") 1788 ((evil-replace-state-p) "nf-md-alpha_r_circle") 1789 (t "nf-md-alpha_u_circle")) 1790 (cond 1791 ((evil-normal-state-p) "đ ") 1792 ((evil-emacs-state-p) "đ ") 1793 ((evil-insert-state-p) "đ ") 1794 ((evil-motion-state-p) "đ ") 1795 ((evil-visual-state-p) "đ Ĩ") 1796 ((evil-operator-state-p) "đ ") 1797 ((evil-replace-state-p) "đ Ą") 1798 (t "đ ¤"))))) 1799 1800 (defsubst doom-modeline--overwrite () 1801 "The current overwrite state which is enabled by command `overwrite-mode'." 1802 (when (and (bound-and-true-p overwrite-mode) 1803 (not (bound-and-true-p evil-local-mode))) 1804 (doom-modeline--modal-icon 1805 "<W>" 'doom-modeline-overwrite "Overwrite mode" 1806 "nf-md-marker" "đ Ļ"))) 1807 1808 (defsubst doom-modeline--god () 1809 "The current god state which is enabled by the command `god-mode'." 1810 (when (bound-and-true-p god-local-mode) 1811 (doom-modeline--modal-icon 1812 "<G>" 'doom-modeline-god "God mode" 1813 "nf-md-account_circle" "đ "))) 1814 1815 (defsubst doom-modeline--ryo () 1816 "The current ryo-modal state which is enabled by the command `ryo-modal-mode'." 1817 (when (bound-and-true-p ryo-modal-mode) 1818 (doom-modeline--modal-icon 1819 "<R>" 'doom-modeline-ryo "Ryo modal" 1820 "nf-md-star_circle" "âĒ"))) 1821 1822 (defsubst doom-modeline--xah-fly-keys () 1823 "The current `xah-fly-keys' state." 1824 (when (bound-and-true-p xah-fly-keys) 1825 (if xah-fly-insert-state-p 1826 (doom-modeline--modal-icon 1827 "<I>" 'doom-modeline-fly-insert-state "Xah-fly insert mode" 1828 "nf-md-airplane_edit" "đ§") 1829 (doom-modeline--modal-icon 1830 "<C>" 'doom-modeline-fly-normal-state "Xah-fly command mode" 1831 "nf-md-airplane_cog" "đ§")))) 1832 1833 (defsubst doom-modeline--boon () 1834 "The current Boon state. Requires `boon-mode' to be enabled." 1835 (when (bound-and-true-p boon-local-mode) 1836 (doom-modeline--modal-icon 1837 (boon-state-string) 1838 (cond 1839 (boon-command-state 'doom-modeline-boon-command-state) 1840 (boon-insert-state 'doom-modeline-boon-insert-state) 1841 (boon-special-state 'doom-modeline-boon-special-state) 1842 (boon-off-state 'doom-modeline-boon-off-state) 1843 (t 'doom-modeline-boon-off-state)) 1844 (boon-modeline-string) 1845 "nf-md-coffee" "đĩ"))) 1846 1847 (defsubst doom-modeline--meow () 1848 "The current Meow state. Requires `meow-mode' to be enabled." 1849 (when (bound-and-true-p meow-mode) 1850 (doom-modeline--modal-icon 1851 (substring-no-properties meow--indicator) 1852 (cond 1853 ((meow-normal-mode-p) 'doom-modeline-meow-normal-state) 1854 ((meow-insert-mode-p) 'doom-modeline-meow-insert-state) 1855 ((meow-beacon-mode-p) 'doom-modeline-meow-beacon-state) 1856 ((meow-motion-mode-p) 'doom-modeline-meow-motion-state) 1857 ((meow-keypad-mode-p) 'doom-modeline-meow-keypad-state) 1858 (t 'doom-modeline-meow-normal-state)) 1859 (symbol-name (meow--current-state)) 1860 (cond 1861 ((meow-normal-mode-p) "nf-md-alpha_n_circle") 1862 ((meow-insert-mode-p) "nf-md-alpha_i_circle") 1863 ((meow-beacon-mode-p) "nf-md-alpha_b_circle") 1864 ((meow-motion-mode-p) "nf-md-alpha_m_circle") 1865 ((meow-keypad-mode-p) "nf-md-alpha_k_circle") 1866 (t "nf-md-alpha_n_circle")) 1867 (cond 1868 ((meow-normal-mode-p) "đ ") 1869 ((meow-insert-mode-p) "đ ") 1870 ((meow-beacon-mode-p) "đ ") 1871 ((meow-motion-mode-p) "đ ") 1872 ((meow-keypad-mode-p) "đ ") 1873 (t "đ "))))) 1874 1875 (doom-modeline-def-segment modals 1876 "Displays modal editing states. 1877 1878 Including `evil', `overwrite', `god', `ryo' and `xha-fly-kyes', etc." 1879 (when doom-modeline-modal 1880 (let* ((evil (doom-modeline--evil)) 1881 (ow (doom-modeline--overwrite)) 1882 (god (doom-modeline--god)) 1883 (ryo (doom-modeline--ryo)) 1884 (xf (doom-modeline--xah-fly-keys)) 1885 (boon (doom-modeline--boon)) 1886 (meow (doom-modeline--meow)) 1887 (vsep (doom-modeline-vspc)) 1888 (sep (and (or evil ow god ryo xf boon meow) (doom-modeline-spc)))) 1889 (concat sep 1890 (and evil (concat evil (and (or ow god ryo xf boon meow) vsep))) 1891 (and ow (concat ow (and (or god ryo xf boon meow) vsep))) 1892 (and god (concat god (and (or ryo xf boon meow) vsep))) 1893 (and ryo (concat ryo (and (or xf boon meow) vsep))) 1894 (and xf (concat xf (and (or boon meow) vsep))) 1895 (and boon (concat boon (and meow vsep))) 1896 meow 1897 sep)))) 1898 1899 ;; 1900 ;; Objed state 1901 ;; 1902 1903 (defvar doom-modeline--objed-active nil) 1904 1905 (defun doom-modeline-update-objed (_ &optional reset) 1906 "Update `objed' status, inactive when RESET is true." 1907 (setq doom-modeline--objed-active (not reset))) 1908 1909 (setq objed-modeline-setup-func #'doom-modeline-update-objed) 1910 1911 (doom-modeline-def-segment objed-state () 1912 "The current objed state." 1913 (when (and doom-modeline--objed-active 1914 (doom-modeline--active)) 1915 (propertize (format " %s(%s) " 1916 (symbol-name objed--object) 1917 (char-to-string (aref (symbol-name objed--obj-state) 0))) 1918 'face 'doom-modeline-evil-emacs-state 1919 'help-echo (format "Objed object: %s (%s)" 1920 (symbol-name objed--object) 1921 (symbol-name objed--obj-state))))) 1922 1923 1924 ;; 1925 ;; Input method 1926 ;; 1927 1928 (doom-modeline-def-segment input-method 1929 "The current input method." 1930 (when-let* ((im (cond 1931 (current-input-method 1932 current-input-method-title) 1933 ((and (bound-and-true-p evil-local-mode) 1934 (bound-and-true-p evil-input-method)) 1935 (nth 3 (assoc default-input-method input-method-alist))) 1936 (t nil))) 1937 (sep (doom-modeline-spc))) 1938 (concat 1939 sep 1940 (propertize im 1941 'face (doom-modeline-face 1942 (if (and (bound-and-true-p rime-mode) 1943 (equal current-input-method "rime")) 1944 (if (and (rime--should-enable-p) 1945 (not (rime--should-inline-ascii-p))) 1946 'doom-modeline-input-method 1947 'doom-modeline-input-method-alt) 1948 'doom-modeline-input-method)) 1949 'help-echo (concat 1950 "Current input method: " 1951 current-input-method 1952 "\n\ 1953 mouse-2: Disable input method\n\ 1954 mouse-3: Describe current input method") 1955 'mouse-face 'doom-modeline-highlight 1956 'local-map mode-line-input-method-map) 1957 sep))) 1958 1959 1960 ;; 1961 ;; Info 1962 ;; 1963 1964 (doom-modeline-def-segment info-nodes 1965 "The topic and nodes in the Info buffer." 1966 (concat 1967 " (" 1968 ;; topic 1969 (propertize (if (stringp Info-current-file) 1970 (replace-regexp-in-string 1971 "%" "%%" 1972 (file-name-sans-extension 1973 (file-name-nondirectory Info-current-file))) 1974 (format "*%S*" Info-current-file)) 1975 'face (doom-modeline-face 'doom-modeline-info)) 1976 ") " 1977 ;; node 1978 (when Info-current-node 1979 (propertize (replace-regexp-in-string 1980 "%" "%%" Info-current-node) 1981 'face (doom-modeline-face 'doom-modeline-buffer-path) 1982 'help-echo 1983 "mouse-1: scroll forward, mouse-3: scroll back" 1984 'mouse-face 'doom-modeline-highlight 1985 'local-map Info-mode-line-node-keymap)))) 1986 1987 1988 ;; 1989 ;; REPL 1990 ;; 1991 1992 (defun doom-modeline-repl-icon (text face) 1993 "Display REPL icon (or TEXT in terminal) with FACE." 1994 (doom-modeline-icon 'faicon "nf-fa-terminal" "$" text :face face)) 1995 1996 (defvar doom-modeline--cider nil) 1997 1998 (defun doom-modeline-update-cider () 1999 "Update cider repl state." 2000 (setq doom-modeline--cider 2001 (let* ((connected (cider-connected-p)) 2002 (face (if connected 'doom-modeline-repl-success 'doom-modeline-repl-warning)) 2003 (repl-buffer (cider-current-repl nil nil)) 2004 (cider-info (when repl-buffer 2005 (cider--connection-info repl-buffer t))) 2006 (icon (doom-modeline-repl-icon "REPL" face))) 2007 (propertize icon 2008 'help-echo 2009 (if connected 2010 (format "CIDER Connected %s\nmouse-2: CIDER quit" cider-info) 2011 "CIDER Disconnected\nmouse-1: CIDER jack-in") 2012 'mouse-face 'doom-modeline-highlight 2013 'local-map (let ((map (make-sparse-keymap))) 2014 (if connected 2015 (define-key map [mode-line mouse-2] 2016 #'cider-quit) 2017 (define-key map [mode-line mouse-1] 2018 #'cider-jack-in)) 2019 map))))) 2020 2021 (add-hook 'cider-connected-hook #'doom-modeline-update-cider) 2022 (add-hook 'cider-disconnected-hook #'doom-modeline-update-cider) 2023 (add-hook 'cider-mode-hook #'doom-modeline-update-cider) 2024 2025 (doom-modeline-def-segment repl 2026 "The REPL state." 2027 (when doom-modeline-repl 2028 (when-let* ((icon (when (bound-and-true-p cider-mode) 2029 doom-modeline--cider)) 2030 (sep (doom-modeline-spc))) 2031 (concat 2032 sep 2033 (doom-modeline-display-icon icon) 2034 sep)))) 2035 2036 2037 ;; 2038 ;; LSP 2039 ;; 2040 2041 (defun doom-modeline-lsp-icon (text face) 2042 "Display LSP icon (or TEXT in terminal) with FACE." 2043 (if doom-modeline-lsp-icon 2044 (doom-modeline-icon 'octicon "nf-oct-rocket" "đ" text :face face) 2045 (propertize text 'face face))) 2046 2047 (defvar-local doom-modeline--lsp nil) 2048 (defun doom-modeline-update-lsp (&rest _) 2049 "Update `lsp-mode' state." 2050 (setq doom-modeline--lsp 2051 (let* ((workspaces (lsp-workspaces)) 2052 (face (if workspaces 'doom-modeline-lsp-success 'doom-modeline-lsp-warning)) 2053 (icon (doom-modeline-lsp-icon "LSP" face))) 2054 (propertize icon 2055 'help-echo 2056 (if workspaces 2057 (concat "LSP connected " 2058 (string-join 2059 (mapcar (lambda (w) 2060 (format "[%s]\n" (lsp--workspace-print w))) 2061 workspaces)) 2062 "C-mouse-1: Switch to another workspace folder 2063 mouse-1: Describe current session 2064 mouse-2: Quit server 2065 mouse-3: Reconnect to server") 2066 "LSP Disconnected 2067 mouse-1: Reload to start server") 2068 'mouse-face 'doom-modeline-highlight 2069 'local-map (let ((map (make-sparse-keymap))) 2070 (if workspaces 2071 (progn 2072 (define-key map [mode-line C-mouse-1] 2073 #'lsp-workspace-folders-open) 2074 (define-key map [mode-line mouse-1] 2075 #'lsp-describe-session) 2076 (define-key map [mode-line mouse-2] 2077 #'lsp-workspace-shutdown) 2078 (define-key map [mode-line mouse-3] 2079 #'lsp-workspace-restart)) 2080 (progn 2081 (define-key map [mode-line mouse-1] 2082 (lambda () 2083 (interactive) 2084 (ignore-errors (revert-buffer t t)))))) 2085 map))))) 2086 (add-hook 'lsp-before-initialize-hook #'doom-modeline-update-lsp) 2087 (add-hook 'lsp-after-initialize-hook #'doom-modeline-update-lsp) 2088 (add-hook 'lsp-after-uninitialized-functions #'doom-modeline-update-lsp) 2089 (add-hook 'lsp-before-open-hook #'doom-modeline-update-lsp) 2090 (add-hook 'lsp-after-open-hook #'doom-modeline-update-lsp) 2091 2092 (defun doom-modeline--eglot-pending-count (server) 2093 "Get count of pending eglot requests to SERVER." 2094 (if (fboundp 'jsonrpc-continuation-count) 2095 (jsonrpc-continuation-count server) 2096 (hash-table-count (jsonrpc--request-continuations server)))) 2097 2098 (defvar-local doom-modeline--eglot nil) 2099 (defun doom-modeline-update-eglot () 2100 "Update eglot state." 2101 (setq doom-modeline--eglot 2102 (let* ((server (and (eglot-managed-p) (eglot-current-server))) 2103 (nick (and server (eglot-project-nickname server))) 2104 (pending (and server (doom-modeline--eglot-pending-count server))) 2105 (last-error (and server (jsonrpc-last-error server))) 2106 (face (cond (last-error 'doom-modeline-lsp-error) 2107 ((and pending (cl-plusp pending)) 'doom-modeline-lsp-warning) 2108 (nick 'doom-modeline-lsp-success) 2109 (t 'doom-modeline-lsp-warning))) 2110 (server-info (and server (eglot--server-info server))) 2111 (server-name (or (plist-get server-info :name) 2112 (and server (jsonrpc-name server)) "")) 2113 (major-modes (or (and server (eglot--major-modes server)) "")) 2114 (icon (doom-modeline-lsp-icon eglot-menu-string face))) 2115 (propertize icon 2116 'help-echo (format "Eglot connected [%s]\n%s %s 2117 mouse-1: Display minor mode menu 2118 mouse-3: LSP server control menu" 2119 nick server-name major-modes) 2120 'mouse-face 'doom-modeline-highlight 2121 'local-map (let ((map (make-sparse-keymap))) 2122 (define-key map [mode-line mouse-1] eglot-menu) 2123 (define-key map [mode-line mouse-3] eglot-server-menu) 2124 map))))) 2125 (add-hook 'eglot-managed-mode-hook #'doom-modeline-update-eglot) 2126 2127 (defvar-local doom-modeline--tags nil) 2128 (defun doom-modeline-update-tags () 2129 "Update tags state." 2130 (setq doom-modeline--tags 2131 (propertize 2132 (doom-modeline-lsp-icon "Tags" 'doom-modeline-lsp-success) 2133 'help-echo "Tags: Citre mode 2134 mouse-1: Toggle citre mode" 2135 'mouse-face 'doom-modeline-highlight 2136 'local-map (make-mode-line-mouse-map 'mouse-1 #'citre-mode)))) 2137 (add-hook 'citre-mode-hook #'doom-modeline-update-tags) 2138 2139 (defun doom-modeline-update-lsp-icon () 2140 "Update lsp icon." 2141 (cond ((bound-and-true-p lsp-mode) 2142 (doom-modeline-update-lsp)) 2143 ((bound-and-true-p eglot--managed-mode) 2144 (doom-modeline-update-eglot)) 2145 ((bound-and-true-p citre-mode) 2146 (doom-modeline-update-tags)))) 2147 2148 (doom-modeline-add-variable-watcher 2149 'doom-modeline-lsp-icon 2150 (lambda (_sym val op _where) 2151 (when (eq op 'set) 2152 (setq doom-modeline-lsp-icon val) 2153 (dolist (buf (buffer-list)) 2154 (with-current-buffer buf 2155 (doom-modeline-update-lsp-icon)))))) 2156 2157 (doom-modeline-add-variable-watcher 2158 'doom-modeline-icon 2159 (lambda (_sym val op _where) 2160 (when (eq op 'set) 2161 (setq doom-modeline-icon val) 2162 (dolist (buf (buffer-list)) 2163 (with-current-buffer buf 2164 (doom-modeline-update-lsp-icon)))))) 2165 2166 (doom-modeline-add-variable-watcher 2167 'doom-modeline-unicode-fallback 2168 (lambda (_sym val op _where) 2169 (when (eq op 'set) 2170 (setq doom-modeline-unicode-fallback val) 2171 (dolist (buf (buffer-list)) 2172 (with-current-buffer buf 2173 (doom-modeline-update-lsp-icon)))))) 2174 2175 (doom-modeline-def-segment lsp 2176 "The LSP server state." 2177 (when doom-modeline-lsp 2178 (when-let* ((icon (cond ((bound-and-true-p lsp-mode) 2179 doom-modeline--lsp) 2180 ((bound-and-true-p eglot--managed-mode) 2181 doom-modeline--eglot) 2182 ((bound-and-true-p citre-mode) 2183 doom-modeline--tags))) 2184 (sep (doom-modeline-spc))) 2185 (concat 2186 sep 2187 (doom-modeline-display-icon icon) 2188 sep)))) 2189 2190 (defun doom-modeline-override-eglot () 2191 "Override `eglot' mode-line." 2192 (if (and doom-modeline-lsp 2193 (bound-and-true-p doom-modeline-mode)) 2194 (setq mode-line-misc-info 2195 (delq (assq 'eglot--managed-mode mode-line-misc-info) mode-line-misc-info)) 2196 (add-to-list 'mode-line-misc-info 2197 `(eglot--managed-mode (" [" eglot--mode-line-format "] "))))) 2198 (add-hook 'eglot-managed-mode-hook #'doom-modeline-override-eglot) 2199 (add-hook 'doom-modeline-mode-hook #'doom-modeline-override-eglot) 2200 2201 (doom-modeline-add-variable-watcher 2202 'doom-modeline-battery 2203 (lambda (_sym val op _where) 2204 (when (eq op 'set) 2205 (setq doom-modeline-lsp val) 2206 (doom-modeline-override-eglot)))) 2207 2208 2209 ;; 2210 ;; GitHub 2211 ;; 2212 2213 (defvar doom-modeline--github-notification-number 0) 2214 (defvar doom-modeline-before-github-fetch-notification-hook nil 2215 "Hooks before fetching GitHub notifications. 2216 Example: 2217 (add-hook \\='doom-modeline-before-github-fetch-notification-hook 2218 #\\='auth-source-pass-enable)") 2219 2220 (defvar doom-modeline-after-github-fetch-notification-hook nil 2221 "Hooks after fetching GitHub notifications.") 2222 2223 (defun doom-modeline--github-fetch-notifications () 2224 "Fetch GitHub notifications." 2225 (when (and doom-modeline-github 2226 (require 'async nil t)) 2227 (async-start 2228 `(lambda () 2229 ,(async-inject-variables 2230 "\\`\\(load-path\\|auth-sources\\|doom-modeline-before-github-fetch-notification-hook\\)\\'") 2231 (run-hooks 'doom-modeline-before-github-fetch-notification-hook) 2232 (when (require 'ghub nil t) 2233 (with-timeout (10) 2234 (ignore-errors 2235 (when-let* ((username (ghub--username ghub-default-host)) 2236 (token (or (ghub--token ghub-default-host username 'forge t) 2237 (ghub--token ghub-default-host username 'ghub t)))) 2238 (ghub-get "/notifications" 2239 '((notifications . t)) 2240 :host ghub-default-host 2241 :username username 2242 :auth token 2243 :unpaginate t 2244 :noerror t)))))) 2245 (lambda (result) 2246 (message "") ; suppress message 2247 (setq doom-modeline--github-notification-number (length result)) 2248 (run-hooks 'doom-modeline-after-github-fetch-notification-hook))))) 2249 2250 (defvar doom-modeline--github-timer nil) 2251 (defun doom-modeline-github-timer () 2252 "Start/Stop the timer for GitHub fetching." 2253 (if (timerp doom-modeline--github-timer) 2254 (cancel-timer doom-modeline--github-timer)) 2255 (setq doom-modeline--github-timer 2256 (and doom-modeline-github 2257 (run-with-idle-timer 30 2258 doom-modeline-github-interval 2259 #'doom-modeline--github-fetch-notifications)))) 2260 2261 (doom-modeline-add-variable-watcher 2262 'doom-modeline-github 2263 (lambda (_sym val op _where) 2264 (when (eq op 'set) 2265 (setq doom-modeline-github val) 2266 (doom-modeline-github-timer)))) 2267 2268 (doom-modeline-github-timer) 2269 2270 (doom-modeline-def-segment github 2271 "The GitHub notifications." 2272 (when (and doom-modeline-github 2273 (doom-modeline--segment-visible 'github) 2274 (numberp doom-modeline--github-notification-number)) 2275 (let ((sep (doom-modeline-spc))) 2276 (concat 2277 sep 2278 (propertize 2279 (concat 2280 (doom-modeline-icon 'octicon "nf-oct-mark_github" "đ" "&" 2281 :face 'doom-modeline-notification) 2282 (and (> doom-modeline--github-notification-number 0) (doom-modeline-vspc)) 2283 (propertize 2284 (cond 2285 ((<= doom-modeline--github-notification-number 0) "") 2286 ((> doom-modeline--github-notification-number 99) "99+") 2287 (t (number-to-string doom-modeline--github-notification-number))) 2288 'face '(:inherit 2289 (doom-modeline-unread-number doom-modeline-notification)))) 2290 'help-echo "Github Notifications 2291 mouse-1: Show notifications 2292 mouse-3: Fetch notifications" 2293 'mouse-face 'doom-modeline-highlight 2294 'local-map (let ((map (make-sparse-keymap))) 2295 (define-key map [mode-line mouse-1] 2296 (lambda () 2297 "Open GitHub notifications page." 2298 (interactive) 2299 (run-with-idle-timer 300 nil #'doom-modeline--github-fetch-notifications) 2300 (browse-url "https://github.com/notifications"))) 2301 (define-key map [mode-line mouse-3] 2302 (lambda () 2303 "Fetching GitHub notifications." 2304 (interactive) 2305 (message "Fetching GitHub notifications...") 2306 (doom-modeline--github-fetch-notifications))) 2307 map)) 2308 sep)))) 2309 2310 2311 ;; 2312 ;; Debug states 2313 ;; 2314 2315 ;; Highlight the doom-modeline while debugging. 2316 (defvar-local doom-modeline--debug-cookie nil) 2317 (defun doom-modeline--debug-visual (&rest _) 2318 "Update the face of mode-line for debugging." 2319 (mapc (lambda (buffer) 2320 (with-current-buffer buffer 2321 (setq doom-modeline--debug-cookie 2322 (face-remap-add-relative 'doom-modeline 'doom-modeline-debug-visual)) 2323 (force-mode-line-update))) 2324 (buffer-list))) 2325 2326 (defun doom-modeline--normal-visual (&rest _) 2327 "Restore the face of mode-line." 2328 (mapc (lambda (buffer) 2329 (with-current-buffer buffer 2330 (when doom-modeline--debug-cookie 2331 (face-remap-remove-relative doom-modeline--debug-cookie) 2332 (force-mode-line-update)))) 2333 (buffer-list))) 2334 2335 (add-hook 'dap-session-created-hook #'doom-modeline--debug-visual) 2336 (add-hook 'dap-terminated-hook #'doom-modeline--normal-visual) 2337 2338 (defun doom-modeline-debug-icon (face) 2339 "Display debug icon with FACE and ARGS." 2340 (doom-modeline-icon 'codicon "nf-cod-debug" "đ" "!" :face face)) 2341 2342 (defun doom-modeline--debug-dap () 2343 "The current `dap-mode' state." 2344 (when (and (bound-and-true-p dap-mode) 2345 (bound-and-true-p lsp-mode)) 2346 (when-let* ((session (dap--cur-session))) 2347 (when (dap--session-running session) 2348 (propertize (doom-modeline-debug-icon 'doom-modeline-info) 2349 'help-echo (format "DAP (%s - %s) 2350 mouse-1: Display debug hydra 2351 mouse-2: Display recent configurations 2352 mouse-3: Disconnect session" 2353 (dap--debug-session-name session) 2354 (dap--debug-session-state session)) 2355 'mouse-face 'doom-modeline-highlight 2356 'local-map (let ((map (make-sparse-keymap))) 2357 (define-key map [mode-line mouse-1] 2358 #'dap-hydra) 2359 (define-key map [mode-line mouse-2] 2360 #'dap-debug-recent) 2361 (define-key map [mode-line mouse-3] 2362 #'dap-disconnect) 2363 map)))))) 2364 2365 (defvar-local doom-modeline--debug-dap nil) 2366 (defun doom-modeline-update-debug-dap (&rest _) 2367 "Update dap debug state." 2368 (setq doom-modeline--debug-dap (doom-modeline--debug-dap))) 2369 2370 (add-hook 'dap-session-created-hook #'doom-modeline-update-debug-dap) 2371 (add-hook 'dap-session-changed-hook #'doom-modeline-update-debug-dap) 2372 (add-hook 'dap-terminated-hook #'doom-modeline-update-debug-dap) 2373 2374 (defsubst doom-modeline--debug-edebug () 2375 "The current `edebug' state." 2376 (when (bound-and-true-p edebug-mode) 2377 (propertize (doom-modeline-debug-icon 'doom-modeline-info) 2378 'help-echo (format "EDebug (%s) 2379 mouse-1: Show help 2380 mouse-2: Next 2381 mouse-3: Stop debugging" 2382 edebug-execution-mode) 2383 'mouse-face 'doom-modeline-highlight 2384 'local-map (let ((map (make-sparse-keymap))) 2385 (define-key map [mode-line mouse-1] 2386 #'edebug-help) 2387 (define-key map [mode-line mouse-2] 2388 #'edebug-next-mode) 2389 (define-key map [mode-line mouse-3] 2390 #'edebug-stop) 2391 map)))) 2392 2393 (defsubst doom-modeline--debug-on-error () 2394 "The current `debug-on-error' state." 2395 (when debug-on-error 2396 (propertize (doom-modeline-debug-icon 'doom-modeline-urgent) 2397 'help-echo "Debug on Error 2398 mouse-1: Toggle Debug on Error" 2399 'mouse-face 'doom-modeline-highlight 2400 'local-map (make-mode-line-mouse-map 'mouse-1 #'toggle-debug-on-error)))) 2401 2402 (defsubst doom-modeline--debug-on-quit () 2403 "The current `debug-on-quit' state." 2404 (when debug-on-quit 2405 (propertize (doom-modeline-debug-icon 'doom-modeline-warning) 2406 'help-echo "Debug on Quit 2407 mouse-1: Toggle Debug on Quit" 2408 'mouse-face 'doom-modeline-highlight 2409 'local-map (make-mode-line-mouse-map 'mouse-1 #'toggle-debug-on-quit)))) 2410 2411 (doom-modeline-def-segment debug 2412 "The current debug state." 2413 (when (doom-modeline--segment-visible 'debug) 2414 (let* ((dap doom-modeline--debug-dap) 2415 (edebug (doom-modeline--debug-edebug)) 2416 (on-error (doom-modeline--debug-on-error)) 2417 (on-quit (doom-modeline--debug-on-quit)) 2418 (vsep (doom-modeline-vspc)) 2419 (sep (and (or dap edebug on-error on-quit) (doom-modeline-spc)))) 2420 (concat sep 2421 (and dap (concat dap (and (or edebug on-error on-quit) vsep))) 2422 (and edebug (concat edebug (and (or on-error on-quit) vsep))) 2423 (and on-error (concat on-error (and on-quit vsep))) 2424 on-quit 2425 sep)))) 2426 2427 2428 ;; 2429 ;; PDF pages 2430 ;; 2431 2432 (defvar-local doom-modeline--pdf-pages nil) 2433 (defun doom-modeline-update-pdf-pages () 2434 "Update PDF pages." 2435 (setq doom-modeline--pdf-pages 2436 (format " P%d/%d " 2437 (or (eval `(pdf-view-current-page)) 0) 2438 (pdf-cache-number-of-pages)))) 2439 (add-hook 'pdf-view-change-page-hook #'doom-modeline-update-pdf-pages) 2440 2441 (doom-modeline-def-segment pdf-pages 2442 "Display PDF pages." 2443 doom-modeline--pdf-pages) 2444 2445 2446 ;; 2447 ;; `mu4e' notifications 2448 ;; 2449 2450 (doom-modeline-def-segment mu4e 2451 "Show notifications of any unread emails in `mu4e'." 2452 (when (and doom-modeline-mu4e 2453 (doom-modeline--segment-visible 'mu4e)) 2454 (let ((sep (doom-modeline-spc)) 2455 (vsep (doom-modeline-vspc)) 2456 (icon (doom-modeline-icon 'mdicon "nf-md-email" "đ§" "#" 2457 :face 'doom-modeline-notification))) 2458 (cond ((and (bound-and-true-p mu4e-alert-mode-line) 2459 (numberp mu4e-alert-mode-line) 2460 ;; don't display if the unread mails count is zero 2461 (> mu4e-alert-mode-line 0)) 2462 (concat 2463 sep 2464 (propertize 2465 (concat 2466 icon 2467 vsep 2468 (propertize 2469 (if (> mu4e-alert-mode-line doom-modeline-number-limit) 2470 (format "%d+" doom-modeline-number-limit) 2471 (number-to-string mu4e-alert-mode-line)) 2472 'face '(:inherit 2473 (doom-modeline-unread-number doom-modeline-notification)))) 2474 'mouse-face 'doom-modeline-highlight 2475 'keymap '(mode-line keymap 2476 (mouse-1 . mu4e-alert-view-unread-mails) 2477 (mouse-2 . mu4e-alert-view-unread-mails) 2478 (mouse-3 . mu4e-alert-view-unread-mails)) 2479 'help-echo (concat (if (= mu4e-alert-mode-line 1) 2480 "You have an unread email" 2481 (format "You have %s unread emails" mu4e-alert-mode-line)) 2482 "\nClick here to view " 2483 (if (= mu4e-alert-mode-line 1) "it" "them"))) 2484 sep)) 2485 ((bound-and-true-p mu4e-modeline-mode) 2486 (concat sep icon vsep 2487 (propertize (mu4e--modeline-string) 2488 'face 'doom-modeline-notification) 2489 sep)))))) 2490 2491 (defun doom-modeline-override-mu4e-alert (&rest _) 2492 "Delete `mu4e-alert-mode-line' from global modeline string." 2493 (when (and (featurep 'mu4e-alert) 2494 (bound-and-true-p mu4e-alert-mode-line)) 2495 (if (and doom-modeline-mu4e 2496 (bound-and-true-p doom-modeline-mode)) 2497 ;; Delete original modeline 2498 (progn 2499 (setq global-mode-string 2500 (delete '(:eval mu4e-alert-mode-line) global-mode-string)) 2501 (setq mu4e-alert-modeline-formatter #'identity)) 2502 ;; Recover default settings 2503 (setq mu4e-alert-modeline-formatter #'mu4e-alert-default-mode-line-formatter)))) 2504 (advice-add #'mu4e-alert-enable-mode-line-display 2505 :after #'doom-modeline-override-mu4e-alert) 2506 (add-hook 'doom-modeline-mode-hook #'doom-modeline-override-mu4e-alert) 2507 2508 (defun doom-modeline-override-mu4e-modeline (&rest _) 2509 "Delete `mu4e-alert-mode-line' from global modeline string." 2510 (when (bound-and-true-p mu4e-modeline-mode) 2511 (if (and doom-modeline-mu4e 2512 (bound-and-true-p doom-modeline-mode)) 2513 ;; Delete original modeline 2514 (setq global-mode-string 2515 (delete mu4e--modeline-item global-mode-string)) 2516 ;; Recover default settings 2517 (add-to-list 'global-mode-string mu4e--modeline-item)))) 2518 (add-hook 'mu4e-modeline-mode-hook #'doom-modeline-override-mu4e-modeline) 2519 (add-hook 'doom-modeline-mode-hook #'doom-modeline-override-mu4e-modeline) 2520 2521 (doom-modeline-add-variable-watcher 2522 'doom-modeline-mu4e 2523 (lambda (_sym val op _where) 2524 (when (eq op 'set) 2525 (setq doom-modeline-mu4e val) 2526 (doom-modeline-override-mu4e-alert) 2527 (doom-modeline-override-mu4e-modeline)))) 2528 2529 2530 ;; 2531 ;; `gnus' notifications 2532 ;; 2533 2534 (defvar doom-modeline--gnus-unread-mail 0) 2535 (defvar doom-modeline--gnus-started nil 2536 "Used to determine if gnus has started.") 2537 (defun doom-modeline-update-gnus-status (&rest _) 2538 "Get the total number of unread news of gnus group." 2539 (setq doom-modeline--gnus-unread-mail 2540 (when (and doom-modeline-gnus 2541 doom-modeline--gnus-started) 2542 (let ((total-unread-news-number 0)) 2543 (mapc (lambda (g) 2544 (let* ((group (car g)) 2545 (unread (eval `(gnus-group-unread ,group)))) 2546 (when (and (not (seq-contains-p doom-modeline-gnus-excluded-groups group)) 2547 (numberp unread) 2548 (> unread 0)) 2549 (setq total-unread-news-number (+ total-unread-news-number unread))))) 2550 gnus-newsrc-alist) 2551 total-unread-news-number)))) 2552 2553 ;; Update the modeline after changes have been made 2554 (add-hook 'gnus-group-update-hook #'doom-modeline-update-gnus-status) 2555 (add-hook 'gnus-summary-update-hook #'doom-modeline-update-gnus-status) 2556 (add-hook 'gnus-group-update-group-hook #'doom-modeline-update-gnus-status) 2557 (add-hook 'gnus-after-getting-new-news-hook #'doom-modeline-update-gnus-status) 2558 2559 ;; Only start to listen to gnus when gnus is actually running 2560 (defun doom-modeline-start-gnus-listener () 2561 "Start GNUS listener." 2562 (when (and doom-modeline-gnus 2563 (not doom-modeline--gnus-started)) 2564 (setq doom-modeline--gnus-started t) 2565 ;; Scan gnus in the background if the timer is higher than 0 2566 (doom-modeline-update-gnus-status) 2567 (if (> doom-modeline-gnus-timer 0) 2568 (gnus-demon-add-handler 'gnus-demon-scan-news doom-modeline-gnus-timer doom-modeline-gnus-idle)))) 2569 (add-hook 'gnus-started-hook #'doom-modeline-start-gnus-listener) 2570 2571 ;; Stop the listener if gnus isn't running 2572 (defun doom-modeline-stop-gnus-listener () 2573 "Stop GNUS listener." 2574 (setq doom-modeline--gnus-started nil)) 2575 (add-hook 'gnus-exit-gnus-hook #'doom-modeline-stop-gnus-listener) 2576 2577 (doom-modeline-def-segment gnus 2578 "Show notifications of any unread emails in `gnus'." 2579 (when (and (doom-modeline--segment-visible 'gnus) 2580 doom-modeline-gnus 2581 doom-modeline--gnus-started 2582 ;; Don't display if the unread mails count is zero 2583 (numberp doom-modeline--gnus-unread-mail) 2584 (> doom-modeline--gnus-unread-mail 0)) 2585 (let ((sep (doom-modeline-spc)) 2586 (vsep (doom-modeline-vspc))) 2587 (concat 2588 sep 2589 (propertize 2590 (concat 2591 (doom-modeline-icon 'mdicon "nf-md-email" "đ§" "#" 2592 :face 'doom-modeline-notification) 2593 vsep 2594 (propertize 2595 (if (> doom-modeline--gnus-unread-mail doom-modeline-number-limit) 2596 (format "%d+" doom-modeline-number-limit) 2597 (number-to-string doom-modeline--gnus-unread-mail)) 2598 'face '(:inherit 2599 (doom-modeline-unread-number doom-modeline-notification)))) 2600 'mouse-face 'doom-modeline-highlight 2601 'help-echo (if (= doom-modeline--gnus-unread-mail 1) 2602 "You have an unread email" 2603 (format "You have %s unread emails" doom-modeline--gnus-unread-mail))) 2604 sep)))) 2605 2606 2607 ;; 2608 ;; IRC notifications 2609 ;; 2610 2611 (defun doom-modeline-shorten-irc (name) 2612 "Shorten IRC buffer `name' according to IRC mode. 2613 2614 Calls the mode specific function to return the shortened 2615 version of `NAME' if applicable: 2616 - Circe: `tracking-shorten' 2617 - ERC: `erc-track-shorten-function' 2618 - rcirc: `rcirc-shorten-buffer-name' 2619 2620 The specific function will decide how to stylize the buffer name, 2621 read the individual functions documentation for more." 2622 (or (and (fboundp 'tracking-shorten) 2623 (car (tracking-shorten (list name)))) 2624 (and (boundp 'erc-track-shorten-function) 2625 (functionp erc-track-shorten-function) 2626 (car (funcall erc-track-shorten-function (list name)))) 2627 (and (fboundp 'rcirc-short-buffer-name) 2628 (rcirc-short-buffer-name name)) 2629 name)) 2630 2631 (defun doom-modeline--tracking-buffers (buffers) 2632 "Logic to convert some irc BUFFERS to their font-awesome icon." 2633 (mapconcat 2634 (lambda (b) 2635 (propertize 2636 (funcall doom-modeline-irc-stylize b) 2637 'face '(:inherit (doom-modeline-unread-number doom-modeline-notification)) 2638 'help-echo (format "IRC Notification: %s\nmouse-1: Switch to buffer" b) 2639 'mouse-face 'doom-modeline-highlight 2640 'local-map (make-mode-line-mouse-map 2641 'mouse-1 2642 (lambda () 2643 (interactive) 2644 (when (buffer-live-p (get-buffer b)) 2645 (switch-to-buffer b)))))) 2646 buffers 2647 (doom-modeline-vspc))) 2648 2649 (defun doom-modeline--circe-p () 2650 "Check if `circe' is in use." 2651 (boundp 'tracking-mode-line-buffers)) 2652 2653 (defun doom-modeline--erc-p () 2654 "Check if `erc' is in use." 2655 (boundp 'erc-modified-channels-alist)) 2656 2657 (defun doom-modeline--rcirc-p () 2658 "Check if `rcirc' is in use." 2659 (bound-and-true-p rcirc-track-minor-mode)) 2660 2661 (defun doom-modeline--get-buffers () 2662 "Gets the buffers that have activity." 2663 (cond 2664 ((doom-modeline--circe-p) 2665 tracking-buffers) 2666 ((doom-modeline--erc-p) 2667 (mapcar (lambda (l) 2668 (buffer-name (car l))) 2669 erc-modified-channels-alist)) 2670 ((doom-modeline--rcirc-p) 2671 (mapcar (lambda (b) 2672 (buffer-name b)) 2673 rcirc-activity)))) 2674 2675 ;; Create a modeline segment that contains all the irc tracked buffers 2676 (doom-modeline-def-segment irc-buffers 2677 "The list of shortened, unread irc buffers." 2678 (when (and doom-modeline-irc 2679 (doom-modeline--segment-visible 'irc-buffers)) 2680 (let* ((buffers (doom-modeline--get-buffers)) 2681 (number (length buffers)) 2682 (sep (doom-modeline-spc))) 2683 (when (> number 0) 2684 (concat 2685 sep 2686 (doom-modeline--tracking-buffers buffers) 2687 sep))))) 2688 2689 (doom-modeline-def-segment irc 2690 "A notification icon for any unread irc buffer." 2691 (when (and doom-modeline-irc 2692 (doom-modeline--segment-visible 'irc)) 2693 (let* ((buffers (doom-modeline--get-buffers)) 2694 (number (length buffers)) 2695 (sep (doom-modeline-spc)) 2696 (vsep (doom-modeline-vspc))) 2697 (when (> number 0) 2698 (concat 2699 sep 2700 2701 (propertize (concat 2702 (doom-modeline-icon 'mdicon "nf-md-message_processing" "đ" "#" 2703 :face 'doom-modeline-notification) 2704 vsep 2705 ;; Display the number of unread buffers 2706 (propertize (number-to-string number) 2707 'face '(:inherit 2708 (doom-modeline-unread-number 2709 doom-modeline-notification)))) 2710 'help-echo (format "IRC Notifications: %s\n%s" 2711 (mapconcat 2712 (lambda (b) (funcall doom-modeline-irc-stylize b)) 2713 buffers 2714 ", ") 2715 (cond 2716 ((doom-modeline--circe-p) 2717 "mouse-1: Switch to previous unread buffer 2718 mouse-3: Switch to next unread buffer") 2719 ((doom-modeline--erc-p) 2720 "mouse-1: Switch to buffer 2721 mouse-3: Switch to next unread buffer") 2722 ((doom-modeline--rcirc-p) 2723 "mouse-1: Switch to server buffer 2724 mouse-3: Switch to next unread buffer"))) 2725 'mouse-face 'doom-modeline-highlight 2726 'local-map (let ((map (make-sparse-keymap))) 2727 (cond 2728 ((doom-modeline--circe-p) 2729 (define-key map [mode-line mouse-1] 2730 #'tracking-previous-buffer) 2731 (define-key map [mode-line mouse-3] 2732 #'tracking-next-buffer)) 2733 ((doom-modeline--erc-p) 2734 (define-key map [mode-line mouse-1] 2735 #'erc-switch-to-buffer) 2736 (define-key map [mode-line mouse-3] 2737 #'erc-track-switch-buffer)) 2738 ((doom-modeline--rcirc-p) 2739 (define-key map [mode-line mouse-1] 2740 #'rcirc-switch-to-server-buffer) 2741 (define-key map [mode-line mouse-3] 2742 #'rcirc-next-active-buffer))) 2743 map)) 2744 2745 ;; Display the unread irc buffers as well 2746 (when doom-modeline-irc-buffers 2747 (concat sep (doom-modeline--tracking-buffers buffers))) 2748 2749 sep))))) 2750 2751 (defun doom-modeline-override-rcirc () 2752 "Override default `rcirc' mode-line." 2753 (if (and doom-modeline-irc 2754 (bound-and-true-p doom-modeline-mode)) 2755 (setq global-mode-string 2756 (delq 'rcirc-activity-string global-mode-string)) 2757 (when (and rcirc-track-minor-mode 2758 (not (memq 'rcirc-activity-string global-mode-string))) 2759 (setq global-mode-string 2760 (append global-mode-string '(rcirc-activity-string)))))) 2761 (add-hook 'rcirc-track-minor-mode-hook #'doom-modeline-override-rcirc) 2762 (add-hook 'doom-modeline-mode-hook #'doom-modeline-override-rcirc) 2763 2764 (doom-modeline-add-variable-watcher 2765 'doom-modeline-irc 2766 (lambda (_sym val op _where) 2767 (when (eq op 'set) 2768 (setq doom-modeline-irc val) 2769 (doom-modeline-override-rcirc)))) 2770 2771 2772 ;; 2773 ;; Battery status 2774 ;; 2775 2776 (defun doom-modeline-battery-icon (icon unicode text face) 2777 "Displays the battery ICON with FACE. 2778 2779 UNICODE and TEXT are fallbacks. 2780 Uses `nerd-icons-mdicon' to fetch the icon." 2781 (doom-modeline-icon 'mdicon icon unicode text :face face)) 2782 2783 (defvar doom-modeline--battery-status nil) 2784 (defun doom-modeline-update-battery-status () 2785 "Update battery status." 2786 (setq doom-modeline--battery-status 2787 (when (and doom-modeline-battery 2788 (bound-and-true-p display-battery-mode)) 2789 (let* ((data (and battery-status-function 2790 (functionp battery-status-function) 2791 (funcall battery-status-function))) 2792 (status (cdr (assoc ?L data))) 2793 (charging? (or (string-equal "AC" status) 2794 (string-equal "on-line" status))) 2795 (percentage (car (read-from-string (or (cdr (assq ?p data)) "ERR")))) 2796 (valid-percentage? (and (numberp percentage) 2797 (>= percentage 0) 2798 (<= percentage battery-mode-line-limit))) 2799 (face (if valid-percentage? 2800 (cond (charging? 'doom-modeline-battery-charging) 2801 ((< percentage battery-load-critical) 'doom-modeline-battery-critical) 2802 ((< percentage 25) 'doom-modeline-battery-warning) 2803 ((< percentage 95) 'doom-modeline-battery-normal) 2804 (t 'doom-modeline-battery-full)) 2805 'doom-modeline-battery-error)) 2806 (icon (if valid-percentage? 2807 (cond 2808 ((>= percentage 100) 2809 (doom-modeline-battery-icon (if charging? 2810 "nf-md-battery_charging_100" 2811 "nf-md-battery") 2812 "đ" "-" face)) 2813 ((>= percentage 90) 2814 (doom-modeline-battery-icon (if charging? 2815 "nf-md-battery_charging_90" 2816 "nf-md-battery_90") 2817 "đ" "-" face)) 2818 ((>= percentage 80) 2819 (doom-modeline-battery-icon (if charging? 2820 "nf-md-battery_charging_80" 2821 "nf-md-battery_80") 2822 "đ" "-" face)) 2823 ((>= percentage 70) 2824 (doom-modeline-battery-icon (if charging? 2825 "nf-md-battery_charging_70" 2826 "nf-md-battery_70") 2827 "đ" "-" face)) 2828 ((>= percentage 60) 2829 (doom-modeline-battery-icon (if charging? 2830 "nf-md-battery_charging_60" 2831 "nf-md-battery_60") 2832 "đ" "-" face)) 2833 ((>= percentage 50) 2834 (doom-modeline-battery-icon (if charging? 2835 "nf-md-battery_charging_50" 2836 "nf-md-battery_50") 2837 "đ" "-" face)) 2838 ((>= percentage 40) 2839 (doom-modeline-battery-icon (if charging? 2840 "nf-md-battery_charging_40" 2841 "nf-md-battery_40") 2842 "đ" "-" face)) 2843 ((>= percentage 30) 2844 (doom-modeline-battery-icon (if charging? 2845 "nf-md-battery_charging_30" 2846 "nf-md-battery_30") 2847 "đ" "-" face)) 2848 ((>= percentage 20) 2849 (doom-modeline-battery-icon (if charging? 2850 "nf-md-battery_charging_20" 2851 "nf-md-battery_20") 2852 "đ" "-" face)) 2853 ((>= percentage 10) 2854 (doom-modeline-battery-icon (if charging? 2855 "nf-md-battery_charging_10" 2856 "nf-md-battery_10") 2857 "đĒĢ" "-" face)) 2858 (t (doom-modeline-battery-icon (if charging? 2859 "nf-md-battery_charging_outline" 2860 "nf-md-battery_outline") 2861 "đĒĢ" "!" face))) 2862 (doom-modeline-battery-icon "nf-md-battery_alert" "â " "N/A" face))) 2863 (text (if valid-percentage? (format "%d%s" percentage "%%") "")) 2864 (help-echo (if (and battery-echo-area-format data valid-percentage?) 2865 (battery-format battery-echo-area-format data) 2866 "Battery status not available"))) 2867 (cons (propertize icon 'help-echo help-echo) 2868 (propertize text 'face face 'help-echo help-echo)))))) 2869 2870 (doom-modeline-add-variable-watcher 2871 'doom-modeline-icon 2872 (lambda (_sym val op _where) 2873 (when (eq op 'set) 2874 (setq doom-modeline-icon val) 2875 (doom-modeline-update-battery-status)))) 2876 2877 (doom-modeline-add-variable-watcher 2878 'doom-modeline-unicode-fallback 2879 (lambda (_sym val op _where) 2880 (when (eq op 'set) 2881 (setq doom-modeline-unicode-fallback val) 2882 (doom-modeline-update-battery-status)))) 2883 2884 (doom-modeline-def-segment battery 2885 "Display battery status." 2886 (when (and doom-modeline-battery 2887 (bound-and-true-p display-battery-mode) 2888 (doom-modeline--segment-visible 'battery)) 2889 (let ((sep (doom-modeline-spc)) 2890 (vsep (doom-modeline-vspc))) 2891 (concat sep 2892 (car doom-modeline--battery-status) 2893 vsep 2894 (cdr doom-modeline--battery-status) 2895 sep)))) 2896 2897 (defun doom-modeline-override-battery () 2898 "Override default battery mode-line." 2899 (if (and doom-modeline-battery 2900 (bound-and-true-p doom-modeline-mode)) 2901 (progn 2902 (advice-add #'battery-update :override #'doom-modeline-update-battery-status) 2903 (setq global-mode-string 2904 (delq 'battery-mode-line-string global-mode-string)) 2905 (and (bound-and-true-p display-battery-mode) (battery-update))) 2906 (progn 2907 (advice-remove #'battery-update #'doom-modeline-update-battery-status) 2908 (when (and display-battery-mode battery-status-function battery-mode-line-format 2909 (not (memq 'battery-mode-line-string global-mode-string))) 2910 (setq global-mode-string 2911 (append global-mode-string '(battery-mode-line-string))))))) 2912 (add-hook 'display-battery-mode-hook #'doom-modeline-override-battery) 2913 (add-hook 'doom-modeline-mode-hook #'doom-modeline-override-battery) 2914 2915 (doom-modeline-add-variable-watcher 2916 'doom-modeline-battery 2917 (lambda (_sym val op _where) 2918 (when (eq op 'set) 2919 (setq doom-modeline-battery val) 2920 (doom-modeline-override-battery)))) 2921 2922 2923 ;; 2924 ;; Package information 2925 ;; 2926 2927 (doom-modeline-def-segment package 2928 "Show package information via `paradox'." 2929 (concat 2930 (doom-modeline-display-text 2931 (format-mode-line 'mode-line-front-space)) 2932 2933 (when (and doom-modeline-icon doom-modeline-major-mode-icon) 2934 (concat 2935 (doom-modeline-spc) 2936 (doom-modeline-icon 'faicon "nf-fa-archive" nil nil 2937 :face (doom-modeline-face 2938 (if doom-modeline-major-mode-color-icon 2939 'nerd-icons-silver 2940 'mode-line))))) 2941 (doom-modeline-display-text 2942 (format-mode-line 'mode-line-buffer-identification)))) 2943 2944 2945 ;; 2946 ;; Helm 2947 ;; 2948 2949 (defvar doom-modeline--helm-buffer-ids 2950 '(("*helm*" . "HELM") 2951 ("*helm M-x*" . "HELM M-x") 2952 ("*swiper*" . "SWIPER") 2953 ("*Projectile Perspectives*" . "HELM Projectile Perspectives") 2954 ("*Projectile Layouts*" . "HELM Projectile Layouts") 2955 ("*helm-ag*" . (lambda () 2956 (format "HELM Ag: Using %s" 2957 (car (split-string helm-ag-base-command)))))) 2958 "Alist of custom helm buffer names to use. 2959 The cdr can also be a function that returns a name to use.") 2960 2961 (doom-modeline-def-segment helm-buffer-id 2962 "Helm session identifier." 2963 (when (bound-and-true-p helm-alive-p) 2964 (let ((sep (doom-modeline-spc))) 2965 (concat 2966 sep 2967 (when doom-modeline-icon 2968 (concat 2969 (doom-modeline-icon 'sucicon "nf-custom-emacs" nil nil 2970 :face (doom-modeline-face 2971 (and doom-modeline-major-mode-color-icon 2972 'nerd-icons-blue))) 2973 sep)) 2974 (propertize 2975 (let ((custom (cdr (assoc (buffer-name) doom-modeline--helm-buffer-ids))) 2976 (case-fold-search t) 2977 (name (replace-regexp-in-string "-" " " (buffer-name)))) 2978 (cond ((stringp custom) custom) 2979 ((functionp custom) (funcall custom)) 2980 (t 2981 (string-match "\\*helm:? \\(mode \\)?\\([^\\*]+\\)\\*" name) 2982 (concat "HELM " (capitalize (match-string 2 name)))))) 2983 'face (doom-modeline-face 'doom-modeline-buffer-file)) 2984 sep)))) 2985 2986 (doom-modeline-def-segment helm-number 2987 "Number of helm candidates." 2988 (when (bound-and-true-p helm-alive-p) 2989 (concat 2990 (propertize (format " %d/%d" 2991 (helm-candidate-number-at-point) 2992 (helm-get-candidate-number t)) 2993 'face (doom-modeline-face 'doom-modeline-buffer-path)) 2994 (propertize (format " (%d total) " (helm-get-candidate-number)) 2995 'face (doom-modeline-face 'doom-modeline-info))))) 2996 2997 (doom-modeline-def-segment helm-help 2998 "Helm keybindings help." 2999 (when (bound-and-true-p helm-alive-p) 3000 (mapcar 3001 (lambda (s) 3002 (if (string-prefix-p "\\<" s) 3003 (propertize (substitute-command-keys s) 3004 'face (doom-modeline-face 3005 'doom-modeline-buffer-file)) 3006 s)) 3007 '("\\<helm-map>\\[helm-help]" "(help) " 3008 "\\<helm-map>\\[helm-select-action]" "(actions) " 3009 "\\<helm-map>\\[helm-maybe-exit-minibuffer]/F1/F2..." "(action) ")))) 3010 3011 (doom-modeline-def-segment helm-prefix-argument 3012 "Helm prefix argument." 3013 (when (and (bound-and-true-p helm-alive-p) 3014 helm--mode-line-display-prefarg) 3015 (let ((arg (prefix-numeric-value (or prefix-arg current-prefix-arg)))) 3016 (unless (= arg 1) 3017 (propertize (format "C-u %s" arg) 3018 'face (doom-modeline-face 'doom-modeline-info)))))) 3019 3020 (defvar doom-modeline--helm-current-source nil 3021 "The currently active helm source.") 3022 (doom-modeline-def-segment helm-follow 3023 "Helm follow indicator." 3024 (and (bound-and-true-p helm-alive-p) 3025 doom-modeline--helm-current-source 3026 (eq 1 (cdr (assq 'follow doom-modeline--helm-current-source))) 3027 "HF")) 3028 3029 ;; 3030 ;; Git timemachine 3031 ;; 3032 3033 (doom-modeline-def-segment git-timemachine 3034 (concat 3035 (doom-modeline-spc) 3036 (doom-modeline--buffer-mode-icon) 3037 (doom-modeline--buffer-state-icon) 3038 (propertize 3039 "*%b*" 3040 'face (doom-modeline-face 'doom-modeline-buffer-timemachine)))) 3041 3042 ;; 3043 ;; Markdown/Org preview 3044 ;; 3045 3046 (doom-modeline-def-segment grip 3047 (when (bound-and-true-p grip-mode) 3048 (let ((sep (doom-modeline-spc))) 3049 (concat 3050 sep 3051 (let ((face (doom-modeline-face 3052 (if grip--process 3053 (pcase (process-status grip--process) 3054 ('run 'doom-modeline-info) 3055 ('exit 'doom-modeline-warning) 3056 (_ 'doom-modeline-urgent)) 3057 'doom-modeline-urgent)))) 3058 (propertize 3059 (doom-modeline-icon 'codicon "nf-cod-open_preview" "đ" "@" :face face) 3060 'help-echo (format "Preview on %s 3061 mouse-1: Preview in browser 3062 mouse-2: Stop preview 3063 mouse-3: Restart preview" 3064 (grip--preview-url)) 3065 'mouse-face 'doom-modeline-highlight 3066 'local-map (let ((map (make-sparse-keymap))) 3067 (define-key map [mode-line mouse-1] 3068 #'grip-browse-preview) 3069 (define-key map [mode-line mouse-2] 3070 #'grip-stop-preview) 3071 (define-key map [mode-line mouse-3] 3072 #'grip-restart-preview) 3073 map))) 3074 sep)))) 3075 3076 ;; 3077 ;; Follow mode 3078 ;; 3079 3080 (doom-modeline-def-segment follow 3081 (when (bound-and-true-p follow-mode) 3082 (let* ((windows (follow-all-followers)) 3083 (nwindows (length windows)) 3084 (nfollowing (- (length (memq (selected-window) windows)) 1))) 3085 (concat 3086 (doom-modeline-spc) 3087 (propertize (format "Follow %d/%d" (- nwindows nfollowing) nwindows) 3088 'face 'doom-modeline-buffer-minor-mode))))) 3089 3090 ;; 3091 ;; Display time 3092 ;; 3093 3094 (defconst doom-modeline--clock-hour-hand-ratio 0.45 3095 "Length of the hour hand as a proportion of the radius.") 3096 3097 (defconst doom-modeline--clock-minute-hand-ratio 0.7 3098 "Length of the minute hand as a proportion of the radius.") 3099 3100 (defun doom-modeline--create-clock-svg (hour minute radius color) 3101 "Construct an SVG clock showing the time HOUR:MINUTE. 3102 The clock will be of the specified RADIUS and COLOR." 3103 (let ((thickness-factor (image-compute-scaling-factor 'auto)) 3104 (hour-x (* radius (sin (* (- 6 hour (/ minute 60.0)) (/ float-pi 6))) 3105 doom-modeline--clock-hour-hand-ratio)) 3106 (hour-y (* radius (cos (* (- 6 hour (/ minute 60.0)) (/ float-pi 6))) 3107 doom-modeline--clock-hour-hand-ratio)) 3108 (minute-x (* radius (sin (* (- 30 minute) (/ float-pi 30))) 3109 doom-modeline--clock-minute-hand-ratio)) 3110 (minute-y (* radius (cos (* (- 30 minute) (/ float-pi 30))) 3111 doom-modeline--clock-minute-hand-ratio)) 3112 (svg (svg-create (* 2 radius) (* 2 radius) :stroke color))) 3113 (svg-circle svg radius radius (- radius thickness-factor) 3114 :fill "none" :stroke-width (* 2 thickness-factor)) 3115 (svg-circle svg radius radius thickness-factor 3116 :fill color :stroke "none") 3117 (svg-line svg radius radius (+ radius hour-x) (+ radius hour-y) 3118 :stroke-width (* 2 thickness-factor)) 3119 (svg-line svg radius radius (+ radius minute-x) (+ radius minute-y) 3120 :stroke-width (* 1.5 thickness-factor)) 3121 svg)) 3122 3123 (defvar doom-modeline--clock-cache nil 3124 "The last result of `doom-modeline--generate-clock'.") 3125 3126 (defun doom-modeline--generate-clock () 3127 "Return a string containing the current time as an analogue clock svg. 3128 When the svg library is not available, return nil." 3129 (cdr 3130 (or (and (equal (truncate (float-time) 3131 (* doom-modeline-time-clock-minute-resolution 60)) 3132 (car doom-modeline--clock-cache)) 3133 doom-modeline--clock-cache) 3134 (and (require 'svg nil t) 3135 (setq doom-modeline--clock-cache 3136 (cons (truncate (float-time) 3137 (* doom-modeline-time-clock-minute-resolution 60)) 3138 (propertize 3139 " " 3140 'display 3141 (svg-image 3142 (doom-modeline--create-clock-svg 3143 (string-to-number (format-time-string "%-I")) ; hour 3144 (* (truncate (string-to-number (format-time-string "%-M")) 3145 doom-modeline-time-clock-minute-resolution) 3146 doom-modeline-time-clock-minute-resolution) ; minute 3147 (if (integerp doom-modeline-time-clock-size) ; radius 3148 doom-modeline-time-clock-size 3149 (* doom-modeline-height 0.5 doom-modeline-time-clock-size)) 3150 "currentColor") 3151 :scale 1 :ascent 'center) 3152 'face 'doom-modeline-time 3153 'help-echo (lambda (_window _object _pos) 3154 (format-time-string "%c"))))))))) 3155 3156 (defun doom-modeline-time-icon () 3157 "Displays the time icon." 3158 (or (and doom-modeline-time-live-icon 3159 doom-modeline-time-analogue-clock 3160 (display-graphic-p) 3161 (doom-modeline--generate-clock)) 3162 (doom-modeline-icon 3163 'mdicon 3164 (if doom-modeline-time-live-icon 3165 (pcase (% (caddr (decode-time)) 12) 3166 (0 "nf-md-clock_time_twelve_outline") 3167 (1 "nf-md-clock_time_one_outline") 3168 (2 "nf-md-clock_time_two_outline") 3169 (3 "nf-md-clock_time_three_outline") 3170 (4 "nf-md-clock_time_four_outline") 3171 (5 "nf-md-clock_time_five_outline") 3172 (6 "nf-md-clock_time_six_outline") 3173 (7 "nf-md-clock_time_seven_outline") 3174 (8 "nf-md-clock_time_eight_outline") 3175 (9 "nf-md-clock_time_nine_outline") 3176 (10 "nf-md-clock_time_ten_outline") 3177 (11 "nf-md-clock_time_eleven_outline")) 3178 "nf-md-clock_outline") 3179 "â°" 3180 "" 3181 :face '(:inherit doom-modeline-time :weight normal)))) 3182 3183 (doom-modeline-def-segment time 3184 (when (and doom-modeline-time 3185 (bound-and-true-p display-time-mode) 3186 (doom-modeline--segment-visible 'time)) 3187 (concat 3188 (doom-modeline-spc) 3189 (when doom-modeline-time-icon 3190 (concat 3191 (doom-modeline-time-icon) 3192 (and (or doom-modeline-icon doom-modeline-unicode-fallback) 3193 (doom-modeline-vspc)))) 3194 (propertize display-time-string 3195 'face (doom-modeline-face 'doom-modeline-time))))) 3196 3197 (defun doom-modeline-override-time () 3198 "Override default `display-time' mode-line." 3199 (or global-mode-string (setq global-mode-string '(""))) 3200 (if (and doom-modeline-time 3201 (bound-and-true-p doom-modeline-mode)) 3202 (setq global-mode-string (delq 'display-time-string global-mode-string)) 3203 (or (memq 'display-time-string global-mode-string) 3204 (setq global-mode-string 3205 (append global-mode-string '(display-time-string)))))) 3206 (add-hook 'display-time-mode-hook #'doom-modeline-override-time) 3207 (add-hook 'doom-modeline-mode-hook #'doom-modeline-override-time) 3208 3209 (doom-modeline-add-variable-watcher 3210 'doom-modeline-time 3211 (lambda (_sym val op _where) 3212 (when (eq op 'set) 3213 (setq doom-modeline-time val) 3214 (doom-modeline-override-time)))) 3215 3216 ;; 3217 ;; Compilation 3218 ;; 3219 3220 (doom-modeline-def-segment compilation 3221 (and (bound-and-true-p compilation-in-progress) 3222 (propertize "[Compiling] " 3223 'face (doom-modeline-face 'doom-modeline-compilation) 3224 'help-echo "Compiling; mouse-2: Goto Buffer" 3225 'mouse-face 'doom-modeline-highlight 3226 'local-map 3227 (make-mode-line-mouse-map 3228 'mouse-2 3229 #'compilation-goto-in-progress-buffer)))) 3230 3231 ;; 3232 ;; Eldoc 3233 ;; 3234 3235 (doom-modeline-def-segment eldoc 3236 (and (bound-and-true-p eldoc-mode) 3237 '(eldoc-mode-line-string 3238 (" " eldoc-mode-line-string " ")))) 3239 3240 (defun doom-modeline-eldoc-minibuffer-message (format-string &rest args) 3241 "Display message specified by FORMAT-STRING and ARGS on the mode-line as needed. 3242 This function displays the message produced by formatting ARGS 3243 with FORMAT-STRING on the mode line when the current buffer is a minibuffer. 3244 Otherwise, it displays the message like `message' would." 3245 (if (minibufferp) 3246 (progn 3247 (add-hook 'minibuffer-exit-hook 3248 (lambda () (setq eldoc-mode-line-string nil 3249 ;; https://debbugs.gnu.org/16920 3250 eldoc-last-message nil)) 3251 nil t) 3252 (with-current-buffer 3253 (window-buffer 3254 (or (window-in-direction 'above (minibuffer-window)) 3255 (minibuffer-selected-window) 3256 (get-largest-window))) 3257 (setq eldoc-mode-line-string 3258 (when (stringp format-string) 3259 (apply #'format-message format-string args))) 3260 (force-mode-line-update))) 3261 (apply #'message format-string args))) 3262 3263 ;; 3264 ;; Kubernetes 3265 ;; 3266 3267 (doom-modeline-def-segment k8s 3268 (when (and (bound-and-true-p kele-mode) (doom-modeline--segment-visible 'k8s)) 3269 (let* ((ctx (kele-current-context-name :wait nil)) 3270 (ns (kele-current-namespace :wait nil)) 3271 (icon (doom-modeline-icon 'mdicon "nf-md-kubernetes" "K8s:" "K8s:")) 3272 (sep (doom-modeline-spc)) 3273 (help-msg (let ((msgs (list (format "Current context: %s" ctx)))) 3274 (when ns 3275 (setq msgs (append msgs (list (format "Current namespace: %s" ns))))) 3276 (string-join msgs "\n")))) 3277 (propertize (concat 3278 icon sep ctx 3279 (when (and doom-modeline-k8s-show-namespace ns) (format "(%s)" ns)) 3280 sep) 3281 'local-map (let ((map (make-sparse-keymap))) 3282 (define-key map [mode-line down-mouse-1] kele-menu-map) 3283 map) 3284 'mouse-face 'doom-modeline-highlight 3285 'help-echo help-msg)))) 3286 3287 (provide 'doom-modeline-segments) 3288 3289 ;;; doom-modeline-segments.el ends here