Comment dupliquer une ligne entière dans Emacs?

J’ai vu cette même question pour VIM et j’ai voulu savoir comment faire pour Emacs. Dans ReSharper, j’utilise CTRL-D pour cette action. Quel est le nombre minimal de commandes à effectuer dans Emacs?

j’utilise

Ca C-SPACE Cn Mw Cy 

qui se décompose en

  • Ca : déplace le curseur au début de la ligne
  • C-SPACE : commence une sélection (“set mark”)
  • Cn : déplace le curseur sur la ligne suivante
  • Mw : copie région
  • Cy : coller (“yank”)

Le susdit

 Ca Ck Ck Cy Cy 

revient à la même chose (TMTOWTDI)

  • Ca : déplace le curseur au début de la ligne
  • Ck : couper (tuer) la ligne
  • Ck : couper la nouvelle ligne
  • Cy : coller (“yank”) (nous sums de retour à la case départ)
  • Cy : coller à nouveau (maintenant nous avons deux copies de la ligne)

Celles-ci sont à la fois embarrassantes par rapport à Cd dans votre éditeur, mais dans Emacs, il y a toujours une personnalisation. Cd est lié à delete-char par défaut, alors qu’en est-il de Cc Cd ? Ajoutez simplement ce qui suit à vos .emacs :

 (global-set-key "\Cc\Cd" "\Ca\C- \Cn\Mw\Cy") 

(La version elisp de @ Nathan est probablement préférable, car elle ne se cassera pas si l’une des liaisons clés est modifiée.)

Attention: certains modes Emacs peuvent récupérer Cc Cd pour faire autre chose.

En plus des réponses précédentes, vous pouvez également définir votre propre fonction pour dupliquer une ligne. Par exemple, en insérant les éléments suivants dans votre fichier .emacs, Cd dupliquera la ligne en cours.

 (defun duplicate-line() (interactive) (move-beginning-of-line 1) (kill-line) (yank) (open-line 1) (next-line 1) (yank) ) (global-set-key (kbd "Cd") 'duplicate-line) 

Placez le curseur sur la ligne, sinon au début, faites un CTRLA , puis:

CTRLK

CTRLK

CTRLY

CTRLY

Ma version d’une fonction pour dupliquer une ligne qui fonctionne bien avec undo et ne gêne 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-subssortingng 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)) 

Vous pouvez ensuite définir CTRL-D pour appeler cette fonction:

 (global-set-key (kbd "Cd") 'duplicate-line) 

Au lieu de kill-line ( Ck ) comme dans Ca Ck Ck Cy Cy utilise la commande kill-whole-line :

 CS-Backspace Cy Cy 

Les avantages sur Ck incluent le fait que peu importe où se trouve le point sur la ligne (contrairement à Ck qui nécessite d’être au début de la ligne) et qu’il tue également la nouvelle ligne (encore quelque chose que Ck ne fait pas).

Voici encore une autre fonction pour ce faire. Ma version ne touche pas le kill ring 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 par défaut, si elle duplique la ligne. Il fera également plusieurs copies si on lui donne un préfixe arg, et commentera la ligne originale si on lui a donné un préfixe négatif arg (cela 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-subssortingng (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é à Cc d :

 (global-set-key [?\Cc ?d] 'duplicate-line-or-region) 

Cela ne devrait jamais être réaffecté par un mode ou autre, car Cc suivi d’une seule lettre (non modifiée) est réservé aux liaisons utilisateur.

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 "Cd") 'duplicate-line) 

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 au sujet de SciTE: elle 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é en cours, laissant les marques et la sélection actuelle intactes.

BTW, pourquoi est-ce que vous êtes aussi friands de secouer le curseur quand il y a ce truc de kill-Whole-Line (CS-backspace)?

installer le duplicate-chose de melpa

et ajoutez cette reliure:

(duplication-chose de global-set-key (kbd “Mc”))

parce que je ne sais pas, je vais commencer cette partie de golf avec une balle lente:

ctrl-k, y, y

J’ai une commande copy-from-above-command liée à une clé et je 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é depuis “/usr/share/xemacs/21.4.15/lisp/misc.elc” (copie depuis la commande ci-dessus et option ARG)

Documentation: Copiez les caractères de la ligne non vierge précédente , en commençant juste au-dessus du point. Copiez les caractères ARG, mais pas la fin de cette ligne. Si aucun argument n’est donné, copiez le rest de la ligne. Les caractères copiés sont insérés dans le tampon avant le point.

 Ca Ck Ck Cy Cy 

quelque chose que vous pourriez vouloir avoir dans vos .emacs est

 (setq kill-whole-line t) 

Ce qui tue 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

 Ca go to beginning of line Ck kill-line (ie cut the line into clipboard) Cy yank (ie paste); the first time you get the killed line back; second time gives the duplicated line. 

Mais si vous utilisez souvent cette option, une liaison par clé dédiée pourrait être une meilleure idée, mais l’avantage de l’utilisation de Cy Cy Ck est que vous pouvez dupliquer la ligne ailleurs, plutôt que juste en dessous de la ligne actuelle.

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 en cours quand aucun texte n’est sélectionné:

 (transient-mark-mode t) (defadvice kill-ring-save (before slick-copy activate comstack) "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 comstack) "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 le ci-dessus dans .emacs . Ensuite, pour copier une ligne, Mw . Pour supprimer une ligne, Cw . Pour dupliquer une ligne, Ca Mw Cy Cy Cy ...

«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-subssortingng-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) 

Avec les derniers emacs, vous pouvez utiliser Mw n’importe où dans la ligne pour le copier. Alors ça devient:

 Mw Ca RET Cy 

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 "Cx Md") 'duplicate-line) 

Il y a un paquet 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 la 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:

http://soffr.miximages.com/emacs/24fk5eu.png

@ [Kevin Conner]: Assez proche, pour autant que je sache. La seule autre chose à considérer est d’activer kill-whole-line pour inclure la nouvelle ligne dans le Ck.

J’ai aimé la version de FraGGod, sauf deux choses: (1) elle 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 ce dernier line est vide (car vous ne pouvez 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))))) 

