Giết hoặc sao chép dòng hiện tại với tổ hợp phím tối thiểu


32

Tôi làm C-a C-k C-kđể giết toàn bộ điểm dòng là trên.

Nếu tôi muốn sao chép dòng thay vì giết nó, tôi có thể đánh C-/ C-/ ngay sau khi gõ chuỗi trên.

Ngoài ra, tôi có thể làm C-a C-SPC C-n M-w.

Có cách nào nhanh hơn để giết hoặc sao chép toàn bộ điểm dòng đang bật không?


1
Ồ Những câu trả lời này cho thấy độ dài tuyệt vời mà mọi người sẽ sử dụng để tránh sử dụng tích hợp kill-whole-line. :)
Omar

Theo đề xuất dưới đây, sử dụng evil-mode. Tìm hiểu các lệnh Vim, bạn sẽ không hối tiếc!
A. Bão tuyết

Câu trả lời:


44

Bạn có thể sử dụng kill-whole-lineđể tiêu diệt toàn bộ điểm dòng đang bật. Vị trí của điểm không quan trọng. Lệnh này được ràng buộc C-S-DELtheo mặc định.

Bạn cũng có thể ra lệnh kill-line(ràng buộc C-k) để giết toàn bộ dòng bằng cách đặt biến kill-whole-line thành nilgiá trị không :

(setq kill-whole-line t)

Lưu ý rằng điểm phải ở đầu dòng để làm việc này.


Sau đó, có hai viên đá quý (thông qua 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)))))

Với những vị trí này, bạn có thể giết hoặc sao chép điểm dòng được bật bằng một lần nhấn phím :

  • C-w giết chết dòng hiện tại
  • M-w sao chép dòng hiện tại

Lưu ý rằng nếu có một khu vực hoạt động kill-regionkill-ring-savesẽ tiếp tục làm những gì họ thường làm: Giết hoặc sao chép nó.


Chuyển slick-cutslick-copyhệ thống tư vấn mới

Emacs 24.4 giới thiệu một hệ thống tư vấn mới . Mặc dù defadvice vẫn hoạt động , có khả năng nó có thể bị từ chối ủng hộ hệ thống mới trong các phiên bản tương lai của Emacs. Để chuẩn bị cho điều đó, bạn có thể muốn sử dụng các phiên bản cập nhật của slick-cutslick-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
Lưu ý rằng kill-regionkill-ring-savevẫn hoạt động ngay cả khi khu vực không "hoạt động". Điều này sẽ ghi đè hành vi đó. Thỉnh thoảng tôi vẫn sử dụng hành vi đó, nhưng nếu bạn không quen sử dụng chúng theo cách này, thì có lẽ bạn sẽ không nhận thấy sự khác biệt.
nispio

@nispio Vui lòng mở rộng khi nào / như thế nào kill-regionvv có thể sử dụng / hữu ích khi mark-activenil.
Phil Hudson

1
@PhilHudson Dấu có thể được đặt (và thường là) mà không được kích hoạt. Hãy thử thực hiện C-SPChai lần để kích hoạt và sau đó hủy kích hoạt nhãn hiệu. Di chuyển con trỏ đến nơi khác trong tệp và chạy kill-regionvà nó sẽ giết vùng giữa điểm và điểm, mặc dù dấu không hoạt động. Một vài ví dụ về các lệnh đã đặt (nhưng không kích hoạt) dấu là yankisearch. Sau khi thực hiện các lệnh sắp xếp này, tôi biết dấu hiệu ở đâu, ngay cả khi nó không hoạt động và nhiều lệnh (bao gồm kill-region) sẽ cho phép tôi sử dụng dấu mà không kích hoạt rõ ràng.
nispio

Cảm ơn @nispio. Tất nhiên. Đó là cách nó đã từng, độc quyền, trước khi làm nổi bật vùng hiển thị trở thành mặc định một vài bản phát hành chính trở lại, phải không? Tôi đã nhầm lẫn "hoạt động" với "thiết lập".
Phil Hudson

1
Đây là câu trả lời lớn nhất từng được đăng trên bất kỳ SX. Nghiêm túc.
Benjamin Lindqvist

15

Giải pháp tôi đã tìm thấy cho bản thân mình là sử dụng các đối số tiền tố.

