it-swarm-id.com

Bagaimana cara menduplikasi seluruh baris di Emacs?

Saya melihat pertanyaan yang sama untuk VIM dan ini adalah sesuatu yang saya sendiri ingin tahu bagaimana melakukannya untuk Emacs. Di ReSharper saya menggunakan CTRL-D untuk tindakan ini. Berapa jumlah perintah paling sedikit untuk melakukan ini di Emacs?

136
Ray Vega

Saya menggunakan 

C-a C-SPACE C-n M-w C-y

yang terurai menjadi

  • C-a: pindahkan kursor untuk memulai baris
  • C-SPACE: mulai seleksi ("set mark")
  • C-n: pindahkan kursor ke baris berikutnya
  • M-w: salin wilayah
  • C-y: paste ("yank")

Yang disebutkan di atas

C-a C-k C-k C-y C-y

sama dengan jumlah yang sama (TMTOWTDI)

  • C-a: pindahkan kursor untuk memulai baris
  • C-k: potong ("bunuh") baris
  • C-k: potong baris baru
  • C-y: paste ("yank") (kami kembali ke titik awal)
  • C-y: rekatkan lagi (sekarang kami punya dua salinan baris)

Keduanya sama-sama memalukan dibandingkan dengan C-d di editor Anda, tetapi di Emacs selalu ada penyesuaian. C-d terikat ke delete-char secara default, jadi bagaimana dengan C-c C-d? Tambahkan saja yang berikut ke .emacs Anda:

(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")

(Versi elisp dari Nathan mungkin lebih disukai, karena itu tidak akan rusak jika ada salah satu binding kunci yang diubah.)

Hati-hati: beberapa mode Emacs dapat mengklaim kembali C-c C-d untuk melakukan sesuatu yang lain.

135
Chris Conway

Selain jawaban sebelumnya, Anda juga dapat menentukan fungsi Anda sendiri untuk menduplikasi sebuah baris. Misalnya, meletakkan yang berikut ini dalam file .emacs Anda akan membuat C-d menduplikasi baris saat ini.

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (open-line 1)
  (next-line 1)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
92
Nate

Tempatkan kursor on line, jika tidak di awal lakukan a CTRL-A, kemudian:

CTRL-K

CTRL-K

CTRL-Y

CTRL-Y

60
epatel

Versi saya dari fungsi untuk menduplikasi baris yang berfungsi dengan baik dengan membatalkan dan tidak mengacaukan posisi kursor. Itu adalah hasil dari diskusi di gnu.emacs.sources dari November 1997 .

(defun duplicate-line (arg)
  "Duplicate current line, leaving point in lower line."
  (interactive "*p")

  ;; save the point for undo
  (setq buffer-undo-list (cons (point) buffer-undo-list))

  ;; local variables for start and end of line
  (let ((bol (save-excursion (beginning-of-line) (point)))
        eol)
    (save-excursion

      ;; don't use forward-line for this, because you would have
      ;; to check whether you are at the end of the buffer
      (end-of-line)
      (setq eol (point))

      ;; store the line and disable the recording of undo information
      (let ((line (buffer-substring bol eol))
            (buffer-undo-list t)
            (count arg))
        ;; insert the line arg times
        (while (> count 0)
          (newline)         ;; because there is no newline in 'line'
          (insert line)
          (setq count (1- count)))
        )

      ;; create the undo information
      (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list)))
    ) ; end-of-let

  ;; put the point in the lowest line and return
  (next-line arg))

Kemudian Anda dapat mendefinisikan CTRL-D untuk memanggil fungsi ini:

