From b4d0e91dade20b2dbb41ad34b112323fa3b36def Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Sun, 19 Mar 2023 11:29:55 -0700 Subject: [PATCH 1/5] a comment re: a starting point on mode rings --- rigpa-mode-mode.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rigpa-mode-mode.el b/rigpa-mode-mode.el index 93959a1..b35734a 100644 --- a/rigpa-mode-mode.el +++ b/rigpa-mode-mode.el @@ -160,6 +160,10 @@ to ensure, upon state transitions, that: 0))) (let ((mode-name (rigpa-editing-entity-name (rigpa-ensemble-member-at-position tower level-number)))) + ;; so, we're expecting the tower to be a list containing + ;; _modes_. Instead, we want to change it to contain + ;; _mode rings_. Let's first convert it into a mode ring + ;; containing a single element. (rigpa-enter-mode mode-name) (setq rigpa--current-level level-number)))) From 5905e290a822b6f8028e3c234e59ce4e8f0aeec6 Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Tue, 26 Mar 2024 11:21:54 -0700 Subject: [PATCH 2/5] Basic working mode rings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rings are a natural structure to use for modes. This has been planned for a long time and this is a basic working version that we can iterate on. It replaces modes with mode rings at a particular level in a specific tower (lisp tower, so that we can rotate normal → symex → normal), and stays behind black box interfaces. --- rigpa-mode-mode.el | 38 ++++++++++++++++++++++++++++++++++---- rigpa-types.el | 3 ++- rigpa.el | 3 +-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/rigpa-mode-mode.el b/rigpa-mode-mode.el index b35734a..9c1bf89 100644 --- a/rigpa-mode-mode.el +++ b/rigpa-mode-mode.el @@ -31,6 +31,7 @@ (require 'chimera) (require 'rigpa-text-parsers) (require 'rigpa-meta) +(require 'dynaring) (evil-define-state mode "Mode state." @@ -151,15 +152,44 @@ to ensure, upon state transitions, that: "Enter mode MODE-NAME." (chimera-enter-mode (ht-get rigpa-modes mode-name))) +(defun rigpa--rotate-mode-ring (direction) + "Rotate the current mode ring in DIRECTION." + (interactive) + (let* ((tower (rigpa--local-tower)) + (tower-height (rigpa-ensemble-size tower)) + (level-number (max (min rigpa--current-level + (1- tower-height)) + 0)) + (ring (rigpa-ensemble-member-at-position tower + level-number))) + (funcall direction ring) + (rigpa-enter-mode + (rigpa-editing-entity-name + (dynaring-value ring))))) + +(defun rigpa-rotate-mode-ring-left () + "Rotate the current mode ring to the left." + (interactive) + (rigpa--rotate-mode-ring #'dynaring-rotate-left)) + +(defun rigpa-rotate-mode-ring-right () + "Rotate the current mode ring to the right." + (interactive) + (rigpa--rotate-mode-ring #'dynaring-rotate-right)) + (defun rigpa--enter-level (level-number) "Enter level LEVEL-NUMBER" (let* ((tower (rigpa--local-tower)) (tower-height (rigpa-ensemble-size tower)) (level-number (max (min level-number (1- tower-height)) - 0))) - (let ((mode-name (rigpa-editing-entity-name - (rigpa-ensemble-member-at-position tower level-number)))) + 0)) + (level (rigpa-ensemble-member-at-position tower + level-number)) + (mode (if (dynaringp level) + (dynaring-value level) + level))) + (let ((mode-name (rigpa-editing-entity-name mode))) ;; so, we're expecting the tower to be a list containing ;; _modes_. Instead, we want to change it to contain ;; _mode rings_. Let's first convert it into a mode ring @@ -317,7 +347,7 @@ is precisely the thing to be done." (defun rigpa-serialize-mode (mode tower level-number) "A string representation of a mode." - (let ((name (rigpa-editing-entity-name mode))) + (let ((name (rigpa-editing-entity-name (if (dynaringp mode) (dynaring-value mode) mode)))) (concat "|―――" (number-to-string level-number) "―――|" diff --git a/rigpa-types.el b/rigpa-types.el index 568358b..635047c 100644 --- a/rigpa-types.el +++ b/rigpa-types.el @@ -28,6 +28,7 @@ (require 'cl-lib) (require 'chimera) +(require 'dynaring) (cl-defstruct editing-ensemble "Specification for an editing ensemble." @@ -48,7 +49,7 @@ entity, such as modes, towers or complexes.") (defun rigpa-ensemble-member-position-by-name (ensemble name) "The position of a member in an ensemble, by name." - (seq-position (seq-map #'rigpa-editing-entity-name + (seq-position (seq-map (lambda (m) (rigpa-editing-entity-name (if (dynaringp m) (dynaring-value m) m))) (editing-ensemble-members ensemble)) name)) diff --git a/rigpa.el b/rigpa.el index 61b5306..89b1487 100644 --- a/rigpa.el +++ b/rigpa.el @@ -333,8 +333,7 @@ and simply toggles whether the menu is visible or not." (make-editing-ensemble :name "lisp" :default "symex" :members (list chimera-insert-mode - chimera-symex-mode - chimera-normal-mode))) + (dynaring chimera-normal-mode chimera-symex-mode)))) ;; complexes for base editing levels (setq rigpa-general-complex From 8dc2003ea30ca6dfca4307f526e8b0e237918b9c Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Tue, 26 Mar 2024 16:18:17 -0700 Subject: [PATCH 3/5] improve a predicate --- chimera-hydra.el | 4 ++-- rigpa-mode-mode.el | 22 +++++++++++----------- rigpa-tower-mode.el | 4 ++-- rigpa-types.el | 11 +++++++---- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/chimera-hydra.el b/chimera-hydra.el index b8cbbc6..e87c4d0 100644 --- a/chimera-hydra.el +++ b/chimera-hydra.el @@ -91,8 +91,8 @@ If no VALUE is provided, this clears the flag." ;; already in the tower? ;; [doing this for now to fix symex margins issue, but ;; not sure exactly what is happening there] - (unless (rigpa-ensemble-member-position-by-name (rigpa--local-tower) - (symbol-name evil-state)) + (unless (rigpa--member-of-ensemble-p (rigpa--local-tower) + (symbol-name evil-state)) (rigpa--enter-appropriate-mode))) (let* ((hydra (chimera--hydra-for-state mode-name)) (entry-buffer (hydra-get-property hydra :entry-buffer))) diff --git a/rigpa-mode-mode.el b/rigpa-mode-mode.el index 9c1bf89..c7a9ea8 100644 --- a/rigpa-mode-mode.el +++ b/rigpa-mode-mode.el @@ -201,8 +201,8 @@ to ensure, upon state transitions, that: "Enter lower level." (interactive) (let ((mode-name (symbol-name evil-state))) - (if (rigpa-ensemble-member-position-by-name (rigpa--local-tower) - mode-name) + (if (rigpa--member-of-ensemble-p (rigpa--local-tower) + mode-name) (when (> rigpa--current-level 0) (rigpa--enter-level (1- rigpa--current-level))) ;; "not my tower, not my problem" @@ -230,8 +230,8 @@ Priority: (1) provided mode if admissible (i.e. present in tower) [TODO] (current-mode-name (chimera-mode-name current-mode)) (recall-mode-name (rigpa--local-recall-mode)) (default-mode-name (editing-ensemble-default (rigpa--local-tower)))) - (cond ((rigpa--member-of-ensemble-p current-mode - (rigpa--local-tower)) + (cond ((rigpa--member-of-ensemble-p (rigpa--local-tower) + current-mode-name) ;; we don't want to do anything in this case, ;; but re-enter the current mode to ensure ;; that it reconciles state with the new tower @@ -250,8 +250,8 @@ Priority: (1) provided mode if admissible (i.e. present in tower) [TODO] ;; TODO: using evil-state doesn't work in buffer mode ;; since the other buffer is in a local (e.g. Insert) state ;; rather than buffer state - (if (rigpa-ensemble-member-position-by-name (rigpa--local-tower) - mode-name) + (if (rigpa--member-of-ensemble-p (rigpa--local-tower) + mode-name) (when (< rigpa--current-level (1- (rigpa-ensemble-size (rigpa--local-tower)))) (rigpa--enter-level (1+ rigpa--current-level))) @@ -334,11 +334,11 @@ is precisely the thing to be done." (recall rigpa-recall)) ;; only set recall here if it is currently in the tower AND ;; going to a state outside the tower - (when (and (rigpa-ensemble-member-position-by-name (rigpa--local-tower) - mode-name) - (not (rigpa-ensemble-member-position-by-name - (rigpa--local-tower) - (symbol-name evil-next-state)))) + (when (and (rigpa--member-of-ensemble-p (rigpa--local-tower) + mode-name) + (not + (rigpa--member-of-ensemble-p (rigpa--local-tower) + (symbol-name evil-next-state)))) (rigpa-set-mode-recall mode-name))))) (defun rigpa-set-mode-recall (mode-name) diff --git a/rigpa-tower-mode.el b/rigpa-tower-mode.el index 3e720de..cdb067a 100644 --- a/rigpa-tower-mode.el +++ b/rigpa-tower-mode.el @@ -74,10 +74,10 @@ (ground-recall (with-current-buffer ground-buffer rigpa-recall)) (level (or (rigpa-ensemble-member-position-by-name tower - ground-mode-name) + ground-mode-name) (and ground-recall (rigpa-ensemble-member-position-by-name tower - ground-recall)) + ground-recall)) 0)) (tower-height (rigpa-ensemble-size tower))) (evil-goto-line (- tower-height level)))) diff --git a/rigpa-types.el b/rigpa-types.el index 635047c..1b37d7a 100644 --- a/rigpa-types.el +++ b/rigpa-types.el @@ -53,6 +53,13 @@ entity, such as modes, towers or complexes.") (editing-ensemble-members ensemble)) name)) +(defun rigpa--member-of-ensemble-p (ensemble entity-name) + "A predicate asserting whether ENTITY-NAME is a member of ENSEMBLE." + (not + (not + (rigpa-ensemble-member-position-by-name ensemble + entity-name)))) + (defun rigpa-ensemble-size (ensemble) "Size of ensemble (e.g. height of a tower)." (length (editing-ensemble-members ensemble))) @@ -61,10 +68,6 @@ entity, such as modes, towers or complexes.") "Mode at LEVEL in the TOWER." (nth position (editing-ensemble-members tower))) -(defun rigpa--member-of-ensemble-p (entity ensemble) - "A predicate asserting whether ENTITY is a member of ENSEMBLE." - (memq entity (editing-ensemble-members ensemble))) - (provide 'rigpa-types) ;;; rigpa-types.el ends here From 0359e90acc66f4179a63e5e19b7d1fabf19b90f9 Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Wed, 27 Mar 2024 17:06:46 -0700 Subject: [PATCH 4/5] Overload Esc to rotate ring in non-insertion states This is just a quick hack to get the desired behavior. We'll revisit it down the line. --- rigpa.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rigpa.el b/rigpa.el index 89b1487..106c456 100644 --- a/rigpa.el +++ b/rigpa.el @@ -254,8 +254,9 @@ and simply toggles whether the menu is visible or not." (let ((keymap (symbol-value (intern (concat "evil-" state "-state-map"))))) - (define-key keymap [escape] #'rigpa-enter-higher-level) - (unless (member state chimera-insertion-states) + (if (member state chimera-insertion-states) + (define-key keymap [escape] #'rigpa-enter-higher-level) + (define-key keymap [escape] #'rigpa-rotate-mode-ring-left) (define-key keymap [return] #'rigpa--enter-lower-or-pass-through)))) ;; exit visual state gracefully (define-key evil-visual-state-map [escape] (lambda () From 908c0ade9e4e6b2cdd8d02d772f2225b87a884df Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Wed, 3 Apr 2024 17:41:45 -0700 Subject: [PATCH 5/5] basic keybinding override to use ring rotation --- rigpa.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rigpa.el b/rigpa.el index 106c456..bdb7b95 100644 --- a/rigpa.el +++ b/rigpa.el @@ -256,7 +256,13 @@ and simply toggles whether the menu is visible or not." (concat "evil-" state "-state-map"))))) (if (member state chimera-insertion-states) (define-key keymap [escape] #'rigpa-enter-higher-level) - (define-key keymap [escape] #'rigpa-rotate-mode-ring-left) + (define-key keymap [escape] (lambda () + (interactive) + (if (equal "lisp" + (rigpa-editing-entity-name + (rigpa--local-tower))) + (rigpa-rotate-mode-ring-left) + (rigpa-enter-higher-level)))) (define-key keymap [return] #'rigpa--enter-lower-or-pass-through)))) ;; exit visual state gracefully (define-key evil-visual-state-map [escape] (lambda ()