¿Cómo duplico una línea completa en Emacs?
text editor (29)
Vi esta misma pregunta para VIM y ha sido algo que yo mismo quería saber cómo hacer para Emacs. En ReSharper utilizo CTRL-D para esta acción. ¿Cuál es la menor cantidad de comandos para realizar esto en Emacs?
''Escribí mi propia versión de duplicate-line
, porque no quiero estropear el anillo asesino.
(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)
@ [Kevin Conner]: Muy cerca, por lo que sé. La única otra cosa a considerar es encender kill-whole-line
para incluir la nueva línea en el Ck.
Además de las respuestas anteriores, también puedes definir tu propia función para duplicar una línea. Por ejemplo, poner lo siguiente en su archivo .emacs hará que Cd duplique la línea actual.
(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)
Aquí hay otra función para hacer esto. Mi versión no toca el anillo de sacrificio, y el cursor termina en la nueva línea donde estaba en el original. Duplicará la región si está activa (modo de marca transitoria) o, de lo contrario, duplicará la línea. También hará copias múltiples si se le da un prefijo arg, y comentará la línea original si se le da un prefijo negativo arg (esto es útil para probar una versión diferente de un comando / instrucción manteniendo el anterior).
(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)))))
Lo tengo obligado a Cc d
:
(global-set-key [?/C-c ?d] ''duplicate-line-or-region)
Esto nunca debería ser reasignado por un modo ni nada, ya que Cc
seguido de una sola letra (no modificada) está reservada para enlaces de usuario.
Aquí hay una función para duplicar la línea actual. Con los argumentos de prefijo, duplicará la línea varias veces. Por ejemplo, C-3 CSo
duplicará la línea actual tres veces. No cambia el anillo de matar.
(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)
Coloque el cursor en línea, si no al principio, haga una CTRL - A , luego:
CTRL - K
CTRL - K
CTRL - Y
CTRL - Y
Con argumentos de prefijo, y qué es (espero) comportamiento intuitivo:
(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))))))
El cursor permanecerá en la última línea. Alternativamente, es posible que desee especificar un prefijo para duplicar las siguientes líneas a la vez:
(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))
Me encuentro usando ambos a menudo, usando una función de envoltura para cambiar el comportamiento del argumento de prefijo.
Y una combinación de teclas: (global-set-key (kbd "CSd") ''duplicate-line)
Con emacs recientes, puede usar Mw en cualquier lugar de la línea para copiarlo. Entonces se convierte en:
M-w C-a RET C-y
Cuando se llama interactivamente sin región activa, COPY (Mw) una sola línea en su lugar:
(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)))))
Cuando se llama interactivamente sin una región activa, KILL (Cw) una sola línea en su lugar.
(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)))))
Además, en una nota relacionada:
(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)
En lugar de kill-line
( Ck
) como en Ca
Ck
Ck
Cy
Cy
usa el comando kill-whole-line
:
C-S-Backspace
C-y
C-y
Las ventajas sobre Ck
incluyen que no importa dónde está el punto en la línea (a diferencia de Ck
que requiere estar al inicio de la línea) y también mata a la línea nueva (de nuevo, algo que Ck
no hace).
Escribo uno para mi preferencia.
(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)
Pero encontré que esto tendría algún problema cuando la línea actual contiene caracteres de varios bytes (por ejemplo, caracteres CJK). Si encuentra este problema, intente esto en su lugar:
(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)
Esta funcionalidad debe coincidir con la implementación de JetBrains en términos de duplicación por línea o región, y luego dejar el punto y / o la región activa como se esperaba:
Solo un envoltorio alrededor del formulario interactivo:
(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)))
Lo que llama esto,
(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))
O esto
(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://.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))
Y luego tengo esto obligado a meta + shift + d
(global-set-key (kbd "M-D") ''wrx/duplicate-line-or-region)
Hay un paquete llamado Avy Tiene el comando avy-copy-line. Cuando usa ese comando, cada línea de su ventana obtiene una combinación de letras. Entonces solo tienes que escribir la combinación y obtienes esa línea. Esto también funciona para la región. Entonces solo tienes que escribir dos combinaciones.
Aquí puedes ver la interfaz:
La forma más simple es el método de Chris Conway.
C-a C-SPACE C-n M-w C-y
Esa es la forma predeterminada ordenada por EMACS. En mi opinión, es mejor usar el estándar. Siempre tengo cuidado con la personalización del enlace de claves en EMACS. EMACS ya es lo suficientemente potente, creo que deberíamos hacer todo lo posible para adaptarnos a sus propias vinculaciones.
Aunque es un poco largo, pero cuando estás acostumbrado, puedes hacerlo rápido y encontrarás que es divertido.
La incorporación de Nathan a su archivo .emacs es el camino a seguir, pero podría simplificarse ligeramente reemplazando
(open-line 1)
(next-line 1)
con
(newline)
flexible
(defun duplicate-line()
(interactive)
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
)
(global-set-key (kbd "C-d") ''duplicate-line)
Los valores predeterminados son horribles para esto. Sin embargo, puede extender Emacs para que funcione como SlickEdit y TextMate, es decir, copiar / cortar la línea actual cuando no se selecciona texto:
(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)))))
Coloque lo anterior en .emacs
. Entonces, para copiar una línea, Mw
. Para eliminar una línea, Cw
. Para duplicar una línea, Ca Mw Cy Cy Cy ...
Me gustó la versión de FraGGod, excepto por dos cosas: (1) No comprueba si el búfer ya es de solo lectura con (interactive "*")
, y (2) falla en la última línea del búfer si ese último la línea está vacía (ya que no se puede eliminar la línea en ese caso), dejando el búfer como de solo lectura.
Hice los siguientes cambios para resolver eso:
(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)))))
Mi versión de una función para duplicar una línea que funciona bien con deshacer y no molesta con la posición del cursor. Fue el resultado de una discusión en gnu.emacs.sources desde noviembre de 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))
Luego puede definir CTRL-D para llamar a esta función:
(global-set-key (kbd "C-d") ''duplicate-line)
No recuerdo exactamente cómo funciona la duplicación de líneas en ningún otro lado, pero como antiguo usuario de SciTE, me gustó una cosa sobre SciTE-way: ¡no toca la posición del cursor! Entonces, todas las recetas anteriores no eran lo suficientemente buenas para mí, aquí está mi versión hippie:
(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))))
Tenga en cuenta que nada se mata realmente en el proceso, dejando intactas las marcas y la selección actual.
Por cierto, ¿por qué ustedes tan aficionado a sacudir el cursor cuando hay esta cosita bonita de matar toda la línea (CS-backspace)?
Tengo copy-from-above-command
vinculado a una clave y lo uso. Está provisto con XEmacs, pero no sé sobre GNU Emacs.
`copy-from-above-command ''es una función Lisp compilada interactiva
- cargado desde "/usr/share/xemacs/21.4.15/lisp/misc.elc" (comando copy-from-above y ARG opcional)Documentación: Copie los caracteres de la línea anterior que no está en blanco , comenzando justo por encima del punto. Copie los caracteres ARG, pero no más allá del final de esa línea. Si no se ofrece ningún argumento, copie el resto de la línea. Los caracteres copiados se insertan en el búfer antes del punto.
Vi soluciones muy complejas, de todos modos ...
(defun duplicate-line ()
"Duplicate current line"
(interactive)
(kill-whole-line)
(yank)
(yank))
(global-set-key (kbd "C-x M-d") ''duplicate-line)
algo que es posible que desee tener en su .emacs es
(setq kill-whole-line t)
Que básicamente mata toda la línea más la línea nueva cada vez que invocas kill-line (es decir, a través de Ck). Luego, sin código adicional, puedes hacer Ca Ck Cy Cy para duplicar la línea. Se descompone en
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.
Pero si usa esto con frecuencia, tal vez un enlace de clave dedicado sea una mejor idea, pero la ventaja de usar Ca Ck Cy Cy es que puede duplicar la línea en otro lugar, en lugar de simplemente debajo de la línea actual.
bien ive usualmente usado:
Ctl-Space (set the mark) move to end of line Ctl-K kill line Ctl-Y * 2 (yank the line back)
sin embargo, puede haber una manera mucho mejor: P
instalar duplicado-cosa de melpa
y agrega esta combinación de teclas:
(global-set-key (kbd "Mc") ''duplicado-cosa)
porque no sé, comenzaré esta ronda de golf con una bola lenta:
ctrl-k, y, y
yo suelo
C-a C-SPACE C-n M-w C-y
que se descompone en
-
Ca
: mueve el cursor al inicio de la línea -
C-SPACE
: comienza una selección ("set mark") -
Cn
: mover el cursor a la siguiente línea -
Mw
: copiar región -
Cy
: paste ("tirón")
Lo antes mencionado
C-a C-k C-k C-y C-y
equivale a lo mismo (TMTOWTDI)
-
Ca
: mueve el cursor al inicio de la línea -
Ck
: cortar ("matar") la línea -
Ck
: cortar la nueva línea -
Cy
: paste ("tirón") (estamos de vuelta en el cuadrado uno) -
Cy
: pegar nuevamente (ahora tenemos dos copias de la línea)
Estos son embarazosamente verbosos en comparación con Cd
en tu editor, pero en Emacs siempre hay una personalización. Cd
está obligado a delete-char
por defecto, entonces ¿qué hay de Cc Cd
? Simplemente agregue lo siguiente a su .emacs
:
(global-set-key "/C-c/C-d" "/C-a/C- /C-n/M-w/C-y")
(Es probable que sea preferible la versión elisp de @ Nathan, porque no se romperá si se cambian algunas de las combinaciones de teclas).
Cuidado: algunos modos de Emacs pueden reclamar Cc Cd
para hacer otra cosa.
ctrl - k , ctrl - k , (posición a nueva ubicación) ctrl - y
Agregue un ctrl - a si no está comenzando al principio de la línea. Y el segundo ctrl - k es para agarrar el carácter de nueva línea. Se puede eliminar si solo quieres el texto.
;; 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.
agrega la elisp de arriba a init.el, y ahora puedes cortar / copiar la función de línea completa, luego puedes F3 F4 para duplicar una línea.
C-a C-k C-k C-y C-y