all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#66780: [PATCH] Improve rectangle-mark-mode when transient-mark-mode is off
@ 2023-10-27 20:31 Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-10-28  6:24 ` Eli Zaretskii
  0 siblings, 1 reply; 12+ messages in thread
From: Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-10-27 20:31 UTC (permalink / raw)
  To: 66780

[-- Attachment #1: Type: text/plain, Size: 5686 bytes --]

Severity: minor

All issues reported here are about using rectangle-mark-mode (RMM) when
Transient Mark mode (TMM) is off.

Bug#42663 already has mentioned a few issues of this combination, but
IMO did not completely describe or solve them.


So suppose you start in the Emacs source directory tree

  ./src/emacs -Q --eval='(transient-mark-mode -1)' README

When you then press `C-x <SPC>' to enable RMM, the following happens,
which is expected:

1. The mark is NOT activated and, hence, the region-rectangle is NOT
   shown when you move point.  Also, point movement stays regular, in
   that you cannot advance point to after EOL, for example.

Again, this restriction is expected and is described already in commit
06dcd2be5d42 provided by Sean to solve bug#42663.


However, what has not been described yet is that some parts of RMM
actually _are_ active when one enables it with TMM off:

2. The key bindings in `rectangle-mark-mode-map', so that, for example,
   `C-x C-x' does not exchange point and mark, but instead cycles
   through the corners of the rectangle spanned by mark and point (using
   closest accessible buffer positions as an approximation for those
   positions where point regularly cannot be moved to).

   (Short reproducer when starting off the "emacs -Q ..." above:
   M-: (rectangle-mark-mode -1) RET
   M-<   C-x <SPC>   C-4 C-n   C-e   C-x C-x   C-x C-x   C-x C-x)

3. Advices on `region-extract-function' and `region-insert-function', so
   that C-w and C-y still operate on the current rectangle, and not the
   regular region.

   (Short reproducer when starting off the "emacs -Q ..." above:
   M-: (rectangle-mark-mode -1) RET
   M-<   C-x <SPC>   C-4 C-n   C-4 C-f   C-w)


I found 2. and 3. surprising because I would have expected that RMM is
completely off.  Moreover, RMM does not provide a minor mode lighter so
you cannot easily tell whether it is on or off.

I have attempted to improve the situation by providing documentation
(fix A) in a patch on emacs-29, and some minor code fixes (B and C) in a
patch on emacs-master.  That latter patch still has a placeholder
"bug#XXXXX" which needs to be updated once I have a bug number.


* Fix A: Improve Documentation

Here is the text that Sean has already added to emacs/killing.tex in
commit 06dcd2be5d42:

+The region-rectangle works only when the mark is active.  In
+particular, when Transient Mark mode is off (@pxref{Disabled Transient
+Mark}), in addition to typing @kbd{C-x @key{SPC}} you will need to
+activate the mark.

I first tried to extend on that, but then decided to completely redo the
material, like this:

+  rectangle-mark-mode behaves in a slightly different way when
+Transient Mark mode is off (@pxref{Disabled Transient Mark}).  In this
+case, when you enable rectangle-mark-mode, the region-rectangle is not
+automatically enabled.  Accordingly, cursor movement with @kbd{C-f},
+@kbd{C-n} etc.@: is confined to the regularly accessible buffer
+positions.  However, killing and yanking still operate on the
+rectangle spanned by point and mark.  Also @kbd{C-x C-x} still cycles
+through the corners of that rectangle, but only as far as these are at
+buffer positions that are regularly accessible.
+
+  As mentioned above, rectangle-mark-mode persists as long the region
+is active: If the region gets deactivated, rectangle-mark-mode gets
+deactivated as well.  But with disabled Transient mark mode there is
+usually no active region that would get deactivated, and so you have
+to explicitly switch off rectangle-mark-mode when you no longer want
+to use it.
+
+  To experience all benefits of rectangle-mark-mode and the
+region-rectangle when Transient Mark mode is off, you can temporarily
+activate Transient Mark mode after enabling rectangle-mark-mode, for
+example, with @kbd{C-@key{SPC} C-@key{SPC}}.  @xref{Disabled Transient
+Mark}.


I also replaced the somewhat unhelpful reference to parent node
"@xref{Killing}" further up by references to sibling nodes:

 so in a rectangular fashion, and killing and yanking operate on the
-rectangle.  @xref{Killing}.  The mode persists only as long as the
-region is active.
+rectangle.  @xref{Deletion and Killing}, @ref{Yanking}.  The mode
+persists only as long as the region is active.


* Fix B: Use a Minor Mode Lighter