Đối với tôi, giết một nửa dòng là một tính năng hữu ích, nhưng tôi cũng muốn một cách dễ dàng hơn để giết toàn bộ dòng. Vì vậy, tôi đã làm cho nó để kill-linegiết chết mọi thứ trong tầm nhìn khi đưa ra một đối số tiền tố.

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

Với macro nhỏ này, C-kvẫn giết chết điểm, nhưng C-3 C-knuốt cả ba dòng. Như một phần thưởng, chúng ta có được kill-whole-linehành vi bằng cách làm C-1 C-k.


Đó là một ý tưởng tuyệt vời, cảm ơn vì đã chia sẻ nó! :) Làm thế nào bạn thích ứng giải pháp này để làm việc để sao chép một hoặc nhiều dòng? kill-ring-savekhông chấp nhận đối số tiền tố ...
itjeyd

@itsjeyd Tôi chắc chắn có thể làm điều gì đó tương tự để hợp nhất hai câu trả lời. Nhưng nó chỉ mất một chút công việc.
Malabarba

Dòng cuối cùng đề cập đến paredit-kill. Có dự định không?
Boccaperta-IT

1
Ồ, được rồi, cảm ơn. Tôi không nhận được hành vi mong đợi, mặc dù. Nếu tôi đặt con trỏ ở giữa một dòng và nhấn C-3 Ck, dòng đầu tiên không hoàn toàn bị giết. Đây có phải là cách nó được cho là đang làm việc hay tôi đang làm gì đó sai?
Boccaperta-IT

1
@Malabarba bạn đúng, kill-visual-linebị ràng buộc C-k. Tôi sẽ sửa chữa nó. Cảm ơn một lần nữa.
Boccaperta-IT

15

Có một gói được gọi là whole-line-or-regiontư vấn cho các lệnh tích hợp khác nhau để chúng hoạt động trên dòng hiện tại nếu không có vùng nào đang hoạt động, vì vậy M-wsẽ sao chép dòng hiện tại và C-wsẽ giết nó. Tôi đã sử dụng gói này trong nhiều năm và thấy nó không thể thiếu.

Ngoài ra, gói này làm cho nó để một tiền tố số sẽ chỉ ra số lượng dòng để hành động, do đó M-2 M-wsẽ sao chép hai dòng. Các câu trả lời khác ở đây không cung cấp chức năng tiện dụng đó.

Tôi đã tiếp tục bảo trì gói tại tài khoản github của mình khi tác giả ngừng bảo trì và không phản hồi.

whole-line-or-region cũng cung cấp các phương tiện để thêm hành vi này vào các lệnh tiếp theo, nếu bạn cần điều đó.


Vui lòng gửi một vấn đề MELPA cho điều đó, bởi vì tôi không chắc ý của bạn là gì: Tôi cài đặt gói này từ MELPA mọi lúc mà không gặp vấn đề gì.
sanityinc

9

Đây không phải là một câu trả lời cho emacs chính thống. Tuy nhiên, nếu bạn sẵn sàng báng bổ với evilchỉnh sửa phương thức, bạn có thể:

  • dd cho dòng tiêu diệt
  • cc cho dòng sao chép

Cả hai có thể được bắt đầu bằng số lượng dòng cần giết / sao chép (ví dụ: 4ccsẽ sao chép 4 dòng tiếp theo).


5

Ngoài câu trả lời @itsjeyd, tôi có thể đề xuất hai chức năng đó không?

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

Sau đó, các định nghĩa chính (có thể bạn sẽ muốn điều chỉnh chúng):

(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

Phép lịch sự của ErgoEmacs


Cảm ơn câu trả lời của bạn! Bạn có thể muốn xem xét mở rộng nó một chút bằng cách mô tả các lệnh này khác với các giải pháp khác được đăng ở đây như thế nào. Vâng, thông tin này có sẵn trong các tài liệu, nhưng nó không gây hại gì để hiển thị rõ hơn cho độc giả trong tương lai :)
itjeyd

1
Có thể làm điều này nhưng sửa đổi nó như bài đăng @Jonathan bên dưới để trước tiên nó lấy sexp hoặc từ và sau đó lấy dòng nếu được gọi lại?
J Spen

@JSpen Những gì tôi đang làm là gán một phím tắt cho chức năng. Những gì Jonathan đang làm là xác định một lời khuyên cho một chức năng. Vì vậy, bạn chỉ có thể tư vấn cho chức năng, sau đó xác định một phím tắt cho chức năng được khuyến khích; và bạn sẽ có kết quả của bạn. Xin lỗi vì sự chậm trễ;)
Nsukami _

