From e4ad515ee64804883c1fd8084b50d24fcc6b733a Mon Sep 17 00:00:00 2001 From: Vladislav Slobodenyuk Date: Fri, 30 Jan 2026 22:10:55 +0900 Subject: [PATCH] Make SSM library actually usable. --- load/simple-state-machines.el | 51 ++++++++++++++++++++++++++++++--- load/simple-state-machines.elc | Bin 3819 -> 4439 bytes 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/load/simple-state-machines.el b/load/simple-state-machines.el index b7f213b..d73eb60 100644 --- a/load/simple-state-machines.el +++ b/load/simple-state-machines.el @@ -61,7 +61,31 @@ ;; 'test-step' -- Calls the handler for the current state. ;; 'test-set-state' -- Tries to set the current state to the provided one, and ;; signals an error if the transition is invalid. - +;; +;; Here is the recreation of the counter example from +;; https://www.emacswiki.org/emacs/StateMachine +;; +;; (ssm-defstate-machine counter +;; :states (start count end) +;; :transitions ((start . count) +;; (count . end) +;; (count . count)) +;; :handlers ((start . (lambda (name) +;; (princ "Starting...") +;; (terpri) +;; (ssm-update-state name 'count 0))) +;; (count . (lambda (name) +;; (cond ((<= (ssm-get-state-data name) 10) +;; (princ (ssm-get-state-data name)) +;; (ssm-update-state +;; name +;; 'count +;; (1+ (ssm-get-state-data name)))) +;; (t (terpri) (ssm-update-state name 'end nil))))))) +;; +;; (ssm-run-until-state 'counter 'end) +;; +;; As you can see, ssm-update-state definitely needs some love. It is unwieldy. ;;; Code: (require 'cl-lib) @@ -142,7 +166,7 @@ Each entry of this alist has the form (FROM . TO).")) (let ((,handler (alist-get ,current-state ,handlers-table)) (,prev-state ,current-state)) (cl-assert ,handler nil "There is no handler for the current state") - (funcall ,handler ,machine-name) + (funcall ,handler ',name) (cl-assert (cl-find (cons ,prev-state ,current-state) @@ -165,12 +189,31 @@ Each entry of this alist has the form (FROM . TO).")) (setq ,current-state state ,state-data new-data)))))))) -(defun ssm-update-state (machine new-state &optional new-data) +(defun ssm-update-state (machine new-state new-data) "Updates the state of the state machine MACHINE. Signals an error if the state transition is invalid." (let ((state-fn - (intern-soft (concat machine "-set-state")))) + (intern-soft (concat (symbol-name machine) "-set-state")))) (funcall state-fn new-state new-data))) +(defun ssm-get-state (machine) + "Returns the state of the specified machine." + (let ((state + (intern-soft (concat (symbol-name machine) "-current-state")))) + (symbol-value state))) + +(defun ssm-get-state-data (machine) + "Returns the state data of the specified machine." + (let ((state-data + (intern-soft (concat (symbol-name machine) "-state-data")))) + (symbol-value state-data))) + +(defun ssm-run-until-state (machine state) + "Steps the specified MACHINE until it enters state STATE." + (let ((step-fn + (intern-soft (concat (symbol-name machine) "-step")))) + (while (not (equal (ssm-get-state machine) state)) + (funcall step-fn)))) + (provide 'simple-state-machines) ;;; simple-state-machines.el ends here diff --git a/load/simple-state-machines.elc b/load/simple-state-machines.elc index 905a51f2acb49eda40f9b41d2f631d0e9efa1d48..1c4420768e3301337bb412dba5887edb6f233fff 100644 GIT binary patch delta 712 zcma))KTpCy7>5-MBoIhk983r=#Y7lN+8z~{lpu+kXpFE?h6-1>q&=GUFmbUT!J&Q& z7ZX2>tGk0=!Q*K76BQlqlJ|yRp7;0MNA68}DI}8yLP{ck`dUo365A*oWgf!M%+sz4 zl7SS3A9bg|Z!LVx=F&xurUUonGD0knh!1> z5R2d;IObqXD6XVZC5yskvvqcU)h_2#r6IOVo0vWv`o1HNFq7vA#h#|umKZUCaa}Mp zRlP7Yr6xhpBa~r}%KpS+umT5?JeYbOrcsvEhbokc2T%c2S2RI=RQ-W^XfpHv=)rI7 zvdH;+ferkk1Cg@|->4%2U#mlh;lPa=Uz8lx3RB964TJ%&0DFGqq||rSMTp@^NNr4=^vG6K bt*LzBRLS)wcVvk9A0duw<2hCMo=txNN|4oa delta 83 zcmcbv^jda