Subject: 28.0.50; repeat-mode: Make rectangle commands repeatable. Also some misc. queries, comments
From: Ramesh Nedunchezian <[email-masked]>
To: [email-masked]
Date: Sat, 10 Apr 2021 13:53:06 +0530
List-Id: <debbugs-submit.debbugs.gnu.org>

Could you please add rectangle commands to the repeatable set?  This
is what I have in my .emacs.  It works reasonably well, except for the
`x' (- `rectangle-exchange-point-and-mark') key below:

Issue 1:
--------

In Non-repeat mode,

1. Press C-x SPC and make a rectangel.

2. Press C-x C-x 4 or more times.  You will see the cursor jumping
   between the corners.

With below snippet installed, in repeat-mode, repeat the above
operations with single key strokes. I am seeing that the 3rd press of
x gets me out of the repeat loop and inserts the char "x" in the
buffer.

Issue 2:  A repeat map can provide a custom `:help'-er
-----------------------------------------------------

This is the message I see in the minibuffer.

    Repeat with c, ESC, w, r, d, k, o, b, C-b, x, C-x, f, C-f, <left>,
    SPC, <down>, C-n, N, <up>, C-p, <right>, t, y

1. `ESC' above correpsonds to `M-w' in the repeat map.  The single
    character `ESC' confused me for some time.  I wonder if the help
    text could be improved in this case.

2. The help text is really really big, and it clutters the echo area.

   It seems that .... Repeatable keys are essentially a poor-man's
   hydra,

   So, a repeat-map, like the rectangle one below, which has lots of
   keybindings can set a `:help' attribute on itself.
   `repeat-post-hook' can then rely on this `:help'-er to provide a
   help much similar to what the hydra package provides.

Issue 3:  A repeat map can take `:keep-pred' (or a `:exit-key') and other properties.
----------------------------------------------------------------------------

When looked askance, `repeat-post-hook' is essentially a wrapper
around `transient-map'.

So, a `repeat-map' can take a `:keep-pred' and `:on-exit' attributes,
in addition to a `:help' attribute.

This will obviate the need for the global `repeat-exit-key' i.e., the
choice of how the map exits should itself be delegated to the repeat
map. `

Suggestion 1:  Provide a macro(?) for creating repeatable commands.
------------------------------------------------------------------

Provide a defmacro for creating repeatable keymaps.  The snippet below
is actually created by my own `defmacro'.  The macro takes an list of
(KEY . CMD) and a name of repeat map and generates what you see below.
(Bonus points, if the API invocation looks much similar to `bind-key'
section in a in a `use-package' directive)

The rectangle commands itself come from two different maps
`ctl-x-r-map' and `rectangle-mark-mode-map'.  The first one has
/non-rectangle/ commands like register commands.

If the repeatable commands all come from a single map (and if there
are no other commands in that map), then there is NO need for this
API. One could do something what diff-hl already does

    (map-keymap
     (lambda (_key cmd)
       (put cmd 'repeat-map 'diff-hl-command-map))
     diff-hl-command-map)

The need for this APIs arise only because one is collecting the keys
from disparate maps.

Suggestion 2:
------------

Provide a defmacro for chained commands.  I am making the suggestion
here. I will provide details in a separate bug report.

----------------------------------------------------------------

Snippet for making rectangle commands repeatable.
-------------------------------------------------

    (progn
      (defvar rectangle-repeat-map
        (let ((map (make-sparse-keymap)))
          map))

      (cl-loop for (cmd . key-sequence) in
               `(
                 (clear-rectangle                       . "c")
                 (copy-rectangle-as-kill                . ,(kbd "M-w"))
                 (copy-rectangle-as-kill                . "w")
                 (copy-rectangle-to-register            . "r")
                 (delete-rectangle                      . "d")
                 (kill-rectangle                        . "k")
                 (open-rectangle                        . "o")
                 (rectangle-backward-char               . "b")
                 (rectangle-backward-char               . ,(kbd "C-b"))
                 (rectangle-exchange-point-and-mark     . "x")
                 (rectangle-exchange-point-and-mark     . ,(kbd "C-x C-x"))
                 (rectangle-forward-char                . "f")
                 (rectangle-forward-char                . ,(kbd "C-f"))
                 (rectangle-left-char                   . ,(kbd "<left>"))
                 (rectangle-mark-mode                   . " ")
                 (rectangle-mark-mode                   . ,(kbd "C-x SPC"))          
                 (rectangle-next-line                   . ,(kbd "<down>"))
                 (rectangle-next-line                   . ,(kbd "C-n"))
                 (rectangle-number-lines                . "N")
                 (rectangle-previous-line               . ,(kbd "<up>"))
                 (rectangle-previous-line               . ,(kbd "C-p"))
                 (rectangle-right-char                  . ,(kbd "<right>"))
                 (string-rectangle                      . "t")
                 (yank-rectangle                        . "y")
                 )
               do
               (define-key rectangle-repeat-map key-sequence cmd)
               (put cmd 'repeat-map 'rectangle-repeat-map)))

----------------------------------------------------------------

In GNU Emacs 28.0.50 (build 4, x86_64-pc-linux-gnu, GTK+ Version 3.24.24, cairo version 1.16.0)
 of 2021-04-07 built on debian
Repository revision: c1173f231d46f14f71886fa343dbc7501f064919
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12010000
System Description: Debian GNU/Linux bullseye/sid

Configured using:
 'configure -with-imagemagick --with-json --with-xwidgets'