doomemacs/modules/ui/modeline/autoload/settings.el

94 lines
4.6 KiB
EmacsLisp
Raw Normal View History

;;; ui/modeline/autoload/settings.el -*- lexical-binding: t; -*-
(defvar +modeline--alist nil)
;;;###autodef
(defun def-modeline-format! (name left &optional right)
"Define a preset modeline format by name.
NAME is a symbol. The convention is to use keywords for global formats, like
:main or :project, but to use regular symbols for buffer-local formats, like
'twitter and 'pdf.
LEFT and RIGHT are lists that assume the same structure as `mode-line-format',
and make up the mode-line in two parts, separated by variable-width space, to
keep them left and right aligned respectively."
(setf (alist-get name +modeline--alist) (list left right)))
;;;###autodef
(defmacro def-modeline-segment! (name &rest rest)
"TODO"
(declare (doc-string 2))
(let ((docstring (if (and (stringp (car rest)) (cdr rest)) (pop rest)))
body)
(macroexp-progn
(if (not (keywordp (car rest)))
(append `((defvar-local ,name nil ,docstring)
(put ',name 'risky-local-variable t))
(if (or (stringp (car rest))
(memq (car (car-safe rest)) '(:eval :propertize)))
`((setq-default ,name ,(car rest)))
(let ((fn (intern (format "+modeline--%s" name))))
`((fset ',fn (lambda () ,@rest))
(byte-compile ',fn)
(setq-default ,name (quote (:eval (,fn))))))))
;; isolate body
(setq body rest)
(while (keywordp (car body))
(setq body (cddr body)))
;;
(cl-destructuring-bind (&key init faces on-hooks on-set activate deactivate &allow-other-keys)
rest
(let ((realvar (if (and body faces)
(intern (format "+modeline--var-%s" name))
name)))
(append (when body
(if (or on-hooks on-set)
(let ((setterfn (intern (format "+modeline--set-%s" name)))
(varsetterfn (intern (format "+modeline--setvar-%s" name))))
(append `((fset ',setterfn
(lambda (&rest _)
(when (or (memq ',name +modeline-format-left)
(memq ',name +modeline-format-right))
(setq-local ,realvar ,(macroexp-progn body)))))
(byte-compile ',setterfn))
(mapcar (lambda (hook) `(add-hook ',hook #',setterfn))
on-hooks)
(when on-set
`((fset ',varsetterfn
(lambda (sym val op where)
(and (eq op 'set) where
(with-current-buffer where
(set sym val)
(,setterfn)))))
,@(mapcar (lambda (var) `(add-variable-watcher ',var #',varsetterfn))
on-set)))))
(setq init `(quote (:eval ,(macroexp-progn body))))
nil))
(if (eq realvar name)
`((defvar-local ,name nil ,docstring)
(setq-default ,name ,init))
`((defvar-local ,realvar nil)
(defvar-local ,name nil ,docstring)
(setq-default
,name '(:eval (cond ((active) ,realvar)
(,realvar (substring-no-properties ,realvar)))))))
`((put ',name 'risky-local-variable t)))))))))
;;;###autodef
(defun set-modeline! (name &optional default)
"Replace the current buffer's modeline with a preset mode-line format defined
with `def-modeline-format!'.
If DEFAULT is non-nil, make it the default mode-line for all buffers."
(cl-check-type name symbol)
(let ((modeline (cdr (assq name +modeline--alist))))
(unless modeline
(error "The %s modeline format does not exist" name))
(if default
(setq-default +modeline-format-left `("" ,@(car modeline))
+modeline-format-right `("" ,@(cadr modeline)))
(setq +modeline-format-left `("" ,@(car modeline))
+modeline-format-right `("" ,@(cadr modeline))))
(force-mode-line-update)))