ฉันจะทำสำเนาทั้งบรรทัดใน Emacs ได้อย่างไร


155

ฉันเห็นคำถามเดียวกันนี้สำหรับ VIMและเป็นสิ่งที่ฉันต้องการรู้วิธีทำเพื่อ Emacs ใน ReSharper ฉันใช้ CTRL-D สำหรับการกระทำนี้ จำนวนคำสั่งที่น้อยที่สุดที่จะดำเนินการใน Emacs คืออะไร?


2
แน่นอนมันเป็น emacs ดังนั้น TMTOWTDI - มี 22 แห่ง! (และเพิ่มขึ้นเรื่อย ๆ
Tom

คำตอบ:


150

ฉันใช้

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

ซึ่งพังทลายลงมา

  • C-a: เลื่อนเคอร์เซอร์ไปที่จุดเริ่มต้นของบรรทัด
  • C-SPACE: เริ่มการเลือก ("เครื่องหมายตั้ง")
  • C-n: เลื่อนเคอร์เซอร์ไปที่บรรทัดถัดไป
  • M-w: คัดลอกภูมิภาค
  • C-y: วาง ("ดึง")

ดังกล่าวข้างต้น

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

จำนวนเงินในสิ่งเดียวกัน (TMTOWTDI)

  • C-a: เลื่อนเคอร์เซอร์ไปที่จุดเริ่มต้นของบรรทัด
  • C-k: cut ("kill") บรรทัด
  • C-k: ตัด newline
  • C-y: paste ("yank") (เรากลับมาที่จตุรัสหนึ่ง)
  • C-y: วางอีกครั้ง (ตอนนี้เรามีสำเนาสองบรรทัด)

สิ่งเหล่านี้มีความหมายที่น่าอับอายเมื่อเทียบกับC-dในตัวแก้ไขของคุณ แต่ใน Emacs จะมีการปรับแต่งอยู่เสมอ โดยค่าเริ่มต้นC-dถูกผูกไว้delete-charดังนั้นจะเป็นC-c C-dอย่างไร เพียงเพิ่มสิ่งต่อไปนี้ใน.emacs:

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

(@ @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ / @ / @ @ @ @ @ @ @ @ @ @ / @ / @ @ @

ระวัง: บางโหมด Emacs อาจเรียกคืนC-c C-dเพื่อทำอย่างอื่น


5
Hi! โปรดระวังว่าถ้าคุณมี '(setq kill-whole-line t)' คุณจะต้องใช้เพียงหนึ่ง 'Ck' (โซลูชัน 2) เนื่องจากมีการฆ่าขึ้นบรรทัดใหม่พร้อมกับเนื้อหาของบรรทัด การใช้งาน 'C-k' ที่ฉันต้องการ ไชโยแดเนียล
danielpoe

179
เรื่องนี้น่าอายจริงๆ
tofutim

18
เกี่ยวกับC-S-backspace C-y C-yอะไร
ericzma

1
Mw คืออะไร คีย์ใดที่จะใช้สำหรับสิ่งนั้น
บาลา

4
@Bala "M" คือ "Meta" (โดยปกติคือ Esc หรือ Alt ขึ้นอยู่กับรูปแบบแป้นพิมพ์ของคุณ) "Mw" คือ "Meta" และ "w" พร้อมกัน (บนคีย์บอร์ดของฉัน "Alt-w")
Chris Conway

96

นอกเหนือจากคำตอบก่อนหน้านี้คุณยังสามารถกำหนดฟังก์ชั่นของคุณเองเพื่อทำซ้ำบรรทัด ตัวอย่างเช่นการใส่ข้อมูลต่อไปนี้ในไฟล์. emacs ของคุณจะทำให้ Cd ซ้ำกับบรรทัดปัจจุบัน

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

ฉันได้รับข้อผิดพลาดดังต่อไปนี้:Symbol's function definition is void: move-beginning-of-line
Rohaq

5
ปัญหานี้ก็คือว่า "เดล" ที่สำคัญยังเป็น binded ที่จะทำซ้ำบรรทัด ...
เดวิดโกเมส

ดังนั้นแนวคิดใดวิธียกเลิกการผูกDelจากฟังก์ชันนี้
Alexander Shcheblikin

ตกลงพบวิธีแก้ปัญหาในการคืนDelกลับสู่สภาวะปกติในขณะที่รักษาสิ่งใหม่C-d: (global-set-key (kbd "<delete>") 'delete-char)ต้องเพิ่มหลังจากการC-dกำหนด
Alexander Shcheblikin

การลองใช้บรรทัดว่างจะทำให้เกิดการแทรกสองบรรทัดแทนที่จะเป็นเพียงบรรทัดเดียว ฉันไม่รู้ว่าทำไม มีวิธีแก้ไขที่ง่ายไหม?
Zelphir Kaltstahl

68

วางเคอร์เซอร์บนบรรทัดหากไม่ใช่ที่จุดเริ่มต้นให้ทำCTRL- Aจากนั้น:

CTRL-K

CTRL-K

CTRL-Y

CTRL-Y


ฉันไม่คิดว่าจำเป็นต้องใช้ CY ตัวที่สอง
Bastien Léonard

4
มันจะไม่ซ้ำกันโดยไม่ต้อง
epatel

17
ใช้ CS-Backspace (ทำลายทั้งบรรทัด) แทน Ck คุณไม่ต้องขันกับตำแหน่งเคอร์เซอร์หรือฆ่าบรรทัดใหม่
Nietzche-jou

ใช้งานได้ดี แต่ไม่มีวิธีสั้น ๆ ในการทำเช่นนี้หรือ
สไตรเกอร์

52

ฟังก์ชันรุ่นของฉันเพื่อทำซ้ำบรรทัดที่ทำงานได้ดีกับการเลิกทำและไม่ยุ่งกับตำแหน่งเคอร์เซอร์ มันเป็นผลมาจากการอภิปรายใน gnu.emacs.sources จากพฤศจิกายน 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))

จากนั้นคุณสามารถกำหนด CTRL-D เพื่อเรียกใช้ฟังก์ชันนี้:

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

ยอดเยี่ยม คุณลักษณะการเลิกทำและตำแหน่งเคอร์เซอร์ทำให้สิ่งนี้ดีที่สุด ขอบคุณ!
ptrn

ที่ลิงค์มีรหัสสำหรับภูมิภาคด้วยเช่นกัน!
pcarvalho

ทางออกที่ดีมาก ขอบคุณ
Plankalkül

ใช้งานได้ดี ขอบคุณสำหรับการแก้ปัญหา
สไตรเกอร์

@pesche crux-duplicate-current-line-or-regionทำงานได้ดีขึ้นสำหรับฉันเพราะด้วยฟังก์ชั่นของคุณมันจะยกเลิกการทำซ้ำบรรทัดและการทำงานครั้งสุดท้ายด้วย
rofrol

47

แทนที่จะเป็นkill-line( C-k) ในการC-a C-k C-k C-y C-y ใช้งานkill-whole-lineคำสั่ง:

C-S-Backspace
C-y
C-y

ข้อดีต่าง ๆC-kรวมถึงมันไม่สำคัญว่าจุดใดที่อยู่บนเส้น (ต่างจากC-kที่ต้องอยู่ที่จุดเริ่มต้นของบรรทัด) และมันยังฆ่า newline (อีกสิ่งที่C-kไม่ทำ)


2
รุ่งโรจน์ @ RayVega! ฉันลองใช้วิธีนี้และใช้งานได้เหมือนแชมเปียน (ใน GNU Emacs 23.3.1 ของฉัน) วิธีนี้ไม่ได้ผลสำหรับบางคนใช่ไหม นี่คือคำตอบที่ดีที่สุดสำหรับคำถาม (ของคุณเอง)
JS

1
คุณควรยอมรับคำตอบนี้เป็นคำตอบที่ถูกต้อง มันทำสิ่งที่คุณขออย่างแน่นอนและใน "คำสั่งจำนวนน้อยที่สุด"
Davor Cubranic

24

นี่เป็นอีกฟังก์ชั่นสำหรับทำสิ่งนี้ เวอร์ชันของฉันไม่ได้แตะวงแหวนฆ่าและเคอร์เซอร์จะจบลงที่บรรทัดใหม่ซึ่งอยู่บนต้นฉบับ มันจะทำซ้ำภูมิภาคหากมีการใช้งาน (โหมดเครื่องหมายชั่วคราว) หรือเริ่มต้นการทำซ้ำสายมิฉะนั้น นอกจากนี้ยังจะสร้างสำเนาหลายชุดหากใช้คำนำหน้า ARG และแสดงความคิดเห็นในบรรทัดเดิมหากได้รับคำนำหน้า ARG เชิงลบ (สิ่งนี้มีประโยชน์สำหรับการทดสอบคำสั่ง / คำสั่งรุ่นอื่น

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

ฉันผูกพันกับC-c d:

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

สิ่งนี้ไม่ควรถูกกำหนดใหม่โดยโหมดหรืออะไรก็ตามเพราะC-cตามด้วยตัวอักษร (ไม่มีการแก้ไข) ตัวเดียวถูกสงวนไว้สำหรับการผูกผู้ใช้


ทางออกที่ดีที่สุดในตอนนี้
Leo Ufimtsev

1
ฉันใส่นี้ในแฟ้ม .emacs ของฉัน แต่เมื่อฉันพยายามที่จะใช้ฉันได้รับข้อผิดพลาดC-c d command-execute: Wrong type argument: commandp, duplicate-line-or-regionมีความคิดอะไรขึ้นบ้าง ฉันใช้ Emacs 25.1.1 บน Windows
Junius

วิธีแก้ปัญหาที่ดีจริง ๆ ฉันขอขอบคุณคุณลักษณะภูมิภาคและคุณลักษณะการแสดงความคิดเห็นพร้อมกับข้อโต้แย้งเชิงลบ เช่นเดียวกับการผูกกุญแจที่แนะนำ
Alex Trueman

18

นาธานการเพิ่มไฟล์. emacs ของคุณเป็นวิธีที่จะดำเนินการ แต่อาจง่ายขึ้นเล็กน้อยโดยการแทนที่

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

กับ

  (newline)

ยอมให้

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

นี่เป็นสิ่งที่ดี ขอบคุณ!
tejasbubane

7

ติดตั้งซ้ำสิ่งจาก Melpa:

Mx แพ็คเกจติดตั้ง RET รายการซ้ำ

และเพิ่มการโยงปุ่มนี้เพื่อเริ่มต้นไฟล์ :

(global-set-key (kbd "Mc") 'รายการที่ซ้ำกัน'


ดูเหมือนว่าจะไม่มีวันที่นี้
MarkSkayff

5

ฉันจำไม่ได้ว่าการทำสำเนาบรรทัดใช้งานที่อื่นได้อย่างไร แต่ในฐานะผู้ใช้ SciTE ในอดีตฉันชอบสิ่งหนึ่งเกี่ยวกับ SciTE-way: มันไม่ได้สัมผัสตำแหน่งเคอร์เซอร์! ดังนั้นผู้รับทั้งหมดข้างต้นไม่ดีพอสำหรับฉันนี่คือรุ่นฮิปปี้ของฉัน:

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

โปรดทราบว่าไม่มีสิ่งใดถูกฆ่าตายจริงๆในกระบวนการโดยปล่อยเครื่องหมายและการเลือกปัจจุบันไว้เหมือนเดิม

BTW ทำไมพวกคุณถึงชอบกระตุกเคอร์เซอร์ไปรอบ ๆ เมื่อมันมีสิ่งที่ดีที่ทำลายล้าง (CS-backspace)



4

สิ่งที่คุณอาจต้องการมีใน. emac ของคุณคือ

(setq kill-whole-line t)

ซึ่งโดยทั่วไปจะฆ่าทั้งบรรทัดบวกกับบรรทัดใหม่ทุกครั้งที่คุณเรียกใช้ kill-line (เช่นผ่าน Ck) จากนั้นไม่มีรหัสพิเศษคุณสามารถทำ Ca Ck Cy Cy เพื่อทำสำเนาบรรทัด มันพังทลายลงมา

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.

แต่ถ้าคุณใช้สิ่งนี้บ่อยครั้งการเชื่อมโยงคีย์เฉพาะอาจเป็นความคิดที่ดีกว่า แต่ข้อดีของการใช้ Ca Ck Cy Cy ก็คือคุณสามารถทำซ้ำบรรทัดที่อื่นแทนที่จะเป็นใต้บรรทัดปัจจุบัน


4

ฉันcopy-from-above-commandผูกพันกับกุญแจและใช้สิ่งนั้น มันมาพร้อมกับ XEmacs แต่ฉันไม่รู้เกี่ยวกับ GNU Emacs

`copy-from-above-command 'เป็นฟังก์ชั่น Lisp ที่คอมไพล์แบบอินเทอร์แอคทีฟ
- โหลดจาก" /usr/share/xemacs/21.4.15/lisp/misc.elc "(การคัดลอกจากเหนือคำสั่ง & ตัวเลือก ARG)

เอกสารประกอบ: คัดลอกอักขระจากบรรทัดที่ไม่ว่างก่อนหน้าโดยเริ่มจากจุดเหนือ คัดลอกอักขระ ARG แต่ไม่ผ่านจุดสิ้นสุดของบรรทัดนั้น หากไม่มีการโต้แย้งให้คัดลอกส่วนที่เหลือทั้งหมดของบรรทัด อักขระที่คัดลอกจะถูกแทรกในบัฟเฟอร์ก่อนจุด


สำหรับรุ่น 23 มันเป็นส่วนหนึ่งของการกระจาย GNU Emacs มาตรฐานเช่นกัน
viam0Zah

ดูเหมือนจะไม่อยู่ในรุ่นของฉัน ต้องโหลดบางสิ่งหรือไม่ GNU Emacs 23.2.1 (amd64-portbld-freebsd8.1) of 2010-11-14 on [host clipped]รุ่นของฉันคือ
qmega

2
@qmega คุณต้องทำ (ต้องการ 'misc)
Dmitry

4

มีแพ็คเกจชื่อAvyมันมีคำสั่ง avy-copy-line เมื่อคุณใช้คำสั่งนั้นทุกบรรทัดในหน้าต่างของคุณจะได้รับตัวอักษรผสมกัน จากนั้นคุณต้องพิมพ์ชุดค่าผสมและคุณจะได้บรรทัดนั้น นอกจากนี้ยังใช้งานได้สำหรับภูมิภาค จากนั้นคุณต้องพิมพ์ชุดค่าผสมสองชุด

ที่นี่คุณสามารถเห็นอินเทอร์เฟซ:

ป้อนคำอธิบายรูปภาพที่นี่



3

ค่าเริ่มต้นน่ากลัวสำหรับสิ่งนี้ อย่างไรก็ตามคุณสามารถขยาย Emacs ให้ทำงานเช่น SlickEdit และ TextMate นั่นคือคัดลอก / ตัดบรรทัดปัจจุบันเมื่อไม่มีข้อความถูกเลือก:

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

.emacsสถานที่ในข้างต้น M-wจากนั้นคัดลอกบรรทัด C-wในการลบบรรทัด เพื่อทำสำเนาบรรทัด, C-a M-w C-y C-y C-y ....


3

'ฉันเขียนเวอร์ชันของฉันเองduplicate-lineเพราะฉันไม่ต้องการทำให้แหวนสังหารตาย

  (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

ฉันชอบเวอร์ชั่นของ FraGGod ยกเว้นสองสิ่ง: (1) มันไม่ได้ตรวจสอบว่าบัฟเฟอร์นั้นเป็นแบบอ่านอย่างเดียว(interactive "*")แล้วและ (2) มันล้มเหลวในบรรทัดสุดท้ายของบัฟเฟอร์ถ้าบรรทัดสุดท้ายนั้นว่างเปล่า (ตามที่คุณ ไม่สามารถฆ่าบรรทัดในกรณีนั้น) ทำให้บัฟเฟอร์ของคุณเป็นแบบอ่านอย่างเดียว

ฉันทำการเปลี่ยนแปลงต่อไปนี้เพื่อแก้ไขปัญหานั้น:

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

3

ด้วย emacs ล่าสุดคุณสามารถใช้ Mw ที่ใดก็ได้ในบรรทัดเพื่อคัดลอก ดังนั้นมันจะกลายเป็น:

M-w C-a RET C-y

จริงๆ? อันไหน "ล่าสุด" Emacs นั่นจะเป็นอย่างไร? ไม่ใช่ในกรณีที่มี 24.4: คุณจะได้รับ "ไม่ได้ตั้งเครื่องหมายไว้ในขณะนี้จึงไม่มีภูมิภาค"
Davor Cubranic

ปัจจุบัน Emacs เป็น 24.5 และถูกผูกไว้กับM-w easy-killตรวจสอบว่าเป็นสิ่งที่คุณจะได้รับเมื่อคุณทำC-h c M-w
Louis Kottmann

ไม่ทำงานใน Emacs 24.5.1 คัดลอกเฉพาะจากจุดเริ่มต้นของบรรทัดไปยังจุดที่จุดเริ่มต้นของบรรทัดเดียวกันหลังจากแทรกบรรทัดว่างก่อนหน้า
Derek Mahar

3

ฉันเห็นวิธีแก้ปัญหาที่ซับซ้อนมากต่อไป ...

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

โปรดทราบว่าสิ่งนี้จะยุ่งกับวงแหวนฆ่า
Dodgie

สิ่งนี้จะผนวกบรรทัดเข้ากับตัวเองเมื่อเป็นบรรทัดสุดท้ายและไฟล์ไม่ได้ลงท้ายด้วยบรรทัดใหม่
Mark

2

@ [Kevin Conner]: ใกล้มากเท่าที่ฉันรู้ สิ่งเดียวที่ต้องพิจารณาอีกประการคือการเปิดkill-whole-lineเพื่อรวมบรรทัดใหม่ใน Ck


@Allen: ลบ[และ]ใน@[Kevin Conner]
jfs

2

ctrl- k, ctrl- k, (ตำแหน่งไปยังตำแหน่งใหม่) ctrl-y

เพิ่มctrl- aหากคุณไม่ได้เริ่มต้นที่บรรทัด และที่สองctrl- kคือการคว้าตัวละครขึ้นบรรทัดใหม่ สามารถลบออกได้หากคุณต้องการข้อความ


นี่เป็นวิธีที่ตรงไปตรงมาที่สุด ขอบคุณ!
bartlomiej.n

2

เมื่อเรียกใช้แบบไม่มีการโต้ตอบให้คัดลอก (Mw) บรรทัดเดียวแทน:

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

เมื่อเรียกใช้แบบไม่มีการโต้ตอบ KILL (Cw) บรรทัดเดียวแทน

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

นอกจากนี้ในบันทึกที่เกี่ยวข้อง:

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

1

ฉันเขียนหนึ่งสำหรับการตั้งค่าของฉัน

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

แต่ฉันพบว่าสิ่งนี้จะมีปัญหาเมื่อบรรทัดปัจจุบันมีอักขระหลายไบต์ (เช่นตัวอักษร CJK) หากคุณพบปัญหานี้ให้ลองทำดังนี้:

(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

ฟังก์ชั่นนี้ควรตรงกับการใช้งานของ JetBrains ในแง่ของการทำซ้ำทั้งตามสายหรือภูมิภาคจากนั้นออกจากจุดและ / หรือภูมิภาคที่ใช้งานตามที่คาดไว้:

เพียงห่อหุ้มรอบรูปแบบการโต้ตอบ:

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

ซึ่งเรียกสิ่งนี้ว่า

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

หรือสิ่งนี้

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

จากนั้นฉันก็มีเมตาดาต้า + shift + d นี้

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

1

ดังที่ได้กล่าวไว้ในคำตอบอื่น ๆ การกดแป้นลัดเพื่อผูกรหัสเสียงกระเพื่อมเป็นความคิดที่ดีกว่าการผูกไว้กับการกดปุ่มอีกครั้ง ด้วยคำตอบของ @ mw รหัสซ้ำบรรทัดและย้ายเครื่องหมายไปที่จุดสิ้นสุดของบรรทัดใหม่ การปรับเปลี่ยนนี้จะรักษาตำแหน่งเครื่องหมายไว้ที่คอลัมน์เดียวกันในบรรทัดใหม่:

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


0

ด้วยคำนำหน้าอาร์กิวเมนต์และสิ่งที่ (ฉันหวัง) พฤติกรรมที่ใช้งานง่าย:

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

เคอร์เซอร์จะยังคงอยู่ในบรรทัดสุดท้าย หรือคุณอาจต้องการระบุคำนำหน้าเพื่อทำซ้ำสองสามบรรทัดถัดไปพร้อมกัน:

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

ฉันพบว่าตัวเองใช้ทั้งสองบ่อยครั้งโดยใช้ฟังก์ชั่น wrapper เพื่อสลับพฤติกรรมของอาร์กิวเมนต์ prefix

และปุ่มลัด: (global-set-key (kbd "C-S-d") 'duplicate-line)


0
;; 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.

เพิ่ม elisp ด้านบนให้กับคุณ init.el และคุณได้รับฟังก์ชั่นตัด / คัดลอกทั้งบรรทัดแล้วคุณสามารถ F3 F4 เพื่อทำซ้ำบรรทัด


0

วิธีที่ง่ายที่สุดคือวิธีของ Chris Conway

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

นั่นเป็นวิธีเริ่มต้นที่ได้รับคำสั่งจาก EMACS ในความคิดของฉันดีกว่าที่จะใช้มาตรฐาน ฉันมักจะระมัดระวังในการปรับแต่งการเชื่อมโยงคีย์ของตนเองใน EMACS EMACS มีพลังมากพอฉันคิดว่าเราควรพยายามอย่างดีที่สุดเพื่อปรับให้เข้ากับการผูกกุญแจของตัวเอง

แม้ว่ามันจะค่อนข้างยาว แต่เมื่อคุณชินกับมันแล้วคุณสามารถทำได้เร็วและจะพบว่ามันสนุก!


4
ทุกสิ่งที่พิจารณา Emacs สั่งน้อยมาก - ชัยชนะอันยิ่งใหญ่ที่มอบให้คุณคือความง่ายในการปรับแต่งตามความต้องการของคุณ แน่นอนในทางปฏิบัติมีอยู่หลายวิธีมาตรฐานในการทำสิ่งที่มันเป็นประโยชน์ที่จะติด แต่ถ้าคุณกำลังใช้ "เริ่มต้น" Emacs และทำสิ่งที่เป็นวิธีที่ยากเกินความจำเป็นเพียงเพราะคุณคิดว่า "มันเป็นเรื่องดีที่จะใช้มาตรฐาน" คุณทำผิดไปมาก
phils

0

นี่คือฟังก์ชั่นสำหรับการทำซ้ำบรรทัดปัจจุบัน ด้วยคำนำหน้าอาร์กิวเมนต์มันจะทำซ้ำบรรทัดหลายครั้ง เช่นC-3 C-S-oจะทำซ้ำบรรทัดปัจจุบันสามครั้ง ไม่เปลี่ยนแหวนฆ่า

(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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.