emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ergoemacs-mode fa095e8 295/325: Use Kim Storms approach


From: Stefan Monnier
Subject: [elpa] externals/ergoemacs-mode fa095e8 295/325: Use Kim Storms approach for cua binding
Date: Sat, 23 Oct 2021 18:49:14 -0400 (EDT)

branch: externals/ergoemacs-mode
commit fa095e8d763bddd40179217aa3c128fa7de55cac
Author: Matthew Fidler <514778+mattfidler@users.noreply.github.com>
Commit: Matthew Fidler <514778+mattfidler@users.noreply.github.com>

    Use Kim Storms approach for cua binding
---
 ergoemacs-calculate-bindings.el |   2 +-
 ergoemacs-cua.el                | 287 ++++++++++++++++++++++++++++++++++++++++
 ergoemacs-mode.el               |  19 ++-
 ergoemacs-themes.el             |   2 +
 4 files changed, 306 insertions(+), 4 deletions(-)

diff --git a/ergoemacs-calculate-bindings.el b/ergoemacs-calculate-bindings.el
index f09b8e7..4202453 100644
--- a/ergoemacs-calculate-bindings.el
+++ b/ergoemacs-calculate-bindings.el
@@ -2,7 +2,7 @@
 
 ;; Copyright © 2013-2021  Free Software Foundation, Inc.
 
-;; Filename: ergoemacs-translate.el
+;; Filename: ergoemacs-calculate-bindings.el
 ;; Description:
 ;; Author: Matthew L. Fidler
 ;; Maintainer:
