How do I duplicate a whole line in Emacs?

前端 未结 30 969
时光取名叫无心
时光取名叫无心 2020-12-04 05:20

I saw this same question for VIM and it has been something that I myself wanted to know how to do for Emacs. In ReSharper I use CTRL-D for this action. What is the least num

相关标签:
30条回答
  • 2020-12-04 05:37

    When called interactively with no active region, COPY (M-w) a single line instead :

    (defadvice kill-ring-save (before slick-copy activate compile)
      "When called interactively with no active region, COPY a single line instead."
      (interactive
       (if mark-active (list (region-beginning) (region-end))
         (message "Copied line")
         (list (line-beginning-position)
               (line-beginning-position 2)))))
    

    When called interactively with no active region, KILL (C-w) a single line instead.

    (defadvice kill-region (before slick-cut activate compile)
      "When called interactively with no active region, KILL a single line instead."
      (interactive
       (if mark-active (list (region-beginning) (region-end))
         (message "Killed line")
         (list (line-beginning-position)
               (line-beginning-position 2)))))
    

    Also, on a related note:

    (defun move-line-up ()
      "Move up the current line."
      (interactive)
      (transpose-lines 1)
      (forward-line -2)
      (indent-according-to-mode))
    
    (defun move-line-down ()
      "Move down the current line."
      (interactive)
      (forward-line 1)
      (transpose-lines 1)
      (forward-line -1)
      (indent-according-to-mode))
    
    (global-set-key [(meta shift up)]  'move-line-up)
    (global-set-key [(meta shift down)]  'move-line-down)
    
    0 讨论(0)
  • 2020-12-04 05:38

    I cannot believe all these complicated solutions. This is two keystrokes:

    <C-S-backspace> runs the command kill-whole-line

    C-/ runs the command undo

    So <C-S-backspace> C-/ to "copy" a whole line (kill and undo).

    You can, of course, combine this with numeric and negative args to kill multiple lines either forward or backward.

    0 讨论(0)
  • 2020-12-04 05:39

    Nathan's addition to your .emacs file is the way to go but it could be simplified slightly by replacing

      (open-line 1)
      (next-line 1)
    

    with

      (newline)
    

    yielding

    (defun duplicate-line()
      (interactive)
      (move-beginning-of-line 1)
      (kill-line)
      (yank)
      (newline)
      (yank)
    )
    (global-set-key (kbd "C-d") 'duplicate-line)
    
    0 讨论(0)
  • 2020-12-04 05:39

    I liked FraGGod's version, except for two things: (1) It doesn't check whether the buffer is already read-only with (interactive "*"), and (2) it fails on the last line of the buffer if that last line is empty (as you cannot kill the line in that case), leaving your buffer read-only.

    I made the following changes to resolve that:

    (defun duplicate-line ()
      "Clone line at cursor, leaving the latter intact."
      (interactive "*")
      (save-excursion
        ;; The last line of the buffer cannot be killed
        ;; if it is empty. Instead, simply add a new line.
        (if (and (eobp) (bolp))
            (newline)
          ;; Otherwise kill the whole line, and yank it back.
          (let ((kill-read-only-ok t)
                deactivate-mark)
            (toggle-read-only 1)
            (kill-whole-line)
            (toggle-read-only 0)
            (yank)))))
    
    0 讨论(0)
  • 2020-12-04 05:40

    This functionality should match up with JetBrains' implementation in terms of duplicating both by line or region, and then leaving the point and/ or active region as expected:

    Just a wrapper to around the interactive form:

    (defun wrx/duplicate-line-or-region (beg end)
      "Implements functionality of JetBrains' `Command-d' shortcut for `duplicate-line'.
       BEG & END correspond point & mark, smaller first
       `use-region-p' explained: 
       http://emacs.stackexchange.com/questions/12334/elisp-for-applying-command-to-only-the-selected-region#answer-12335"
      (interactive "r")
      (if (use-region-p)
          (wrx/duplicate-region-in-buffer beg end)
        (wrx/duplicate-line-in-buffer)))
    

    Which calls this,

    (defun wrx/duplicate-region-in-buffer (beg end)
      "copy and duplicate context of current active region
       |------------------------+----------------------------|
       |        before          |           after            |
       |------------------------+----------------------------|
       | first <MARK>line here  | first line here            |
       | second item<POINT> now | second item<MARK>line here |
       |                        | second item<POINT> now     |
       |------------------------+----------------------------|
       TODO: Acts funky when point < mark"
      (set-mark-command nil)
      (insert (buffer-substring beg end))
      (setq deactivate-mark nil))
    

    Or this

    (defun wrx/duplicate-line-in-buffer ()
      "Duplicate current line, maintaining column position.
       |--------------------------+--------------------------|
       |          before          |          after           |
       |--------------------------+--------------------------|
       | lorem ipsum<POINT> dolor | lorem ipsum dolor        |
       |                          | lorem ipsum<POINT> dolor |
       |--------------------------+--------------------------|
       TODO: Save history for `Cmd-Z'
       Context: 
       http://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs#answer-551053"
      (setq columns-over (current-column))
      (save-excursion
        (kill-whole-line)
        (yank)
        (yank))
      (let (v)
        (dotimes (n columns-over v)
          (right-char)
          (setq v (cons n v))))
      (next-line))
    

    And then I have this bound to meta+shift+d

    (global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)
    
    0 讨论(0)
  • 2020-12-04 05:42

    something you might want to have in your .emacs is

    (setq kill-whole-line t)
    

    Which basically kills the entire line plus the newline whenever you invoke kill-line (i.e. via C-k). Then without extra code, you can just do C-a C-k C-y C-y to duplicate the line. It breaks down to

    C-a go to beginning of line
    C-k kill-line (i.e. cut the line into clipboard)
    C-y yank (i.e. paste); the first time you get the killed line back; 
        second time gives the duplicated line.
    

    But if you use this often then maybe a dedicated key binding might be a better idea, but the advantage of just using C-a C-k C-y C-y is you can duplicate the line elsewhere, instead of just below the current line.

    0 讨论(0)
提交回复
热议问题