diff --git a/CHANGELOG.md b/CHANGELOG.md index be59a2b..f440ada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## Master + +### Breaking Changes + +* replace motion remapping with transparent keypad leader. + +The `meow-motion-overwrite-define-key` has been changed to `meow-motion-define-key`. and now it +works just like other key binding helpers. Users don't have to bind a key to remapped the +keybinding. Now the keypad leader is transparent when a key is not bound in motion state. So that +users can still access the original command with `SPC `. + ## 1.5.0 (2024-10-20) ### Features diff --git a/CUSTOMIZATIONS.org b/CUSTOMIZATIONS.org index 9a39787..b0772df 100644 --- a/CUSTOMIZATIONS.org +++ b/CUSTOMIZATIONS.org @@ -25,6 +25,10 @@ Define key bindings in a state. Similar to ~meow-define-keys~. Define key in NORMAL state. +** meow-motion-define-key + +Similar to ~meow-define-keys~. Define key in MOTION state. + ** meow-leader-define-key Similar to ~meow-define-keys~. Define key in leader keymap. @@ -33,14 +37,6 @@ The keymap used is the one listed in ~meow-keymap-alist~. By default, it is ~mode-specific-map~. -** meow-motion-overwrite-define-key - -Similar to ~meow-define-keys~. Define key in MOTION state. - -Meow will remap overwritten commands to a keybinding with *HYPER* modifier. - -For example, if you define ~j~ as ~C-N~ , the original command on ~j~ will be bound to ~H-j~. - ** meow-setup-indicator A helper function that puts an indicator at the beginning of mode-line. If you want customize mode-line by hand, see `meow-indicator`. @@ -313,17 +309,27 @@ Default: ~select~ The type of selection activated by ~meow-expand-*~ commands. -** meow-motion-remap-prefix +** meow-keypad-leader-dispatch + +Default: ~nil~ + +The fallback dispatching in KEYPAD when there's no translation. + +The value can be either a string or a keymap: + +A keymap stands for a base keymap used for further translation. A string stands for finding the +keymap at a specified key binding. Nil stands for taking leader keymap from ~meow-keymap-alist~. + +** meow-keypad-leader-transparent -Default: "H-" +Default: ~motion~ -The prefix string used when remapping an occupied key in MOTION state. +Use transparent behaivor when a bound command is not found in leader dispatch. -For examples: -#+begin_example - "C-x C-v" will remap the occupied j to C-x C-v j. - "C-M-" will remap the occupied j to C-M-j. -#+end_example +- Value ~t~ stands for always be transparent. +- Value ~motion~ stands for only be transparent in MOTION state. +- Value ~normal~ stands for only be transparent in NORMAL state. +- Value ~nil~ stands for never be transparent." ** meow-state-mode-alist Association list of symbols of meow states to their corresponding mode functions. diff --git a/TUTORIAL.org b/TUTORIAL.org index a577a42..992f698 100644 --- a/TUTORIAL.org +++ b/TUTORIAL.org @@ -66,30 +66,15 @@ MOTION state is the default state for special modes, like ~dired~, ~proced~, etc By default, MOTION state has no keybindings, except ~SPC~ is used as the leader key. The original command on ~SPC~ can be access via ~SPC SPC~. Users may want a consistent keybindings for movement globally, for example: k/j to move up/down. Usually, you can bind k/j in MOTION state, -however the original command on k/j is not accessible. To solve the problem, Meow introduce a simple solution. - -For any keybinding you defined with ~meow-motion-overwrite-define-key~, the overwritten command will be bound to the key with ~hyper~ modifier. +however then the original command on k/j is not accessible. To access the original command on k/j, use ~SPC k/j~. Here's an example: you want use ~j~ as ~next-line~ globally. #+begin_src emacs-lisp (meow-motion-overwrite-define-key '("j" . next-line)) - (meow-leader-define-key '("j" . "H-j")) -#+end_src - -Now ~j~ will act as ~next-line~, the original command on ~j~ (e.g. ~dired-goto-file~ in ~dired~) will be bound to ~H-j~. -Since we use ~j~ in the leader for ~H-j~, now we can call it via ~SPC j~. - -It is also possible to route the original command(e.g. ~j~) to original motion key(e.g. ~n~). - -#+begin_src emacs-lisp - (meow-motion-overwrite-define-key '("j" . next-line)) - (meow-motion-overwrite-define-key '("n" . "H-j")) #+end_src -Now you have swapped ~j~ and ~n~. - -The settings we made has nothing to do with the name of a command. Thus, it works in all special modes. +The settings we made works in all special modes. ** KEYPAD diff --git a/meow-core.el b/meow-core.el index e3563e5..82a5631 100644 --- a/meow-core.el +++ b/meow-core.el @@ -129,27 +129,13 @@ test on the commands bound to the keys a-z. If any of the command names contains \"self-insert\", then NORMAL state will be used. Otherwise, MOTION state will be used. -Before turning on MOTION state, the original commands will be -remapped. The new keybinding is generated by prepending -`meow-motion-remap-prefix' to the original keybinding. - Note: When this function is called, NORMAL state is already enabled. NORMAL state is enabled globally when `meow-global-mode' is used, because in `fundamental-mode', there's no chance for meow to call an init function." - (let ((state (meow--mode-get-state)) - (motion (lambda () - (meow--disable-current-state) - (meow--save-origin-commands) - (meow-motion-mode 1)))) - (cond - ;; if MOTION is specified - ((eq state 'motion) - (funcall motion)) - - (state - (meow--disable-current-state) - (meow--switch-state state t))))) + (let ((state (meow--mode-get-state))) + (meow--disable-current-state) + (meow--switch-state state t))) (defun meow--disable () "Disable Meow." diff --git a/meow-helpers.el b/meow-helpers.el index afda9a7..57456be 100644 --- a/meow-helpers.el +++ b/meow-helpers.el @@ -94,15 +94,15 @@ with this helper, it will result in recursive calls. Check `meow-normal-define-key' for usages." (apply #'meow-define-keys 'leader keybinds)) -;; Remap Leader SPC -(meow-leader-define-key (cons "SPC" (concat meow-motion-remap-prefix "SPC"))) - -(defun meow-motion-overwrite-define-key (&rest keybinds) +(defun meow-motion-define-key (&rest keybinds) "Define key for MOTION state. Check `meow-normal-define-key' for usages." (apply #'meow-define-keys 'motion keybinds)) +(defalias 'meow-motion-overwrite-define-key 'meow-motion-define-key) +(make-obsolete 'meow-motion-overwrite-define-key 'meow-motion-define-key "1.6.0") + (defun meow-setup-line-number () (add-hook 'display-line-numbers-mode-hook #'meow--toggle-relative-line-number) (add-hook 'meow-insert-mode-hook #'meow--toggle-relative-line-number)) diff --git a/meow-keypad.el b/meow-keypad.el index 105bf92..cb6e576 100644 --- a/meow-keypad.el +++ b/meow-keypad.el @@ -30,6 +30,7 @@ ;; ;;; Code: +(require 'cl-lib) (require 'subr-x) (require 'meow-var) (require 'meow-util) @@ -66,9 +67,7 @@ (let* ((keybind (if meow--keypad-base-keymap (lookup-key meow--keypad-base-keymap keys) (key-binding keys)))) - (unless (and (meow--is-self-insertp keybind) - (not meow-keypad-self-insert-undefined)) - keybind))) + keybind)) (defun meow--keypad-has-sub-meta-keymap-p () "Check if there's a keymap belongs to Meta prefix. @@ -408,8 +407,8 @@ If there are beacons, execute it at every beacon." (defun meow--keypad-try-execute () "Try execute command, return t when the translation progress can be ended. -If there is a command available on the current key binding, -try replacing the last modifier and try again." +This function supports a fallback behavior, where it allows to use `SPC +x f' to execute `C-x C-f' or `C-x f' when `C-x C-f' is not bound." (unless (or meow--use-literal meow--use-meta meow--use-both) @@ -439,23 +438,32 @@ try replacing the last modifier and try again." (meow--keypad-try-execute)) (t (setq meow--prefix-arg nil) - (message "%s is undefined" (meow--keypad-format-keys nil)) (meow--keypad-quit) + (if (or (eq t meow-keypad-leader-transparent) + (eq meow--keypad-previous-state meow-keypad-leader-transparent)) + (let* ((key (meow--parse-input-event last-input-event)) + (origin-cmd (cl-some (lambda (m) + (lookup-key m key)) + (current-active-maps))) + (remapped-cmd (command-remapping origin-cmd)) + (cmd-to-call (if (member remapped-cmd '(undefined nil)) + (or origin-cmd 'undefined) + remapped-cmd))) + (meow--keypad-execute cmd-to-call)) + (message "%s is undefined" key-str)) t))))) (defun meow--keypad-handle-input-with-keymap (input-event) "Handle INPUT-EVENT with `meow-keypad-state-keymap'. Return t if handling is completed." - (if (numberp input-event) - (let* ((k (if (= 27 input-event) - [escape] - (kbd (single-key-description input-event)))) - (cmd (lookup-key meow-keypad-state-keymap k))) - (if cmd - (call-interactively cmd) - (meow--keypad-handle-input-event input-event))) - (meow--keypad-quit))) + (if (equal 'escape last-input-event) + (meow--keypad-quit) + (setq last-command-event last-input-event) + (let ((kbd (single-key-description input-event))) + (if-let* ((cmd (lookup-key meow-keypad-state-keymap (read-kbd-macro kbd)))) + (call-interactively cmd) + (meow--keypad-handle-input-event input-event))))) (defun meow--keypad-handle-input-event (input-event) "Handle the INPUT-EVENT. diff --git a/meow-tutor.el b/meow-tutor.el index 28bc062..1c9dd0c 100644 --- a/meow-tutor.el +++ b/meow-tutor.el @@ -569,7 +569,7 @@ added to your search if the selection is created with \\[meow-visit], \\[meow-mark-word] and \\[meow-mark-symbol]. ================================================================= -= KEYPAD AND MOTION MODE = += KEYPAD = ================================================================= One of the most notable features of Meow is the Keypad. It diff --git a/meow-util.el b/meow-util.el index 212ed6c..07e7555 100644 --- a/meow-util.el +++ b/meow-util.el @@ -470,41 +470,6 @@ Looks up the state in meow-replace-state-name-list" (format "<%s>" e)) (t nil))) -(defun meow--save-origin-commands () - "Save the commands overridden by the Motion map to modified bindings. - -The new key binding, modified by the prefix in -`meow-motion-remap-prefix', is bound to a command that calls the -command locally bound to the original key binding, or, if that is -nil, the original command. - -For example, under the default and suggested settings, in a -Magit status buffer, `k' could be bound to `meow-previous' -and `H-k' would be bound to a command that would try -to use the status buffer's original `k' binding at point." - (cl-loop for key-code being the key-codes of meow-motion-state-keymap do - (ignore-errors - (let* ((key (meow--parse-input-event key-code)) - (cmd (key-binding (kbd key)))) - (when (and (commandp cmd) - (not (equal cmd 'undefined))) - (let ((rebind-key (concat meow-motion-remap-prefix key))) - (local-set-key (kbd rebind-key) - (lambda () - (interactive) - ;; Local maps are those local to the buffer - ;; or a region of the buffer. - (let* ((local (lookup-key (current-local-map) key)) - (remapped (command-remapping local))) - (call-interactively - (cond - ((commandp remapped) - remapped) - ((commandp local) - local) - (t - cmd)))))))))))) - (defun meow--prepare-region-for-kill () (when (and (equal 'line (cdr (meow--selection-type))) (meow--direction-forward-p) diff --git a/meow-var.el b/meow-var.el index d6f198f..83b569c 100644 --- a/meow-var.el +++ b/meow-var.el @@ -134,11 +134,6 @@ Each item is a (THING FORWARD_SYNTAX_TO_INCLUDE BACKWARD-SYNTAX_TO_INCLUDE)." :group 'meow :type 'boolean) -(defcustom meow-keypad-self-insert-undefined t - "Whether to self-insert a key in keypad mode if it is undefined" - :group 'meow - :type 'boolean) - (defcustom meow-char-thing-table '((?r . round) (?s . square) @@ -282,6 +277,19 @@ Set to `t' to always update. :type '(choice (const select) (const expand))) +(defcustom meow-keypad-leader-transparent 'motion + "Use transparent behaivor when a bound command is not found in leader dispatch. + +Value `t' stands for always be transparent. +Value `motion' stands for only be transparent in MOTION state. +Value `normal' stands for only be transparent in NORMAL state. +Value `nil' stands for never be transparent." + :group 'meow + :type '(choice (const t :tag "Always be transparent") + (const motion :tag "Transparent only in MOTION state") + (const normal :tag "Transparent only in NORMAL state") + (const nil :tag "Never be transparent"))) + (defcustom meow-keypad-leader-dispatch nil "The fallback dispatching in KEYPAD when there's no translation. @@ -320,15 +328,6 @@ prompted to finish the command." :type '(alist :key-type (character :tag "From") :value-type (character :tag "To"))) -(defcustom meow-motion-remap-prefix "H-" - "The prefix string used when remapping an occupied key in MOTION state. - -For examples: - \"C-x C-v\" will remap the occupied j to C-x C-v j. - \"C-M-\" will remap the occupied j to C-M-j." - :group 'meow - :type 'string) - (defcustom meow-goto-line-function nil "Function to use in `meow-goto-line'.