[-- Attachment #1: Type: text/plain, Size: 149 bytes --] Why there is still no such fundamental command as duplicating the current line? This command slightly extends the existing copy-from-above-command: [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: copy-line.patch --] [-- Type: text/x-diff, Size: 491 bytes --] diff --git a/lisp/misc.el b/lisp/misc.el index 09f6011f98..b3b7d8355f 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -61,6 +61,16 @@ copy-from-above-command (+ n (point))))))) (insert string))) +;;;###autoload +(defun copy-line (&optional arg) + "Duplicate the current line ARG times." + (interactive "p") + (dotimes (_ arg) + (forward-line 1) + (insert "\n") + (forward-line -1) + (copy-from-above-command))) + ;; Variation of `zap-to-char'. ;;;###autoload
> Why there is still no such fundamental command as duplicating the
> current line? This command slightly extends the existing
> copy-from-above-command:
"still"?
"fundamental command"?
In the 35+ years of Emacs, has anyone actually
requested/missed this?
We seem to be adding this & that simple command
more & more - perhaps just because it's available
in other editors?
(Next, we'll dedicate a default key for this...)
The right approach for this kind of thing, IMO, is
for users to create and use such a command. Then
after a while they start asking for it by default,
and we maybe add it, if it's a real lack.
I've nothing against such a command. But I've
also never felt the need for it.
Juri Linkov <juri@linkov.net> writes: > Why there is still no such fundamental command as duplicating the current > line? This command slightly extends the existing copy-from-above-command: Hm... So this would basically just allow you to get X number of the line? Well, I don't object to adding it, but I'm not sure what the use case is here? The only time I can remember wanting something like that is when I'm filling a buffer with text for test purposes, which is perhaps not a compelling use case. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Lars Ingebrigtsen <larsi@gnus.org> writes: > > Well, I don't object to adding it, but I'm not sure what the use case is > here? The only time I can remember wanting something like that is when > I'm filling a buffer with text for test purposes, which is perhaps not a > compelling use case. In programming modes, if you need to declare a bunch of variables, you may duplicate the current line several times and then proceed to rename them. I see the proposed new command may be useful in that scenario. Also, why not name the command `duplicate-line'? I think it's a more descriptive name and more discoverable via apropos (along with `delete-duplicate-lines', for example). This has been a hot topic in Q&A sites: https://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs
> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
> Date: Fri, 19 Feb 2021 21:27:09 +0100
> From: Daniel Martín via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
>
> > Well, I don't object to adding it, but I'm not sure what the use case is
> > here? The only time I can remember wanting something like that is when
> > I'm filling a buffer with text for test purposes, which is perhaps not a
> > compelling use case.
>
> In programming modes, if you need to declare a bunch of variables, you
> may duplicate the current line several times and then proceed to rename
> them.
I usually use M-/ for that. It makes typing something that you just
typed very easy: just a single character followed by M-/ usually does
the job. This allows me to type just what is needed, without
redundant "renaming".
[[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > We seem to be adding this & that simple command > more & more - perhaps just because it's available > in other editors? I agree. Just because we don't need any longer to struggle to keep Emacs down to 8 megabytes is no reason to add commands without real demand. -- Dr Richard Stallman Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org)
Daniel Martín <mardani29@yahoo.es> writes: > In programming modes, if you need to declare a bunch of variables, you > may duplicate the current line several times and then proceed to rename > them. I see the proposed new command may be useful in that scenario. Right; makes sense. > This has been a hot topic in Q&A sites: > https://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs OK, so there seems to be some general demand for this command, so I think we should go ahead and add it, unless somebody strongly objects. > Also, why not name the command `duplicate-line'? I think it's a more > descriptive name and more discoverable via apropos (along with > `delete-duplicate-lines', for example). That does seem like an even better name for the command. What do you think, Juri? -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Eli Zaretskii <eliz@gnu.org> writes: > I usually use M-/ for that. It makes typing something that you just > typed very easy: just a single character followed by M-/ usually does > the job. This allows me to type just what is needed, without > redundant "renaming". `dabbrev-expand'? I just tried "emacs -Q" and then `M-/' and Emacs just beeped at me: --- user-error: No dynamic expansion for ‘buffer. ’ found --- (Because "buffer." was the previous word in the *scratch* buffer.) -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
> From: Lars Ingebrigtsen <larsi@gnus.org>
> Cc: Daniel Martín <mardani29@yahoo.es>,
> 46621@debbugs.gnu.org,
> juri@linkov.net
> Date: Sat, 20 Feb 2021 14:05:44 +0100
>
> Eli Zaretskii <eliz@gnu.org> writes:
>
> > I usually use M-/ for that. It makes typing something that you just
> > typed very easy: just a single character followed by M-/ usually does
> > the job. This allows me to type just what is needed, without
> > redundant "renaming".
>
> `dabbrev-expand'? I just tried "emacs -Q" and then `M-/' and Emacs just
> beeped at me:
You need to type the beginning of what you want it to complete before
M-/. Try
b M-/
f M-/
f M-/ M-/ M-/
etc.
Eli Zaretskii <eliz@gnu.org> writes: > You need to type the beginning of what you want it to complete before > M-/. Try > > b M-/ > f M-/ > f M-/ M-/ M-/ > > etc. Ah, I see. I've never used that command before. However, this just copies a single word, and not a line? So a line-copying command still sounds somewhat useful. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
> From: Lars Ingebrigtsen <larsi@gnus.org> > Cc: mardani29@yahoo.es, 46621@debbugs.gnu.org, juri@linkov.net > Date: Sat, 20 Feb 2021 14:18:06 +0100 > > > b M-/ > > f M-/ > > f M-/ M-/ M-/ > > > > etc. > > Ah, I see. I've never used that command before. It's a great means to type much less, and not just in programming modes. When writing email as well, for example. > However, this just copies a single word, and not a line? I mentioned M-/ because of this rationale: > > In programming modes, if you need to declare a bunch of variables, you > > may duplicate the current line several times and then proceed to rename > > them. > In programming modes, if you need to declare a bunch of variables, you > may duplicate the current line several times and then proceed to rename > them. So assume you have this: ptrdiff_t foobar; and you want to add this: ptrdiff_t bazquux; Instead of copying the "foobar" line and then editing "foobar" into "bazquux", you can do p M-/ bazquux; IOW, instead of copying lines, it usually makes more sense in PL modes to be able to easily repeat what has been typed recently, because source lines are rarely exact copies of some other line. So that use case I think is not the best one to justify this new command. Which is not to say I object to adding it, just that at least some people may think they need it because they aren't aware of some Emacs feature. Because I _never_ in all the years of writing code felt the need to have such a command.
On 20.02.2021 16:15, Eli Zaretskii wrote:
> Which is not to say I object to adding it, just that at
> least some people may think they need it because they aren't aware of
> some Emacs feature. Because I_never_ in all the years of writing
> code felt the need to have such a command.
FWIW, I routinely use copy-from-above-command, most often when writing
tests, when a lot of lines look similar to each other, with minor
variations.
Never felt a need for another variation of it, though.
>> In programming modes, if you need to declare a bunch of variables, you >> may duplicate the current line several times and then proceed to rename >> them. I see the proposed new command may be useful in that scenario. > > Right; makes sense. > >> This has been a hot topic in Q&A sites: >> https://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs > > OK, so there seems to be some general demand for this command, so I > think we should go ahead and add it, unless somebody strongly objects. Also tired of reading endless discussions on Q&A sites about reinventing such fundamental feature as duplicating a line. >> Also, why not name the command `duplicate-line'? I think it's a more >> descriptive name and more discoverable via apropos (along with >> `delete-duplicate-lines', for example). > > That does seem like an even better name for the command. What do you > think, Juri? `duplicate-line' is a better name, but the problem is that is based on the existing command `copy-from-above-command'. Should they share the same name prefix? Please decide, I have no opinion on this. :-)
[[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > >> In programming modes, if you need to declare a bunch of variables, you > >> may duplicate the current line several times and then proceed to rename > >> them. I see the proposed new command may be useful in that scenario. Once in a while I want to do that. It is easy: C-a C-k C-k, they C-y as many times as needed. Instead of a command to duplicate the current line repeatedly, how about a command to yank the current kill repeatedly? That would be useful in a much broader range of situations. I wonder if the current meaning of the numeric argument to C-y (reach back in the kill ring) is actually useful. Would it be better for it to repeat the yank in this way? -- Dr Richard Stallman Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org)
[[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > >> In programming modes, if you need to declare a bunch of variables, you > >> may duplicate the current line several times and then proceed to rename > >> them. I see the proposed new command may be useful in that scenario. Once in a while I want to do that. It is easy: C-a C-k C-k, they C-y as many times as needed. Instead of a command to duplicate the current line repeatedly, how about a command to yank the current kill repeatedly? That would be useful in a much broader range of situations. I wonder if the current meaning of the numeric argument to C-y (reach back in the kill ring) is actually useful. Would it be better for it to repeat the yank in this way? -- Dr Richard Stallman Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org)
> > >> In programming modes, if you need to declare a bunch of variables, you > > >> may duplicate the current line several times and then proceed to rename > > >> them. I see the proposed new command may be useful in that scenario. > > Once in a while I want to do that. It is easy: C-a C-k C-k, > they C-y as many times as needed. Let's compare these two solutions. Trying to copy 10 lines: C-a C-k C-k C-y C-y C-y C-y C-y C-y C-y C-y C-y C-y and adds an unrequested entry to the kill ring that the user needs to remove from the kill ring later. When bound to a short key, it's just C-12 C-c c and doesn't change the contents of the kill ring. > Instead of a command to duplicate the current line repeatedly, > how about a command to yank the current kill repeatedly? > That would be useful in a much broader range of situations. > > I wonder if the current meaning of the numeric argument to C-y (reach > back in the kill ring) is actually useful. Would it be better for > it to repeat the yank in this way? It's not realistic to change the meaning of the numeric arg to C-y. People already use the current meaning for decades.
On February 21, 2021 10:54:24 AM GMT+02:00, Juri Linkov <juri@linkov.net> wrote:
> > > >> In programming modes, if you need to declare a bunch of
> variables, you
> > > >> may duplicate the current line several times and then proceed
> to rename
> > > >> them. I see the proposed new command may be useful in that
> scenario.
> >
> > Once in a while I want to do that. It is easy: C-a C-k C-k,
> > they C-y as many times as needed.
>
> Let's compare these two solutions. Trying to copy 10 lines:
>
> C-a C-k C-k C-y C-y C-y C-y C-y C-y C-y C-y C-y C-y
>
> and adds an unrequested entry to the kill ring
> that the user needs to remove from the kill ring later.
>
> When bound to a short key, it's just
>
> C-12 C-c c
>
> and doesn't change the contents of the kill ring.
What is the use case for an Emacs user to need to copy a line 12 times, and is it frequent enough to justify binding the command to a key, and to C-c key on top of that?
Also, let's not forget that Emacs has keyboard macros, and those can be run with a repeat count.
Eli Zaretskii <eliz@gnu.org> writes: > What is the use case for an Emacs user to need to copy a line 12 > times, and is it frequent enough to justify binding the command to a > key, and to C-c key on top of that? That users are asking about a command like this on stackexchange seems to indicate that some users would find this useful. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Juri Linkov <juri@linkov.net> writes: > `duplicate-line' is a better name, but the problem is that is based on the > existing command `copy-from-above-command'. Should they share > the same name prefix? Please decide, I have no opinion on this. :-) I think it's fine to go with `duplicate-line', even if it's conceptually similar to `copy-from-above-command'. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
On February 21, 2021 3:12:19 PM GMT+02:00, Lars Ingebrigtsen <larsi@gnus.org> wrote:
> Eli Zaretskii <eliz@gnu.org> writes:
>
> > What is the use case for an Emacs user to need to copy a line 12
> > times, and is it frequent enough to justify binding the command to a
> > key, and to C-c key on top of that?
>
> That users are asking about a command like this on stackexchange seems
> to
> indicate that some users would find this useful.
They asked about making a dozen copies of a line?
Eli Zaretskii <eliz@gnu.org> writes: > They asked about making a dozen copies of a line? I don't think anybody asked for a dozen copies in particular. I think we should add the command, but I'm not convinced it deserves a default key binding -- we can add that later if it turns out that this is the break-out most-popular new command in Emacs 28. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
> From: Lars Ingebrigtsen <larsi@gnus.org> > Cc: Juri Linkov <juri@linkov.net>, Richard Stallman <rms@gnu.org>, > 46621@debbugs.gnu.org, mardani29@yahoo.es > Date: Sun, 21 Feb 2021 16:51:34 +0100 > > Eli Zaretskii <eliz@gnu.org> writes: > > > They asked about making a dozen copies of a line? > > I don't think anybody asked for a dozen copies in particular. Then why did Juri decide to countermand Richard's arguments by a strawman? > I think we should add the command, but I'm not convinced it deserves a > default key binding -- we can add that later if it turns out that this > is the break-out most-popular new command in Emacs 28. Richard's arguments still stand, and I'd prefer to seriously consider rather than dismiss them.
Eli Zaretskii <eliz@gnu.org> writes: > Richard's arguments still stand, and I'd prefer to seriously consider > rather than dismiss them. Richard said that he didn't see the point of this command since we have `C-a C-k C-k'. Nevertheless, it has been demonstrated that this is a command that users do ask about, so I didn't see any point in repeating that. But in the interest of non-dismissal, I've now done so. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
> Also, let's not forget that Emacs has keyboard
> macros, and those can be run with a repeat count.
+1 for emphasizing this.
We should maybe emphasize it more, particularly
when someone used to another editor asks why
Emacs doesn't have this or that key/action.
Instead, we too often, I think, start thinking
about whether Emacs should indeed add such a
command (and key).
Newbies, in particular, could do well to learn
about using keyboard macros early.
(I haven't used the tutorial in ages. Do we
introduce recording and playing back macros?)
Speaking of which, it might be good to speak
more of "recording" and "playing back" a
sequence of actions, and less of "macros" in
this context.
I think that many people are used to turning
on "recording" in various contexts - it's not
a big deal as a notion, whereas "macro" sounds
exotic and can sound complicated/intimidating.
> That users are asking about a command like this
> on stackexchange seems to indicate that some
> users would find this useful.
Not necessarily. Which users? Sometimes newbies
to Emacs are looking for what they're used to in
some other editor, and not seeing that in Emacs
they think "missing feature".
And answers on emacs.SE often set newbies straight
in this regard, saying "this is how you use Emacs
to do what you want".
The first response by us shouldn't be a knee-jerk
reaction to add what someone says is missing. We
should first check what people who use Emacs do,
i.e., see if what seems to be missing really
represents a problem to be fixed.
> I think we should add the command, but I'm not convinced it deserves a > default key binding I'd support that. Doesn't hurt; anyone can make use of it. Not a big deal. > we can add that later if it turns out that this > is the break-out most-popular new command in Emacs 28. I'd hope that we'd hold off for quite a while, and real, popular acclaim. It's trivial for users to bind a command. And users will let Emacs know if they really, really want a default binding for some command. Be conservative handing out keys by default.
>> > Once in a while I want to do that. It is easy: C-a C-k C-k, >> > they C-y as many times as needed. >> >> Let's compare these two solutions. Trying to copy 10 lines: >> >> C-a C-k C-k C-y C-y C-y C-y C-y C-y C-y C-y C-y C-y >> >> and adds an unrequested entry to the kill ring >> that the user needs to remove from the kill ring later. >> >> When bound to a short key, it's just >> >> C-12 C-c c >> >> and doesn't change the contents of the kill ring. > > What is the use case for an Emacs user to need to copy a line 12 > times, and is it frequent enough Yes, it is frequently used, as these Q&A sites indicate. > to justify binding the command to a key, and to C-c key on top > of that? ISTR, 'C-c letter' keys are reserved for users, so users can bind the command to 'C-c c' or any other short key. But I can't prove if such convention of 'C-c letter' for user keys really exists, I can't find it in the manual. Or it could be bound to some short key sequence by default. Even without a keybinding the key sequence is very short: M-10 M-x dup RET > Also, let's not forget that Emacs has keyboard macros, and those can > be run with a repeat count. This is how long it takes with keyboard macros: C-a C-k C-k C-x ( C-y C-x ) C-10 C-x e
> I can't prove if such convention of 'C-c letter' for
> user keys really exists, I can't find it in the manual.
In the Elisp manual, `i key bind TAB':
key binding
key binding, conventions for
Or `i conven TAB': (with substring matching):
buffer display conventions
coding conventions in Emacs Lisp
comments, Lisp convention for
conventions for writing major modes
conventions for writing minor modes
documentation conventions
documentation strings, conventions and tips
key binding, conventions for
major mode conventions
minor mode conventions
programming conventions
set-advertised-calling-convention
typographic conventions
(Yet another advertisement for completion candidates
as an aid to discovery.)
Candidate `key binding, conventions for' takes you
to node `Key Binding Conventions', where you find
this, among other conventions:
Don't define 'C-c LETTER' as a key in Lisp programs.
Sequences consisting of 'C-c' and a letter (either
upper or lower case) are reserved for users; they
are the *only* sequences reserved for users, so do
not block them.
Juri Linkov <juri@linkov.net> writes: >> Once in a while I want to do that. It is easy: C-a C-k C-k, >> they C-y as many times as needed. I do this occasionally. Usually it's in something like markdown-mode. Typically I'm creating lists and want to write out a bunch of formatting characters before going back and filling in text. So I might want 10-12 lines like: - [ ] which is a markdown list item with a checkbox, before going back and filing in text without having to type odd punctuation characters. Sometimes I might put a date string in there too or some other prefix string. It's emacs I can do this many different ways. I might do the C-a C-k C-k C-y C-y ... dance. Typically I'll make 4 lines then kill those 4 lines and yank them 3 times. I might just type my text and then go back and use string-rectangle to insert the markup. If it were more involved I might use a macro. If there were a duplicate-line command that took an arg to duplicate it arg times I'd probably start using that. I probably wouldn't bother to write it myself (I haven't in 30+ years). >> Instead of a command to duplicate the current line repeatedly, >> how about a command to yank the current kill repeatedly? >> That would be useful in a much broader range of situations. >> >> I wonder if the current meaning of the numeric argument to C-y (reach >> back in the kill ring) is actually useful. Would it be better for >> it to repeat the yank in this way? > > It's not realistic to change the meaning of the numeric arg to C-y. > People already use the current meaning for decades. Actually, I'd like that and this is a place where I think completion systems influence that decision. I don't use an arg to C-y. If I want something from the kill-ring that isn't the last thing, I'll C-y and then M-y until I get it. I'm not remembering I want the 3rd to last thing I killed and if I'm off by one I think it's a pain to fix. I might do that if I were writing a complex keyboard macro and concentrating for it but I'd probably use registers instead. But in particular with modern completion systems I'd definitely like this change to yank's arg. While I do C-y M-y for simple stuff, if I want something I've yanked from longer ago, instead I'll use something like consult-yank or counsel-yank. These use the kill-region as completion candidates and show the candidates, one per line, in the minibuffer with all the completion tools available (most have options to cope with multi-line text). I bind it to M-y globally so if I want to yank something old I skip C-y entirely and just type M-y and then might use completion and narrowing if I don't see it near the top of the list. As a result, the current arg to C-y is useless to me because completion offers a much better experience. -- Howard
[[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > > What is the use case for an Emacs user to need to copy a line 12 > > times, and is it frequent enough to justify binding the command to a > > key, and to C-c key on top of that? > That users are asking about a command like this on stackexchange seems to > indicate that some users would find this useful. Sure, but how much? Is it enough interest that we should cater to it? Adding to Emacs every function or command that some users would like would make it even more bloated. Of course, we add commands, but we should make sure each one is substantially useful. -- Dr Richard Stallman Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org)
[[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > > Once in a while I want to do that. It is easy: C-a C-k C-k, > > they C-y as many times as needed. > Let's compare these two solutions. Trying to copy 10 lines: > C-a C-k C-k C-y C-y C-y C-y C-y C-y C-y C-y C-y C-y > and adds an unrequested entry to the kill ring > that the user needs to remove from the kill ring later. With my proposd change to C-y, it would be C-a C-k C-k C-u 12 C-y and it would not require the user to make a new key binding. Changing the contents of the kill ring is not a drawback. It is the normal way you move text around in Emacs. > It's not realistic to change the meaning of the numeric arg to C-y. > People already use the current meaning for decades. We could inquire of the users to see what they think about the issue. -- Dr Richard Stallman Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org)
> > It's not realistic to change the meaning of the numeric arg to C-y. > > People already use the current meaning for decades. > > We could inquire of the users to see what they think about the issue. Every once in a while the lack of such fundamental command sparks very long discussions how to reinvent the wheel. Some recent examples: https://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs https://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs?page=2 https://stackoverflow.com/questions/27129147/efficent-way-to-copy-and-paste-a-line https://stackoverflow.com/questions/12132601/duplicating-the-current-line https://emacs.stackexchange.com/questions/22705/quickly-duplicate-line-and-increase-number-for-lots-of-lines https://old.reddit.com/r/emacs/comments/lkyadp/weekly_tipstricketc_thread/gnnniq3/ https://old.reddit.com/r/emacs/comments/jvpccf/weekly_tipstricketc_thread/gcr8h68/ https://old.reddit.com/r/emacs/comments/jwhr6g/batteries_included_with_emacs/gcqdmp9/ with questions like from the last: Why does emacs doesn't have a built-in ergonomic way to duplicate a line? Genuinely curious, seems like something fundamental. Guess it is one of the reasons evil-mode has rise so much. Any new comer will feel disgusted by having to do C-a C-space C-e M-w and more keystrokes to place it The proposed tiny 8-line patch was intended to help people avoid wasting their time on such trivial things.
> From: Juri Linkov <juri@linkov.net> > Date: Mon, 22 Feb 2021 11:07:58 +0200 > Cc: 46621@debbugs.gnu.org, larsi@gnus.org, mardani29@yahoo.es > > > > It's not realistic to change the meaning of the numeric arg to C-y. > > > People already use the current meaning for decades. > > > > We could inquire of the users to see what they think about the issue. > > Every once in a while the lack of such fundamental command sparks very > long discussions how to reinvent the wheel. Some recent examples: Thanks for the links. However, I don't think they add anything substantial to this discussion. For starters, many posters there just wanted to know how many keystrokes it takes in Emacs to copy a line, and some even said they wanted to compare the result with Vim. They don't necessarily ask for a command or a single short key sequence to do that, at least not in every post. More importantly, I see no description of the situations where such a copy is needed, so it is hard to analyze reason about the necessity. For example, perhaps some of the posters wanted this because they are unaware of some existing Emacs features which can do the job efficiently enough. This is why I asked here to describe the use cases, i.e. the situations where such a command would be needed. I didn't get any answers to that, AFAIR. Just one person posted his experiences. Without knowing what situations necessitate such a command, I don't see how we will be able to reason whether the needs justify adding the command. And reason we must, because we cannot possibly implement feature after feature just because someone asks about it on stackexchange. > The proposed tiny 8-line patch was intended to help people avoid > wasting their time on such trivial things. Yes, this command is relatively small. But we must have some criteria for adding new commands and features, because otherwise we will add 8 lines, then another 10 lines, then 5 more, etc. etc. These things add up, and that's even before you consider the supporting docs and other consequences. Bottom line, if we want to consider this command, we should somehow come up with the relevant use cases, and then weigh them against the added complexity and maintenance costs. I therefore urge people who think they know these details to please speak up and contribute to this discussion.
> From: Juri Linkov <juri@linkov.net>
> Cc: bug-gnu-emacs@gnu.org, Richard Stallman <rms@gnu.org>,
> 46621@debbugs.gnu.org, larsi@gnus.org, mardani29@yahoo.es
> Date: Sun, 21 Feb 2021 22:37:28 +0200
>
> > Also, let's not forget that Emacs has keyboard macros, and those can
> > be run with a repeat count.
>
> This is how long it takes with keyboard macros:
>
> C-a C-k C-k C-x ( C-y C-x ) C-10 C-x e
But that's a one-time investment. Thereafter one can bind this to a
key and save it to the init file.
So counting the keystrokes required for defining the macro is not
unlike counting keystrokes required for coding the function you
propose.
On Mon, Feb 22 2021, Eli Zaretskii wrote:
> More importantly, I see no description of the situations where such a
> copy is needed, so it is hard to analyze reason about the necessity.
One example where copy-line would be useful is editing configuration
files. E.g. /etc/ssh/sshd_config list many options with the default
value but as comments, like so:
#SyslogFacility AUTH
#LogLevel INFO
... other options ...
Now, if I want to change LogLevel to say DEBUG, I would copy the line,
keep the original, and edit the copied line.
Not hard to do in Emacs, but somehow the vi way of doing this feels more
efficient.
Helmut
On Feb 22 2021, Helmut Eller wrote:
> On Mon, Feb 22 2021, Eli Zaretskii wrote:
>
>> More importantly, I see no description of the situations where such a
>> copy is needed, so it is hard to analyze reason about the necessity.
>
> One example where copy-line would be useful is editing configuration
> files. E.g. /etc/ssh/sshd_config list many options with the default
> value but as comments, like so:
>
> #SyslogFacility AUTH
> #LogLevel INFO
> ... other options ...
>
> Now, if I want to change LogLevel to say DEBUG, I would copy the line,
> keep the original, and edit the copied line.
But you don't need the repeat count for that. copy-from-above-command
will work well for this task.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
[-- Attachment #1: Type: text/plain, Size: 1681 bytes --] > > Bottom line, if we want to consider this command, we should somehow come > up with the relevant use cases, and then weigh them against the added > complexity and maintenance costs. I therefore urge people who think > they know these details to please speak up and contribute to this > discussion. > My 2 cents: a typical case where this could be useful is: switch (foobar) { case long_enum_value_name_a: printf ("a"); break; case long_enum_value_name_b: printf ("b"); break; case long_enum_value_name_c: printf ("c"); break; case long_enum_value_name_d: printf ("d"); break; case long_enum_value_name_e: printf ("e"); break; case long_enum_value_name_f: printf ("f"); break; case long_enum_value_name_g: printf ("g"); break; case long_enum_value_name_h: printf ("h"); break; case long_enum_value_name_i: printf ("i"); break; default: printf ("?"); break; } Another typical case: import java.util.Set; import java.util.TreeSet; import java.util.HashSet; import java.util.LinkedHashSet; I agree with Richard that this can be done with C-a C-k C-k C-y..., which is what I've been using in such cases, but that doesn't mean that the proposed command wouldn't be welcome. I agree with Juri that Richard's solution "pollutes" the kill-ring with something that the user actually did not want to kill. I would suggest the following (based on Juri's code): (defun duplicate-line (&optional arg) (interactive "p") (save-mark-and-excursion (dotimes (_ arg) (forward-line 1) (insert "\n") (forward-line -1) (copy-from-above-command)))) (global-set-key (kbd "C-x r z") 'duplicate-line)
> From: Helmut Eller <eller.helmut@gmail.com>
> Date: Mon, 22 Feb 2021 17:28:39 +0100
>
> One example where copy-line would be useful is editing configuration
> files. E.g. /etc/ssh/sshd_config list many options with the default
> value but as comments, like so:
>
> #SyslogFacility AUTH
> #LogLevel INFO
> ... other options ...
>
> Now, if I want to change LogLevel to say DEBUG, I would copy the line,
> keep the original, and edit the copied line.
I already mentioned M-/ as the alternative. In the above case, type
"#L M-/", and Emacs will complete to "#LogLevel". IOW, if these cases
are considered as "repeat a previous word" rather than "copy a
previous line, then edit it", the solution already exists. I suspect
that people who are looking for this command simply don't know about
M-/ in Emacs, because IME it's still quite a unique feature.
> Date: Mon, 22 Feb 2021 17:04:02 +0000
> From: Gregory Heytings <gregory@heytings.org>
>
> My 2 cents: a typical case where this could be useful is:
>
> switch (foobar) {
> case long_enum_value_name_a: printf ("a"); break;
> case long_enum_value_name_b: printf ("b"); break;
> case long_enum_value_name_c: printf ("c"); break;
> case long_enum_value_name_d: printf ("d"); break;
> case long_enum_value_name_e: printf ("e"); break;
> case long_enum_value_name_f: printf ("f"); break;
> case long_enum_value_name_g: printf ("g"); break;
> case long_enum_value_name_h: printf ("h"); break;
> case long_enum_value_name_i: printf ("i"); break;
> default: printf ("?"); break;
> }
Here's how I'd type this:
case long_enum_value_name_a: printf ("a"); break;
c M-/ DEL b : p M-/ ("b"); b M-/
c M-/ DEL c : p M-/ ("c"); b M-/
c M-/ M-/ DEL d : p M-/ ("d"); b M-/
etc. (And if the series are indeed longer than a couple of lines, a
rare case indeed, then a keyboard macro is in order.)
[-- Attachment #1: Type: text/plain, Size: 1547 bytes --] >> My 2 cents: a typical case where this could be useful is: >> >> switch (foobar) { >> case long_enum_value_name_a: printf ("a"); break; >> case long_enum_value_name_b: printf ("b"); break; >> case long_enum_value_name_c: printf ("c"); break; >> case long_enum_value_name_d: printf ("d"); break; >> case long_enum_value_name_e: printf ("e"); break; >> case long_enum_value_name_f: printf ("f"); break; >> case long_enum_value_name_g: printf ("g"); break; >> case long_enum_value_name_h: printf ("h"); break; >> case long_enum_value_name_i: printf ("i"); break; >> default: printf ("?"); break; >> } > > Here's how I'd type this: > > case long_enum_value_name_a: printf ("a"); break; > c M-/ DEL b : p M-/ ("b"); b M-/ > c M-/ DEL c : p M-/ ("c"); b M-/ > c M-/ M-/ DEL d : p M-/ ("d"); b M-/ > > etc. (And if the series are indeed longer than a couple of lines, a > rare case indeed, then a keyboard macro is in order.) > Yes, that's one way to do it, perhaps the most "emacsish" way to do it. But it takes more keystrokes than what you write: case long_enum_value_name_a: printf ("a"); break; RET c M-/ SPC l M-/ DEL DEL b : SPC p M-/ SPC ("b"); b M-/ ; RET c M-/ SPC l M-/ DEL DEL c : SPC p M-/ SPC ("c"); b M-/ ; RET ... And yes, keyboard macros can also be used. That doesn't mean that the proposed feature wouldn't be useful; I'd say it's more intuitive: case long_enum_value_name_a: printf ("a"); break; RET C-u 8 C-x r z C-s a : RET C-b C-b C-d b C-n C-b C-d c C-n C-b C-d d ...
On Mon, Feb 22 2021, Andreas Schwab wrote:
>> One example where copy-line would be useful is editing configuration
>> files. E.g. /etc/ssh/sshd_config list many options with the default
>> value but as comments, like so:
>>
>> #SyslogFacility AUTH
>> #LogLevel INFO
>> ... other options ...
>>
>> Now, if I want to change LogLevel to say DEBUG, I would copy the line,
>> keep the original, and edit the copied line.
>
> But you don't need the repeat count for that. copy-from-above-command
> will work well for this task.
I didn't know about this. But if I place point between LogLevel and
INFO and then execute M-x copy-from-above-command then the result is
#LogLevelcility AUTH INFO
which is not what is needed in this situation.
Helmut
On Mon, Feb 22 2021, Eli Zaretskii wrote:
>> One example where copy-line would be useful is editing configuration
>> files. E.g. /etc/ssh/sshd_config list many options with the default
>> value but as comments, like so:
>>
>> #SyslogFacility AUTH
>> #LogLevel INFO
>> ... other options ...
>>
>> Now, if I want to change LogLevel to say DEBUG, I would copy the line,
>> keep the original, and edit the copied line.
>
> I already mentioned M-/ as the alternative. In the above case, type
> "#L M-/", and Emacs will complete to "#LogLevel". IOW, if these cases
> are considered as "repeat a previous word" rather than "copy a
> previous line, then edit it", the solution already exists. I suspect
> that people who are looking for this command simply don't know about
> M-/ in Emacs, because IME it's still quite a unique feature.
I certainly know about M-/, but in this situation it's pretty far down
the list of alternatives I would consider. Killing the whole line and
inserting it two times is what I usually end up doing.
Admittedly, I do have my own copy-line command and it's bound to C-x-,.
But I often forget the key binding.
Helmut
>> But you don't need the repeat count for that. copy-from-above-command
>> will work well for this task.
>
> I didn't know about this. But if I place point between LogLevel and
> INFO and then execute M-x copy-from-above-command then the result is
>
> #LogLevelcility AUTH INFO
>
> which is not what is needed in this situation.
I never knew about copy-from-above-command either. It's not
bound to any keys. It's not in the emacs manual. I think
it's also named incorrectly.
In emacs terminology it's not copying the text (like to the
kill-ring) but inserting or yanking it into the buffer (just
not from the kill-ring but from the previous line). It seems
closer in concept to how dabbrev and hippie use the term
"expand".
--
Howard
Why on earth is this called `copy-from-above-command'? "-command"? Maybe it would help to add a more discoverable alias?
On Mon, 22 Feb 2021 17:43:28 +0200 Eli Zaretskii <eliz@gnu.org> wrote:
> Bottom line, if we want to consider this command, we should somehow
> come up with the relevant use cases, and then weigh them against the
> added complexity and maintenance costs. I therefore urge people who
> think they know these details to please speak up and contribute to
> this discussion.
I frequently use the following command (bound to `C-c l'), which suits
my needs better than the proposed command would or dabbrev-expand does:
(defun srb-select-line ()
"Select line at point and copy to kill ring."
(interactive)
(copy-region-as-kill (line-beginning-position) (line-end-position)))
A common use case for me is copying somewhat complex shell commands I
keep stored in a file; they are stored as one liners to be easy to copy.
I don't want them to be immediately yanked into the file and for these
cases I don't need the feature of multiple copies via a prefix argument
(though in some documents I often do want multiple copies of a single
line, but usually at different parts of the document, so then just
yanking at the different locations is better than moving the copies).
Steve Berman
On 22.02.2021 21:46, Drew Adams wrote:
> Why on earth is this called `copy-from-above-command'?
>
> "-command"?
>
> Maybe it would help to add a more discoverable alias?
Both good points.
Juri Linkov <juri@linkov.net> writes: > Why there is still no such fundamental command as duplicating the current > line? This command slightly extends the existing copy-from-above-command: I've now added this command to Emacs 29 as `duplicate-line'. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Lars Ingebrigtsen <larsi@gnus.org> writes:
> I've now added this command to Emacs 29 as `duplicate-line'.
Cool! I've had a similar command defined locally since 2015 (which I've
found so useful over time that I've given it a short global keybinding).
I have some suggestions that I think make the command even more useful:
- Making it more DWIM'y by having it duplicate the region instead when
it's active (perhaps giving it a more general name like
`duplicate-thing`, `duplicate-dwim`, or maybe just `duplicate`).
- Having point end up at the duplicated line instead of the original
one, since that's the line you usually want to edit (in my
experience).
- With a prefix argument, comment out the original line/region after
duplicating it. This is perhaps a bit too specialized to be useful in
general compared to the other two suggestions, though I've found it
very useful personally.
Happy to help if any of these sound eligible for inclusion.
Here's my local definition for reference:
(defun duplicate (arg)
"Duplicate the current line, or region if active.
When called with a prefix argument the current line or region is
commented out before it's copied."
(interactive "P")
(setq arg (or arg 1))
(let ((beg (if (region-active-p)
(region-beginning)
(line-beginning-position)))
(end (if (region-active-p)
(region-end)
(line-end-position)))
(point (point)))
(goto-char end)
(let ((to-duplicate (buffer-substring beg end)))
(when (listp arg)
(comment-region beg end)
(setq arg 1))
(dotimes (_ arg)
(end-of-line)
(newline)
(insert to-duplicate)))
(backward-char (- end point))))
Simen Heggestøyl <simenheg@runbox.com> writes: >> I've now added this command to Emacs 29 as `duplicate-line'. > > Cool! I've had a similar command defined locally since 2015 (which I've > found so useful over time that I've given it a short global keybinding). > > I have some suggestions that I think make the command even more useful: > > - Making it more DWIM'y by having it duplicate the region instead when > it's active (perhaps giving it a more general name like > `duplicate-thing`, `duplicate-dwim`, or maybe just `duplicate`). That makes sense, but there are some edge conditions here that the current implementation avoids by using a "line" definition. That is, if we're at the final line in the buffer, and there's no newline at the end, `duplicate-line' will add one. That is, it's really line oriented, and not region oriented, and making it do regions, too, would possibly make it more confusing. Unless we ensure a newline at the end of all the regions we paste in. > - Having point end up at the duplicated line instead of the original > one, since that's the line you usually want to edit (in my > experience). Yes, that's true. > - With a prefix argument, comment out the original line/region after > duplicating it. This is perhaps a bit too specialized to be useful in > general compared to the other two suggestions, though I've found it > very useful personally. I think that sounds a bit too specialised. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
[-- Attachment #1: Type: text/plain, Size: 771 bytes --] > I've now added this command to Emacs 29 as `duplicate-line'. Thank you! There was quite some discussion about generalising the concept last time it came up for discussion, and making it work on the region when active was found to be very useful. It comes quite naturally in use, much like upcase-dwim etc. The attached patch does that. For extra convenience, when the active region is rectangular it is duplicated to the right, since that is what is usually most convenient. There's a few subtleties here: the code takes care to preserve the region because the user may want to press the key again for another copy. (This means that we need to use undo-inhibit-region for undo to work properly.) Do you feel audacious enough for a standard key binding? [-- Attachment #2: duplicate-line-or-region.diff --] [-- Type: application/octet-stream, Size: 2179 bytes --] diff --git a/lisp/misc.el b/lisp/misc.el index 3fb30e5372..d5db0a35ae 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -63,19 +63,51 @@ copy-from-above-command (+ n (point))))))) (insert string))) +(declare-function extract-rectangle-line "rect" (startcol endcol lines)) +(declare-function apply-on-rectangle "rect" (function start end &rest args)) + +(put 'duplicate-line-or-region 'undo-inhibit-region t) + ;;;###autoload -(defun duplicate-line (&optional n) - "Duplicate the current line N times. +(defun duplicate-line-or-region (&optional n) + "Duplicate the current line or region N times. +If the region is inactive, the current line is duplicated. +Otherwise, duplicate the region's contents. The region remains +active afterwards. +If the region is rectangular, duplication is made on its right-hand side. Interactively, N is the prefix numeric argument, and defaults to 1. Also see the `copy-from-above-command' command." (interactive "p") - (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) - (save-excursion - (forward-line 1) - (unless (bolp) - (insert "\n")) - (dotimes (_ n) - (insert line "\n"))))) + (cond + ((bound-and-true-p rectangle-mark-mode) + (require 'rect) + (apply-on-rectangle + (lambda (startcol endcol) + (let ((lines (list nil))) + (extract-rectangle-line startcol endcol lines) + (move-to-column endcol t) + (dotimes (_ n) + (insert (cadr lines))))) + (region-beginning) (region-end)) + (setq deactivate-mark nil)) + ((use-region-p) + (let* ((beg (region-beginning)) + (end (region-end)) + (text (buffer-substring beg end))) + (save-excursion + (goto-char end) + (dotimes (_ n) + (insert text)))) + (setq deactivate-mark nil)) + (t + (let ((line (buffer-substring (line-beginning-position) + (line-end-position)))) + (save-excursion + (forward-line 1) + (unless (bolp) + (insert "\n")) + (dotimes (_ n) + (insert line "\n"))))))) ;; Variation of `zap-to-char'.
> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net> > From: Mattias Engdegård <mattiase@acm.org> > Date: Sat, 18 Jun 2022 20:02:58 +0200 > > -(defun duplicate-line (&optional n) > - "Duplicate the current line N times. > +(defun duplicate-line-or-region (&optional n) > + "Duplicate the current line or region N times. There's no need to include "or region" in the command's name and doc string's first line. We have quite a few commands that are sensitive to the active region, and work on region when it's active. We just mention this in the doc string, and that's that. > +If the region is inactive, the current line is duplicated. Passive tense alert! > +Otherwise, duplicate the region's contents. The region remains > +active afterwards. > +If the region is rectangular, duplication is made on its right-hand side. Another one! Thanks.
Mattias Engdegård <mattiase@acm.org> writes: >> I've now added this command to Emacs 29 as `duplicate-line'. > > Thank you! There was quite some discussion about generalising the > concept last time it came up for discussion, and making it work on the > region when active was found to be very useful. It comes quite > naturally in use, much like upcase-dwim etc. > > The attached patch does that. For extra convenience, when the active > region is rectangular it is duplicated to the right, since that is > what is usually most convenient. Simen proposed something quite similar (added to the CCs), and my only objection was that the semantics of the simpler command is quite clear -- it always creates a new line, even if we're at a final line in a buffer without a newline. When dealing with regions, it's not quite clear what the semantics should be in those corner cases (i.e., regions that doesn't end with a newline)... -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
[-- Attachment #1: Type: text/plain, Size: 502 bytes --] 18 juni 2022 kl. 20.09 skrev Eli Zaretskii <eliz@gnu.org>: > There's no need to include "or region" in the command's name and doc > string's first line. Changed. > Passive tense alert! > Another one! Both changed. Thanks for the comments! The attached patch now handles rectangle duplication better. (Rectangular regions are nice to use but can be surprisingly unpleasant to program with.) That code was moved to rect.el where it probably belongs. There will be tests as well. [-- Attachment #2: duplicate-line.diff --] [-- Type: application/octet-stream, Size: 3144 bytes --] diff --git a/lisp/misc.el b/lisp/misc.el index 3fb30e5372..8a1dd76847 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -63,19 +63,51 @@ copy-from-above-command (+ n (point))))))) (insert string))) +(declare-function rectangle--duplicate-right "rect" (n)) + +;; `duplicate-line' preserves an active region and changes the buffer +;; outside of it: disregard the region when undoing the actions of +;; this command or the undo wouldn't work properly. +(put 'duplicate-line 'undo-inhibit-region t) + ;;;###autoload (defun duplicate-line (&optional n) "Duplicate the current line N times. +If the region is inactive, duplicate the current line. +Otherwise, duplicate the region's contents. The region remains +active afterwards. +If the region is rectangular, duplicate on its right-hand side. Interactively, N is the prefix numeric argument, and defaults to 1. Also see the `copy-from-above-command' command." (interactive "p") - (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) - (save-excursion - (forward-line 1) - (unless (bolp) - (insert "\n")) - (dotimes (_ n) - (insert line "\n"))))) + (cond + ;; Duplicate rectangle. + ((bound-and-true-p rectangle-mark-mode) + (require 'rect) + (rectangle--duplicate-right n) + (setq deactivate-mark nil)) + + ;; Duplicate (contiguous) region. + ((use-region-p) + (let* ((beg (region-beginning)) + (end (region-end)) + (text (buffer-substring beg end))) + (save-excursion + (goto-char end) + (dotimes (_ n) + (insert text)))) + (setq deactivate-mark nil)) + + ;; Duplicate line. + (t + (let ((line (buffer-substring (line-beginning-position) + (line-end-position)))) + (save-excursion + (forward-line 1) + (unless (bolp) + (insert "\n")) + (dotimes (_ n) + (insert line "\n"))))))) ;; Variation of `zap-to-char'. diff --git a/lisp/rect.el b/lisp/rect.el index e717d2ac7e..3e29868b24 100644 --- a/lisp/rect.el +++ b/lisp/rect.el @@ -931,6 +931,30 @@ rectangle--unhighlight-for-redisplay (mapc #'delete-overlay (nthcdr 5 rol)) (setcar (cdr rol) nil))) +(defun rectangle--duplicate-right (n) + "Duplicate the rectangular region N times on the right-hand side." + (let ((cols (rectangle--pos-cols (point) (mark)))) + (apply-on-rectangle + (lambda (startcol endcol) + (let ((lines (list nil))) + (extract-rectangle-line startcol endcol lines) + (move-to-column endcol t) + (dotimes (_ n) + (insert (cadr lines))))) + (region-beginning) (region-end)) + ;; Recompute the rectangle state since the crutches might be outdated. + (let ((p (point)) + (m (mark))) + (rectangle--reset-crutches) + (goto-char m) + (move-to-column (cdr cols) t) + ;(rectangle--col-pos (cdr cols) 'mark) + (set-mark (point)) + (goto-char p) + (move-to-column (car cols) t) + ;(rectangle--col-pos (car cols) 'point) + ))) + (provide 'rect) ;;; rect.el ends here [-- Attachment #3: Type: text/plain, Size: 3 bytes --]
19 juni 2022 kl. 13.43 skrev Lars Ingebrigtsen <larsi@gnus.org>: > Simen proposed something quite similar (added to the CCs), and my only > objection was that the semantics of the simpler command is quite > clear -- it always creates a new line, even if we're at a final line in > a buffer without a newline. Actually shouldn't duplicating such a line add a newline + a copy of the current line with no terminal newline? Right now the copy is always newline-terminated even if the original wasn't, which seems a bit inconsistent. What do you think? > When dealing with regions, it's not quite > clear what the semantics should be in those corner cases (i.e., regions > that doesn't end with a newline)... Not much of a edge case, is it? If you select "bon" and duplicate you end up with "bonbon", as promised. Region-sensitive commands are useful since they multiplex functionality on the same keys without added cognitive load. (It's high time we rebound M-u to upcase-dwim etc.)
Mattias Engdegård <mattiase@acm.org> writes: > Actually shouldn't duplicating such a line add a newline + a copy of > the current line with no terminal newline? Right now the copy is > always newline-terminated even if the original wasn't, which seems a > bit inconsistent. What do you think? No, it's consistent -- it always creates a new line. >> When dealing with regions, it's not quite >> clear what the semantics should be in those corner cases (i.e., regions >> that doesn't end with a newline)... > > Not much of a edge case, is it? If you select "bon" and duplicate you > end up with "bonbon", as promised. It's edgy compared to what it's supposed to be doing -- duplicating lines. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
[-- Attachment #1: Type: text/plain, Size: 717 bytes --] 19 juni 2022 kl. 17.22 skrev Lars Ingebrigtsen <larsi@gnus.org>: > No, it's consistent -- it always creates a new line. Either behaviour can be seen as consistent. I suppose it's a matter of what behaviour we find more convenient. It's expected to be a rare case and I have no strong opinion about it. > It's edgy compared to what it's supposed to be doing -- duplicating > lines. Well, now it does more. Do you mean that you prefer it wouldn't, or that we change the name? I have no strong opinion about the name but it would be a shame to make the command less useful. Here is an updated patch that fixes a bug in the original code (would crash when called without an argument) and adds tests. [-- Attachment #2: 0001-Make-duplicate-line-work-on-regions-bug-46621.patch --] [-- Type: application/octet-stream, Size: 5415 bytes --] From 8f210a9ee0f61c22a2b1996b1b61c7242e2372dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org> Date: Mon, 20 Jun 2022 11:16:26 +0200 Subject: [PATCH] Make duplicate-line work on regions (bug#46621) With an active region, duplicate that region instead of the current line. Rectangular regions are duplicated on the right-hand side. * lisp/rect.el (rectangle--duplicate-right): New. * lisp/misc.el (duplicate-line): Work on regions. Allow calls without an argument. * test/lisp/misc-tests.el (misc--duplicate-line): New test. --- lisp/misc.el | 48 +++++++++++++++++++++++++++++++++++------ lisp/rect.el | 21 ++++++++++++++++++ test/lisp/misc-tests.el | 35 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/lisp/misc.el b/lisp/misc.el index 3fb30e5372..906d6c2012 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -63,19 +63,53 @@ copy-from-above-command (+ n (point))))))) (insert string))) +(declare-function rectangle--duplicate-right "rect" (n)) + +;; `duplicate-line' preserves an active region and changes the buffer +;; outside of it: disregard the region when immediately undoing the +;; actions of this command. +(put 'duplicate-line 'undo-inhibit-region t) + ;;;###autoload (defun duplicate-line (&optional n) "Duplicate the current line N times. +If the region is inactive, duplicate the current line. +Otherwise, duplicate the region's contents. The region remains +active afterwards. +If the region is rectangular, duplicate on its right-hand side. Interactively, N is the prefix numeric argument, and defaults to 1. Also see the `copy-from-above-command' command." (interactive "p") - (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) - (save-excursion - (forward-line 1) - (unless (bolp) - (insert "\n")) - (dotimes (_ n) - (insert line "\n"))))) + (unless n + (setq n 1)) + (cond + ;; Duplicate rectangle. + ((bound-and-true-p rectangle-mark-mode) + (require 'rect) + (rectangle--duplicate-right n) + (setq deactivate-mark nil)) + + ;; Duplicate (contiguous) region. + ((use-region-p) + (let* ((beg (region-beginning)) + (end (region-end)) + (text (buffer-substring beg end))) + (save-excursion + (goto-char end) + (dotimes (_ n) + (insert text)))) + (setq deactivate-mark nil)) + + ;; Duplicate line. + (t + (let ((line (buffer-substring (line-beginning-position) + (line-end-position)))) + (save-excursion + (forward-line 1) + (unless (bolp) + (insert "\n")) + (dotimes (_ n) + (insert line "\n"))))))) ;; Variation of `zap-to-char'. diff --git a/lisp/rect.el b/lisp/rect.el index e717d2ac7e..c41a545e85 100644 --- a/lisp/rect.el +++ b/lisp/rect.el @@ -931,6 +931,27 @@ rectangle--unhighlight-for-redisplay (mapc #'delete-overlay (nthcdr 5 rol)) (setcar (cdr rol) nil))) +(defun rectangle--duplicate-right (n) + "Duplicate the rectangular region N times on the right-hand side." + (let ((cols (rectangle--pos-cols (point) (mark)))) + (apply-on-rectangle + (lambda (startcol endcol) + (let ((lines (list nil))) + (extract-rectangle-line startcol endcol lines) + (move-to-column endcol t) + (dotimes (_ n) + (insert (cadr lines))))) + (region-beginning) (region-end)) + ;; Recompute the rectangle state; no crutches should be needed now. + (let ((p (point)) + (m (mark))) + (rectangle--reset-crutches) + (goto-char m) + (move-to-column (cdr cols) t) + (set-mark (point)) + (goto-char p) + (move-to-column (car cols) t)))) + (provide 'rect) ;;; rect.el ends here diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el index 236223ef49..2036488f13 100644 --- a/test/lisp/misc-tests.el +++ b/test/lisp/misc-tests.el @@ -80,5 +80,40 @@ misc-test-backward-to-word (backward-to-word 3) (should (equal (point) 1)))) +(ert-deftest misc--duplicate-line () + ;; Duplicate a line (twice). + (with-temp-buffer + (insert "abc\ndefg\nh\n") + (goto-char 7) + (duplicate-line 2) + (should (equal (buffer-string) "abc\ndefg\ndefg\ndefg\nh\n")) + (should (equal (point) 7))) + ;; Duplicate a non-terminated line. + (with-temp-buffer + (insert "abc") + (goto-char 2) + (duplicate-line) + (should (equal (buffer-string) "abc\nabc\n")) + (should (equal (point) 2))) + ;; Duplicate a region. + (with-temp-buffer + (insert "abc\ndef\n") + (set-mark 2) + (goto-char 7) + (should (use-region-p)) + (duplicate-line) + (should (equal (buffer-string) "abc\ndebc\ndef\n")) + (should (equal (point) 7))) + ;; Duplicate a rectangular region. + (with-temp-buffer + (insert "x\n>a\n>bcde\n>fg\nyz\n") + (goto-char 4) + (rectangle-mark-mode) + (goto-char 15) + (rectangle-forward-char 1) + (duplicate-line) + (should (equal (buffer-string) "x\n>a a \n>bcdbcde\n>fg fg \nyz\n")) + (should (equal (point) 24)))) + (provide 'misc-tests) ;;; misc-tests.el ends here -- 2.32.0 (Apple Git-132)
[[[ To any NSA and FBI agents reading my email: please consider ]]] [[[ whether defending the US Constitution against all enemies, ]]] [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > > Why there is still no such fundamental command as duplicating the current > > line? This command slightly extends the existing copy-from-above-command: there is nothng "fundamenal" about that operation. It's one special case of a general operation. The traditional way to do it in Emacs is C-p C-a C-k C-k C-y C-y. Every user who can do basic editing in Emacs knows how to do this, and givem how (n)frequent this operation is, that's short enough. -- Dr Richard Stallman (https://stallman.org) Chief GNUisance of the GNU Project (https://gnu.org) Founder, Free Software Foundation (https://fsf.org) Internet Hall-of-Famer (https://internethalloffame.org)
Mattias Engdegård <mattiase@acm.org> writes: >> It's edgy compared to what it's supposed to be doing -- duplicating >> lines. > > Well, now it does more. Do you mean that you prefer it wouldn't, or > that we change the name? > I have no strong opinion about the name but it would be a shame to > make the command less useful. I found the concept of "an easy command to duplicate the current line a number of times" to be slightly useful in general, but I'm not sure about whether extending it to regions makes much sense. If you have a region already, then `M-w C-y' will be more convenient to say, anyway. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
21 juni 2022 kl. 12.35 skrev Lars Ingebrigtsen <larsi@gnus.org>:
> If you have a region already, then `M-w C-y' will be more convenient to say
Two commands are not necessarily more convenient than one command.
There is also the advantage of not disturbing the kill ring.
(And for rectangular regions the benefit of a duplication command is even greater.)
There does not seem to be any significant benefit from omitting the region-sensitive behaviour.
We could add `duplicate-dwim` as a separate command but then there would be no reason to use the neutered variant, would there?
> I found the concept of "an easy command to duplicate the current line a
> number of times" to be slightly useful in general, but I'm not sure
> about whether extending it to regions makes much sense. If you have a
> region already, then `M-w C-y' will be more convenient to say, anyway.
This would also mean that the problem is a missing command that
saves the current line to the kill-ring? If such a command existed,
then duplicating the line would take two keys as well: the first
key to save the current line to the kill-ring, and the second key
to yank it.
Juri Linkov <juri@linkov.net> writes: > This would also mean that the problem is a missing command that > saves the current line to the kill-ring? If such a command existed, > then duplicating the line would take two keys as well: the first > key to save the current line to the kill-ring, and the second key > to yank it. A command to save the current line to the kill ring might be nice (if it settles on some definition of "line"), but it doesn't really offer the convenience. To insert a copy of a region: `M-w C-y'. To insert a copy of the current line with such a command: `NEW-COMMAND C-n' (see if you landed on the next line or whether that took you to the end of the buffer) `RET'/`C-a' `C-y'. I.e., `duplicate-line' offers both a practical and mental simplification over what we have today, but making that command do region stuff doesn't really give anything except muddling up the command semantics. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Mattias Engdegård <mattiase@acm.org> writes: > There does not seem to be any significant benefit from omitting the > region-sensitive behaviour. The benefit of adding the region sensitive behaviour seems even slighter, and the problem is, as I said, that it subverts the (currently) clear semantics the new command has. For instance, if you mark one and a half line, and say `C-u 5 M-x duplicate-line', you'll get something that nobody wants -- ever. There might be some utility if the region version also worked on lines -- that is, it inserts that it only inserts new complete lines. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
>> This would also mean that the problem is a missing command that >> saves the current line to the kill-ring? If such a command existed, >> then duplicating the line would take two keys as well: the first >> key to save the current line to the kill-ring, and the second key >> to yank it. > > A command to save the current line to the kill ring might be nice (if it > settles on some definition of "line"), but it doesn't really offer the > convenience. > > To insert a copy of a region: `M-w C-y'. > > To insert a copy of the current line with such a command: `NEW-COMMAND > C-n' (see if you landed on the next line or whether that took you to the > end of the buffer) `RET'/`C-a' `C-y'. Now I realized what's actually missing is a command `mark-line'. After marking the line it could move point to the beginning of the next line. Then the key sequence would be `mark-line M-w C-y'. And the case of a missing training newline is very rare, so an extra RET is not a problem. > I.e., `duplicate-line' offers both a practical and mental simplification > over what we have today, but making that command do region stuff doesn't > really give anything except muddling up the command semantics. The above suggestion is just an alternative way to do the same. BTW, what do you think about the already suggested leaving point at the end of duplicated lines? This means removing save-excursion and adding backward-char to the end of `duplicate-line' to move point before the last newline.
Juri Linkov <juri@linkov.net> writes: > BTW, what do you think about the already suggested leaving point > at the end of duplicated lines? This means removing save-excursion > and adding backward-char to the end of `duplicate-line' to move point > before the last newline. It was also suggested to leave point at the start of the duplicated lines. I think that makes more sense -- the use case here is to copy lines so that you can start altering them, after all. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
> Now I realized what's actually missing is a command `mark-line'. About a decade ago I added command `mark-line' to my ad hoc library `misc-cmds.el', with this comment: ;; Probably not very useful. And yeah, IMO it's not very useful (for me, at least). > After marking the line it could move point to the > beginning of the next line. FWIW, my version moves to the end of the marked line. IOW, it marks only the line, not its trailing newline. (defun mark-line (&optional arg) "Put mark at end of line, point at beginning. A numeric prefix arg means move forward (backward if negative) that many lines, thus marking a line other than the one point was originally in." (interactive "P") (setq arg (if arg (prefix-numeric-value arg) 0)) (let ((inhibit-field-motion t)) (forward-line arg) (push-mark nil t t) (goto-char (line-end-position)))) > Then the key sequence would be `mark-line M-w C-y'. And the case of > a missing trai[l]ing newline is very rare, so an extra RET is not a > problem. > > > I.e., `duplicate-line' offers both a practical and > > mental simplification over what we have today, Bof. > > but making that command do region stuff doesn't > > really give anything except muddling up the command semantics. > > The above suggestion is just an alternative way to do the same. > > BTW, what do you think about the already suggested leaving point > at the end of duplicated lines? This means removing save-excursion > and adding backward-char to the end of `duplicate-line' to move point > before the last newline. IMO, it's fine to add any commands you like, whatever their general use(ful|less)ness. But please don't succumb to giving them key bindings just because some new contributor requested them. Even if you feel you want to encourage new participants, that's not appropriate. (My impression is that this is in fact sometimes a thing with Emacs dev.) Emacs has gotten along quite well for a very long time without feeling the crying need for a `duplicate-line', a `copy-line' or a `mark-line' command. Maybe ask yourself why. Just imagine that some such request doesn't come from a new contributor - treat it as you would from a longtime participant.
Lars Ingebrigtsen <larsi@gnus.org> writes:
>> BTW, what do you think about the already suggested leaving point
>> at the end of duplicated lines? This means removing save-excursion
>> and adding backward-char to the end of `duplicate-line' to move point
>> before the last newline.
>
> It was also suggested to leave point at the start of the duplicated
> lines. I think that makes more sense -- the use case here is to copy
> lines so that you can start altering them, after all.
Behaviour could be different, depending upon what programming construct
your are in. For example, in C,
#include <a.h>
#include <b.h>
...
if I have to include a new library I’ll go to line-no 2 call
duplicate-line and then I want the point at the end. But in the
following lines, I want the opposite behaviour if I want to declare a
variables of other types.
int a1, b1, c1
float a2, b2, c2
// now I want variables of type char
In this case I want the cursor at beginning.
But I feel that former is more useful i.e. point at the end. Think of
different types of statements in a programming language.
Drew Adams <drew.adams@oracle.com> writes:
> But please don't succumb to giving them key
> bindings just because some new contributor
> requested them. Even if you feel you want
> to encourage new participants, that's not
> appropriate. (My impression is that this is
> in fact sometimes a thing with Emacs dev.)
>
> Emacs has gotten along quite well for a very
> long time without feeling the crying need
> for a `duplicate-line', a `copy-line' or a
> `mark-line' command. Maybe ask yourself why.
>
> Just imagine that some such request doesn't
> come from a new contributor - treat it as
> you would from a longtime participant.
I agree. But please, maintainers, keep the duplicate-line command. :-)
I have started using it 2 days back and I might have used it 100s of
times already. Really useful.
>>> BTW, what do you think about the already suggested leaving point
>>> at the end of duplicated lines? This means removing save-excursion
>>> and adding backward-char to the end of `duplicate-line' to move point
>>> before the last newline.
>>
>> It was also suggested to leave point at the start of the duplicated
>> lines. I think that makes more sense -- the use case here is to copy
>> lines so that you can start altering them, after all.
>
> Behaviour could be different, depending upon what programming construct
> your are in. For example, in C,
>
> #include <a.h>
> #include <b.h>
> ...
>
> if I have to include a new library I’ll go to line-no 2 call
> duplicate-line and then I want the point at the end. But in the
> following lines, I want the opposite behaviour if I want to declare a
> variables of other types.
>
> int a1, b1, c1
> float a2, b2, c2
> // now I want variables of type char
>
> In this case I want the cursor at beginning.
>
> But I feel that former is more useful i.e. point at the end. Think of
> different types of statements in a programming language.
It seems in both cases you expect point to be at the duplicated line,
either at the beginning or the end of the duplicated line. But the
problem is that currently point stays at the original line.
Juri Linkov <juri@linkov.net> writes: > It seems in both cases you expect point to be at the duplicated line, > either at the beginning or the end of the duplicated line. But the > problem is that currently point stays at the original line. Everybody agrees that that should be fixed. I haven't done so yet because people are submitting patches to the function, and I don't want to get in the way of those. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Hello,
On Sat 18 Jun 2022 at 08:02pm +02, Mattias Engdegård wrote:
> Do you feel audacious enough for a standard key binding?
Just to put it out there, if the result of the current discussion is
that point is left at the beginning of the upper of the two lines, then
using it would feel like using C-o, so duplicate-line could go on M-o.
--
Sean Whitton
> > Do you feel audacious enough for a standard key binding?
>
> Just to put it out there, if the result of the current discussion is
> that point is left at the beginning of the upper of the two lines, then
> using it would feel like using C-o, so duplicate-line could go on M-o.
Please don't give this command a default key binding.
There are a zillion commands that deserve a default
binding more than this one does. And nearly all of
those zillion also don't need a default binding.
> Resent-Sender: help-debbugs@gnu.org
> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
> From: Sean Whitton <spwhitton@spwhitton.name>
> Date: Wed, 22 Jun 2022 13:44:31 -0700
>
> Just to put it out there, if the result of the current discussion is
> that point is left at the beginning of the upper of the two lines, then
> using it would feel like using C-o, so duplicate-line could go on M-o.
Which will be one more blow to those who don't want to lose facemenu,
to whom we told just one major release ago they can get the old
behavior back by binding M-o to facemenu-keymap. If we usurp M-o now,
that recipe in NEWS.28 will no longer be completely accurate.
Full disclosure: I'm one of those who happen to like facemenu-keymap
on M-o.
Pankaj Jangid <pankaj@codeisgreat.org> writes: > Behaviour could be different, depending upon what programming construct > your are in. For example, in C, > > #include <a.h> > #include <b.h> > ... > > if I have to include a new library I’ll go to line-no 2 call > duplicate-line and then I want the point at the end. But why do you want point at the end? You want to edit those duplicated lines, presumably. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Lars Ingebrigtsen <larsi@gnus.org> writes:
>> Behaviour could be different, depending upon what programming construct
>> your are in. For example, in C,
>>
>> #include <a.h>
>> #include <b.h>
>> ...
>>
>> if I have to include a new library I’ll go to line-no 2 call
>> duplicate-line and then I want the point at the end.
>
> But why do you want point at the end? You want to edit those duplicated
> lines, presumably.
Yes I want to edit it from the end. Beginning of the statement is mostly
common, I just want to replace "b.h>" with "c.h>".
In some languages (like Java), it is even more required because the class
hierarchy is usually very deep. For example,
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
and now I want to import "Value" or "Required" class from the same
package. So I would like to do,
M-x duplicate-line RET M-<backspace> V a l u e ;
And repeating would be even more easier,
M-x RET M-<backspace> R e q u i r e d ;
If the pointer is at the beginning then it might be slightly
inconvenient.
On Jun 23 2022, Pankaj Jangid wrote:
> Lars Ingebrigtsen <larsi@gnus.org> writes:
>
>>> Behaviour could be different, depending upon what programming construct
>>> your are in. For example, in C,
>>>
>>> #include <a.h>
>>> #include <b.h>
>>> ...
>>>
>>> if I have to include a new library I’ll go to line-no 2 call
>>> duplicate-line and then I want the point at the end.
>>
>> But why do you want point at the end? You want to edit those duplicated
>> lines, presumably.
>
> Yes I want to edit it from the end.
duplicate-line should keep point at the same column.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Pankaj Jangid <pankaj@codeisgreat.org> writes: >> But why do you want point at the end? You want to edit those duplicated >> lines, presumably. > > Yes I want to edit it from the end. Beginning of the statement is mostly > common, I just want to replace "b.h>" with "c.h>". "The end" here would be after the final duplicate line -- not at the end of the final duplicated line, though. So I think that putting it at the start of the duplicated lines would make more sense even here. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Andreas Schwab <schwab@suse.de> writes: > duplicate-line should keep point at the same column. Ah, yes, that might be nice... -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
>>>>> On Thu, 23 Jun 2022 10:17:04 +0200, Andreas Schwab <schwab@suse.de> said:
Andreas> On Jun 23 2022, Pankaj Jangid wrote:
>> Lars Ingebrigtsen <larsi@gnus.org> writes:
>>
>>>> Behaviour could be different, depending upon what programming construct
>>>> your are in. For example, in C,
>>>>
>>>> #include <a.h>
>>>> #include <b.h>
>>>> ...
>>>>
>>>> if I have to include a new library I’ll go to line-no 2 call
>>>> duplicate-line and then I want the point at the end.
>>>
>>> But why do you want point at the end? You want to edit those duplicated
>>> lines, presumably.
>>
>> Yes I want to edit it from the end.
Andreas> duplicate-line should keep point at the same column.
duplicate-line-pre-hook and duplicate-line-post-hook anyone? 😛
Seriously, itʼs a primitive operation, so Andreas is right. Anyone who
wants to customize the behaviour can advise it.
Robert
--
Lars Ingebrigtsen <larsi@gnus.org> writes:
> Pankaj Jangid <pankaj@codeisgreat.org> writes:
>
>>> But why do you want point at the end? You want to edit those duplicated
>>> lines, presumably.
>>
>> Yes I want to edit it from the end. Beginning of the statement is mostly
>> common, I just want to replace "b.h>" with "c.h>".
>
> "The end" here would be after the final duplicate line -- not at the end
> of the final duplicated line, though. So I think that putting it at the
> start of the duplicated lines would make more sense even here.
If it is /after/ the final duplicate line than that is not what I was
vouching for. I wanted it /at/ the end.
Robert Pluim <rpluim@gmail.com> writes:
> Andreas> duplicate-line should keep point at the same column.
>
> duplicate-line-pre-hook and duplicate-line-post-hook anyone? 😛
>
> Seriously, itʼs a primitive operation, so Andreas is right. Anyone who
> wants to customize the behaviour can advise it.
I like Andreas' suggestion also. Now, as I am thinkng, it looks more
natural.
Instead of hooks, how about just a customisation variable?
duplicate-line-point-postion - start, same, end?
Pankaj Jangid <pankaj@codeisgreat.org> writes: >> Seriously, itʼs a primitive operation, so Andreas is right. Anyone who >> wants to customize the behaviour can advise it. > > I like Andreas' suggestion also. Now, as I am thinkng, it looks more > natural. I think we'll go with that, but note that it basically saves you only one single key press -- <down>. > Instead of hooks, how about just a customisation variable? > duplicate-line-point-postion - start, same, end? I doubt that'll find much use. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
22 juni 2022 kl. 09.54 skrev Lars Ingebrigtsen <larsi@gnus.org>: > It was also suggested to leave point at the start of the duplicated > lines. I think that makes more sense -- the use case here is to copy > lines so that you can start altering them, after all. We need experience of how it feels in practice. That is, bind the command to a convenient key in your init.el and try remember to use it while editing. Note where it works as desired and where not. Some of what I found: * Having the cursor remain in the same column is very useful as it's usually near the spot to be edited in the original or copied line. Automatically moving it to the beginning or end of the line would make it worse. * Whether it is better to keep the cursor on the first line (as if duplicating downwards) or the last line (as if duplicating upwards) is less clear. It basically comes down to whether it is more common to want a similar but different line above or below the original line. I weakly favour the current design because it generalises better and it's slightly more convenient to edit a sequence of lines top-down than bottom-up. * A single-key binding (like H-y but not C-x y) makes quite a difference because that way I can quickly stutter out copies as needed without having to plan ahead and use prefix arguments. * Rectangle duplication is very useful when editing tables or code with similar structure. Compared to copy-paste, it saves a lot of cursor movement and permits immediate repetition if more than one copy is required. I would be very interested in your own experience (much more than anyone's theoretical speculation). > The benefit of adding the region sensitive behaviour seems even > slighter, and the problem is, as I said, that it subverts the > (currently) clear semantics the new command has. It's not an unnatural combination; several other editors have similar commands. Moreover, even if you don't find the region-sensitive behaviour, others do -- for rectangular regions in particular. Nobody is going to complain that there are functions in Emacs that they don't care to use, especially when they don't take up extra keybindings.
Mattias Engdegård <mattiase@acm.org> writes: > * Having the cursor remain in the same column is very useful as it's > usually near the spot to be edited in the original or copied > line. Automatically moving it to the beginning or end of the line > would make it worse. [...] > * A single-key binding (like H-y but not C-x y) makes quite a > difference because that way I can quickly stutter out copies as needed > without having to plan ahead and use prefix arguments. I think that means that it might make sense to keep the command as is (point movement wise). I.e., if we move point to the duplicated line, then hitting `H-y' a whole bunch of times would leave point at the final line. > Moreover, even if you don't find the region-sensitive behaviour, > others do -- for rectangular regions in particular. Nobody is going to > complain that there are functions in Emacs that they don't care to > use, especially when they don't take up extra keybindings. If we decide to move to the duplicated line, but keep the same column -- then that makes no sense in a region-sensitive context at all. If you mark a word and hit `H-y', then there's no way to keep the "current column". Unless the region commands are also line-based, so the word is copied to a new line on its own, then you could keep to the same "column" in the word. In short: It makes no sense to mash up these two totally different things into one command, and people do complain about commands that make no sense. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
> Please don't give this command a default key binding.
>
> There are a zillion commands that deserve a default
> binding more than this one does. And nearly all of
> those zillion also don't need a default binding.
There is are default bindings for transpose-lines and for
count-lines-page. Neither of those seems particularly useful.
Maybe there could be a prefix map for "line commands". Something like
ctl-x-r-map for rectangle commands. Perhaps ctl-x-l-map.
Helmut
> From: Helmut Eller <eller.helmut@gmail.com>
> Date: Thu, 23 Jun 2022 17:47:18 +0200
>
> > Please don't give this command a default key binding.
> >
> > There are a zillion commands that deserve a default
> > binding more than this one does. And nearly all of
> > those zillion also don't need a default binding.
>
> There is are default bindings for transpose-lines and for
> count-lines-page. Neither of those seems particularly useful.
I use both all the time, so they are definitely very useful to me.
Hello,
On Thu 23 Jun 2022 at 08:47am +03, Eli Zaretskii wrote:
>> Resent-Sender: help-debbugs@gnu.org
>> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
>> From: Sean Whitton <spwhitton@spwhitton.name>
>> Date: Wed, 22 Jun 2022 13:44:31 -0700
>>
>> Just to put it out there, if the result of the current discussion is
>> that point is left at the beginning of the upper of the two lines, then
>> using it would feel like using C-o, so duplicate-line could go on M-o.
>
> Which will be one more blow to those who don't want to lose facemenu,
> to whom we told just one major release ago they can get the old
> behavior back by binding M-o to facemenu-keymap. If we usurp M-o now,
> that recipe in NEWS.28 will no longer be completely accurate.
>
> Full disclosure: I'm one of those who happen to like facemenu-keymap
> on M-o.
Maybe it would be good to add M-o to the list of keys explicitly
reserved to end users, in that case?
--
Sean Whitton
> We need experience of how it feels in practice. That is, bind the > command to a convenient key in your init.el and try remember to use it > while editing. Note where it works as desired and where not. > > Some of what I found: > > * Having the cursor remain in the same column is very useful as it's > usually near the spot to be edited in the original or copied line. > Automatically moving it to the beginning or end of the line would make > it worse. I agree that keeping the same column would be more useful. > * Whether it is better to keep the cursor on the first line (as if > duplicating downwards) or the last line (as if duplicating upwards) is less > clear. It basically comes down to whether it is more common to want > a similar but different line above or below the original line. I weakly > favour the current design because it generalises better and it's slightly > more convenient to edit a sequence of lines top-down than bottom-up. Usually I duplicate only 1 line, and in 100% of cases the cursor needs to be on the copied line to start editing it. But when duplicating more lines with a prefix arg, often it's expected to have the cursor on the top copied line to start editing copied lines top-down. I wonder if this is a common use case. > * A single-key binding (like H-y but not C-x y) makes quite > a difference because that way I can quickly stutter out copies as > needed without having to plan ahead and use prefix arguments. I don't believe everyone would agree on such short keys. Maybe better to try finding a key in the 'C-x x' keymap (that already contains a line-related binding 'C-x x t' `toggle-truncate-lines'). > * Rectangle duplication is very useful when editing tables or code > with similar structure. Compared to copy-paste, it saves a lot of > cursor movement and permits immediate repetition if more than one copy > is required. Shouldn't rectangle command be on the 'C-x r' keymap? There are already copy-rectangle-as-kill and yank-rectangle. OTOH, it seems 'M-w C-y' already can duplicate rectangle regions?
Hello,
On Thu 23 Jun 2022 at 10:00am -07, Sean Whitton wrote:
> Hello,
>
> On Thu 23 Jun 2022 at 08:47am +03, Eli Zaretskii wrote:
>
>>> Resent-Sender: help-debbugs@gnu.org
>>> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
>>> From: Sean Whitton <spwhitton@spwhitton.name>
>>> Date: Wed, 22 Jun 2022 13:44:31 -0700
>>>
>>> Just to put it out there, if the result of the current discussion is
>>> that point is left at the beginning of the upper of the two lines, then
>>> using it would feel like using C-o, so duplicate-line could go on M-o.
>>
>> Which will be one more blow to those who don't want to lose facemenu,
>> to whom we told just one major release ago they can get the old
>> behavior back by binding M-o to facemenu-keymap. If we usurp M-o now,
>> that recipe in NEWS.28 will no longer be completely accurate.
>>
>> Full disclosure: I'm one of those who happen to like facemenu-keymap
>> on M-o.
>
> Maybe it would be good to add M-o to the list of keys explicitly
> reserved to end users, in that case?
Sorry, re-reading, I think you're saying you think it should remain
unbound for longer but not necessarily indefinitely. In which case it
doesn't make sense to add it to the keybinding conventions.
--
Sean Whitton
> > Please don't give this command a default key binding.
> >
> > There are a zillion commands that deserve a default
> > binding more than this one does. And nearly all of
> > those zillion also don't need a default binding.
>
> There is are default bindings for transpose-lines and for
> count-lines-page. Neither of those seems particularly useful.
>
> Maybe there could be a prefix map for "line commands". Something like
> ctl-x-r-map for rectangle commands. Perhaps ctl-x-l-map.
My suggestion, if some people here are intent
on adding new default key bindings, to _not_
discuss and decide that in a bug thread.
Instead, please propose whatever you want on
emacs-devel@gnu.org. New default key bindings
deserve discussion/review by a wider audience
than just whoever might be following some bug
thread about the introduction of a new command.
A second suggestion is that a new key binding
not be proposed at all for a new command. In
general, at least.
Instead, wait a while, for _users_ to try the
new command and maybe bind it to different keys.
User input on their experience with commands
and keys is helpful in deciding what should
happen by default.
In general, it's not a good idea to be too eager
to add new default key bindings. Especially
without a basis in real user experience.
> > * A single-key binding (like H-y but not C-x y) makes quite
> > a difference because that way I can quickly stutter out copies as
> > needed without having to plan ahead and use prefix arguments.
>
> I don't believe everyone would agree on such short keys.
> Maybe better to try finding a key in the 'C-x x' keymap
> (that already contains a line-related binding 'C-x x t'
> `toggle-truncate-lines').
Please take all proposals of new default key bindings
to emacs-devel.
And I'd suggest not making any suggestions of new
bindings for _new_ commands. That's premature UI
"optimization".
> From: Sean Whitton <spwhitton@spwhitton.name>
> Cc: mattiase@acm.org, larsi@gnus.org, 46621@debbugs.gnu.org, juri@linkov.net
> Date: Thu, 23 Jun 2022 10:00:05 -0700
>
> Hello,
>
> On Thu 23 Jun 2022 at 08:47am +03, Eli Zaretskii wrote:
>
> >> Resent-Sender: help-debbugs@gnu.org
> >> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
> >> From: Sean Whitton <spwhitton@spwhitton.name>
> >> Date: Wed, 22 Jun 2022 13:44:31 -0700
> >>
> >> Just to put it out there, if the result of the current discussion is
> >> that point is left at the beginning of the upper of the two lines, then
> >> using it would feel like using C-o, so duplicate-line could go on M-o.
> >
> > Which will be one more blow to those who don't want to lose facemenu,
> > to whom we told just one major release ago they can get the old
> > behavior back by binding M-o to facemenu-keymap. If we usurp M-o now,
> > that recipe in NEWS.28 will no longer be completely accurate.
> >
> > Full disclosure: I'm one of those who happen to like facemenu-keymap
> > on M-o.
>
> Maybe it would be good to add M-o to the list of keys explicitly
> reserved to end users, in that case?
I won't mind.
23 juni 2022 kl. 17.20 skrev Lars Ingebrigtsen <larsi@gnus.org>: > I think that means that it might make sense to keep the command as is > (point movement wise). I.e., if we move point to the duplicated line, > then hitting `H-y' a whole bunch of times would leave point at the final > line. Right. Again, it is slightly more consistent to have it duplicate "below" than "above" so I weakly favour this way of working, but don't take my word for it -- try it out in anger. > If we decide to move to the duplicated line, but keep the same column -- > then that makes no sense in a region-sensitive context at all. If you > mark a word and hit `H-y', then there's no way to keep the "current > column". That's unavoidable because Emacs's region concept prevents the cursor from moving independently of the selection. (Same goes for most other modern editors although they use a slightly different selection paradigm.) In no way does this diminish the utility of the command in either of its modes of usage. > It makes no sense to mash up these two totally different > things into one command, and people do complain about commands that make > no sense. But the semantics do make sense -- let's not look for problems that don't exist. It's like `upcase-dwim`: without an active region it acts on the current word, which is the most practical unit for that operation. If it helps, call the new command `duplicate-dwim` or just `duplicate`. The user who only uses it to duplicate lines is unlikely to be disturbed by its other ways of functioning.
23 juni 2022 kl. 19.35 skrev Juri Linkov <juri@linkov.net>: > Usually I duplicate only 1 line, and in 100% of cases the cursor needs > to be on the copied line to start editing it. But when duplicating > more lines with a prefix arg, often it's expected to have the cursor > on the top copied line to start editing copied lines top-down. > I wonder if this is a common use case. If only one duplicate was made then perhaps it doesn't matter that much if the cursor has to be moved down one step before editing? (I don't find it to be 100 % of the cases at all; sometimes I want the modified line to be above the original line, sometimes below.) >> * A single-key binding (like H-y but not C-x y) makes quite >> a difference because that way I can quickly stutter out copies as >> needed without having to plan ahead and use prefix arguments. > > I don't believe everyone would agree on such short keys. Quite the contrary, they definitely would! What they wouldn't agree on is what pre-existing binding to repurpose. Fortunately there are still a few single-key bindings available. > Maybe better to try finding a key in the 'C-x x' keymap > (that already contains a line-related binding 'C-x x t' > `toggle-truncate-lines'). Unfortunately that removes some of the convenience that the command would bring. I can't see anyone typing `C-x x d` (for example) 3 times in a row to get 3 copies, much less 7 times. >> * Rectangle duplication is very useful when editing tables or code >> with similar structure. Compared to copy-paste, it saves a lot of >> cursor movement and permits immediate repetition if more than one copy >> is required. > > Shouldn't rectangle command be on the 'C-x r' keymap? No, no special binding should be necessary. That's the point. (Several commands work specially on an active rectangle.) > There are already copy-rectangle-as-kill and yank-rectangle. > OTOH, it seems 'M-w C-y' already can duplicate rectangle > regions? Not nearly as conveniently. Try it and you'll see. - You can make another copy immediately without having to move the cursor, just by pressing the key again. - You keep the marked rectangle for any operation (cut, copy, delete, etc). - You keep the kill-ring unmodified for your own purposes.
> > I don't believe everyone would agree on such short keys.
>
> Quite the contrary, they definitely would! What they wouldn't agree on
> is what pre-existing binding to repurpose.
> Fortunately there are still a few single-key bindings available.
>
> > Maybe better to try finding a key in the 'C-x x' keymap
> > (that already contains a line-related binding 'C-x x t'
> > `toggle-truncate-lines').
>
> Unfortunately that removes some of the convenience that the command
> would bring. I can't see anyone typing `C-x x d` (for example) 3 times
> in a row to get 3 copies, much less 7 times.
FWIW, I don't agree that _any_ keys should be bound
by default for such a command.
Do not add a new command and immediately give it a
default key binding. That makes little sense.
Let user experience guide spending/wasting default
keys. Users can bind the command to any key they
like. If it becomes super popular, and if there are
good reasons at that point to give it a default key,
then you can take into account the keys that users
at that point say they like for it.
Emacs has survived well for 40 years without such a
command. Just because someone asks for it now is
not a reason that it deserves a default key binding.
There are tons of keys that deserve bindings before
this one does.
Binding this new command to a default key is just
irrational exuberance.
>> Maybe better to try finding a key in the 'C-x x' keymap
>> (that already contains a line-related binding 'C-x x t'
>> `toggle-truncate-lines').
>
> Unfortunately that removes some of the convenience that the command
> would bring. I can't see anyone typing `C-x x d` (for example) 3
> times in a row to get 3 copies, much less 7 times.
But it accepts a prefix arg, so a shorter key sequence is possible:
`C-3 C-x x d`.
27 juni 2022 kl. 21.40 skrev Juri Linkov <juri@linkov.net>:
>> Unfortunately that removes some of the convenience that the command
>> would bring. I can't see anyone typing `C-x x d` (for example) 3
>> times in a row to get 3 copies, much less 7 times.
>
> But it accepts a prefix arg, so a shorter key sequence is possible:
> `C-3 C-x x d`.
That's not nearly as useful: it forces you to plan ahead and know the exact number in advance.
With a single keybinding, you can duplicate once, visually confirm that this is what you want to do, and keep duplicating (possibly even holding the key down to repeat!) until you have the number of copies you want. If you go too far, just undo. In other words, it behaves just like any basic text-editing feature. And all of this is available, with exactly the same key, for regions and rectangles!
None of that is possible with a multi-key binding. If you made too many copies you have to erase them by hand, or undo and restart the process with a new prefix number. All of this adds cognitive load, and each attempt requires a series of keypresses.
(Not all commands benefit equally from having a single-key binding, of course. For example, it would not do much to `kill-buffer`.)
> With a single keybinding, you can duplicate once, visually confirm
> that this is what you want to do, and keep duplicating (possibly even
> holding the key down to repeat!) until you have the number of copies
> you want. If you go too far, just undo. In other words, it behaves
> just like any basic text-editing feature. And all of this is
> available, with exactly the same key, for regions and rectangles!
>
> None of that is possible with a multi-key binding. If you made too
> many copies you have to erase them by hand, or undo and restart the
> process with a new prefix number. All of this adds cognitive load, and
> each attempt requires a series of keypresses.
For this use case 'repeat' seems quite usable:
M-x copy-line C-x z z z z z
or whatever number of zs you need.
Helmut
> > > In emacs terminology it's not copying the text > > > (like to the kill-ring) but inserting or yanking > > > it into the buffer (just not from the kill-ring > > > but from the previous line). It seems closer in > > > concept to how dabbrev and hippie use the term > > > "expand". This is important, IMO. The name is awful - not helpful. > > Why on earth is this called `copy-from-above-command'? > > > > "-command"? > > > > Maybe it would help to add a more discoverable alias? > > Both good points. The command inserts chars from the previous line at point. By default it inserts all of the text of the previous line, starting just above point. Can we please rename this poorly named command? E.g. defalias a new name and deprecate the old one. Do I need to create a separate bug / enhancement request for this, or could it be taken care of in this thread? Maybe a name such as `insert-from-previous-line'? ___ `yank' isn't appropriate in the name, because the `kill-ring' isn't involved. `insert' is pretty good, though it might not be super helpful for discovery. `duplicate' could maybe be used in the name, but I'm not sure how. The name shouldn't include both `duplicate' and `line', as that would be misleading.
Hello Lars,
On Thu 23 Jun 2022 at 09:31pm +03, Eli Zaretskii wrote:
>> From: Sean Whitton <spwhitton@spwhitton.name>
>> Cc: mattiase@acm.org, larsi@gnus.org, 46621@debbugs.gnu.org, juri@linkov.net
>> Date: Thu, 23 Jun 2022 10:00:05 -0700
>>
>> Hello,
>>
>> On Thu 23 Jun 2022 at 08:47am +03, Eli Zaretskii wrote:
>>
>> >> Resent-Sender: help-debbugs@gnu.org
>> >> Cc: 46621@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
>> >> From: Sean Whitton <spwhitton@spwhitton.name>
>> >> Date: Wed, 22 Jun 2022 13:44:31 -0700
>> >>
>> >> Just to put it out there, if the result of the current discussion is
>> >> that point is left at the beginning of the upper of the two lines, then
>> >> using it would feel like using C-o, so duplicate-line could go on M-o.
>> >
>> > Which will be one more blow to those who don't want to lose facemenu,
>> > to whom we told just one major release ago they can get the old
>> > behavior back by binding M-o to facemenu-keymap. If we usurp M-o now,
>> > that recipe in NEWS.28 will no longer be completely accurate.
>> >
>> > Full disclosure: I'm one of those who happen to like facemenu-keymap
>> > on M-o.
>>
>> Maybe it would be good to add M-o to the list of keys explicitly
>> reserved to end users, in that case?
>
> I won't mind.
Do you have any thoughts on this, Lars? I asked you about this shortly
after M-o was unbound, and you said we should wait and see, but as it's
been a year, I wanted to ask again.
I don't especially want to push for M-o to be reserved to end users
myself, but if it is already de facto reserved, I think a lot of people
would be grateful to be given a green light to put something there and
have the confidence it won't ever clash with something useful from
upstream.
--
Sean Whitton
Sean Whitton <spwhitton@spwhitton.name> writes: > I don't especially want to push for M-o to be reserved to end users > myself, but if it is already de facto reserved, I think a lot of people > would be grateful to be given a green light to put something there and > have the confidence it won't ever clash with something useful from > upstream. I'm not sure, actually. If we come up with a super important new command that should be a one keystroke long, it'd be nice to have somewhere to put it. (And `copy-line' is definitely not such a command.) -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
Hello,
On Fri 01 Jul 2022 at 11:27AM +02, Lars Ingebrigtsen wrote:
> Sean Whitton <spwhitton@spwhitton.name> writes:
>
>> I don't especially want to push for M-o to be reserved to end users
>> myself, but if it is already de facto reserved, I think a lot of people
>> would be grateful to be given a green light to put something there and
>> have the confidence it won't ever clash with something useful from
>> upstream.
>
> I'm not sure, actually. If we come up with a super important new
> command that should be a one keystroke long, it'd be nice to have
> somewhere to put it. (And `copy-line' is definitely not such a
> command.)
Makes sense to me.
--
Sean Whitton
[-- Attachment #1: Type: text/plain, Size: 152 bytes --] Here is an updated patch. It sounded like Eli was largely happy with it but Lars wanted a change of name? I don't mind either, but please do tell. [-- Attachment #2: 0001-Make-duplicate-line-work-on-regions-bug-46621.patch --] [-- Type: application/octet-stream, Size: 6260 bytes --] From aa0d3d5b1eadbc7adcf9d12461c5855a6847730a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org> Date: Mon, 20 Jun 2022 11:16:26 +0200 Subject: [PATCH] Make duplicate-line work on regions (bug#46621) With an active region, duplicate that region instead of the current line. Rectangular regions are duplicated on the right-hand side. The region remains active afterwards, to facilitate further duplication or other operations on the same text. * lisp/rect.el (rectangle--duplicate-right): New. * lisp/misc.el (duplicate-line): Work on regions. * test/lisp/misc-tests.el (misc--duplicate-line): Add tests. --- etc/NEWS | 2 ++ lisp/misc.el | 44 ++++++++++++++++++++++++++++++++++------- lisp/rect.el | 21 ++++++++++++++++++++ test/lisp/misc-tests.el | 32 +++++++++++++++++++++++++++++- 4 files changed, 91 insertions(+), 8 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 3d679fdec6..1b9d690e92 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -372,6 +372,8 @@ between these modes while the user is inputting a command by hitting --- ** New command 'duplicate-line'. This command duplicates the current line the specified number of times. +When the region is active, the command duplicates that region instead, +on the right-hand side if the region is rectangular. --- ** Files with the '.eld' extension are now visited in 'lisp-data-mode'. diff --git a/lisp/misc.el b/lisp/misc.el index 8a01b51c6d..80ba1517c8 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -63,21 +63,51 @@ copy-from-above-command (+ n (point))))))) (insert string))) +(declare-function rectangle--duplicate-right "rect" (n)) + +;; `duplicate-line' preserves an active region and changes the buffer +;; outside of it: disregard the region when immediately undoing the +;; actions of this command. +(put 'duplicate-line 'undo-inhibit-region t) + ;;;###autoload (defun duplicate-line (&optional n) "Duplicate the current line N times. +If the region is inactive, duplicate the current line. +Otherwise, duplicate the region's contents. The region remains active. +If the region is rectangular, duplicate on its right-hand side. Interactively, N is the prefix numeric argument, and defaults to 1. Also see the `copy-from-above-command' command." (interactive "p") (unless n (setq n 1)) - (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) - (save-excursion - (forward-line 1) - (unless (bolp) - (insert "\n")) - (dotimes (_ n) - (insert line "\n"))))) + (cond + ;; Duplicate rectangle. + ((bound-and-true-p rectangle-mark-mode) + (rectangle--duplicate-right n) + (setq deactivate-mark nil)) + + ;; Duplicate (contiguous) region. + ((use-region-p) + (let* ((beg (region-beginning)) + (end (region-end)) + (text (buffer-substring beg end))) + (save-excursion + (goto-char end) + (dotimes (_ n) + (insert text)))) + (setq deactivate-mark nil)) + + ;; Duplicate line. + (t + (let ((line (buffer-substring (line-beginning-position) + (line-end-position)))) + (save-excursion + (forward-line 1) + (unless (bolp) + (insert "\n")) + (dotimes (_ n) + (insert line "\n"))))))) ;; Variation of `zap-to-char'. diff --git a/lisp/rect.el b/lisp/rect.el index e717d2ac7e..c41a545e85 100644 --- a/lisp/rect.el +++ b/lisp/rect.el @@ -931,6 +931,27 @@ rectangle--unhighlight-for-redisplay (mapc #'delete-overlay (nthcdr 5 rol)) (setcar (cdr rol) nil))) +(defun rectangle--duplicate-right (n) + "Duplicate the rectangular region N times on the right-hand side." + (let ((cols (rectangle--pos-cols (point) (mark)))) + (apply-on-rectangle + (lambda (startcol endcol) + (let ((lines (list nil))) + (extract-rectangle-line startcol endcol lines) + (move-to-column endcol t) + (dotimes (_ n) + (insert (cadr lines))))) + (region-beginning) (region-end)) + ;; Recompute the rectangle state; no crutches should be needed now. + (let ((p (point)) + (m (mark))) + (rectangle--reset-crutches) + (goto-char m) + (move-to-column (cdr cols) t) + (set-mark (point)) + (goto-char p) + (move-to-column (car cols) t)))) + (provide 'rect) ;;; rect.el ends here diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el index a56feaa049..83f82d0554 100644 --- a/test/lisp/misc-tests.el +++ b/test/lisp/misc-tests.el @@ -80,6 +80,8 @@ misc-test-backward-to-word (backward-to-word 3) (should (equal (point) 1)))) +(require 'rect) + (ert-deftest misc--duplicate-line () ;; Duplicate a line (twice). (with-temp-buffer @@ -88,13 +90,41 @@ misc--duplicate-line (duplicate-line 2) (should (equal (buffer-string) "abc\ndefg\ndefg\ndefg\nh\n")) (should (equal (point) 7))) + ;; Duplicate a non-terminated line. (with-temp-buffer (insert "abc") (goto-char 2) (duplicate-line) (should (equal (buffer-string) "abc\nabc\n")) - (should (equal (point) 2)))) + (should (equal (point) 2))) + + ;; Duplicate a region. + (with-temp-buffer + (insert "abc\ndef\n") + (set-mark 2) + (goto-char 7) + (transient-mark-mode) + (should (use-region-p)) + (duplicate-line) + (should (equal (buffer-string) "abc\ndebc\ndef\n")) + (should (equal (point) 7)) + (should (region-active-p)) + (should (equal (mark) 2))) + + ;; Duplicate a rectangular region. + (with-temp-buffer + (insert "x\n>a\n>bcde\n>fg\nyz\n") + (goto-char 4) + (rectangle-mark-mode) + (goto-char 15) + (rectangle-forward-char 1) + (duplicate-line) + (should (equal (buffer-string) "x\n>a a \n>bcdbcde\n>fg fg \nyz\n")) + (should (equal (point) 24)) + (should (region-active-p)) + (should rectangle-mark-mode) + (should (equal (mark) 4)))) (provide 'misc-tests) ;;; misc-tests.el ends here -- 2.32.0 (Apple Git-132)
Mattias Engdegård <mattiase@acm.org> writes:
> Here is an updated patch. It sounded like Eli was largely happy with
> it but Lars wanted a change of name? I don't mind either, but please
> do tell.
I feel that duplicate-line and duplicate-region should be separate
commands for the sake of semantics.
May be that we implement duplicate-region as more generic and
duplicate-line as a wrapper around it and just pass the line as
argument. If we do that then users are not required to bind two separate
keys for these. Binding with the generic command will serve the
purpose. And users who prefer to call using M-x can still have the right
semantics.
reopen 46621 stop Let's keep it open until completely done.
Mattias Engdegård <mattiase@acm.org> writes: > Let's keep it open until completely done. As I've said several times now, from my point of view the command is fine as is. I understand that you want to add unrelated functionality to this conceptually simple command (and functionality that's already available much easier via the standard kill/yank commands), but I don't agree with that. So I'm re-closing this bug report. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
5 juli 2022 kl. 18.52 skrev Lars Ingebrigtsen <larsi@gnus.org>:
> As I've said several times now, from my point of view the command is
> fine as is.
We are talking past each other. I'm perfectly happy to keep duplicate-line exactly what you committed; we can make a new command with the new features. I'll open a new bug for it.
>> duplicate-line should keep point at the same column. > > Ah, yes, that might be nice... Here is the patch that does this. So if you have foo 1 bar and need to get foo 1 bar foo 2 bar foo 3 bar foo 4 bar foo 5 bar it requires typing the minimal number of keys - move point to the column with 1, and type: C-u <copy-line> 2 <down> 3 <down> 4 <down> 5 <down> ``` diff --git a/lisp/misc.el b/lisp/misc.el index 28c5d6e07f..57cf8c59ed 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -71,13 +71,15 @@ duplicate-line (interactive "p") (unless n (setq n 1)) - (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) + (let ((line (buffer-substring (line-beginning-position) (line-end-position))) + (column (current-column))) + (forward-line 1) + (unless (bolp) + (insert "\n")) (save-excursion - (forward-line 1) - (unless (bolp) - (insert "\n")) (dotimes (_ n) - (insert line "\n"))))) + (insert line "\n"))) + (move-to-column column))) ;; Variation of `zap-to-char'. ```
Juri Linkov <juri@linkov.net> writes: >>> duplicate-line should keep point at the same column. >> >> Ah, yes, that might be nice... > > Here is the patch that does this. So if you have > > foo 1 bar > > and need to get > > foo 1 bar > foo 2 bar > foo 3 bar > foo 4 bar > foo 5 bar > > it requires typing the minimal number of keys - > move point to the column with 1, and type: > > C-u <copy-line> 2 <down> 3 <down> 4 <down> 5 <down> I think I've changed my mind about moving point -- leaving it where it is makes sense if you've bound `duplicate-line' to a single key, and then you'd say, for instance, `M-o' `M-o' `M-o' `M-o'. And then you'd not want point to move, but be left where it is, so you can start editing by hitting <down>. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
>> Here is the patch that does this. So if you have
>>
>> foo 1 bar
>>
>> and need to get
>>
>> foo 1 bar
>> foo 2 bar
>> foo 3 bar
>> foo 4 bar
>> foo 5 bar
>>
>> it requires typing the minimal number of keys -
>> move point to the column with 1, and type:
>>
>> C-u <copy-line> 2 <down> 3 <down> 4 <down> 5 <down>
>
> I think I've changed my mind about moving point -- leaving it where it
> is makes sense if you've bound `duplicate-line' to a single key, and
> then you'd say, for instance, `M-o' `M-o' `M-o' `M-o'. And then you'd
> not want point to move, but be left where it is, so you can start
> editing by hitting <down>.
This is optimized for a rare workflow. Why would anyone want
to type a long key sequence `M-o M-o M-o M-o ... <down>' when
it's much easier to type just `M-4 M-o' and immediately start editing.
Juri Linkov <juri@linkov.net> writes: > This is optimized for a rare workflow. Why would anyone want > to type a long key sequence `M-o M-o M-o M-o ... <down>' when > it's much easier to type just `M-4 M-o' and immediately start editing. I don't think it's rare -- I think many people rarely say `C-u 3' or `M-4' and just lean on the keyboard instead. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
>> This is optimized for a rare workflow. Why would anyone want
>> to type a long key sequence `M-o M-o M-o M-o ... <down>' when
>> it's much easier to type just `M-4 M-o' and immediately start editing.
>
> I don't think it's rare -- I think many people rarely say `C-u 3' or
> `M-4' and just lean on the keyboard instead.
But there is no one-key binding for this command.
Juri Linkov <juri@linkov.net> writes: > But there is no one-key binding for this command. People may bind it to whatever they choose, like `H-c', if they like the command. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
>> But there is no one-key binding for this command.
>
> People may bind it to whatever they choose, like `H-c', if they like the
> command.
Or copy and edit the whole command in their init files
when they don't like the default implementation 😉.
Juri Linkov <juri@linkov.net> writes: > Or copy and edit the whole command in their init files > when they don't like the default implementation 😉. Sure. But we do add commands without default bindings with the expectation that if somebody finds it useful, they'll put it somewhere convenient. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no
>> But there is no one-key binding for this command.
>
> People may bind it to whatever they choose, like `H-c', if they like the
> command.
Why would one want to sacrifice a short keybinding when
it's easier to use a keybinding of any length to copy the
current line, then use C-y C-y C-y ... Also it solves
the main discrepancy of this feature request - whether
to keep point unmoved or to move it on the copied line:
C-y supports the prefix arg `C-u C-y', problem solved.
On Jul 14 2022, Juri Linkov wrote:
> Why would one want to sacrifice a short keybinding when
> it's easier to use a keybinding of any length to copy the
> current line, then use C-y C-y C-y ...
C-y requires moving point to bol, which is the main reason I wrote my
own version of duplicate-line.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
>> Why would one want to sacrifice a short keybinding when
>> it's easier to use a keybinding of any length to copy the
>> current line, then use C-y C-y C-y ...
>
> C-y requires moving point to bol, which is the main reason I wrote
> my own version of duplicate-line.
And I use my own version of duplicate-line that moves point
to the copied line. This means that adding duplicate-line
to misc.el requested by this feature request was a failure.