Lorsqu’elle est appelée de manière interactive sans région active, COPY (Mw) une seule ligne à la place:

 (defadvice kill-ring-save (before slick-copy activate comstack) "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’elle est appelée de manière interactive sans région active, tuez (Cw) une seule ligne à la place.

 (defadvice kill-region (before slick-cut activate comstack) "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) 

ctrlk , ctrlk , (position vers nouvel emplacement) ctrly

Ajoutez un ctrla si vous ne commencez pas au début de la ligne. Et le second ctrlk consiste à saisir le caractère de nouvelle ligne. Il peut être supprimé si vous voulez juste le texte.

J’écris une pour ma préférence.

 (defun duplicate-line () "Duplicate current line." (interactive) (let ((text (buffer-subssortingng-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 "Cc dl") '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-subssortingng-no-properties (point-at-bol) (point-at-eol))) (cur-col (length (buffer-subssortingng-no-properties (point-at-bol) (point))))) (end-of-line) (insert "\n" text) (beginning-of-line) (right-char cur-col))) (global-set-key (kbd "Cc dl") 'duplicate-line) 

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 restra sur la dernière ligne. Vous pouvez également spécifier un préfixe pour dupliquer les quelques lignes suivantes:

 (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 à utiliser les deux souvent, en utilisant une fonction wrapper pour changer le comportement de l’argument préfixe.

Et une reliure: (global-set-key (kbd "CSd") '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-subssortingng (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-subssortingng (line-beginning-position) (line-beginning-position 2) t) nil '(yank-line)))) (defun yank-line (ssortingng) "Insert STRING above the current line." (beginning-of-line) (unless (= (elt ssortingng (1- (length ssortingng))) ?\n) (save-excursion (insert "\n"))) (insert ssortingng)) (global-set-key (kbd "") 'kill-region) ; cut. (global-set-key (kbd "") 'kill-ring-save) ; copy. (global-set-key (kbd "") 'yank) ; paste. 

ajoutez le fichier elisp ci-dessus à init.el, et vous obtenez maintenant la fonction couper / copier la ligne entière, puis vous pouvez F3 F4 pour dupliquer une ligne.

La méthode la plus simple est la méthode de Chris Conway.

 Ca C-SPACE Cn Mw Cy 

C’est la méthode par défaut imposée par EMACS. À mon avis, il est préférable d’utiliser la norme. Je suis toujours attentif à la personnalisation de la liaison de clés dans EMACS. EMACS est déjà assez puissant, je pense que nous devrions faire de notre mieux pour nous adapter à ses propres raccourcis.

Bien que ce soit un peu long, mais quand vous en avez l’habitude, vous pouvez faire vite et vous verrez que c’est amusant!

Cette fonctionnalité devrait correspondre à l’implémentation de JetBrains en termes de duplication par ligne ou région, puis en laissant le point et / ou la région active comme prévu:

Juste une enveloppe autour de la forme interactive:

 (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 cela,

 (defun wrx/duplicate-region-in-buffer (beg end) "copy and duplicate context of current active region |------------------------+----------------------------| | before | after | |------------------------+----------------------------| | first line here | first line here | | second item now | second itemline here | | | second item 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 dolor | lorem ipsum dolor | | | lorem ipsum 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 nv)))) (next-line)) 

Et puis j'ai ce lié à meta + shift + d

 (global-set-key (kbd "MD") 'wrx/duplicate-line-or-region) 

Voici une fonction pour dupliquer la ligne courante. Avec des arguments de préfixe, il dupliquera la ligne plusieurs fois. Par exemple, C-3 CSo dupliquera la ligne actuelle trois fois. Ne change pas l’anneau mortel.

 (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-subssortingng-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 "CSo") 'duplicate-lines) 

bien ive habituellement utilisé:

  Ctl-Space (marquez le repère)
 se déplacer en fin de ligne
 Ligne de destruction Ctl-K
 Ctl-Y * 2 (ramenez la ligne) 

il peut y avoir une bien meilleure façon cependant: P