diff --git a/.github/workflows/melpazoid.yml b/.github/workflows/melpazoid.yml index fa289fb..fb5dd79 100644 --- a/.github/workflows/melpazoid.yml +++ b/.github/workflows/melpazoid.yml @@ -10,10 +10,11 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.6 - uses: actions/setup-python@v1 - with: { python-version: 3.6 } + - uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: '3.10' - name: Install run: | python -m pip install --upgrade pip diff --git a/chimera.el b/chimera.el index 089890f..7007fe5 100644 --- a/chimera.el +++ b/chimera.el @@ -28,6 +28,7 @@ (require 'cl-lib) (require 'evil) +(require 'ht) (cl-defstruct chimera-mode "Specification for a mode." @@ -50,16 +51,43 @@ to be run by the mode provider.")) "visual" "replace" "operator" - "char" - "symex")) + "char")) + +(defvar rigpa-lithium-modes + (ht ('rigpa-char-mode "char") + ('rigpa-word-mode "word") + ('rigpa-line-mode "line") + ('symex-editing-mode "symex") + ('rigpa-view-mode "view") + ('rigpa-window-mode "window") + ('rigpa-file-mode "file") + ('rigpa-buffer-mode "buffer") + ('rigpa-system-mode "system") + ('rigpa-application-mode "application") + ('rigpa-activity-mode "activity") + ('rigpa-text-mode "text") + ('rigpa-tab-mode "tab") + ('rigpa-history-mode "history"))) (defvar chimera-insertion-states (list "insert" "emacs")) +(defun rigpa-name-for-lithium-mode (name) + "Rigpa name for lithium mode NAME." + (ht-get rigpa-lithium-modes + name)) + ;; TODO: note name confusion (defun rigpa-current-mode () "Current rigpa mode." - (chimera--mode-for-state (symbol-name evil-state))) + (let ((current-lithium-mode (lithium-current-mode-name))) + (or (and current-lithium-mode + (chimera--mode-by-name + (rigpa-name-for-lithium-mode + current-lithium-mode))) + (and (member (symbol-name evil-state) chimera-evil-states) + (chimera--mode-by-name + (symbol-name evil-state)))))) (defun chimera-switch-mode (to-mode) "Switch to TO-MODE. @@ -91,8 +119,9 @@ exiting by entering." (when (chimera-mode-manage-hooks mode) (run-hooks (chimera-mode-post-exit-hook mode)))) -(defun chimera--mode-for-state (mode-name) - (symbol-value (intern (concat "chimera-" mode-name "-mode")))) +(defun chimera--mode-by-name (name) + "Get the chimera mode by NAME, a string." + (ht-get rigpa-modes name)) (provide 'chimera) diff --git a/rigpa-activity-mode.el b/rigpa-activity-mode.el index f37d3bf..a07751a 100644 --- a/rigpa-activity-mode.el +++ b/rigpa-activity-mode.el @@ -111,7 +111,7 @@ (defun rigpa--on-activity-mode-post-exit () "Actions to take upon exiting activity mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-activity-mode (make-chimera-mode :name "activity" diff --git a/rigpa-application-mode.el b/rigpa-application-mode.el index dc910d8..2b20ba8 100644 --- a/rigpa-application-mode.el +++ b/rigpa-application-mode.el @@ -156,7 +156,7 @@ (defun rigpa--on-application-mode-post-exit () "Actions to take upon exiting application mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-application-mode (make-chimera-mode :name "application" diff --git a/rigpa-buffer-mode.el b/rigpa-buffer-mode.el index d281819..2623b0d 100644 --- a/rigpa-buffer-mode.el +++ b/rigpa-buffer-mode.el @@ -392,7 +392,7 @@ current ('original') buffer." ;; TODO: probably do this (entering appropriate mode in current and original buffer) ;; via a standard internal rigpa hook in mode registration. ;; we can enter appropriate in original if different from current buffer - (rigpa--for-all-buffers #'rigpa--enter-appropriate-mode)) + (rigpa--for-all-buffers #'rigpa--enter-local-evil-state)) (defvar chimera-buffer-mode (make-chimera-mode :name "buffer" diff --git a/rigpa-char-mode.el b/rigpa-char-mode.el index 0cb65c8..c1114bb 100644 --- a/rigpa-char-mode.el +++ b/rigpa-char-mode.el @@ -203,7 +203,7 @@ (defun rigpa--on-char-mode-post-exit () "Enable word minor mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-char-mode (make-chimera-mode :name "char" diff --git a/rigpa-evil-support.el b/rigpa-evil-support.el index f777fb1..dfd2233 100644 --- a/rigpa-evil-support.el +++ b/rigpa-evil-support.el @@ -28,20 +28,12 @@ (require 'evil) -(defun rigpa--define-evil-key (key fn map state) - "Define an evil keybinding in an evil-backed rigpa mode." - (evil-define-key* (list state 'visual 'operator) - map - (kbd key) - fn)) - -(defun rigpa--define-evil-keys-from-spec (keyspec keymap state) - "Define evil keys from a specification." - (dolist (keybinding keyspec) - (rigpa--define-evil-key (car keybinding) - (cdr keybinding) - keymap - state))) +(defun rigpa-evil-state-by-name (name) + "Evil state handle for mode NAME, by string." + (intern + (concat "evil-" + name + "-state"))) (provide 'rigpa-evil-support) diff --git a/rigpa-file-mode.el b/rigpa-file-mode.el index 18d5078..ab72bd6 100644 --- a/rigpa-file-mode.el +++ b/rigpa-file-mode.el @@ -90,7 +90,7 @@ Version 2016-04-04" (defun rigpa--on-file-mode-post-exit () "Actions to take upon exiting file mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-file-mode (make-chimera-mode :name "file" diff --git a/rigpa-history-mode.el b/rigpa-history-mode.el index 85cb09f..3493bfc 100644 --- a/rigpa-history-mode.el +++ b/rigpa-history-mode.el @@ -62,7 +62,7 @@ "Actions to take upon exit from history mode." ;; TODO: probably do this via a standard internal ;; rigpa hook in mode registration - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-history-mode (make-chimera-mode :name "history" diff --git a/rigpa-line-mode.el b/rigpa-line-mode.el index 291cd8d..37e5f3f 100644 --- a/rigpa-line-mode.el +++ b/rigpa-line-mode.el @@ -342,7 +342,7 @@ From: https://emacs.stackexchange.com/questions/17846/calculating-the-length-of- (internal-show-cursor nil t) (hl-line-mode -1) (evil-goto-column rigpa-line--column) - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-line-mode (make-chimera-mode :name "line" diff --git a/rigpa-mode-mode.el b/rigpa-mode-mode.el index 92ecfd0..7aabea5 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 'rigpa-evil-support) (evil-define-state mode "Mode state." @@ -42,8 +43,8 @@ (defvar-local rigpa-recall nil) ;; registry of known modes -(defvar rigpa-modes - (ht)) +(defvar rigpa-modes (ht) + "Lookup chimera modes by their name.") (cl-defun rigpa-register-mode (mode &key @@ -82,9 +83,31 @@ MODE." (when post-exit (add-hook post-exit-hook post-exit)))) +(defun rigpa--enter-local-evil-state () + "Enter evil state for the local mode." + (let* ((current-lithium-mode (lithium-current-mode-name)) + (name (if current-lithium-mode + (rigpa-name-for-lithium-mode + current-lithium-mode) + (rigpa--local-recall-mode))) + (evil-state-fn (rigpa-evil-state-by-name name))) + (funcall evil-state-fn))) + (defun rigpa-enter-mode (mode-name) - "Enter mode MODE-NAME." - (chimera-switch-mode (ht-get rigpa-modes mode-name))) + "Enter mode MODE-NAME. + +If the target mode is in the current tower, or if the current mode +is not in the current tower, then exit the current mode before +entering the new mode. Otherwise, simply enter the new mode so that +upon exit, we are implicitly returned to a native mode." + (let ((from-mode (rigpa-current-mode)) + (to-mode (ht-get rigpa-modes mode-name))) + (if (or (rigpa--member-of-ensemble-p to-mode + (rigpa--local-tower)) + (not (rigpa--member-of-ensemble-p from-mode + (rigpa--local-tower)))) + (chimera-switch-mode to-mode) + (chimera--enter-mode to-mode)))) (defun rigpa--enter-level (level-number) "Enter level LEVEL-NUMBER" @@ -101,25 +124,13 @@ MODE." (defun rigpa-enter-lower-level () "Enter lower level." (interactive) - (let ((mode-name (symbol-name evil-state))) - (if (rigpa-ensemble-member-position-by-name (rigpa--local-tower) - mode-name) + (let ((mode (rigpa-current-mode))) + (if (rigpa--member-of-ensemble-p mode + (rigpa--local-tower)) (when (> rigpa--current-level 0) (rigpa--enter-level (1- rigpa--current-level))) ;; first (low-level) exit the current mode - (chimera--exit-mode (ht-get rigpa-modes mode-name)) - ;; "not my tower, not my problem" - ;; if we exited a buffer via a state that isn't in its tower, then - ;; returning to it "out of band" would find it still that way, - ;; and Enter/Escape would a priori do nothing since the mode is still - ;; outside the local tower. Ordinarily, we would return to this - ;; buffer in a rigpa mode such as buffer mode, which upon - ;; exiting would look for a recall. Since that isn't the case - ;; here, nothing would happen at this point, and this is the spot - ;; where we could have taken some action had we been more civic - ;; minded. So preemptively go to a safe "default" as a failsafe, - ;; which would be overridden by a recall if there is one. - (rigpa--enter-appropriate-mode)))) + (chimera--exit-mode mode)))) (defun rigpa--enter-appropriate-mode (&optional buffer) "Enter the most appropriate mode in BUFFER. @@ -149,19 +160,14 @@ Priority: (1) provided mode if admissible (i.e. present in tower) [TODO] (defun rigpa-enter-higher-level () "Enter higher level." (interactive) - (let ((mode-name (symbol-name evil-state))) - ;; 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) + (let ((mode (rigpa-current-mode))) + (if (rigpa--member-of-ensemble-p mode + (rigpa--local-tower)) (when (< rigpa--current-level (1- (rigpa-ensemble-size (rigpa--local-tower)))) (rigpa--enter-level (1+ rigpa--current-level))) ;; first (low-level) exit the current mode - (chimera--exit-mode (ht-get rigpa-modes mode-name)) - ;; see note for rigpa-enter-lower-level - (rigpa--enter-appropriate-mode)))) + (chimera--exit-mode mode)))) (defun rigpa-enter-lowest-level () "Enter lowest (manual) level." diff --git a/rigpa-symex-mode.el b/rigpa-symex-mode.el index 89ab330..b59c005 100644 --- a/rigpa-symex-mode.el +++ b/rigpa-symex-mode.el @@ -29,28 +29,19 @@ (require 'symex) (require 'chimera) -(defvar chimera-symex-mode-entry-hook nil - "Entry hook for rigpa symex mode.") - -(defvar chimera-symex-mode-exit-hook nil - "Exit hook for rigpa symex mode.") - -(defun rigpa--on-symex-mode-pre-entry () - "Enable symex minor mode." - (symex-enable-editing-minor-mode)) - -(defun rigpa--on-symex-mode-exit () - "Disable symex minor mode." - (symex-disable-editing-minor-mode)) - (defvar chimera-symex-mode (make-chimera-mode :name "symex" :enter #'symex-mode-interface - :pre-entry-hook 'chimera-symex-mode-entry-hook - :post-exit-hook 'chimera-symex-mode-exit-hook - :entry-hook 'evil-symex-state-entry-hook - :exit-hook 'evil-symex-state-exit-hook)) - + :exit #'symex-editing-mode-exit + :pre-entry-hook 'symex-editing-mode-pre-entry-hook + :post-exit-hook 'symex-editing-mode-post-exit-hook + :entry-hook 'symex-editing-mode-post-entry-hook + :exit-hook 'symex-editing-mode-pre-exit-hook + :manage-hooks nil)) + +(defun rigpa--on-symex-mode-entry () + "Actions to take upon entering symex mode." + (evil-symex-state)) (provide 'rigpa-symex-mode) ;;; rigpa-symex-mode.el ends here diff --git a/rigpa-system-mode.el b/rigpa-system-mode.el index f804cfa..4b596b0 100644 --- a/rigpa-system-mode.el +++ b/rigpa-system-mode.el @@ -56,7 +56,7 @@ (defun rigpa--on-system-mode-post-exit () "Actions to take upon exiting system mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-system-mode (make-chimera-mode :name "system" diff --git a/rigpa-tab-mode.el b/rigpa-tab-mode.el index a0bf993..7bd44a2 100644 --- a/rigpa-tab-mode.el +++ b/rigpa-tab-mode.el @@ -126,7 +126,7 @@ buffer mode." (defun rigpa--on-tab-mode-post-exit () "Actions to take upon exiting tab mode." (rigpa-tab-flash-to-original) - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-tab-mode (make-chimera-mode :name "tab" diff --git a/rigpa-text-mode.el b/rigpa-text-mode.el index 0fdf0d4..b9ccbf5 100644 --- a/rigpa-text-mode.el +++ b/rigpa-text-mode.el @@ -51,7 +51,7 @@ (defun rigpa--on-text-mode-post-exit () "Actions to take upon exiting text mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-text-mode (make-chimera-mode :name "text" diff --git a/rigpa-view-mode.el b/rigpa-view-mode.el index bddb182..6ec5b45 100644 --- a/rigpa-view-mode.el +++ b/rigpa-view-mode.el @@ -241,7 +241,7 @@ reference to which we are zooming." (evil-window-middle)) ;; TODO: probably do this via a standard internal ;; rigpa hook in mode registration - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-view-mode (make-chimera-mode :name "view" diff --git a/rigpa-window-mode.el b/rigpa-window-mode.el index 756fa47..56cb9e9 100644 --- a/rigpa-window-mode.el +++ b/rigpa-window-mode.el @@ -360,7 +360,7 @@ happen quickly enough not to be noticeable." (auto-dim-other-buffers-mode -1) ;; TODO: probably do this via a standard internal ;; rigpa hook in mode registration - (rigpa--for-all-buffers #'rigpa--enter-appropriate-mode)) + (rigpa--for-all-buffers #'rigpa--enter-local-evil-state)) (defvar chimera-window-mode (make-chimera-mode :name "window" diff --git a/rigpa-word-mode.el b/rigpa-word-mode.el index 8d74995..9335cfc 100644 --- a/rigpa-word-mode.el +++ b/rigpa-word-mode.el @@ -333,7 +333,7 @@ (defun rigpa--on-word-mode-post-exit () "Enable word minor mode." - (rigpa--enter-appropriate-mode)) + (rigpa--enter-local-evil-state)) (defvar chimera-word-mode (make-chimera-mode :name "word" diff --git a/rigpa.el b/rigpa.el index 9435de3..8c2d655 100644 --- a/rigpa.el +++ b/rigpa.el @@ -298,8 +298,7 @@ :post-entry #'rigpa--on-text-mode-entry :post-exit #'rigpa--on-text-mode-post-exit) (rigpa-register-mode chimera-symex-mode - :pre-entry #'rigpa--on-symex-mode-pre-entry - :pre-exit #'rigpa--on-symex-mode-exit)) + :post-entry #'rigpa--on-symex-mode-entry)) (defun rigpa--create-editing-structures () "Create standard editing structures."