ฆ่าหรือคัดลอกบรรทัดปัจจุบันด้วยการกดแป้นน้อยที่สุด


32

ฉันC-a C-k C-kจะฆ่าจุดเส้นทั้งหมดที่อยู่บน

หากฉันต้องการคัดลอกบรรทัดแทนที่จะฆ่ามันฉันสามารถกดได้C-/ C-/ หลังจากพิมพ์ลำดับด้านบน

C-a C-SPC C-n M-wหรือฉันสามารถทำได้

มีวิธีที่เร็วกว่าในการฆ่าหรือคัดลอกจุดเส้นทั้งหมดที่เปิดอยู่?


1
ว้าว! คำตอบเหล่านี้แสดงให้เห็นถึงความยาวของผู้คนที่จะไปเพื่อหลีกเลี่ยงการใช้งานในkill-whole-lineตัว :)
โอมาร์

evil-modeเป็นข้อเสนอแนะดังต่อไปนี้การใช้งาน เรียนรู้คำสั่งเสียงเรียกเข้าคุณจะไม่เสียใจ!
A. Blizzard

คำตอบ:


44

คุณสามารถใช้kill-whole-lineเพื่อฆ่าจุดเส้นทั้งหมดที่อยู่บน ตำแหน่งของจุดไม่สำคัญ คำสั่งนี้ถูกผูกไว้C-S-DELโดยค่าเริ่มต้น

นอกจากนี้คุณยังสามารถสั่งkill-line(ผูกไว้กับC-k) เพื่อฆ่าทั้งบรรทัดโดยการตั้งค่าตัวแปร kill-whole-lineเป็นnilค่าที่ไม่ใช่:

(setq kill-whole-line t)

โปรดทราบว่าจุดนั้นจะต้องอยู่ที่จุดเริ่มต้นของบรรทัดเพื่อให้สามารถใช้งานได้


จากนั้นก็มีอัญมณีสองชนิดนี้ (ผ่านemacs-fu ):

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

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

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

  • C-w ฆ่าบรรทัดปัจจุบัน
  • M-w คัดลอกบรรทัดปัจจุบัน

โปรดทราบว่าหากมีพื้นที่ที่ใช้งานอยู่kill-regionและkill-ring-saveจะทำสิ่งที่พวกเขาทำตามปกติ: ฆ่าหรือคัดลอก


พอร์ตslick-cutและslick-copyระบบคำแนะนำใหม่

Emacs 24.4 เปิดตัวระบบใหม่คำแนะนำ ในขณะที่defadvice ยังใช้งานได้มีความเป็นไปได้ที่จะเลิกใช้งานระบบใหม่ในเวอร์ชันของ Emacs ในอนาคต ในการเตรียมพร้อมสำหรับสิ่งนั้นคุณอาจต้องการใช้เวอร์ชันที่อัปเดตแล้วslick-cutและslick-copy:

