From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#46515: Repeat mode Date: Sun, 14 Feb 2021 20:27:08 +0200 Organization: LINKOV.NET Message-ID: <87pn12o74z.fsf@mail.linkov.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="20079"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu) To: 46515@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Feb 14 20:21:00 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lBMx2-00055P-MJ for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 14 Feb 2021 20:21:00 +0100 Original-Received: from localhost ([::1]:45404 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lBMx1-0002Oe-OS for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 14 Feb 2021 14:20:59 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45326) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lBMWw-0006EV-Lf for bug-gnu-emacs@gnu.org; Sun, 14 Feb 2021 13:54:05 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:53391) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lBMWw-0007Vc-Ee for bug-gnu-emacs@gnu.org; Sun, 14 Feb 2021 13:54:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1lBMWw-0003oo-CQ for bug-gnu-emacs@gnu.org; Sun, 14 Feb 2021 13:54:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Juri Linkov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 14 Feb 2021 18:54:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 46515 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.161332879714580 (code B ref -1); Sun, 14 Feb 2021 18:54:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 14 Feb 2021 18:53:17 +0000 Original-Received: from localhost ([127.0.0.1]:36696 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lBMWD-0003n1-A4 for submit@debbugs.gnu.org; Sun, 14 Feb 2021 13:53:17 -0500 Original-Received: from lists.gnu.org ([209.51.188.17]:53586) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lBMWB-0003mm-FG for submit@debbugs.gnu.org; Sun, 14 Feb 2021 13:53:15 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45126) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lBMW7-0005Kf-RY for bug-gnu-emacs@gnu.org; Sun, 14 Feb 2021 13:53:13 -0500 Original-Received: from relay10.mail.gandi.net ([217.70.178.230]:41513) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lBMW5-0007G0-E5 for bug-gnu-emacs@gnu.org; Sun, 14 Feb 2021 13:53:11 -0500 Original-Received: from mail.gandi.net (m91-129-108-204.cust.tele2.ee [91.129.108.204]) (Authenticated sender: juri@linkov.net) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 10422240005 for ; Sun, 14 Feb 2021 18:53:04 +0000 (UTC) Received-SPF: pass client-ip=217.70.178.230; envelope-from=juri@linkov.net; helo=relay10.mail.gandi.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:200028 Archived-At: --=-=-= Content-Type: text/plain Tags: patch Like discussed in bug#12572, bug#15234 and recently in https://lists.gnu.org/archive/html/emacs-devel/2021-02/msg00139.html here is a patch that provides an opt-in feature for easy-to-repeat key sequences: C-x u u u - undo sequences C-x o o o - switch windows C-x right left right left - next/previous buffer switching M-g n n n p p p - next-error navigation C-x { { { } } } - window resizing ... --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=repeat-mode.patch diff --git a/lisp/repeat.el b/lisp/repeat.el index 795577c93f..1b31963d22 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -329,6 +329,39 @@ repeat-message ;;;;; ************************* EMACS CONTROL ************************* ;;;;; + +;;; repeat-mode + +(defcustom repeat-exit-key [return] ; like `isearch-exit' + "Key that stops the modal repeating of keys in sequence." + :type '(choice (const :tag "No special key to exit repeat sequence" nil) + (key-sequence :tag "Key that exits repeat sequence")) + :group 'convenience + :version "28.1") + +;;;###autoload +(define-minor-mode repeat-mode + "Toggle Repeat mode. +When Repeat mode is enabled, and the command symbol has the property named +`repeat-map', this map is activated temporarily for the next command." + :global t :group 'convenience + (if (not repeat-mode) + (remove-hook 'post-command-hook 'repeat-post-hook) + (add-hook 'post-command-hook 'repeat-post-hook))) + +(defun repeat-post-hook () + "Function run after commands to set transient keymap." + (when repeat-mode + (let ((repeat-map (and (symbolp this-command) + (get this-command 'repeat-map)))) + (when repeat-map + (when (boundp repeat-map) + (setq repeat-map (symbol-value repeat-map))) + (let ((map (copy-keymap repeat-map))) + (when repeat-exit-key + (define-key map repeat-exit-key 'ignore)) + (set-transient-map map)))))) + (provide 'repeat) ;;; repeat.el ends here diff --git a/lisp/bindings.el b/lisp/bindings.el index 2f4bab11cf..70ddd9d9ba 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -950,6 +950,12 @@ global-map ;; Richard said that we should not use C-x and I have ;; no idea whereas to bind it. Any suggestion welcome. -stef ;; (define-key ctl-x-map "U" 'undo-only) +(defvar undo-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "u" 'undo) + map) + "Keymap to repeat undo `C-x u u' sequences. Used in `repeat-mode'.") +(put 'undo 'repeat-map 'undo-repeat-map) (define-key esc-map "!" 'shell-command) (define-key esc-map "|" 'shell-command-on-region) @@ -964,6 +970,17 @@ ctl-x-map (define-key global-map [XF86Back] 'previous-buffer) (put 'previous-buffer :advertised-binding [?\C-x left]) +(defvar next-buffer-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map [right] 'next-buffer) + (define-key map [C-right] 'next-buffer) + (define-key map [left] 'previous-buffer) + (define-key map [C-left] 'previous-buffer) + map) + "Keymap to repeat next-buffer key sequences. Used in `repeat-mode'.") +(put 'next-buffer 'repeat-map 'next-buffer-repeat-map) +(put 'previous-buffer 'repeat-map 'next-buffer-repeat-map) + (let ((map minibuffer-local-map)) (define-key map "\en" 'next-history-element) (define-key map [next] 'next-history-element) @@ -1036,6 +1053,17 @@ global-map (define-key ctl-x-map "`" 'next-error) +(defvar next-error-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "n" 'next-error) + (define-key map "\M-n" 'next-error) + (define-key map "p" 'previous-error) + (define-key map "\M-p" 'previous-error) + map) + "Keymap to repeat next-error key sequences. Used in `repeat-mode'.") +(put 'next-error 'repeat-map 'next-error-repeat-map) +(put 'previous-error 'repeat-map 'next-error-repeat-map) + (defvar goto-map (make-sparse-keymap) "Keymap for navigation commands.") (define-key esc-map "g" goto-map) diff --git a/lisp/window.el b/lisp/window.el index 2d0a73b426..d1a0f80da9 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -10252,6 +10252,30 @@ ctl-x-4-map (define-key ctl-x-4-map "1" 'same-window-prefix) (define-key ctl-x-4-map "4" 'other-window-prefix) +(defvar other-window-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "o" 'other-window) + map) + "Keymap to repeat other-window key sequences. Used in `repeat-mode'.") + +(put 'other-window 'repeat-map 'other-window-repeat-map) + +(defvar resize-window-repeat-map + (let ((map (make-sparse-keymap))) + ;; Standard keys: + (define-key map "^" 'enlarge-window) + (define-key map "}" 'enlarge-window-horizontally) + (define-key map "{" 'shrink-window-horizontally) + ;; Additional keys: + (define-key map "v" 'shrink-window) + map) + "Keymap to repeat window resizing commands. Used in `repeat-mode'.") + +(put 'enlarge-window 'repeat-map 'resize-window-repeat-map) +(put 'enlarge-window-horizontally 'repeat-map 'resize-window-repeat-map) +(put 'shrink-window-horizontally 'repeat-map 'resize-window-repeat-map) +(put 'shrink-window 'repeat-map 'resize-window-repeat-map) + (provide 'window) ;;; window.el ends here --=-=-=--