Tôi đã thấy câu hỏi tương tự cho VIM và đó là điều mà bản thân tôi muốn biết làm thế nào cho Emacs. Trong ReSharper tôi sử dụng CTRL-D cho hành động này. Số lượng lệnh ít nhất để thực hiện điều này trong Emacs là gì?
Tôi đã thấy câu hỏi tương tự cho VIM và đó là điều mà bản thân tôi muốn biết làm thế nào cho Emacs. Trong ReSharper tôi sử dụng CTRL-D cho hành động này. Số lượng lệnh ít nhất để thực hiện điều này trong Emacs là gì?
Câu trả lời:
tôi sử dụng
C-a C-SPACE C-n M-w C-y
mà phá vỡ
C-a
: di chuyển con trỏ đến đầu dòngC-SPACE
: bắt đầu lựa chọn ("đặt dấu")C-n
: di chuyển con trỏ đến dòng tiếp theoM-w
: vùng sao chépC-y
: dán ("yank")Đã nói ở trên
C-a C-k C-k C-y C-y
số tiền cho cùng một điều (TMTOWTDI)
C-a
: di chuyển con trỏ đến đầu dòngC-k
: cắt ("giết") dòngC-k
: cắt dòng mớiC-y
: paste ("yank") (chúng tôi quay lại hình vuông)C-y
: dán lại (bây giờ chúng tôi đã có hai bản sao của dòng)Cả hai đều dài dòng đáng xấu hổ so với C-d
trong trình soạn thảo của bạn, nhưng trong Emacs luôn có một tùy chỉnh. C-d
bị ràng buộc delete-char
theo mặc định, vậy làm thế nào C-c C-d
? Chỉ cần thêm các mục sau vào .emacs
:
(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")
(Phiên bản elisp của @ Nathan có lẽ thích hợp hơn, vì nó sẽ không bị hỏng nếu bất kỳ ràng buộc chính nào bị thay đổi.)
Coi chừng: một số chế độ Emacs có thể lấy lại C-c C-d
để làm việc khác.
C-S-backspace C-y C-y
?
Ngoài các câu trả lời trước, bạn cũng có thể xác định chức năng của riêng mình để nhân đôi một dòng. Ví dụ: đặt phần sau vào tệp .emacs của bạn sẽ khiến Cd nhân đôi dòng hiện tại.
(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
Del
từ chức năng này?
Del
lại bình thường trong khi vẫn giữ nguyên cái mới C-d
: (global-set-key (kbd "<delete>") 'delete-char)
cần được thêm vào sau C-d
định nghĩa.
Đặt con trỏ trên dòng, nếu không bắt đầu, hãy làm CTRL- A, sau đó:
CTRL-K
CTRL-K
CTRL-Y
CTRL-Y
Phiên bản của tôi về chức năng sao chép một dòng hoạt động tốt với hoàn tác và không gây rối với vị trí con trỏ. Đó là kết quả của một cuộc thảo luận trong gnu.emacs.source từ tháng 11 năm 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))
Sau đó, bạn có thể xác định CTRL-D để gọi hàm này:
(global-set-key (kbd "C-d") 'duplicate-line)
crux-duplicate-current-line-or-region
hoạt động tốt hơn đối với tôi, bởi vì với chức năng của bạn, nó hoàn tác sao chép dòng và hoạt động cuối cùng.
Thay vì kill-line
( C-k
) như trong C-a
C-k
C-k
C-y
C-y
sử dụng kill-whole-line
lệnh:
C-S-Backspace
C-y
C-y
Những lợi thế C-k
bao gồm không quan trọng điểm nằm ở đâu trên đường thẳng (không giống như C-k
điểm bắt đầu của dòng) và nó cũng giết chết dòng mới (một lần nữa điều gì đó C-k
không làm được).
Đây là một chức năng khác để làm điều này. Phiên bản của tôi không chạm vào vòng khử và con trỏ kết thúc trên dòng mới, nơi nó ở trên bản gốc. Nó sẽ nhân đôi vùng nếu nó hoạt động (chế độ đánh dấu thoáng qua) hoặc mặc định để sao chép dòng khác. Nó cũng sẽ tạo nhiều bản sao nếu được cung cấp tiền tố arg và nhận xét dòng gốc nếu được cung cấp tiền tố phủ định arg (điều này hữu ích để kiểm tra phiên bản khác của lệnh / câu lệnh trong khi vẫn giữ nguyên phiên bản cũ).
(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)))))
Tôi có nó ràng buộc với C-c d
:
(global-set-key [?\C-c ?d] 'duplicate-line-or-region)
Điều này không bao giờ được gán lại bởi một chế độ hoặc bất cứ điều gì vì C-c
theo sau là một chữ cái duy nhất (chưa sửa đổi) được dành riêng cho các ràng buộc người dùng.
C-c d
tôi gặp lỗi command-execute: Wrong type argument: commandp, duplicate-line-or-region
. Có ý kiến gì không? Tôi đang sử dụng Emacs 25.1.1 trên Windows
Sự bổ sung của Nathan vào tệp .emacs của bạn là cách để đi nhưng nó có thể được đơn giản hóa một chút bằng cách thay thế
(open-line 1)
(next-line 1)
với
(newline)
năng suất
(defun duplicate-line()
(interactive)
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
cài đặt trùng lặp từ melpa:
Mx gói cài đặt RET trùng lặp
và thêm keybinding này vào tệp init :
(key-set-key (kbd "Mc") 'trùng lặp)
Tôi không nhớ cách sao chép dòng hoạt động ở bất cứ nơi nào khác, nhưng với tư cách là một người dùng SciTE trước đây, tôi thích một điều về SciTE-way: nó không chạm vào vị trí con trỏ! Vì vậy, tất cả những người nhận ở trên không đủ tốt cho tôi, đây là phiên bản hippie của tôi:
(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))))
Lưu ý rằng không có gì thực sự bị giết trong quá trình, giữ nguyên dấu và lựa chọn hiện tại.
BTW, tại sao các bạn lại thích giật con trỏ xung quanh khi có thứ giết người toàn diện đẹp đẽ này (CS-backspace)?
bởi vì tôi không biết, tôi sẽ bắt đầu vòng golf này bằng một quả bóng chậm:
ctrl-k, y, y
một cái gì đó bạn có thể muốn có trong .emacs của bạn là
(setq kill-whole-line t)
Về cơ bản sẽ giết chết toàn bộ dòng cộng với dòng mới bất cứ khi nào bạn gọi kill-line (tức là thông qua Ck). Sau đó, không cần thêm mã, bạn chỉ có thể thực hiện Ca Ck Cy Cy để nhân đôi dòng. Nó bị hỏng
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.
Nhưng nếu bạn sử dụng điều này thường xuyên thì có lẽ một ràng buộc khóa chuyên dụng có thể là một ý tưởng tốt hơn, nhưng lợi thế của việc chỉ sử dụng Ca Ck Cy Cy là bạn có thể sao chép dòng ở nơi khác, thay vì ngay dưới dòng hiện tại.
Tôi đã copy-from-above-command
ràng buộc với một chìa khóa và sử dụng đó. Nó được cung cấp với XEmac, nhưng tôi không biết về GNU Emacs.
`copy-from-trên-lệnh 'là một hàm Lisp được biên dịch tương tác
- được tải từ" /usr/share/xemacs/21.4.15/lisp/misc.elc "(copy-from-trên-lệnh & ARG tùy chọn)Tài liệu: Sao chép các ký tự từ dòng không trống trước đó , bắt đầu ngay trên điểm. Sao chép các ký tự ARG, nhưng không qua cuối dòng đó. Nếu không có đối số được đưa ra, sao chép toàn bộ phần còn lại của dòng. Các ký tự được sao chép được chèn vào bộ đệm trước điểm.
GNU Emacs 23.2.1 (amd64-portbld-freebsd8.1) of 2010-11-14 on [host clipped]
.
Có gói có tên Avy Nó có lệnh avy-copy-line. Khi bạn sử dụng lệnh đó, mọi dòng trong cửa sổ của bạn sẽ được kết hợp chữ cái. Sau đó, bạn chỉ cần gõ kết hợp và bạn nhận được dòng đó. Điều này cũng hoạt động cho khu vực. Sau đó, bạn chỉ cần gõ hai kết hợp.
Tại đây bạn có thể thấy giao diện:
Mặc định là khủng khiếp cho điều này. Tuy nhiên, bạn có thể mở rộng Emacs để hoạt động như SlickEdit và TextMate, nghĩa là sao chép / cắt dòng hiện tại khi không có văn bản nào được chọn:
(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)))))
Đặt ở trên .emacs
. Sau đó, để sao chép một dòng , M-w
. Để xóa một dòng , C-w
. Để nhân đôi một dòng , C-a M-w C-y C-y C-y ...
.
'Tôi đã viết phiên bản của riêng mình duplicate-line
, vì tôi không muốn làm hỏng vòng giết chóc.
(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)
Tôi thích phiên bản của FraGGod, ngoại trừ hai điều: (1) Nó không kiểm tra xem bộ đệm đã chỉ đọc với chưa (interactive "*")
và (2) nó không thành công ở dòng cuối cùng của bộ đệm nếu dòng cuối cùng trống (như bạn không thể tắt dòng trong trường hợp đó), để bộ đệm của bạn chỉ đọc.
Tôi đã thực hiện các thay đổi sau để giải quyết rằng:
(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)))))
Với các emacs gần đây, bạn có thể sử dụng Mw ở bất cứ đâu trong dòng để sao chép nó. Vì vậy, nó trở thành:
M-w C-a RET C-y
M-w
bị ràng buộc easy-kill
. Kiểm tra xem đó là những gì bạn nhận được khi làmC-h c M-w
Dù sao thì tôi cũng thấy những giải pháp rất phức tạp ...
(defun duplicate-line ()
"Duplicate current line"
(interactive)
(kill-whole-line)
(yank)
(yank))
(global-set-key (kbd "C-x M-d") 'duplicate-line)
ctrl- k, ctrl- k, (vị trí đến vị trí mới) ctrl-y
Thêm một ctrl- anếu bạn không bắt đầu ở đầu dòng. Và thứ 2 ctrl- klà lấy nhân vật dòng mới. Nó có thể được gỡ bỏ nếu bạn chỉ muốn văn bản.
Khi được gọi tương tác không có vùng hoạt động, thay vào đó, COPY (Mw) một dòng duy nhấ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)))))
Khi được gọi tương tác không có vùng hoạt động, thay vào đó, KILL (Cw) một dòng duy nhất.
(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)))))
Ngoài ra, trên một lưu ý liên quan:
(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)
Tôi viết một cho sở thích của tôi.
(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)
Nhưng tôi thấy điều này sẽ có một số vấn đề khi dòng hiện tại chứa các ký tự nhiều byte (ví dụ: các ký tự CJK). Nếu bạn gặp phải vấn đề này, hãy thử điều này thay vào đó:
(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)
Chức năng này phải phù hợp với triển khai của JetBrains về mặt sao chép cả theo dòng hoặc khu vực, sau đó để lại điểm và / hoặc khu vực hoạt động như mong đợi:
Chỉ là một trình bao bọc xung quanh các hình thức tương tác:
(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)))
Cái này gọi là
(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))
Hoặc cái này
(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))
Và sau đó tôi có ràng buộc này với meta + shift + d
(global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)
Như đã đề cập trong các câu trả lời khác, ràng buộc các nét chính với mã lisp là một ý tưởng tốt hơn so với ràng buộc chúng với các nét chính khác. Với câu trả lời của @ mw, mã sẽ nhân đôi dòng và di chuyển dấu đến cuối dòng mới. Sửa đổi này giữ vị trí đánh dấu ở cùng một cột trên dòng mới:
fun duplicate-line ()
(interactive)
(let ((col (current-column)))
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
(move-to-column col)))
Nếu bạn đang sử dụng Spacemac, bạn chỉ cần sử dụng duplicate-line-or-region
, ràng buộc với:
SPC x l d
Với các đối số tiền tố và hành vi trực quan (tôi hy vọng) là gì:
(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))))))
Con trỏ sẽ vẫn ở dòng cuối cùng. Ngoài ra, bạn có thể muốn chỉ định một tiền tố để nhân đôi một vài dòng tiếp theo cùng một lúc:
(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))
Tôi thấy mình sử dụng cả hai thường xuyên, sử dụng hàm bao bọc để chuyển đổi hành vi của đối số tiền tố.
Và một phím bấm:
(global-set-key (kbd "C-S-d") 'duplicate-line)
;; 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.
thêm elisp ở trên cho bạn init.el và bạn có chức năng cắt / sao chép toàn bộ dòng ngay bây giờ, sau đó bạn có thể F3 F4 để nhân đôi một dòng.
Cách đơn giản nhất là phương pháp của Chris Conway.
C-a C-SPACE C-n M-w C-y
Đó là cách mặc định được ủy quyền bởi EMACS. Theo tôi, tốt hơn là sử dụng tiêu chuẩn. Tôi luôn cẩn thận đối với việc tùy chỉnh ràng buộc khóa của chính mình trong EMACS. EMACS đã đủ mạnh, tôi nghĩ chúng ta nên cố gắng hết sức để thích nghi với các ràng buộc chính của nó.
Mặc dù nó hơi dài, nhưng khi bạn đã quen với nó, bạn có thể làm nhanh và sẽ thấy điều này thật thú vị!
Đây là một chức năng để nhân đôi dòng hiện tại. Với các đối số tiền tố, nó sẽ nhân đôi dòng nhiều lần. Ví dụ, C-3 C-S-o
sẽ nhân đôi dòng hiện tại ba lần. Không thay đổi vòng giết.
(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)