J'ai vu cette même question pour VIM et c'est quelque chose que je voulais moi-même savoir faire pour Emacs. Dans ReSharper, j'utilise CTRL-D pour cette action. Quel est le plus petit nombre de commandes pour effectuer cela dans Emacs?
J'ai vu cette même question pour VIM et c'est quelque chose que je voulais moi-même savoir faire pour Emacs. Dans ReSharper, j'utilise CTRL-D pour cette action. Quel est le plus petit nombre de commandes pour effectuer cela dans Emacs?
Réponses:
j'utilise
C-a C-SPACE C-n M-w C-y
qui se décompose en
C-a
: déplacer le curseur au début de la ligneC-SPACE
: commencer une sélection ("set mark")C-n
: déplacer le curseur sur la ligne suivanteM-w
: copier la régionC-y
: coller ("yank")Le précité
C-a C-k C-k C-y C-y
revient au même (TMTOWTDI)
C-a
: déplacer le curseur au début de la ligneC-k
: couper ("tuer") la ligneC-k
: couper la nouvelle ligneC-y
: paste ("yank") (nous sommes de retour à la case départ)C-y
: collez à nouveau (maintenant nous avons deux copies de la ligne)Ce sont tous les deux embarrassants par rapport à C-d
votre éditeur, mais dans Emacs, il y a toujours une personnalisation. C-d
est lié delete-char
par défaut, alors qu'en est-il C-c C-d
? Ajoutez simplement ce qui suit à votre .emacs
:
(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")
(La version elisp de @ Nathan est probablement préférable, car elle ne se cassera pas si l'une des combinaisons de touches est modifiée.)
Attention: certains modes Emacs peuvent réclamer C-c C-d
autre chose.
C-S-backspace C-y C-y
?
En plus des réponses précédentes, vous pouvez également définir votre propre fonction pour dupliquer une ligne. Par exemple, en plaçant ce qui suit dans votre fichier .emacs, Cd dupliquera la ligne actuelle.
(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 cette fonction?
Del
à la normale tout en conservant le nouveau C-d
: (global-set-key (kbd "<delete>") 'delete-char)
doit être ajouté après la C-d
définition.
Placez le curseur sur la ligne, sinon au début, faites un CTRL- A, puis:
CTRL-K
CTRL-K
CTRL-Y
CTRL-Y
Ma version d'une fonction pour dupliquer une ligne qui fonctionne bien avec undo et ne gâche pas la position du curseur. C'était le résultat d'une discussion dans gnu.emacs.sources de novembre 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))
Ensuite, vous pouvez définir CTRL-D pour appeler cette fonction:
(global-set-key (kbd "C-d") 'duplicate-line)
crux-duplicate-current-line-or-region
fonctionne mieux pour moi, car avec votre fonction, il annule la duplication de ligne et la dernière opération également.
Au lieu de kill-line
( C-k
) comme dans l' C-a
C-k
C-k
C-y
C-y
utilisation de la kill-whole-line
commande:
C-S-Backspace
C-y
C-y
Les avantages par rapport à cela C-k
incluent que peu importe où se trouve le point sur la ligne (contrairement à C-k
ce qui nécessite d'être au début de la ligne) et qu'il tue également la nouvelle ligne (encore une fois, quelque chose C-k
ne fonctionne pas).
Voici encore une autre fonction pour faire cela. Ma version ne touche pas l'anneau de destruction et le curseur se retrouve sur la nouvelle ligne où il se trouvait sur l'original. Il dupliquera la région si elle est active (mode de marque transitoire), ou dupliquera par défaut la ligne dans le cas contraire. Il fera également plusieurs copies si on lui donne un préfixe arg, et commentera la ligne d'origine si on lui donne un préfixe négatif arg (ceci est utile pour tester une version différente d'une commande / instruction tout en conservant l'ancienne).
(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)))))
Je l'ai lié à C-c d
:
(global-set-key [?\C-c ?d] 'duplicate-line-or-region)
Cela ne doit jamais être réaffecté par un mode ou quoi que ce soit, car C-c
suivi d'une seule lettre (non modifiée) est réservé aux liaisons utilisateur.
C-c d
j'obtiens l'erreur command-execute: Wrong type argument: commandp, duplicate-line-or-region
. Une idée de ce qui se passe? J'utilise Emacs 25.1.1 sur Windows
L'ajout de Nathan à votre fichier .emacs est la voie à suivre, mais il pourrait être légèrement simplifié en remplaçant
(open-line 1)
(next-line 1)
avec
(newline)
céder
(defun duplicate-line()
(interactive)
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
installez duplicate-thing de melpa:
Mx package-install RET duplicate-thing
et ajoutez cette liaison de touches au fichier init :
(global-set-key (kbd "Mc") 'duplicate-thing)
Je ne me souviens pas très bien comment la duplication de ligne fonctionne ailleurs, mais en tant qu'ancien utilisateur de SciTE, j'ai aimé une chose à propos de SciTE-way: cela ne touche pas la position du curseur! Donc, toutes les recettes ci-dessus n'étaient pas assez bonnes pour moi, voici ma version 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))))
Notez que rien n'est réellement tué dans le processus, laissant les marques et la sélection actuelle intactes.
BTW, pourquoi vous aimez tant à secouer le curseur quand il y a ce joli truc de kill-whole-line (CS-backspace)?
parce que je ne sais pas, je vais commencer cette ronde de golf avec une balle lente:
ctrl-k, y, y
quelque chose que vous voudrez peut-être avoir dans votre .emacs est
(setq kill-whole-line t)
Ce qui tue fondamentalement la ligne entière plus la nouvelle ligne chaque fois que vous invoquez kill-line (c'est-à-dire via Ck). Ensuite, sans code supplémentaire, vous pouvez simplement faire Ca Ck Cy Cy pour dupliquer la ligne. Il se décompose 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.
Mais si vous l'utilisez souvent, alors peut-être qu'une liaison de clé dédiée pourrait être une meilleure idée, mais l'avantage d'utiliser simplement Ca Ck Cy Cy est que vous pouvez dupliquer la ligne ailleurs, au lieu de juste en dessous de la ligne actuelle.
J'ai copy-from-above-command
lié à une clé et l'utilise. Il est fourni avec XEmacs, mais je ne connais pas GNU Emacs.
`copy-from-above-command 'est une fonction Lisp compilée interactive
- chargée depuis" /usr/share/xemacs/21.4.15/lisp/misc.elc "(commande copy-from-above et ARG optionnel)Documentation: Copiez les caractères de la ligne non vide précédente , en commençant juste au-dessus du point. Copiez les caractères ARG, mais pas au-delà de la fin de cette ligne. Si aucun argument n'est donné, copiez le reste de la ligne. Les caractères copiés sont insérés dans le tampon avant le point.
GNU Emacs 23.2.1 (amd64-portbld-freebsd8.1) of 2010-11-14 on [host clipped]
.
Il existe un package appelé Avy Il a la commande avy-copy-line. Lorsque vous utilisez cette commande, chaque ligne de votre fenêtre reçoit une combinaison de lettres. Ensuite, il vous suffit de taper combinaison et vous obtenez cette ligne. Cela fonctionne également pour la région. Ensuite, il vous suffit de taper deux combinaisons.
Ici vous pouvez voir l'interface:
Les défauts sont horribles pour cela. Cependant, vous pouvez étendre Emacs pour qu'il fonctionne comme SlickEdit et TextMate, c'est-à-dire copier / couper la ligne actuelle lorsqu'aucun texte n'est sélectionné:
(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)))))
Placez ce qui précède dans .emacs
. Ensuite, pour copier une ligne M-w
,. Pour supprimer une ligne C-w
,. Pour dupliquer une ligne C-a M-w C-y C-y C-y ...
,.
`` J'ai écrit ma propre version de duplicate-line
, parce que je ne veux pas bousiller le ring.
(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)
J'ai aimé la version de FraGGod, sauf pour deux choses: (1) Il ne vérifie pas si le tampon est déjà en lecture seule avec (interactive "*")
, et (2) il échoue sur la dernière ligne du tampon si cette dernière ligne est vide (comme vous ne peut pas tuer la ligne dans ce cas), laissant votre tampon en lecture seule.
J'ai apporté les modifications suivantes pour résoudre ce problème:
(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)))))
Avec les emacs récents, vous pouvez utiliser Mw n'importe où dans la ligne pour le copier. Alors ça devient:
M-w C-a RET C-y
M-w
est lié à easy-kill
. Vérifiez que c'est ce que vous obtenez quand vous faitesC-h c M-w
J'ai vu des solutions très complexes, de toute façon ...
(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, (position au nouvel emplacement) ctrl-y
Ajoutez un ctrl- asi vous ne commencez pas au début de la ligne. Et le 2ème ctrl- kest de saisir le caractère de nouvelle ligne. Il peut être supprimé si vous voulez juste le texte.
Lorsqu'il est appelé de manière interactive sans région active, COPY (Mw) une seule ligne à la place:
(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)))))
Lorsqu'il est appelé de manière interactive sans région active, KILL (Cw) une seule ligne à la place.
(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)))))
Aussi, sur une note connexe:
(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)
J'en écris un pour ma préférence.
(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)
Mais j'ai trouvé que cela poserait un problème lorsque la ligne actuelle contient des caractères multi-octets (par exemple des caractères CJK). Si vous rencontrez ce problème, essayez plutôt ceci:
(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)
Cette fonctionnalité doit correspondre à l'implémentation de JetBrains en termes de duplication à la fois par ligne ou par région, puis en laissant le point et / ou la région active comme prévu:
Juste un wrapper pour contourner le formulaire interactif:
(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)))
Qui appelle ça,
(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))
Ou ca
(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))
Et puis j'ai ce lié à meta + shift + d
(global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)
Comme mentionné dans d'autres réponses, lier les traits de touche au code lisp est une meilleure idée que de les lier à d'autres frappes de touche. Avec la réponse de @ mw, le code duplique la ligne et déplace la marque à la fin de la nouvelle ligne. Cette modification maintient la position de la marque à la même colonne sur la nouvelle ligne:
fun duplicate-line ()
(interactive)
(let ((col (current-column)))
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
(move-to-column col)))
Si vous utilisez Spacemacs, vous pouvez simplement utiliser duplicate-line-or-region
, lié à:
SPC x l d
Avec des arguments de préfixe, et quel est (j'espère) un comportement intuitif:
(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))))))
Le curseur restera sur la dernière ligne. Vous pouvez également spécifier un préfixe pour dupliquer les prochaines lignes à la fois:
(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))
Je me retrouve souvent à utiliser les deux, en utilisant une fonction wrapper pour changer le comportement de l'argument de préfixe.
Et un raccourci clavier:
(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.
ajoutez elisp ci-dessus à votre init.el, et vous obtenez la fonction couper / copier toute la ligne maintenant, alors vous pouvez F3 F4 pour dupliquer une ligne.
Le moyen le plus simple est la méthode de Chris Conway.
C-a C-SPACE C-n M-w C-y
C'est la méthode par défaut mandatée par EMACS. À mon avis, il vaut mieux utiliser la norme. Je suis toujours attentif à la personnalisation de sa propre liaison de clé dans EMACS. EMACS est déjà assez puissant, je pense que nous devrions faire de notre mieux pour nous adapter à ses propres raccourcis clavier.
Bien que ce soit un peu long, mais quand vous y êtes habitué, vous pouvez faire vite et vous trouverez que c'est amusant!
Voici une fonction pour dupliquer la ligne courante. Avec des arguments de préfixe, il dupliquera la ligne plusieurs fois. Par exemple, C-3 C-S-o
dupliquera la ligne actuelle trois fois. Ne change pas de tuerie.
(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)