Add :persistent keyword for micro-state

Persistent micro-state stay active unless an explicit
exit key is pressed
This commit is contained in:
syl20bnr 2015-02-21 02:17:39 -05:00
parent 15f2ea403f
commit e794d0ef11

View file

@ -53,6 +53,10 @@ Available PROPS:
`:doc STRING or SEXP' `:doc STRING or SEXP'
A STRING or a SEXP that evaluates to a string A STRING or a SEXP that evaluates to a string
`:persistent BOOLEAN'
If BOOLEAN in non nil then the micro-state never exits. A binding
with an explicitly set `exit t' property is required.
`:bindings EXPRESSIONS' `:bindings EXPRESSIONS'
One or several EXPRESSIONS with the form One or several EXPRESSIONS with the form
(STRING1 SYMBOL1 :doc STRING :exit SYMBOL) (STRING1 SYMBOL1 :doc STRING :exit SYMBOL)
@ -65,6 +69,7 @@ Available PROPS:
(declare (indent 1)) (declare (indent 1))
(let* ((func (spacemacs//micro-state-func-name name)) (let* ((func (spacemacs//micro-state-func-name name))
(doc (spacemacs/mplist-get props :doc)) (doc (spacemacs/mplist-get props :doc))
(persistent (plist-get props :persistent))
(on-enter (spacemacs/mplist-get props :on-enter)) (on-enter (spacemacs/mplist-get props :on-enter))
(on-exit (spacemacs/mplist-get props :on-exit)) (on-exit (spacemacs/mplist-get props :on-exit))
(bindings (spacemacs/mplist-get props :bindings)) (bindings (spacemacs/mplist-get props :bindings))
@ -83,7 +88,7 @@ Available PROPS:
'set-transient-map) 'set-transient-map)
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
,@keymap-body map) ',(spacemacs//micro-state-create-exit-func ,@keymap-body map) ',(spacemacs//micro-state-create-exit-func
name wrappers on-exit))))) name wrappers persistent on-exit)))))
(defun spacemacs//micro-state-func-name (name) (defun spacemacs//micro-state-func-name (name)
"Return the name of the micro-state function." "Return the name of the micro-state function."
@ -99,10 +104,13 @@ Available PROPS:
(defun spacemacs//micro-state-create-wrapper (name default-doc binding) (defun spacemacs//micro-state-create-wrapper (name default-doc binding)
"Create a wrapper of FUNC and return a tuple (key wrapper BINDING)." "Create a wrapper of FUNC and return a tuple (key wrapper BINDING)."
(let* ((wrapped (cadr binding)) (let* ((key (car binding))
(wrapped (cadr binding))
(binding-doc (spacemacs/mplist-get binding :doc)) (binding-doc (spacemacs/mplist-get binding :doc))
(wrapper-name (intern (format "spacemacs//%s-%s" (symbol-name name) (wrapper-name (intern (format "spacemacs//%s-%s-%s"
(symbol-name wrapped)))) (symbol-name name)
(symbol-name wrapped)
key)))
(wrapper-func (wrapper-func
(eval `(defun ,wrapper-name () (eval `(defun ,wrapper-name ()
"Auto-generated function" "Auto-generated function"
@ -114,7 +122,8 @@ Available PROPS:
(if bdoc (if bdoc
(lv-message (spacemacs//micro-state-propertize-doc (lv-message (spacemacs//micro-state-propertize-doc
(concat ,(symbol-name name) ": " bdoc))) (concat ,(symbol-name name) ": " bdoc)))
(when (and defdoc ',wrapped) (when (and defdoc
',wrapped (not (plist-get ',binding :exit)))
(lv-message (spacemacs//micro-state-propertize-doc (lv-message (spacemacs//micro-state-propertize-doc
(concat ,(symbol-name name) ": " (concat ,(symbol-name name) ": "
defdoc)))))))))) defdoc))))))))))
@ -125,7 +134,8 @@ Available PROPS:
(mapcar (lambda (x) `(define-key map ,(kbd (car x)) ',(cadr x))) (mapcar (lambda (x) `(define-key map ,(kbd (car x)) ',(cadr x)))
wrappers)) wrappers))
(defun spacemacs//micro-state-create-exit-func (name wrappers on-exit) (defun spacemacs//micro-state-create-exit-func
(name wrappers persistent on-exit)
"Return a function to execute when leaving the micro-state. "Return a function to execute when leaving the micro-state.
The returned function returns nil if the executed command exits the The returned function returns nil if the executed command exits the
@ -133,25 +143,27 @@ micro-state."
(let ((func (intern (format "spacemacs//%s-on-exit" name)))) (let ((func (intern (format "spacemacs//%s-on-exit" name))))
(eval `(defun ,func () (eval `(defun ,func ()
"Function executed after each micro-state command." "Function executed after each micro-state command."
(if (reduce (lambda (x y) (or x y)) (let* ((cur-wrapper (spacemacs//get-current-wrapper
(mapcar (lambda (x) ',name ',wrappers))
(spacemacs//micro-state-stay? ',name x)) (exitp (if cur-wrapper (plist-get cur-wrapper :exit)
',wrappers) ,(not persistent))))
:initial-value nil) (when exitp ,@on-exit (spacemacs//micro-state-close-window))
't (not exitp))))))
,@on-exit
(spacemacs//micro-state-close-window)
nil)))))
(defun spacemacs//micro-state-stay? (name wrapper) (defun spacemacs//get-current-wrapper (name wrappers)
"Return non nil if WRAPPER does not leave the micro-state." "Return the wrapper being executed.
(let ((micro-state-fun (spacemacs//micro-state-func-name name)) Returns nil if no wrapper is being executed (i.e. an unbound key has been
(key (car wrapper)) pressed)."
(let ((micro-state-fun (spacemacs//micro-state-func-name name)))
(catch 'found
(dolist (wrapper wrappers)
(let ((key (car wrapper))
(func (cadr wrapper))) (func (cadr wrapper)))
(when (and (or (eq this-command micro-state-fun) (if (and (or (eq this-command micro-state-fun)
(eq this-command func)) (eq this-command func))
(equal (this-command-keys) (kbd key))) (equal (this-command-keys) (kbd key)))
(not (plist-get wrapper :exit))))) (throw 'found wrapper))))
nil)))
(defun spacemacs//micro-state-propertize-doc (doc) (defun spacemacs//micro-state-propertize-doc (doc)
"Return a propertized doc string from DOC." "Return a propertized doc string from DOC."