4

Là một phần mở rộng cho câu trả lời của @ Itsjeyd ở trên, tôi có những điều sau đây. (Logic có thể có thể được làm sạch một chút và tôi sẽ chuyển sang hệ thống tư vấn mới, tôi cũng có thể mở rộng nó để mở rộng đến sexp/ paragraphnếu lặp lại lần nữa).

Một chữ cái đầu tiên C-w/ M-wsẽ chỉ lấy từ tại điểm, trong khi gọi nó là lần thứ hai sẽ lấy toàn bộ dòng.

;; *** 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)))))))

Bạn đã cập nhật điều này và nếu vậy một bản sao ở đâu? Ngoài ra, điều này thêm một tấn nhãn hiệu vào vòng đánh dấu. Nó có thể chỉ cần thêm một dấu ở đầu nơi nó được sao chép. Vì vậy, bắt đầu của từ hoặc bắt đầu của dòng. Bây giờ nó thêm như bốn điểm mỗi lần gây phiền nhiễu. Tôi thực sự đã thay đổi nó để sử dụng (back-sexp) nhưng đôi khi nó không thể tìm thấy và nó gây ra lỗi. Nó chỉ có thể sao chép dòng nếu nó không tìm thấy? Tôi không chắc chắn làm thế nào để làm điều này hoặc chỉ bỏ qua lỗi và không gây ra tiếng ồn. Xin lỗi, tôi không phải là người giỏi nhất.
J Spen

1

Vì bạn muốn làm điều đó với các phím phím tối thiểu, bạn có thể sử dụng gói hợp âm phím tuyệt vời của David Andersson . "Hợp âm phím" là hai phím được bấm đồng thời hoặc một phím được bấm hai lần.

Bạn có thể liên kết bất kỳ hợp âm quan trọng nào với các chức năng đó.

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

Cảm ơn câu trả lời của bạn :) Tôi đã thử các hợp âm chính một vài lần trong quá khứ và không thể thực sự quen với chúng. Nhưng đây chắc chắn là một bổ sung hữu ích cho bộ nếu câu trả lời được thu thập ở đây!
itjeyd

1

Một cách ít đặc biệt hơn là xác định mark-whole-line, mà Emacs thực sự nên có một lệnh mặc định.

(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

Rồi C-2 C-wsẽ làm việc.

Nó cũng làm cho mọi thứ dễ dàng hơn như bình luận toàn bộ dòng hiện tại.


0

Đây là bản sửa đổi câu trả lời của itjeyd - hiện là câu trả lời được bình chọn cao nhất và là câu trả lời tôi đã sử dụng trong nhiều năm. Tuy nhiên, nó có vấn đề: Phiên bản được khuyến khích kill-ring-saveđôi khi sẽ thất bại vì nhãn hiệu không được đặt (thường là trong bộ đệm mới) và ngay cả khi nó hoạt động, con trỏ đã thực hiện một điệu nhảy lạ sau khi sử dụng chức năng để sao chép một dòng . Sau khi đào bới, tôi nhận ra rằng điều này xảy ra bởi vì kill-ring-savecác cuộc gọi indicate-copied-regionsau khi nó đã hoàn thành công việc của nó, nhưng vì điểm và dấu không khớp với vùng đã sao chép, indicate-copied-regionđánh dấu vùng sai.

Đủ nói. Đây là một giải pháp khắc phục điều này:

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

Không có gì sai với lời khuyên của itjeyd kill-region. Dù sao, đây là một biến thể của nó, phù hợp hơn với phong cách trên:

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

Lưu ý rằng nếu transient-mark-modekhông được bật, những lời khuyên này không làm gì cả.


Nếu bạn muốn một giải pháp toàn diện hơn, hãy xem xét sử dụng gói whole-line-or-regionthay thế; xem câu trả lời của @sanityinc.
Harald Hanche-Olsen

0

Tôi sử dụng một gói được gọi là composable.el . Điều thú vị của gói là nó sửa đổi Mw và Cw (sao chép và hủy các lệnh) để giống Vim hơn với sự thay đổi khi nó chấp nhận các lệnh emacs truyền thống. Vì vậy, C-w lgiết chết cả một dòng. Nhưng bạn cũng có thể làm những việc như C-w M->giết hết tập tin. Cả hai lệnh hoạt động như bình thường khi đánh dấu một khu vực.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.