0

I want to create bindings for rectangle-mark-mode though the methods described above haven't worked for me.

I've tried using an alist that I thought it possessed, but Emacs returned a bug saying its variable is void. I tried what I did below (assuming that it followed a similar naming convention as minor/major mode hooks):

(add-to-list 'rectangle-mark-mode-alist '("M-, ;" . yank-rectangle))

define-key has worked just fine for unbinding the minor mode's current bindings, but it hasn't worked for creating bindings (hence the attempt of alists)

(defun rect-util-unbind()
  (define-key rectangle-mark-mode-map (kbd "C-o") nil)    ;; open-rectangle
  (define-key rectangle-mark-mode-map (kbd "C-t") nil))    ;; string-rectangle

(defun rect-util-bind()
    (define-key rectangle-mark-mode-map (kbd "C-y") 'yank-rectangle))

(add-hook 'rectangle-mark-mode-hook
    'rect-util-unbind
    'rect-util-bind)
5
  • 1
    emacs.stackexchange.com/tags/elisp/info
    – Drew
    Jul 7, 2023 at 19:58
  • It's not clear what you want to do. Do you want to create a new minor mode, and bind keys in its map to invoke rectangle-mark-mode commands? (You've already shown how to remove key bindings for such commands from rectangle-mark-mode-map.)
    – Drew
    Jul 7, 2023 at 20:02
  • There is no variable called rectangle-mark-mode-alist, so trying to add something to it is wrong. You can always make your own, but what good will that do if nobody uses it? The question is: what exactly are you trying to do? Forget about alists, minor modes etc. Just describe what you are trying to accomplish.
    – NickD
    Jul 7, 2023 at 20:17
  • Okay, so what I'm trying to do is that I want to create bindings in rectangle-mark-mode but the current methods I've tried haven't been successful. Jul 7, 2023 at 20:56
  • 1
    See my answer for details, but the executive summary is: you were successful in creating (and removing) bindings in the mode map (although the method you used can be simplified), it's just that you tried to use the binding while the mode is inactive (and so its keymap is also inactive). The problem is that this mode is transient: you turn it on and it goes away again at the end of most buffer-modifying commands.
    – NickD
    Jul 9, 2023 at 2:37

1 Answer 1

1

First, check the value of rectangle-mark-mode-map with C-h v rectangle-mark-mode-map which gives me:

(keymap
 (remap keymap
    (previous-line . rectangle-previous-line)
    (next-line . rectangle-next-line)
    (backward-char . rectangle-backward-char)
    (forward-char . rectangle-forward-char)
    (left-char . rectangle-left-char)
    (right-char . rectangle-right-char)
    (exchange-point-and-mark . rectangle-exchange-point-and-mark))
 (20 . string-rectangle)
 (15 . open-rectangle))

Most of it is remapping existing commands, but it also includes C-o (that's the 15 entry) bound to open-rectangle and C-t (the 20 entry) bound to string-rectangle.

Stripping away unnecessary complications in your question, add this to your init file and restart your emacs:

(with-eval-after-load 'rect
     (define-key rectangle-mark-mode-map (kbd "C-o") nil)    ;; open-rectangle
     (define-key rectangle-mark-mode-map (kbd "C-t") nil)   ;; string-rectangle
     (define-key rectangle-mark-mode-map (kbd "C-y") 'yank-rectangle))

You don't need to do it in a hook (where the same thing will be done again and again unnecessarily - note BTW that the hook of a minor mode will be invoked both on activation and deactivation of the mode, so in this case, it would be doing even more unnecessary work).

Then examine rectangle-mark-mode-map again:

(keymap
 (25 . yank-rectangle)
 (remap keymap
    (previous-line . rectangle-previous-line)
    (next-line . rectangle-next-line)
    (backward-char . rectangle-backward-char)
    (forward-char . rectangle-forward-char)
    (left-char . rectangle-left-char)
    (right-char . rectangle-right-char)
    (exchange-point-and-mark . rectangle-exchange-point-and-mark))
 (20)
 (15))

As you can see, C-y (the 25 entry) bound to yank-rectangle has been added and the C-o and C-t entries have been rebound to nil - as desired.

So it isn't that you are unable to add/remove the entries from the keymap - that works fine; it is that despite the fact that you have made changes to the keymap, you still don't see the "correct" actions happening when you invoke them. And for that, you have to dig deeper.

The deeper level is that rectangle-mark-mode is only active when the region is active (i.e. you have Transient Mark mode on - which is on by default, so I assume that you have not turned it off - and that the mark is set). When the region becomes inactive - for whatever reason - rectangle-mark-mode is not active any longer.

So if you activate rectange-mark-mode with C-x <SPC> and you ask what is bound to C-y (that is C-h c C-y) it will tell you that it is bound to yank-rectangle, but after you finish most buffer-modifying operations (e.g. you kill a rectangle with C-x r k) or press C-g and ask the same question, it will tell you it is bound to yank: rectangle-mark-mode is not active, so its keymap does not matter. You can check whether the mode is active or not by evaluating the variable rectangle-mark-mode with C-h v rectangle-mark-mode: if it is nil then the mode is not active.

So the problem is that the mode can go away under your feet so to speak. You will need to reactivate it with C-x <SPC> select a rectangular region (probably of width 0) and then do C-y to yank the rectangle at that position.

See the doc string of the mode with C-h f rectangle-mark-mode, the section Rectangles in the Emacs manual and review the transient-mark-mode documentation in the section The Mark of the Emacs Lisp Reference manual.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.