3

A common use-case that I have is to add a string to the same position of each line of text.

For example, I might start with

expect(one).toEqual(true);
expect(two).toEqual(false);

which I want to transform into

expect(oneValue).toEqual(true);
expect(twoValue).toEqual(false);

What I currently do is:

  • place my cursor after one
  • press C-x <SPC> (invoking rectangle-mark-mode)
  • press C-n to extend the zero-width rectangle down one row
  • (look up the keystrokes and then) press C-x r t Value <RET> to invoke string-rectangle, thereby adding the string Value to the desired locations

I would like to simply start typing after selecting a rectangle with rectangle-mark-mode, and the rectangular selection would be interactively replaced with what I'm typing (including the case where I've marked a zero-width rectangle). In other words, I want to eliminate the C-x r t step above and just start typing Value immediately. How can I accomplish this?

I'm also curious why this isn't the default behavior of Emacs, since I can't think of a disadvantage to this approach.

  • There is no magic. Keys are all equals in Emacs. C-x r t runs a command, V, a, l, u and e all run a command as well. You have to teach Emacs what's the mean of "start typing". – xuchunyang Mar 14 '18 at 10:27
  • Also multiple-cursors offers a convenient way to do this, once you get used to the key-bindings. – InHarmsWay Apr 14 '18 at 11:23
  • string-rectangle long pre-dates rectangle-mark-mode -- you can save yourself a keystroke by using C-SPC rather than C-x SPC. – phils Jul 12 '18 at 9:57
  • 1
    I recently wrote some code for this on reddit. – Omar Jul 12 '18 at 18:00
  • @Omar, would you please copy your solution into an Answer here? – phils Jul 13 '18 at 9:07
2

Offhand I'm inclined to agree with the feature request -- with rectangle-mark-mode enabled, self-insert-command seems (AFAICS) to exit the rectangle mode and insert at point, just as if the rectangle wasn't selected; so your idea seems like a good idea for a new option. M-x report-emacs-bug and suggest it?

There is a shorter key sequence than the one you're using in rectangle-mark-mode-map however. If you mark the rectangle with C-x SPC then:

  • C-t runs string-rectangle.
  • C-o runs open-rectangle.

FYI I use string-rectangle that way when I want to replace existing text; but if I'm purely inserting then I tend to make use of the rectangle support in cua-selection-mode which can operate rather like what you're asking for:

  • C-RET to mark the top of the column
  • Move point down to the bottom position
  • Start typing
  • C-RET to exit

That's just one use-case for it. M-x find-library RET cua-base RET and read about "CUA rectangle support" for the full details.

2

This came up on reddit where I wrote two ways of achieving this, but I think the nicest solution was offered by Stefan Monnier:

(defun string-rectangle-with-initial (char)
  (interactive (list last-input-event))
  (push char unread-command-events)
  (call-interactively 'string-rectangle))

(define-key rectangle-mark-mode-map
  [remap self-insert-command] 'string-rectangle-with-initial)

On Emacs 25 and later, string-rectangle has a lovely dynamic preview of the result. If you want similar interactivity on older Emacsen, you can try one of my solutions:

(defun string-rectangle-single-char ()
  (interactive)
  (when (< (point) (mark)) (exchange-point-and-mark))
  (string-rectangle (region-beginning)
                    (region-end)
                    (this-command-keys))
  (exchange-point-and-mark)
  (forward-char)
  (exchange-point-and-mark)
  (setq deactivate-mark nil))

(define-key rectangle-mark-mode-map
  [remap self-insert-command] 'string-rectangle-single-char)
0

(This answer doesn't tell you how to do what you request. It tries to tell you why that behavior is not the default behavior.)

There are lots of things you might want to do with a rectangular region, just like there are lots of things you might want to do with a regular region. Why suppose that whatever you type should be considered only as text to be used as string-rectangle? That would seriously limit what you can do with a rectangular region.

The problem, I think, is that you are in the habit of creating a rectangular region, and not in the habit of just putting point and mark at the corners of what you want to consider as a rectangle.

(That said, maybe you could get the behavior you request, if you really want it, by fiddling with the delete-selection code.)

  • Good point about the analogy to regular regions. But to follow that analogy, my assumption was that anything special you'd want to do to with region would involve a modifier key such as C- or M-, and anything else would be considered an attempt to overwrite the region with text input. – mark Mar 14 '18 at 1:33
  • Thank you for the point and mark suggestion, that is an good approach. 1) Set point and mark at the corners of a rectangle 2) invoke C-x r t and begin typing – mark Mar 14 '18 at 1:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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