ChatGPT解决这个技术问题 Extra ChatGPT

Edit multiple lines at once in Emacs

I believe TextMate has a mode where if you start typing, the same thing will be entered on all the lines you've selected. Is there something similar to this in Emacs?

I'm guessing there's a way rectangles can help me, but I'm not sure how...

If you re-read the help notes for that you'll see that, since it was originally posted, it's been superseded by multiple-cursors.el
Yeah, @phils, multiple-cursors.el is awesome.

D
Dave Smith

It's as simple as this: C-x r t

Some examples are here: http://ergoemacs.org/emacs/emacs_string-rectangle_ascii-art.html


This is great but not very useful to someone completely new to emacs, can you help me decipher this please?
@cone You should read the built-in emacs tutorial. It explains how to read the hieroglyphics ;). To up the tutorial while in emacs, hit 'h' while holding the ctrl key. Then, hit 't' (for "tutorial).
I have C-x mapped to cut (cua-mode), so this is not a good idea.
Perhaps it's your idea of mapping C-x to cut, which is not good :)
@cone I was able to use this to make a list out of multiple lines of text by setting the mark with C-<SPC> and later C-g. Then I did C-x r t, typed - (dash and a space) in the mini buffer, and <RET>. Voila! A list was created.
P
Peter Mortensen

You absolutely need to try installing multiple cursors.

It's in Marmalade and MELPA so just do:

M-x package-install multiple-cursors

This is a good solution. Very easy to use. To add multiple selection from clicking (the standard for lost of people including me) add (global-unset-key (kbd "M-<down-mouse-1>")) (global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click) to your configuration.
Here in 2021, this is the solution that I think most people would expect.
It's even integrated with swiper, with 'C-7' as the default keybinding. xenodium.com/emacs-swiper-and-multiple-cursors
s
smonff

One of the solutions is using CUA mode. Activate cua mode with M-x cua-mode, select rectangle begin: first press C-Enter then move cursor with standard movement commands to make selection, now pressing enter at any time will cycle cursor through corners of the rectangle enabling you to prepend or append text to the selection.


Thanks, boskom. I'm using version 21.3.1, so this mode doesn't seem to be installed. I probably won't install it, because I'm finding that I like C-x r t.
thanks! i just thought cua mode was for people who didn't want to learn emacs copy n paste bindings :P This is awesome!
If you use cua-selection-mode instead of cua-mode, you won't get the unwanted cut/copy/paste bindings. You will get some other functionality that you might not want, though (most notably, editing commands replacing the region).
p
paweloque

You can use the following commands (and keys) to accomplish this:

open-rectangle (C-x, r, o) add spaces

kill-rectangle (C-x, r, k) delete

clear-rectangle (C-x, r, c) replace with spaces

M-x string-insert-rectangle fill with specified text

Here is a complete description of those features: http://www.gnu.org/software/emacs/manual/html_node/emacs/Rectangles.html


3
3 revs, 2 users 65%

For those of you that want to do this for more complicated scenarios and want to do it without installing a new module please read on. (This is possible in Emacs without installing MarkMultiple, although I personally use and love MarkMultiple.)

I recently had to output a SQL query to a file and then format it into a 'MYSQL INSERT' query. Here is how Emacs made my life easy....

The file looks like:

1   I am a random text
2    I am not
3    G, you've gone mad
4    Click on this link
5   Transfer in progress (we've started the transfer process)
6    But transfer happened yesterday
7    No you are
8    Oh please! This is getting too much!
9    I love Emacs
10    I can't be bothered with    this any more
11    it's time to raise the bar
12    show me    how to expand my territory

And I want to make it look like:

(1,   ,'I am a random text'),
(2,   ,'I am not'),
(3,   ,'G, youve gone mad'),
(4,   ,'Click on this link'),
(5,   ,'Transfer in progress (weve started the transfer process)'),
(6,   ,'But transfer happened yesterday'),
(7,   ,'No you are'),
(8,   ,'Oh please! this is getting too much!'),
(9,   ,'I love Emacs'),
(10,  ,'I cant be bothered with this any more'),
(11,  ,'its time to raise the bar'),
(12,  ,'show me how to expand my territory'),

Place cursor at first line Press C-x ( to start recording a macro (at this point, all your key inputs are being recorded so please follow the instructions carefully) Press C-a to go to the beginning of the line Type "(" followed by M-f to move forward a word and then type "," C-n to go to the next line, followed by C-x ) to end the macro C-u 11 C-x e repeat the macro n (11 in this case) times

Eureka! By now if you have not failed you will get something that looks like this:

(1,   I am a random text
(2,   I am not
(3,   G, youve gone mad
(4,   Click on this link
(5,   Transfer in progress (weve started the transfer process)
(6,   But transfer happened yesterday
(7,   No you are
(8,   Oh please! this is getting too much!
(9,   I love Emacs
(10,  I cant be bothered with this any more
(11,  its time to raise the bar
(12,  show me how to expand my territory

At this point, I am going to leave you to figure out the rest. But, before I go I like to mention that there are quite a few ways of achieving this sort of thing. This is just one of those ways and it happens to be my favourite way.


F3 also starts recording macros (at least in my emacs, by default) and F4 stops recording. Subsequent hits on F4 play back the macro. This is much easier to remember than C-x ( etc.
How did the single quotes disappear by this procedure and result in the degenerated text? At least the issue of escaping single quotes in the output ought to be addressed in some fashion in this answer.
s
starblue

Rectangles are for simple stuff like deleting the same amount of spaces in adjacent lines.

Otherwise keyboard macros are the way to go.


A
Amjith

I believe you are looking for the cua-mode that was suggested by boskom. http://www.vimeo.com/1168225?pg=embed&sec=1168225 this screencast might give you an idea of how to use this.


Thank you for the link! A picture says a thousand words :).
g
gdelfino

The answers show above are for inserting text in columns. TextMate's "Edit Each Line in Selection" inserts the same text in each line regardless of the length of each lines. I'm learning Lisp now, so as an exercise I wrote a function to do this:

(defun append-to-lines (text-to-be-inserted)
  ;;Appends text to each line in region
  (interactive "sEnter text to append: ")
  (save-excursion
    (let (point-ln mark-ln initial-ln final-ln count)
      (barf-if-buffer-read-only)
      (setq point-ln (line-number-at-pos))
      (exchange-point-and-mark)
      (setq mark-ln (line-number-at-pos))
      (if (< point-ln mark-ln)
          (progn (setq initial-ln point-ln final-ln mark-ln)
                 (exchange-point-and-mark))
        (setq initial-ln mark-ln final-ln point-ln))
      (setq count initial-ln)
      (while (<= count final-ln)
        (progn (move-end-of-line 1)
               (insert text-to-be-inserted)
               (next-line)
               (setq count (1+ count))))
      (message "From line %d to line %d." initial-ln final-ln ))))

You first make a selection that includes all the lines you want to affect and then run the function with M-x append-to-lines.


I haven't tested this out, but nice work. I was more interested in the "add the same text to the same column" approach, but I'm sure this would come in handy as well.
L
LordMsz

Step by step, how to change prefix for multiple lines with rectangle:

Press CTRL-x, then SPACE. This starts "rectangle mode".
Now move cursor around to select the area you want - like first column of multiple lines.

Press ALT-x and type string-rectangle.
This starts "string rectangle 'action'" where you type what to do with each line.
(That's the C-x r t in @allyourcode 's answer).
So type -. And hit enter.

You'll get a "dash" on each line.

There are other operations you can do with the selection, like delete etc. - see the link in @allyourcode 's answer.

I didn't understand this from others here, nor from docs, sorry :) I hope someone will find it useful.