(global-set-key (kbd "C-d") 'duplicate-line)
51
pesche

Alih-alih kill-line (C-k) seperti pada C-aC-kC-kC-yC-y gunakan perintah kill-whole-line :

C-S-Backspace
C-y
C-y

Keuntungan lebih dari C-k termasuk bahwa tidak masalah di mana titik pada baris (tidak seperti C-k yang mengharuskan berada di awal baris) dan juga membunuh baris baru (lagi sesuatu yang C-k tidak dilakukan).

42
Ray Vega

Inilah fungsi lain untuk melakukan ini. Versi saya tidak menyentuh cincin bunuh, dan kursor berakhir di baris baru di mana itu pada aslinya. Ini akan menggandakan wilayah jika itu aktif (mode tanda sementara), atau default untuk menduplikasi garis sebaliknya. Ini juga akan membuat banyak salinan jika diberi awalan arg, dan mengomentari baris asli jika diberi awalan arg negatif (ini berguna untuk menguji versi perintah/pernyataan yang berbeda sambil mempertahankan yang lama).

(defun duplicate-line-or-region (&optional n)
  "Duplicate current line, or region if active.
With argument N, make N copies.
With negative N, comment out original line and use the absolute value."
  (interactive "*p")
  (let ((use-region (use-region-p)))
    (save-excursion
      (let ((text (if use-region        ;Get region if active, otherwise line
                      (buffer-substring (region-beginning) (region-end))
                    (prog1 (thing-at-point 'line)
                      (end-of-line)
                      (if (< 0 (forward-line 1)) ;Go to beginning of next line, or make a new one
                          (newline))))))
        (dotimes (i (abs (or n 1)))     ;Insert N times, or once if not specified
          (insert text))))
    (if use-region nil                  ;Only if we're working with a line (not a region)
      (let ((pos (- (point) (line-beginning-position)))) ;Save column
        (if (> 0 n)                             ;Comment out original with negative arg
            (comment-region (line-beginning-position) (line-end-position)))
        (forward-line 1)
        (forward-char pos)))))

Saya memilikinya terikat ke C-c d:

(global-set-key [?\C-c ?d] 'duplicate-line-or-region)

Ini tidak boleh ditugaskan kembali oleh mode atau apa pun karena C-c diikuti oleh satu huruf (tidak dimodifikasi) disediakan untuk binding pengguna.

24
qmega

Penambahan Nathan ke file .emacs Anda adalah cara yang harus dilakukan tetapi bisa disederhanakan sedikit dengan mengganti 

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

dengan

  (newline)

menghasilkan

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (newline)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
16
pw.

pasang duplikat dari melpa:

Paket M-x-instal RET duplikat-hal

dan tambahkan pengikat kunci ini ke file init :

(duplikat-global-set-key (kbd "M-c") ')

5
user2626414

Saya tidak begitu ingat bagaimana duplikasi garis bekerja di tempat lain, tetapi sebagai mantan pengguna SciTE saya menyukai satu hal tentang SciTE-way: itu tidak menyentuh posisi kursor! Jadi semua penerima di atas tidak cukup baik bagi saya, inilah versi hippie saya:

(defun duplicate-line ()
    "Clone line at cursor, leaving the latter intact."
    (interactive)
    (save-excursion
        (let ((kill-read-only-ok t) deactivate-mark)
            (toggle-read-only 1)
            (kill-whole-line)
            (toggle-read-only 0)
            (yank))))

Perhatikan bahwa tidak ada yang benar-benar terbunuh dalam proses, meninggalkan tanda dan pilihan saat ini utuh.

BTW, mengapa kalian sangat suka menyentak kursor ketika ada Nice-n'clean kill-seluruh-line thingy (C-S-backspace)?

5
mk-fg

Saya memiliki copy-from-above-command terikat pada kunci dan menggunakannya. Ini disediakan dengan XEmacs, tapi saya tidak tahu tentang GNU Emacs.

`copy-from-above-command 'adalah fungsi kompilasi LISP interaktif
- dimuat dari "/usr/share/xemacs/21.4.15/LISP/misc.elc" (salin dari perintah di atas & opsional ARG)

Dokumentasi: Salin karakter dari baris nonblank sebelumnya , mulai saja titik di atas. Salin karakter ARG, tetapi tidak melewati akhir dari garis itu. Jika tidak argumen yang diberikan, salin seluruh sisanya dari garis. Karakter yang disalin adalah dimasukkan dalam buffer sebelum titik.

4
Darron

karena saya tidak tahu, saya akan memulai putaran golf ini dengan slowball:

ctrl-k, y, y

4
Kevin Conner

Dengan emacs terbaru, Anda dapat menggunakan M-w di mana saja di baris untuk menyalinnya. Jadi itu menjadi:

M-w C-a RET C-y
3
Louis Kottmann
C-a C-k C-k C-y C-y
3
sverrejoh

sesuatu yang Anda mungkin ingin miliki di .emacs Anda 

(setq kill-whole-line t)

Yang pada dasarnya membunuh seluruh baris plus baris baru setiap kali Anda memanggil kill-line (mis. Via C-k). Kemudian tanpa kode tambahan, Anda bisa melakukan C-a C-k C-y C-y untuk menduplikasi baris. Itu rusak menjadi 

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.

Tetapi jika Anda sering menggunakan ini maka mungkin pengikatan kunci khusus mungkin merupakan ide yang lebih baik, tetapi keuntungan dari hanya menggunakan C-a C-k C-y C-y adalah Anda dapat menduplikasi baris di tempat lain, bukan hanya di bawah garis saat ini.

3
polyglot

Defaultnya mengerikan untuk ini. Namun, Anda dapat memperluas Emacs agar berfungsi seperti SlickEdit dan TextMate, yaitu, salin/potong baris saat ini ketika tidak ada teks yang dipilih:

(transient-mark-mode t)
(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)))))
(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))
     (list (line-beginning-position)
           (line-beginning-position 2)))))

Tempatkan di atas dalam .emacs. Kemudian, untuk menyalin sebuah baris, M-w. Untuk menghapus sebuah baris, C-w. Untuk menduplikasi suatu baris, C-a M-w C-y C-y C-y ....

3
Marius Andersen

Saya melihat solusi yang sangat kompleks, ...

(defun duplicate-line ()
  "Duplicate current line"
  (interactive)
  (kill-whole-line)
  (yank)
  (yank))
(global-set-key (kbd "C-x M-d") 'duplicate-line)
3
user6581334

'Saya menulis versi saya sendiri duplicate-line, karena saya tidak ingin mengacaukan cincin pembunuhan.

  (defun jr-duplicate-line ()
    "EASY"
    (interactive)
    (save-excursion
      (let ((line-text (buffer-substring-no-properties
                        (line-beginning-position)
                        (line-end-position))))
        (move-end-of-line 1)
        (newline)
        (insert line-text))))
  (global-set-key "\C-cd" 'jr-duplicate-line)
3
Joyer

Ada paket bernama Avy Memiliki perintah avy-copy-line. Saat Anda menggunakan perintah itu, setiap baris di jendela Anda mendapat kombinasi huruf. Maka Anda hanya perlu mengetikkan kombinasi dan Anda mendapatkan garis itu. Ini juga berfungsi untuk wilayah. Maka Anda hanya perlu mengetikkan dua kombinasi.

Di sini Anda dapat melihat antarmuka: 

http://i68.tinypic.com/24fk5eu.png

3
teksturi

@ [Kevin Conner]: Cukup dekat, sejauh yang saya tahu. Satu-satunya hal lain yang perlu dipertimbangkan adalah menyalakan kill-whole-line untuk memasukkan baris baru dalam C-k.

2
Allen

Saya menyukai versi FraGGod, kecuali untuk dua hal: (1) Tidak memeriksa apakah buffer sudah hanya-baca dengan (interactive "*"), dan (2) gagal pada baris terakhir buffer jika baris terakhir kosong (seperti Anda tidak dapat mematikan baris dalam kasus itu), membiarkan buffer Anda hanya-baca.

Saya membuat perubahan berikut untuk menyelesaikannya:

(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)))))
2
phils

Ketika dipanggil secara interaktif tanpa wilayah aktif, COPY (M-w) sebagai gantinya:

(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)))))

Saat dipanggil secara interaktif tanpa wilayah aktif, BUNUH (C-w) satu baris saja.

(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)))))

Juga, pada catatan terkait:

(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)
2
yPhil

Saya menulis satu untuk preferensi saya.

(defun duplicate-line ()
  "Duplicate current line."
  (interactive)
  (let ((text (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
        (cur-col (current-column)))
    (end-of-line) (insert "\n" text)
    (beginning-of-line) (right-char cur-col)))
(global-set-key (kbd "C-c d l") 'duplicate-line)

Tetapi saya menemukan ini akan memiliki beberapa masalah ketika baris saat ini berisi karakter multi-byte (mis. Karakter CJK). Jika Anda mengalami masalah ini, coba ini:

(defun duplicate-line ()
  "Duplicate current line."
  (interactive)
  (let* ((text (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
         (cur-col (length (buffer-substring-no-properties (point-at-bol) (point)))))
    (end-of-line) (insert "\n" text)
    (beginning-of-line) (right-char cur-col)))
(global-set-key (kbd "C-c d l") 'duplicate-line)
1
kuanyui

ctrl-kctrl-k, (posisi ke lokasi baru) ctrl-y

Tambah sebuah ctrl-a jika Anda tidak memulai di awal baris. Dan yang ke-2 ctrl-k adalah untuk mengambil karakter baris baru. Itu dapat dihapus jika Anda hanya ingin teks.

1
CJP

Fungsi ini harus sesuai dengan implementasi JetBrains dalam hal menduplikasi baik oleh garis atau wilayah, dan kemudian meninggalkan titik dan/atau wilayah aktif seperti yang diharapkan:

Hanya pembungkus di sekitar formulir interaktif:

(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)))

Yang menyebut ini,

(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))

Atau ini

(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))

Dan kemudian saya memiliki ini terikat dengan meta + shift + d

(global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)
1
AesopHimself

M-c, Shift+Insertx2 (atau apa pun pintasan tempel Anda) akan melakukannya.

0
Andrew Naguib
;; http://www.emacswiki.org/emacs/WholeLineOrRegion#toc2
;; cut, copy, yank
(defadvice kill-ring-save (around slick-copy activate)
  "When called interactively with no active region, copy a single line instead."
  (if (or (use-region-p) (not (called-interactively-p)))
      ad-do-it
    (kill-new (buffer-substring (line-beginning-position)
                                (line-beginning-position 2))
              nil '(yank-line))
    (message "Copied line")))
(defadvice kill-region (around slick-copy activate)
  "When called interactively with no active region, kill a single line instead."
  (if (or (use-region-p) (not (called-interactively-p)))
      ad-do-it
    (kill-new (filter-buffer-substring (line-beginning-position)
                                       (line-beginning-position 2) t)
              nil '(yank-line))))
(defun yank-line (string)
  "Insert STRING above the current line."
  (beginning-of-line)
  (unless (= (elt string (1- (length string))) ?\n)
    (save-excursion (insert "\n")))
  (insert string))

(global-set-key (kbd "<f2>") 'kill-region)    ; cut.
(global-set-key (kbd "<f3>") 'kill-ring-save) ; copy.
(global-set-key (kbd "<f4>") 'yank)           ; paste.

tambahkan elisp di atas untuk Anda init.el, dan Anda mendapatkan fungsi cut/copy seluruh baris sekarang, maka Anda dapat F3 F4 untuk menduplikasi satu baris.

0
WisdomFusion

Ini terasa lebih alami, sehubungan dengan jawaban yang dipilih oleh Chris Conway.

(global-set-key "\ C-c\C-d" "\ C-a\C-\C-n\M-w\C-y\C-p\C-e")

Ini memungkinkan Anda untuk menduplikasi baris beberapa kali hanya dengan mengulangi stroke kunci\C-c\C-d.

0
Shim Kporku

Berikut adalah fungsi untuk menduplikasi baris saat ini. Dengan argumen awalan, itu akan menduplikasi baris beberapa kali. E.g., C-3 C-S-o akan menduplikasi baris saat ini tiga kali. Tidak mengubah cincin bunuh. 

(defun duplicate-lines (arg)
  (interactive "P")
  (let* ((arg (if arg arg 1))
         (beg (save-excursion (beginning-of-line) (point)))
         (end (save-excursion (end-of-line) (point)))
         (line (buffer-substring-no-properties beg end)))
    (save-excursion
      (end-of-line)
      (open-line arg)
      (setq num 0)
      (while (< num arg)
        (setq num (1+ num))
        (forward-line 1)
        (insert-string line))
      )))

(global-set-key (kbd "C-S-o") 'duplicate-lines)
0
Dodgie

Seperti disebutkan dalam jawaban lain, mengikat goresan kunci ke kode LISP adalah ide yang lebih baik daripada mengikat mereka dengan goresan kunci lain. Dengan jawaban @ mw, kode menduplikasi baris dan memindahkan tanda ke akhir baris baru. Modifikasi ini menjaga posisi tanda pada kolom yang sama di baris baru:

fun duplicate-line ()
  (interactive)
  (let ((col (current-column)))
    (move-beginning-of-line 1)
    (kill-line)
    (yank)
    (newline)
    (yank)
    (move-to-column col)))
0
krsoni

Saya tidak percaya semua solusi rumit ini. Ini adalah dua penekanan tombol:

<C-S-backspace> menjalankan perintah kill-whole-line

C-/ menjalankan perintah undo

Jadi <C-S-backspace> C-/ untuk "menyalin" seluruh baris (bunuh dan batalkan).

Anda dapat, tentu saja, menggabungkan ini dengan args numerik dan negatif untuk membunuh beberapa baris maju atau mundur.

0
Andy

Cara paling sederhana adalah metode Chris Conway. 

C-a C-SPACE C-n M-w C-y

Itulah cara standar yang diamanatkan oleh EMACS. Menurut pendapat saya, lebih baik menggunakan standar. Saya selalu berhati-hati terhadap penyesuaian kunci sendiri dalam EMACS. EMACS sudah cukup kuat, saya pikir kita harus mencoba yang terbaik untuk beradaptasi dengan kunci-ikatannya sendiri. 

Meskipun agak panjang, tetapi ketika Anda terbiasa, Anda dapat melakukannya dengan cepat dan akan menemukan ini menyenangkan!

0
linbianxiaocao

Dengan argumen awalan, dan apa itu perilaku intuitif (saya harap):

(defun duplicate-line (&optional arg)
  "Duplicate it. With prefix ARG, duplicate ARG times."
  (interactive "p")
  (next-line 
   (save-excursion 
     (let ((beg (line-beginning-position))
           (end (line-end-position)))
       (copy-region-as-kill beg end)
       (dotimes (num arg arg)
         (end-of-line) (newline)
         (yank))))))

Kursor akan tetap di baris terakhir . Atau, Anda mungkin ingin menentukan awalan untuk menduplikasi beberapa baris berikutnya sekaligus:

(defun duplicate-line (&optional arg)
  "Duplicate it. With prefix ARG, duplicate ARG times."
  (interactive "p")
  (save-excursion 
    (let ((beg (line-beginning-position))
          (end 
           (progn (forward-line (1- arg)) (line-end-position))))
      (copy-region-as-kill beg end)
      (end-of-line) (newline)
      (yank)))
  (next-line arg))

Saya menemukan diri saya sering menggunakan keduanya, menggunakan fungsi wrapper untuk mengubah perilaku argumen awalan.

Dan keybinding: (global-set-key (kbd "C-S-d") 'duplicate-line)

0
Karthik