Vi esta misma pregunta para VIM y ha sido algo que yo mismo quería saber cómo hacer para Emacs. En ReSharper uso CTRL-D para esta acción. ¿Cuál es el menor número de comandos para realizar esto en Emacs?
Vi esta misma pregunta para VIM y ha sido algo que yo mismo quería saber cómo hacer para Emacs. En ReSharper uso CTRL-D para esta acción. ¿Cuál es el menor número de comandos para realizar esto en Emacs?
Respuestas:
yo suelo
C-a C-SPACE C-n M-w C-y
que se descompone en
C-a
: mueve el cursor al inicio de la líneaC-SPACE
: comienza una selección ("set mark")C-n
: mueve el cursor a la siguiente líneaM-w
: copiar regiónC-y
: pegar ("tirar")Lo antes mencionado
C-a C-k C-k C-y C-y
equivale a lo mismo (TMTOWTDI)
C-a
: mueve el cursor al inicio de la líneaC-k
: cortar ("matar") la líneaC-k
: cortar la nueva líneaC-y
: paste ("yank") (volvemos al punto de partida)C-y
: pegar de nuevo (ahora tenemos dos copias de la línea)Ambos son vergonzosamente verbosos en comparación con C-d
su editor, pero en Emacs siempre hay una personalización. C-d
está obligado delete-char
por defecto, ¿qué tal C-c C-d
? Simplemente agregue lo siguiente a su .emacs
:
(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")
(La versión elisp de @ Nathan probablemente sea preferible, porque no se romperá si se cambia alguna de las combinaciones de teclas).
Cuidado: algunos modos de Emacs pueden reclamar C-c C-d
para hacer otra cosa.
C-S-backspace C-y C-y
?
Además de las respuestas anteriores, también puede definir su 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)
Symbol's function definition is void: move-beginning-of-line
Del
de esta función?
Del
a la normalidad manteniendo el nuevo C-d
: (global-set-key (kbd "<delete>") 'delete-char)
debe agregarse después de la C-d
definición.
Coloque el cursor en la línea, si no al principio, haga un CTRL- A, luego:
CTRL-K
CTRL-K
CTRL-Y
CTRL-Y
Mi versión de una función para duplicar una línea que funciona bien con deshacer y no se mete con la posición del cursor. Fue el resultado de una discusión en gnu.emacs.sources de 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)
crux-duplicate-current-line-or-region
funciona mejor para mí, porque con su función también deshace la duplicación de línea y la última operación.
En lugar de kill-line
( C-k
) como en C-a
C-k
C-k
C-y
C-y
uso, el kill-whole-line
comando:
C-S-Backspace
C-y
C-y
Las ventajas C-k
incluyen que no importa dónde está el punto en la línea (a diferencia de lo C-k
que requiere estar al comienzo de la línea) y también mata a la nueva línea (de nuevo, algo C-k
no funciona).
Aquí hay otra función para hacer esto. Mi versión no toca el anillo de matar, 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 de forma predeterminada. También hará varias copias si se le da un argumento prefijo arg, y comentará la línea original si se le da un argumento prefijo negativo (esto es útil para probar una versión diferente de un comando / declaración mientras se mantiene la 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 C-c d
:
(global-set-key [?\C-c ?d] 'duplicate-line-or-region)
Esto nunca debe ser reasignado por un modo o cualquier cosa porque C-c
seguido de una sola letra (no modificada) está reservada para enlaces de usuario.
C-c d
me sale el error command-execute: Wrong type argument: commandp, duplicate-line-or-region
. Alguna idea de lo que pasa? Estoy usando Emacs 25.1.1 en Windows
La adició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)
instalar duplicado de melpa:
Mx package-install RET duplicate-thing
y agregue esta combinación de teclas al archivo init :
(global-set-key (kbd "Mc") 'duplicate-thing)
No recuerdo cómo funciona la duplicación de líneas en ningún otro lugar, pero como antiguo usuario de SciTE me gustó una cosa acerca de SciTE-way: ¡no toca la posición del cursor! Entonces, todas las recetas anteriores no fueron 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 en el proceso, dejando intactas las marcas y la selección actual.
Por cierto, ¿por qué ustedes tan aficionados a mover el cursor cuando hay esta cosa agradable y limpia de línea completa (CS-retroceso)?
porque no sé, comenzaré esta ronda de golf con una bola lenta:
Ctrl-k, y, y
algo que tal vez quieras tener en tu .emacs es
(setq kill-whole-line t)
Que básicamente mata toda la línea más la nueva línea cada vez que invocas kill-line (es decir, a través de Ck). Luego, sin código adicional, puede 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 a menudo, tal vez una combinación de teclas dedicada podría ser 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 justo debajo de la línea actual.
Me he copy-from-above-command
atado a una clave y la uso. Se proporciona con XEmacs, pero no sé acerca de GNU Emacs.
`copy-from-above-command 'es una función Lisp compilada interactiva
, cargada desde" /usr/share/xemacs/21.4.15/lisp/misc.elc "(copy-from-above-command & 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 presenta ningún argumento, copie todo el resto de la línea. Los caracteres copiados se insertan en el búfer antes del punto.
GNU Emacs 23.2.1 (amd64-portbld-freebsd8.1) of 2010-11-14 on [host clipped]
.
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. Luego 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:
Los valores predeterminados son horribles para esto. Sin embargo, puede extender Emacs para trabajar 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
. Luego, para copiar una línea M-w
,. Para borrar una línea C-w
,. Para duplicar una línea, C-a M-w C-y C-y C-y ...
.
'Escribí mi propia versión de duplicate-line
, porque no quiero arruinar el anillo de la muerte.
(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)
Me gustó la versión de FraGGod, excepto por dos cosas: (1) No comprueba si el búfer ya es de solo lectura (interactive "*")
, y (2) falla en la última línea del búfer si esa última línea está vacía (como usted no puede matar la línea en ese caso), dejando su búfer 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)))))
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
M-w
está obligado a easy-kill
. Comprueba que eso es lo que obtienes cuando lo hacesC-h c M-w
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)
ctrl- k, ctrl- k, (posición a nueva ubicación) ctrl-y
Agregue un ctrl- asi no está comenzando al principio de la línea. Y el segundo ctrl- kes para agarrar el carácter de nueva línea. Se puede eliminar si solo desea el texto.
Cuando se llama de forma interactiva 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 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)
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 descubrí 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 región activa como se esperaba:
Solo una envoltura 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)))
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://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))
Y luego tengo esto vinculado a meta + shift + d
(global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)
Como se menciona en otras respuestas, vincular las pulsaciones de teclas al código lisp es una mejor idea que vincularlas a otras pulsaciones de teclas. Con la respuesta de @ mw, el código duplica la línea y mueve la marca al final de la nueva línea. Esta modificación mantiene la posición de la marca en la misma columna en la nueva línea:
fun duplicate-line ()
(interactive)
(let ((col (current-column)))
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
(move-to-column col)))
Si está utilizando Spacemacs, simplemente puede usar duplicate-line-or-region
, vinculado a:
SPC x l d
Con argumentos de prefijo, y cuál es (espero) un 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 contenedor para cambiar el comportamiento del argumento prefijo.
Y una combinación de teclas:
(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.
agregue el elisp anterior a su init.el, y obtendrá la función de cortar / copiar toda la línea ahora, luego puede F3 F4 para duplicar una línea.
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 de la propia atadura de teclas en EMACS. EMACS ya es lo suficientemente potente, creo que deberíamos hacer todo lo posible para adaptarnos a sus propias combinaciones de teclas.
Aunque es un poco largo, pero cuando estás acostumbrado, ¡puedes hacerlo rápido y encontrarás que es divertido!
Aquí hay una función para duplicar la línea actual. Con argumentos de prefijo, duplicará la línea varias veces. Por ejemplo, C-3 C-S-o
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)