diff --git a/.github/README.md b/.github/README.md index 04733e8..e57b764 100644 --- a/.github/README.md +++ b/.github/README.md @@ -115,10 +115,11 @@ This package defines the following key mappings: * The literal key (SPC) is sticky. This means you don't have to enter SPC repeatedly for key bindings such as C-x r t. + Entering the literal key again toggles its state. The literal key can be changed through `god-literal-key`. Here are some examples: * x SPC r t → C-x r t - * x SPC r y → C-x r y + * x SPC r SPC g w → C-x r M-w * g is used to indicate the meta modifier (M-). This means that there is no way to enter C-g in God mode, and you must diff --git a/features/c-commands.feature b/features/c-commands.feature index 6418e8a..a001ac3 100644 --- a/features/c-commands.feature +++ b/features/c-commands.feature @@ -54,6 +54,12 @@ Feature: C- commands When I send the key sequence "c SPC b e g" Then the cursor should be at point "1" + Scenario: toggle god-literal-key + Given I bind "C-c k M-l" to "beginning-of-buffer" + And I go to end of buffer + When I send the key sequence "c SPC k SPC g l" + Then the cursor should be at point "1" + Scenario: execute commands with C-arrow Given I bind "C-x C-" to "backward-word" And I go to line "1" diff --git a/god-mode.el b/god-mode.el index 2b54539..462209b 100644 --- a/god-mode.el +++ b/god-mode.el @@ -172,7 +172,7 @@ If it was not active when `god-local-mode-pause' was called, nothing happens." "Enable `god-local-mode' on all buffers.") (defvar god-literal-sequence nil - "Activated after `god-literal-key' is pressed in a command sequence.") + "Toggled when `god-literal-key' is pressed in a command sequence.") ;;;###autoload (defun god-mode () @@ -308,38 +308,34 @@ from the command loop." "Interpret god-mode special keys for KEY. Consumes more keys if appropriate. Appends to key sequence KEY-STRING-SO-FAR." - (let ((key-consumed t) (next-modifier "") next-key) + (let ((modifier "") + (next-key (lambda () (god-mode-sanitized-key-string (read-event key-string-so-far))))) (message key-string-so-far) - (cond - ;; Don't check for `god-literal-key' with the first key. - ((and key-string-so-far (string= key god-literal-key)) - (setq god-literal-sequence t)) - (god-literal-sequence - (setq key-consumed nil)) - ((and (stringp key) (assoc key god-mode-alist)) - (setq next-modifier (cdr (assoc key god-mode-alist)))) - (t - (setq key-consumed nil - next-modifier (cdr (assoc nil god-mode-alist))))) - (setq next-key - (if key-consumed - (god-mode-sanitized-key-string (read-event key-string-so-far)) - key)) - (if (and key-string-so-far (string= next-key (format "%c" help-char))) - (god-mode-help-char-dispatch next-key key-string-so-far) - (when (and (= (length next-key) 1) - (string= (get-char-code-property (aref next-key 0) 'general-category) "Lu") + (when key-string-so-far ; Don't check for `god-literal-key' with the first key. + (while (string= key god-literal-key) + (setq god-literal-sequence (not god-literal-sequence) + key (funcall next-key)))) + (unless god-literal-sequence + (let ((modifier-lookup (and (stringp key) (assoc key god-mode-alist)))) + (if modifier-lookup + (setq modifier (cdr modifier-lookup) + key (funcall next-key)) + (setq modifier (cdr (assoc nil god-mode-alist)))))) + (if (and key-string-so-far (string= key (format "%c" help-char))) + (god-mode-help-char-dispatch key key-string-so-far) + (when (and (= (length key) 1) + (string= (get-char-code-property (aref key 0) 'general-category) "Lu") ;; If C- is part of the modifier, S- needs to be given ;; in order to distinguish the uppercase from the ;; lowercase bindings. If C- is not in the modifier, ;; then emacs natively treats uppercase differently ;; from lowercase, and the S- modifier should not be ;; supplied. - (string-prefix-p "C-" next-modifier)) - (setq next-modifier (concat next-modifier "S-"))) + (string-prefix-p "C-" modifier)) + (setq modifier (concat modifier "S-"))) (if key-string-so-far - (concat key-string-so-far " " next-modifier next-key) - (concat next-modifier next-key))))) + (concat key-string-so-far " " modifier key) + (concat modifier key))))) (defun god-mode-lookup-command (key-string) "Execute extended keymaps in KEY-STRING, or call it if it is a command."