With TMM off and RMM on, the most important indicator of RMM (the
region-rectangle) is not visible.  And since RMM's minor mode lighter is
nil, one has no visible feedback of it still being active.  That can be
surprising since some of its features are still active as described
above.

I tried to improve that by using a minor mode lighter that goes on only
if TMM is off, like this:

+(defvar rectangle-mark-mode-lighter nil
+  "Lighter displayed for `rectangle-mark-mode'.")
+
 ;;;###autoload
 (define-minor-mode rectangle-mark-mode
   "Toggle the region as rectangular.

 Activates the region if it's inactive and Transient Mark mode is
 on.  Only lasts until the region is next deactivated."
-  :lighter nil
+  :lighter rectangle-mark-mode-lighter
   (rectangle--reset-crutches)
   (when rectangle-mark-mode
+    ;; Make us more visible when Transient Mark mode is off and there
+    ;; is no rectangle (bug#XXXXX).
+    (setq rectangle-mark-mode-lighter
+          (and (not transient-mark-mode) " Rect"))


* Fix C: Mark RMM Movement Commands as Shift-Selectable

Finally, to make RMM better usable with shift-select-mode, I added the
necessary interactive specifiers to the RMM-specific movement commands

  rectangle-right-char
  rectangle-left-char
  rectangle-forward-char
  rectangle-backward-char
  rectangle-next-line
  rectangle-previous-line


Please review.

Thanks.

[-- Attachment #2: 0001-29-Improve-rectangle-mark-mode-when-transient-mark-mode.patch --]
[-- Type: text/x-patch, Size: 2900 bytes --]

From 6d7d83f158c3371e59877e02b88c38c664cb0ff9 Mon Sep 17 00:00:00 2001
From: Jens Schmidt <jschmidt4gnu@vodafonemail.de>
Date: Wed, 25 Oct 2023 21:32:17 +0200
Subject: [PATCH] Improve rectangle-mark-mode when transient-mark-mode is off

* doc/emacs/killing.texi (Rectangles): Add documentation on specifics
of rectangle-mark-mode when transient-mark-mode is off.
---
 doc/emacs/killing.texi | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi
index 47e0b5e37ae..e6a8fe2848e 100644
--- a/doc/emacs/killing.texi
+++ b/doc/emacs/killing.texi
@@ -939,13 +939,8 @@ Rectangles
 (first activating the region if necessary).  When this mode is enabled,
 commands that resize the region (@kbd{C-f}, @kbd{C-n} etc.)@: do
 so in a rectangular fashion, and killing and yanking operate on the
-rectangle.  @xref{Killing}.  The mode persists only as long as the
-region is active.
-
-The region-rectangle works only when the mark is active.  In
-particular, when Transient Mark mode is off (@pxref{Disabled Transient
-Mark}), in addition to typing @kbd{C-x @key{SPC}} you will need to
-activate the mark.
+rectangle.  @xref{Deletion and Killing}, @ref{Yanking}.  The mode
+persists only as long as the region is active.
 
 Unlike the standard region, the region-rectangle can have its corners
 extended past the end of buffer, or inside stretches of white space
@@ -962,6 +957,29 @@ Rectangles
 to modify the dimensions of the region-rectangle before invoking an
 operation on the marked text.
 
+  rectangle-mark-mode behaves in a slightly different way when
+Transient Mark mode is off (@pxref{Disabled Transient Mark}).  In this
+case, when you enable rectangle-mark-mode, the region-rectangle is not
+automatically enabled.  Accordingly, cursor movement with @kbd{C-f},
+@kbd{C-n} etc.@: is confined to the regularly accessible buffer
+positions.  However, killing and yanking still operate on the
+rectangle spanned by point and mark.  Also @kbd{C-x C-x} still cycles
+through the corners of that rectangle, but only as far as these are at
+buffer positions that are regularly accessible.
+
+  As mentioned above, rectangle-mark-mode persists as long the region
+is active: If the region gets deactivated, rectangle-mark-mode gets
+deactivated as well.  But with disabled Transient mark mode there is
+usually no active region that would get deactivated, and so you have
+to explicitly switch off rectangle-mark-mode when you no longer want
+to use it.
+
+  To experience all benefits of rectangle-mark-mode and the
+region-rectangle when Transient Mark mode is off, you can temporarily
+activate Transient Mark mode after enabling rectangle-mark-mode, for
+example, with @kbd{C-@key{SPC} C-@key{SPC}}.  @xref{Disabled Transient
+Mark}.
+
 @node CUA Bindings
 @section CUA Bindings
 @findex cua-mode
-- 
2.30.2


[-- Attachment #3: 0001-30-Improve-rectangle-mark-mode-when-transient-mark-mode.patch --]
[-- Type: text/x-patch, Size: 3445 bytes --]

From 2edc489f4f82a72b91624a779f06b488e586507f Mon Sep 17 00:00:00 2001
From: Jens Schmidt <jschmidt4gnu@vodafonemail.de>
Date: Wed, 25 Oct 2023 22:36:15 +0200
Subject: [PATCH] Improve rectangle-mark-mode when transient-mark-mode is off

* lisp/rect.el (rectangle-mark-mode-lighter): Add new variable ...
(rectangle-mark-mode): ... and use it here to make rectangle-mark-mode
more visible.
(rectangle-right-char, rectangle-left-char, rectangle-forward-char)
(rectangle-backward-char, rectangle-next-line)
(rectangle-previous-line): Declare as shift-translatable motion
commands.
---
 lisp/rect.el | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/lisp/rect.el b/lisp/rect.el
index 8dc188b1de0..f0b5a9b806a 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -646,15 +646,22 @@ rectangle-mark-mode-map
   "<remap> <next-line>"               #'rectangle-next-line
   "<remap> <previous-line>"           #'rectangle-previous-line)

+(defvar rectangle-mark-mode-lighter nil
+  "Lighter displayed for `rectangle-mark-mode'.")
+
 ;;;###autoload
 (define-minor-mode rectangle-mark-mode
   "Toggle the region as rectangular.

 Activates the region if it's inactive and Transient Mark mode is
 on.  Only lasts until the region is next deactivated."
-  :lighter nil
+  :lighter rectangle-mark-mode-lighter
   (rectangle--reset-crutches)
   (when rectangle-mark-mode
+    ;; Make us more visible when Transient Mark mode is off and there
+    ;; is no rectangle (bug#XXXXX).
+    (setq rectangle-mark-mode-lighter
+          (and (not transient-mark-mode) " Rect"))
     (advice-add 'region-beginning :around #'rectangle--region-beginning)
     (advice-add 'region-end :around #'rectangle--region-end)
     (add-hook 'deactivate-mark-hook
@@ -727,29 +734,29 @@ rectangle--*-char

 (defun rectangle-right-char (&optional n)
   "Like `right-char' but steps into wide chars and moves past EOL."
-  (interactive "p") (rectangle--*-char #'right-char n #'left-char))
+  (interactive "^p") (rectangle--*-char #'right-char n #'left-char))
 (defun rectangle-left-char (&optional n)
   "Like `left-char' but steps into wide chars and moves past EOL."
-  (interactive "p") (rectangle--*-char #'left-char n #'right-char))
+  (interactive "^p") (rectangle--*-char #'left-char n #'right-char))

 (defun rectangle-forward-char (&optional n)
   "Like `forward-char' but steps into wide chars and moves past EOL."
-  (interactive "p") (rectangle--*-char #'forward-char n #'backward-char))
+  (interactive "^p") (rectangle--*-char #'forward-char n #'backward-char))
 (defun rectangle-backward-char (&optional n)
   "Like `backward-char' but steps into wide chars and moves past EOL."
-  (interactive "p") (rectangle--*-char #'backward-char n #'forward-char))
+  (interactive "^p") (rectangle--*-char #'backward-char n #'forward-char))

 (defun rectangle-next-line (&optional n)
   "Like `next-line' but steps into wide chars and moves past EOL.
 Ignores `line-move-visual'."
-  (interactive "p")
+  (interactive "^p")
   (let ((col (rectangle--point-col (point))))
     (forward-line n)
     (rectangle--col-pos col 'point)))
 (defun rectangle-previous-line (&optional n)
   "Like `previous-line' but steps into wide chars and moves past EOL.
 Ignores `line-move-visual'."
-  (interactive "p")
+  (interactive "^p")
   (let ((col (rectangle--point-col (point))))
     (forward-line (- n))
     (rectangle--col-pos col 'point)))
--
2.30.2

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-11-02  6:33 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-27 20:31 bug#66780: [PATCH] Improve rectangle-mark-mode when transient-mark-mode is off Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-10-28  6:24 ` Eli Zaretskii
2023-10-28 10:50   ` Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-10-28 10:58     ` Eli Zaretskii
2023-10-28 12:51       ` Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-10-28 13:17         ` Eli Zaretskii
2023-10-28 16:36           ` Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-10-28 16:47             ` Eli Zaretskii
2023-10-28 18:30               ` Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-10-28 18:48                 ` Eli Zaretskii
2023-10-29 14:49                   ` Jens Schmidt via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-11-02  6:33                     ` Eli Zaretskii

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.