(defun slick-cut (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-region :before #'slick-cut)

(defun slick-copy (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (message "Copied line")
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-ring-save :before #'slick-copy)

2
โปรดทราบว่าkill-regionและkill-ring-saveยังคงใช้งานได้แม้ว่าภูมิภาคนี้จะไม่ "เปิดใช้งาน" สิ่งนี้จะแทนที่พฤติกรรมนั้น ฉันใช้พฤติกรรมนั้นเป็นครั้งคราว แต่ถ้าคุณไม่คุ้นเคยกับการใช้มันด้วยวิธีนี้คุณอาจไม่สังเกตเห็นความแตกต่าง
nispio

@nispio โปรดขยายเมื่อ / วิธีการkill-regionอื่น ๆ สามารถใช้งานได้ / มีประโยชน์เมื่อเป็นmark-active nil
Phil Hudson

1
@PhilHudson เครื่องหมายสามารถตั้งค่า (และมักจะเป็น) โดยไม่ต้องใช้งาน ลองทำC-SPCสองครั้งเพื่อเปิดใช้งานแล้วปิดการใช้งานเครื่องหมาย ย้ายเคอร์เซอร์ไปที่อื่นในไฟล์และเรียกใช้kill-regionและจะฆ่าพื้นที่ระหว่างจุดและเครื่องหมายแม้ว่าเครื่องหมายจะไม่ทำงาน ตัวอย่างบางส่วนของคำสั่งที่ชุด ( แต่ไม่เปิดใช้งาน) เครื่องหมายที่มีและyank isearchหลังจากดำเนินการคำสั่งเรียงลำดับเหล่านี้ฉันรู้ว่าเครื่องหมายอยู่ที่ไหนแม้ว่าจะไม่ได้ใช้งานอยู่และคำสั่งจำนวนมาก (รวมถึงkill-region) จะให้ฉันใช้เครื่องหมายโดยไม่ต้องเปิดใช้งานอย่างชัดเจน
nispio

ขอบคุณ @nispio แน่นอน. นั่นคือวิธีที่เคยเป็นมาก่อนที่การไฮไลต์ภูมิภาคที่มองเห็นได้กลายเป็นค่าเริ่มต้นของการเผยแพร่ที่สำคัญสองสามครั้งใช่ไหม ฉันสับสน "ใช้งานอยู่" กับ "ตั้ง"
Phil Hudson

1
นี่คือคำตอบที่ยิ่งใหญ่ที่สุดเท่าที่เคยโพสต์ไว้ใน SX ใด ๆ อย่างจริงจัง.
Benjamin Lindqvist

15

วิธีแก้ปัญหาที่ฉันพบสำหรับตัวเองคือใช้อาร์กิวเมนต์คำนำหน้า

สำหรับฉันการฆ่าครึ่งบรรทัดเป็นคุณสมบัติที่มีประโยชน์ แต่ฉันต้องการวิธีที่ง่ายกว่าในการฆ่าทั้งบรรทัดด้วย ดังนั้นฉันจึงสร้างมันขึ้นมาเพื่อที่ kill-lineจะได้สังหารทุกสิ่งทุกอย่างเมื่อได้รับอาร์กิวเมนต์นำหน้า

(defmacro bol-with-prefix (function)
  "Define a new function which calls FUNCTION.
Except it moves to beginning of line before calling FUNCTION when
called with a prefix argument. The FUNCTION still receives the
prefix argument."
  (let ((name (intern (format "endless/%s-BOL" function))))
    `(progn
       (defun ,name (p)
         ,(format 
           "Call `%s', but move to BOL when called with a prefix argument."
           function)
         (interactive "P")
         (when p
           (forward-line 0))
         (call-interactively ',function))
       ',name)))

(global-set-key [remap paredit-kill] (bol-with-prefix paredit-kill))
(global-set-key [remap org-kill-line] (bol-with-prefix org-kill-line))
(global-set-key [remap kill-line] (bol-with-prefix kill-line))
(global-set-key "\C-k" (bol-with-prefix kill-line))

ด้วยมาโครตัวเล็กนี้C-kยังคงสังหารจากจุด แต่ C-3 C-kกลืนทั้งสามบรรทัด เป็นโบนัส, เราได้รับ พฤติกรรมโดยการทำkill-whole-lineC-1 C-k


นั่นเป็นความคิดที่ดีขอบคุณสำหรับการแบ่งปัน! :) คุณจะปรับโซลูชันนี้ให้ทำงานอย่างไรเพื่อคัดลอกหนึ่งบรรทัดขึ้นไป kill-ring-saveไม่ยอมรับคำนำหน้าอาร์กิวเมนต์ ...
itsjeyd

@itsjeyd ฉันแน่ใจว่าสิ่งที่คล้ายกันสามารถทำได้เพื่อรวมสองคำตอบ แต่มันต้องใช้งานเพิ่มอีกเล็กน้อย
Malabarba

บรรทัดสุดท้ายหมายถึง paredit-kill มันตั้งใจหรือไม่
Boccaperta-IT

1
โอ้ตกลงขอบคุณ ฉันไม่ได้รับพฤติกรรมที่คาดหวัง ถ้าฉันวางตัวชี้ที่กึ่งกลางของบรรทัดแล้วกด C-3 Ck บรรทัดแรกจะไม่ถูกฆ่าทั้งหมด นี่เป็นวิธีที่ควรจะทำงานหรือฉันกำลังทำอะไรผิดหรือเปล่า?
Boccaperta-IT

1
@Malabarba คุณขวาถูกผูกไว้กับkill-visual-line C-kฉันจะแก้ไข ขอบคุณอีกครั้ง.
Boccaperta-IT

15

มีแพคเกจที่เรียกว่าwhole-line-or-regionซึ่งให้คำแนะนำในตัวคำสั่งต่าง ๆ เพื่อให้พวกเขาทำหน้าที่ในบรรทัดปัจจุบันหากไม่มีการใช้งานภูมิภาคดังนั้นM-wจะคัดลอกบรรทัดปัจจุบันและC-wจะฆ่ามันตัวอย่างเช่น ฉันใช้แพ็คเกจมาหลายปีแล้วและพบว่ามันขาดไม่ได้

นอกจากนี้แพคเกจนี้สร้างขึ้นเพื่อให้คำนำหน้าตัวเลขจะระบุจำนวนบรรทัดที่จะดำเนินการดังนั้นM-2 M-wจะคัดลอกสองบรรทัด คำตอบอื่น ๆ ที่นี่ไม่ได้มีฟังก์ชั่นที่สะดวก

ฉันเข้ารับการบำรุงรักษาแพคเกจที่บัญชี GitHub ของฉันเมื่อผู้เขียนหยุดการบำรุงรักษาและไม่ตอบสนอง

whole-line-or-region ยังให้บริการสิ่งอำนวยความสะดวกสำหรับการเพิ่มพฤติกรรมนี้ให้กับคำสั่งเพิ่มเติมหากคุณต้องการ


กรุณายื่นเรื่อง MELPA เพราะฉันไม่แน่ใจว่าคุณหมายถึงอะไร: ฉันติดตั้งแพคเกจนี้จาก MELPA ตลอดเวลาโดยไม่มีปัญหา
sanityinc

9

นี่ไม่ใช่คำตอบสำหรับ emacs ดั้งเดิม อย่างไรก็ตามหากคุณยินดีดูหมิ่นevilการแก้ไขคำกริยาคุณสามารถ:

  • dd สำหรับสายฆ่า
  • cc สำหรับสายการคัดลอก

ทั้งสองสามารถนำหน้าด้วยจำนวนบรรทัดที่จะฆ่า / คัดลอก (เช่น4ccจะคัดลอก 4 บรรทัดถัดไป)


5

นอกจาก @itsjeyd คำตอบฉันขอแนะนำฟังก์ชันทั้งสองนี้ได้ไหม?

(defun xah-copy-line-or-region ()
  "Copy current line, or text selection.
When `universal-argument' is called first, copy whole buffer (but respect `narrow-to-region')."
  (interactive)
  (let (p1 p2)
    (if (null current-prefix-arg)
        (progn (if (use-region-p)
                   (progn (setq p1 (region-beginning))
                          (setq p2 (region-end)))
                 (progn (setq p1 (line-beginning-position))
                        (setq p2 (line-end-position)))))
      (progn (setq p1 (point-min))
             (setq p2 (point-max))))
    (kill-ring-save p1 p2)))

(defun xah-cut-line-or-region ()
  "Cut current line, or text selection.
When `universal-argument' is called first, cut whole buffer (but respect `narrow-to-region')."
  (interactive)
  (let (p1 p2)
    (if (null current-prefix-arg)
        (progn (if (use-region-p)
                   (progn (setq p1 (region-beginning))
                          (setq p2 (region-end)))
                 (progn (setq p1 (line-beginning-position))
                        (setq p2 (line-beginning-position 2)))))
      (progn (setq p1 (point-min))
             (setq p2 (point-max))))
    (kill-region p1 p2)))

จากนั้นคำจำกัดความสำคัญ (คุณอาจต้องการปรับเปลี่ยน):

(global-set-key (kbd "<f2>") 'xah-cut-line-or-region) ; cut

(global-set-key (kbd "<f3>") 'xah-copy-line-or-region) ; copy

(global-set-key (kbd "<f4>") 'yank) ; paste

ความอนุเคราะห์จากErgoEmacs


ขอบคุณสำหรับคำตอบ! คุณอาจต้องการพิจารณาขยายออกไปเล็กน้อยโดยอธิบายว่าคำสั่งเหล่านี้แตกต่างจากโซลูชันอื่น ๆ ที่โพสต์ที่นี่หรือไม่ ใช่ข้อมูลนี้มีอยู่ในเอกสาร แต่ไม่เจ็บที่จะทำให้ผู้อ่านในอนาคตเห็นได้ชัดเจนขึ้น :)
itsjeyd

1
เป็นไปได้ที่จะทำเช่นนี้ แต่ปรับเปลี่ยนเช่นโพสต์โจนาธานด้านล่างดังนั้นจึงใช้เวลา sexp หรือคำแรกแล้วใช้สายถ้าเรียกอีกครั้ง?
J Spen

@JSpen สิ่งที่ฉันกำลังทำคือการกำหนดแป้นพิมพ์ลัดให้ทำงาน สิ่งที่โจนาธานทำคือการกำหนดคำแนะนำสำหรับฟังก์ชั่น ดังนั้นคุณสามารถแนะนำฟังก์ชั่นแล้วกำหนดปุ่มทางลัดไปยังฟังก์ชั่นที่แนะนำ; และคุณจะได้ผลลัพธ์ของคุณ ขออภัยในความล่าช้า;)
Nsukami _

4

ในฐานะที่เป็นส่วนขยายของคำตอบของ @ itsjeyd ด้านบนฉันมีดังต่อไปนี้ (ลอจิกอาจจะทำความสะอาดได้เล็กน้อยและฉันจะเมื่อฉันพอร์ตไปยังระบบคำแนะนำใหม่ฉันจะยังขยายมันเพื่อขยายไปยังsexp/ paragraphถ้าทำซ้ำอีกครั้ง)

เริ่มต้นC-w/ M-wจะคว้าเฉพาะคำที่จุดในขณะที่เรียกมันเป็นครั้งที่สองจะคว้าทั้งบรรทัด

;; *** Copy word/line without selecting
(defadvice kill-ring-save (before slick-copy-line activate compile)
  "When called interactively with no region, copy the word or line

Calling it once without a region will copy the current word.
Calling it a second time will copy the current line."
    (interactive
     (if mark-active (list (region-beginning) (region-end))
       (if (eq last-command 'kill-ring-save)
           (progn
             ;; Uncomment to only keep the line in the kill ring
             ;; (kill-new "" t)
             (message "Copied line")
             (list (line-beginning-position)
                   (line-beginning-position 2)))
         (save-excursion
           (forward-char)
           (backward-word)
           (mark-word)
           (message "Copied word")
           (list (mark) (point)))))))

;; *** Kill word/line without selecting
(defadvice kill-region (before slick-cut-line first activate compile)
  "When called interactively kill the current word or line.

Calling it once without a region will kill the current word.
Calling it a second time will kill the current line."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
    (if (eq last-command 'kill-region)
        (progn
          ;; Return the previous kill to rebuild the line
          (yank)
          ;; Add a blank kill, otherwise the word gets appended.
          ;; Change to (kill-new "" t) to remove the word and only
          ;; keep the whole line.
          (kill-new "")
          (message "Killed Line")
          (list (line-beginning-position)
                (line-beginning-position 2)))
      (save-excursion
        (forward-char)
        (backward-word)
        (mark-word)
        (message "Killed Word")
        (list (mark) (point)))))))

คุณได้อัปเดตสิ่งนี้หรือไม่และหากเป็นเช่นนั้น นอกจากนี้ยังเป็นการเพิ่มเครื่องหมายจำนวนมากให้กับวงแหวนเครื่องหมาย มันสามารถเพิ่มเพียงหนึ่งเครื่องหมายที่จุดเริ่มต้นของการคัดลอก ดังนั้นจุดเริ่มต้นของคำหรือจุดเริ่มต้นของบรรทัด ตอนนี้มันเพิ่มเหมือนสี่คะแนนทุกครั้งที่น่ารำคาญ ฉันได้เปลี่ยนไปใช้ (backward-sexp) จริง ๆ แต่บางครั้งมันหาไม่เจอแล้วก็เกิดข้อผิดพลาด มันสามารถเพียงแค่คัดลอกบรรทัดหากไม่พบหรือไม่ ฉันไม่แน่ใจว่าจะทำอย่างไรหรือแค่เพิกเฉยต่อข้อผิดพลาดและไม่ส่งเสียงดัง ขออภัยฉันไม่เก่งที่สุด
J Spen

1

เนื่องจากคุณต้องการใช้ปุ่มกดน้อยที่สุดคุณสามารถใช้แพ็คเกจคีย์คอร์ดที่ยอดเยี่ยมของ David Andersson "คอร์ดปุ่ม" คือกดสองปุ่มพร้อมกันหรือกดปุ่มเดียวสองครั้ง

คุณสามารถผูกคอร์ดกุญแจใด ๆ กับฟังก์ชั่นเหล่านั้นได้

(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "dd"  'kill-whole-line)
(key-chord-define-global "cc"  'yank-whole-line)

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

1

วิธีการเฉพาะกิจน้อยลงคือการกำหนดmark-whole-lineซึ่ง Emacs ควรมีคำสั่งเริ่มต้นสำหรับ

(defun mark-whole-line ()               
    "Combinition of C-a, mark, C-e"
    (interactive)
    (move-beginning-of-line nil)
    (set-mark-command nil)
    (move-end-of-line nil)
)
(global-set-key (kbd "C-2") 'mark-whole-line) ; 2 is near w

จากนั้นC-2 C-wจะทำงาน

นอกจากนี้ยังทำให้สิ่งต่าง ๆ ง่ายขึ้นเช่นการแสดงความคิดเห็นทั้งบรรทัดปัจจุบัน


0

นี่คือการแก้ไขคำตอบโดย itsjeyd - ปัจจุบันเป็นคำตอบที่ได้รับการโหวตสูงสุดและเป็นคำตอบที่ฉันใช้มานานหลายปี อย่างไรก็ตามมีปัญหา: รุ่นที่แนะนำของkill-ring-saveบางครั้งจะล้มเหลวเนื่องจากไม่ได้ตั้งค่าเครื่องหมาย (โดยทั่วไปจะอยู่ในบัฟเฟอร์ใหม่) และแม้ว่าจะทำงานแล้วเคอร์เซอร์ก็เต้นแปลก ๆ หลังจากใช้ฟังก์ชั่นเพื่อคัดลอกบรรทัดเดียว . หลังจากการขุดบางครั้งก็เกิดขึ้นกับฉันว่าสิ่งนี้เกิดขึ้นเพราะการkill-ring-saveโทรindicate-copied-regionหลังจากทำงานเสร็จแล้ว แต่เนื่องจากจุดและเครื่องหมายไม่ตรงกับภูมิภาคที่คัดลอกindicate-copied-regionทำเครื่องหมายว่าภูมิภาคไม่ถูกต้อง

พูดพอแล้ว. นี่คือทางออกที่แก้ไขสิ่งนี้:

(define-advice kill-ring-save
    (:before-while (beg end &optional region) slick)
  (or mark-active
      (not (called-interactively-p 'interactive))
      (prog1 nil
    (copy-region-as-kill
     (line-beginning-position) (line-beginning-position 2))
    (message "Copied current line"))))

มีอะไรผิดปกติกับคำแนะนำ itsjeyd kill-regionบนคือ นี่คือตัวแปรของมัน แต่อย่างใด stylistically สอดคล้องกับข้างต้น:

(define-advice kill-region
    (:around (kill-region beg end &optional region) slick)
  (if (or mark-active (not region))
      (funcall kill-region beg end region)
    (funcall kill-region
             (line-beginning-position) (line-beginning-position 2))
    (message "Killed current line")))

โปรดทราบว่าหากtransient-mark-modeไม่ได้เปิดใช้งานคำแนะนำเหล่านี้จะไม่ทำอะไรเลย


หากคุณต้องการโซลูชันที่ครอบคลุมมากขึ้นให้พิจารณาใช้แพ็คเกจwhole-line-or-regionแทน ดูคำตอบโดย @sanityinc
Harald Hanche-Olsen

0

ผมใช้แพคเกจที่เรียกว่าcomposable.el สิ่งที่เรียบร้อยเกี่ยวกับแพ็กเกจคือการปรับเปลี่ยน Mw และ Cw (คัดลอกและฆ่าคำสั่ง) ให้เหมือน Vim มากขึ้นด้วยการหมุนที่ยอมรับคำสั่ง emacs แบบดั้งเดิมแทน ดังนั้นC-w lฆ่าทั้งเส้น แต่คุณสามารถทำสิ่งต่าง ๆ เช่นC-w M->การกำจัดจุดสิ้นสุดไฟล์ คำสั่งทั้งสองทำหน้าที่เหมือนปกติเมื่อทำเครื่องหมายภูมิภาค

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