diff --git a/ergoemacs-cua.el b/ergoemacs-cua.el
new file mode 100644
index 0000000..79da893
--- /dev/null
+++ b/ergoemacs-cua.el
@@ -0,0 +1,287 @@
+;;; ergoemacs-cua.el --- Keyboard keybinding translation -*- lexical-binding: 
t -*-
+
+;; Copyright © 2013-2021  Free Software Foundation, Inc.
+
+;; Filename: ergoemacs-cua.el
+;; Description:
+;; Author: Matthew L. Fidler
+;; Maintainer:
+;; Created: Sat Sep 28 20:08:09 2013 (-0500)
+;; Version:
+;; Last-Updated:
+;;           By:
+;;     Update #: 0
+;; URL:
+;; Doc URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;;   None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change Log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;; Adapted from 
https://github.com/emacs-mirror/emacs/blob/3ae275eedc1c8d2a61a4a549c39c88bb08fd8ff2/lisp/emulation/cua-base.el#L623
+
+
+(defvar ergoemacs--prefix-override-timer nil
+  "Override timer for cua-style keys.")
+
+(defvar ergoemacs--prefix-override-length nil
+  "The last saved key prefix override length.")
+
+(defvar ergoemacs--prefix-override-keymap
+  (let ((map (make-sparse-keymap)))
+    (define-key map [(control x)] 'ergoemacs--prefix-override-handler)
+    (define-key map [(control c)] 'ergoemacs--prefix-override-handler)
+    map)
+  "Prefix override keymap.")
+
+(defvar ergoemacs--ena-prefix-repeat-keymap nil
+  "Variable that states that `ergoemacs-mode' is in the repeat phase, 
immediately after using the prefix key.")
+
+(defvar ergoemacs--prefix-repeat-keymap
+  (let ((map (make-sparse-keymap)))
+    (define-key map [(control x) (control x)] 
'ergoemacs--prefix-repeat-handler)
+    (define-key map [(control c) (control c)] 
'ergoemacs--prefix-repeat-handler)
+    (dolist (key '(up down left right home end next prior))
+      (define-key map (vector '(control x) key) 'ergoemacs--prefix-cut-handler)
+      (define-key map (vector '(control c) key) 
'ergoemacs--prefix-copy-handler)))
+  "Prefix repeat keymap.")
+
+
+(defcustom ergoemacs-prefix-override-inhibit-delay 0.2
+  "If non-nil, time in seconds to delay before overriding prefix key.
+If there is additional input within this time, the prefix key is
+used as a normal prefix key.  So typing a key sequence quickly will
+inhibit overriding the prefix key.
+As a special case, if the prefix key is repeated within this time, the
+first prefix key is discarded, so typing a prefix key twice in quick
+succession will also inhibit overriding the prefix key.
+If the value is nil, use a shifted prefix key to inhibit the override."
+  :type '(choice (number :tag "Inhibit delay")
+                        (const :tag "No delay" nil))
+  :group 'ergoemacs)
+
+(defcustom ergoemacs-enable-cua-keys t
+  "Enable C-x and C-v for cut and copy.
+If the value is t, these mappings are always enabled.  If the value is
+`shift', these keys are only enabled if the last region was marked with
+a shifted movement key.  If the value is nil, these keys are never
+enabled."
+  :type '(choice (const :tag "Disabled" nil)
+                        (const :tag "Shift region only" shift)
+                        (other :tag "Enabled" t))
+  :group 'cua)
+
+(defvar ergoemacs--ena-region-keymap nil
+  "Variable that tells the `ergoemacs-mode' if the region is selected.
+
+This is also used to select the region keymaps.")
+
+(defvar ergoemacs--ena-prefix-override-keymap nil
+  "Variable that tels the `ergoemacs-mode' of the overide step is active.
+
+This override is enabled for active regions before the copy and paste are 
enabled.")
+
+
+
+(defvar ergoemacs-inhibit-cua-keys nil
+  "Buffer-local variable that may disable the CUA keymappings.")
+(make-variable-buffer-local 'ergoemacs-inhibit-cua-keys)
+
+(defun ergoemacs--select-keymaps ()
+  "Setup conditions for selecting the proper keymaps in 
`ergoemacs--keymap-alist'."
+  ;; The prefix override (when mark-active) operates in three substates:
+  ;; [1] Before using a prefix key
+  ;; [2] Immediately after using a prefix key
+  ;; [3] A fraction of a second later
+  (setq ergoemacs--ena-region-keymap ; Determines if the ergion is active
+        (and (region-active-p) (not deactivate-mark))
+        ;; Enable Override -- This is the first state where the keys are 
intercepted; cua state [1]
+        ergoemacs--ena-prefix-override-keymap
+        (and ergoemacs--ena-region-keymap
+             ergoemacs-enable-cua-keys
+                (not ergoemacs-inhibit-cua-keys)
+                (or (eq ergoemacs-enable-cua-keys t)
+                        (region-active-p))
+                (not executing-kbd-macro)
+                (not ergoemacs--prefix-override-timer))
+        ;; Enable The repeat layer.  This is the layer that the keys are 
intercepted; cua state [2]
+        ergoemacs--ena-prefix-repeat-keymap
+        (and ergoemacs--ena-region-keymap
+                (or (timerp ergoemacs--prefix-override-timer)
+                        (eq ergoemacs--prefix-override-timer 'shift))))
+  ;; In ergoemacs-mode the corresponding `cua--ena-cua-keys-keymap' and 
`cua--ena-global-mark-keymap' are not needed or used
+  (message "r: %s po: %s pr: %s")
+  )
+
+(defun ergoemacs--prefix-override-timeout ()
+  "This is whap happens on the `ergoemacs-mode' timeout for C-c and C-v are 
supplied."
+  (setq ergoemacs--prefix-override-timer t)
+  (when (= (length (this-command-keys)) ergoemacs--prefix-override-length)
+    (setq unread-command-events (cons 'ergoemacs-timeout 
unread-command-events))
+    (if prefix-arg
+        nil
+      ;; FIXME: Why?
+      (setq overriding-terminal-local-map nil))
+    (ergoemacs--select-keymaps)))
+
+(defun ergoemacs--prefix-override-replay (repeat)
+  "This replays the events from the intial key press.
+
+REPEAT is the flag that tells it if is repeated environmennt."
+  (let* ((keys (this-command-keys))
+            (i (length keys))
+            (key (aref keys (1- i))))
+    (setq ergoemacs--prefix-override-length (- i repeat))
+    (setq ergoemacs--prefix-override-timer
+             (or
+              ;; In state [2], change to state [3]
+              (> repeat 0)
+              ;; In state [1], change directly to state [3]
+              (input-pending-p)
+              ;; In state [1], [T] disabled, so change to state [3]
+              (not (numberp ergoemacs-prefix-override-inhibit-delay))
+              (<= ergoemacs-prefix-override-inhibit-delay 0)
+              ;; In state [1], start [T] and change to state [2]
+              (run-with-timer ergoemacs-prefix-override-inhibit-delay nil
+                                      #'ergoemacs--prefix-override-timeout)))
+    ;; Don't record this command
+    (setq this-command last-command)
+    ;; Restore the prefix arg
+    ;; This should make it so that exchange-point-and-mark gets the prefix when
+    ;; you do C-u C-x C-x C-x work (where the C-u is properly passed to the C-x
+    ;; C-x binding after the first C-x C-x was rewritten to just C-x).
+    (prefix-command-preserve-state)
+    ;; Push the key back on the event queue
+    (setq unread-command-events (cons (cons 'no-record key)
+                                      unread-command-events))))
+
+
+(defun ergoemacs--prefix-override-handler ()
+  "Start timer waiting for prefix key to be followed by another key.
+Repeating prefix key when region is active works as a single prefix key."
+  (interactive)
+  (ergoemacs--prefix-override-replay 0))
+
+(defun cua--prefix-repeat-handler ()
+  "Repeating prefix key when region is active works as a single prefix key."
+  (interactive)
+  (ergoemacs--prefix-override-replay 1))
+
+(defun ergoemacs--prefix-copy-handler (arg)
+  "Copy region, then replay last key.
+
+This uses `ergoemacs-copy-line-or-region' (unlike `cua-mode').
+
+Pass prefix ARG to the respective copy functions."
+  (interactive "P")
+  (ergoemacs-copy-line-or-region arg)
+  ;; Send next key
+  (let ((keys (this-single-command-keys)))
+    (setq unread-command-events
+             (cons (aref keys (1- (length keys))) unread-command-events))))
+
+(defun cua--prefix-cut-handler (arg)
+  "Cut region, then replay last key.
+
+This uses `ergoemacs-cut-line-or-region' (unlike `cua-mode').
+
+Pass prefix ARG to the respective copy functions."
+  (interactive "P")
+  (ergoemacs-cut-line-or-region arg)
+  (let ((keys (this-single-command-keys)))
+    (setq unread-command-events
+             (cons (aref keys (1- (length keys))) unread-command-events))))
+
+(defvar ergoemacs-mode)
+;;; Pre-command hook
+
+(defun ergoemacs--cua-pre-command-handler-1 ()
+  "Cancel prefix key timeout if user enters another key."
+  (when ergoemacs--prefix-override-timer
+    (if (timerp ergoemacs--prefix-override-timer)
+           (cancel-timer ergoemacs--prefix-override-timer))
+    (setq ergoemacs--prefix-override-timer nil)))
+
+(defun ergoemacs--cua-pre-command-handler ()
+  "Cancel prefix key timeout if user enters another key. (has error 
protection)"
+  (when ergoemacs-mode
+    (condition-case nil
+           (ergoemacs--cua-pre-command-handler-1)
+      (error nil))))
+
+
+(defun ergoemacs--cua-post-command-handler-1 ()
+  "Post command hook for ergoemacs-mode based cua-keys."
+  ;; Select the keymaps for the next command
+  (ergoemacs--select-keymaps))
+
+(defun ergoemacs--cua-post-command-handler ()
+  "Post command hook for `ergoemacs-mode' based cua keys."
+  (when ergoemacs-mode
+    (condition-case nil
+        (ergoemacs--cua-post-command-handler-1)
+      (error nil))))
+
+(add-hook 'post-command-hook #'ergoemacs--cua-post-command-handler)
+(add-hook 'pre-command-hook  #'ergoemacs--cua-pre-command-handler)
+
+(defun ergoemacs--shift-control-prefix (prefix)
+   "Handle S-C-x and S-C-c by emulating the fast double prefix function.
+PREFIX is the key prefix that is being sent for these keys."
+  ;; Don't record this command
+  (setq this-command last-command)
+  ;; Restore the prefix arg
+  ;; This should make it so that exchange-point-and-mark gets the prefix when
+  ;; you do C-u S-C-x C-x work (where the C-u is properly passed to the C-x
+  ;; C-x binding after the first S-C-x was rewritten to just C-x).
+  (prefix-command-preserve-state)
+  ;; Activate the cua--prefix-repeat-keymap
+  (setq ergoemacs--prefix-override-timer 'shift)
+  ;; Push duplicate keys back on the event queue
+  (setq unread-command-events
+        (cons prefix (cons prefix unread-command-events))))
+
+(defun ergoemacs--shift-control-c-prefix ()
+  "Shift control c prefix."
+  (interactive)
+  (ergoemacs--shift-control-prefix ?\C-c))
+
+(defun ergoemacs--shift-control-x-prefix ()
+  "Shift control x prefix."
+  (interactive)
+  (ergoemacs--shift-control-prefix ?\C-x))
+
+(provide 'ergoemacs-cua)
+;;; ergoemacs-cua.el ends here
diff --git a/ergoemacs-mode.el b/ergoemacs-mode.el
index e522142..213fd7c 100644
--- a/ergoemacs-mode.el
+++ b/ergoemacs-mode.el
@@ -327,7 +327,8 @@ This is structured by valid keyboard layouts for
 (defvar ergoemacs-translation-hash (make-hash-table)
   "Hash table of translations, structured by translatin type.")
 
-(dolist (pkg '(ergoemacs-command-loop
+(dolist (pkg '(ergoemacs-cua
+               ergoemacs-command-loop
                ergoemacs-advice
                ergoemacs-functions
                ergoemacs-key-description
@@ -400,6 +401,8 @@ after initializing ergoemacs-mode.
 
 (defvar ergoemacs-mark-active-keymap (let ((map (make-sparse-keymap)))
                                        (define-key map (kbd "TAB") 
'indent-region)
+                                       (define-key map [(shift control x)] 
'ergoemacs--shift-control-x-prefix)
+                                       (define-key map [(shift control c)] 
'ergoemacs--shift-control-c-prefix)
                                        map)
   "The keybinding that is active when the mark is active.")
 
@@ -411,14 +414,24 @@ after initializing ergoemacs-mode.
 
 (declare-function ergoemacs-advice-undefined "ergoemacs-advice")
 
+(defvar ergoemacs--ena-prefix-override-keymap)
+(defvar ergoemacs--prefix-override-keymap)
+(defvar ergoemacs--ena-prefix-repeat-keymap)
+(defvar ergoemacs--prefix-repeat-keymap)
+(defvar ergoemacs--ena-region-keymap)
+
+  ;; Enable shifted fallbacks for C-x and C-c when region is active
+
 (defun ergoemacs-setup-override-keymap ()
   "Setup `ergoemacs-mode' keymaps."
-  (setq ergoemacs-override-alist `((ergoemacs-mode . ,ergoemacs-user-keymap)
+  (setq ergoemacs-override-alist `((ergoemacs--ena-prefix-override-keymap . 
,ergoemacs--prefix-override-keymap)
+                                   (ergoemacs--ena-prefix-repeat-keymap .   
,ergoemacs--prefix-repeat-keymap)
+                                   (ergoemacs--ena-region-keymap . 
,ergoemacs-mark-active-keymap)
+                                   (ergoemacs-mode . ,ergoemacs-user-keymap)
                                    (ergoemacs-mode . 
,ergoemacs-override-keymap)
                                    (ergoemacs-mode . ,ergoemacs-keymap))
         ergoemacs-minor-alist `(mark-active . ,ergoemacs-mark-active-keymap))
   (add-hook 'emulation-mode-map-alists ergoemacs-override-alist)
-  (add-hook 'minor-mode-map-alist ergoemacs-minor-alist)
   (advice-add 'undefined :around #'ergoemacs-advice-undefined)
   (advice-add 'read-key :before #'ergoemacs-advice-read-key))
 
diff --git a/ergoemacs-themes.el b/ergoemacs-themes.el
index c9a95e4..a4d0a32 100644
--- a/ergoemacs-themes.el
+++ b/ergoemacs-themes.el
@@ -460,7 +460,9 @@ These keys do not depend on the layout."
 (defun ergoemacs-set-copy (keymap)
   "Copy, Cut, Paste, Redo and Undo for KEYMAP."
   (ergoemacs-define-key keymap (kbd "M-x") 'ergoemacs-cut-line-or-region)
+  (define-key keymap (kbd "C-x <ergoemacs-timeout>") 
'ergoemacs-cut-line-or-region)
   (ergoemacs-define-key keymap (kbd "M-c") 'ergoemacs-copy-line-or-region)
+  (define-key keymap (kbd "C-c <ergoemacs-timeout>") 
'ergoemacs-copy-line-or-region)
   (ergoemacs-define-key keymap (kbd "M-v") 'ergoemacs-paste)
   (ergoemacs-define-key keymap (kbd "M-V") 'ergoemacs-paste-cycle)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]