Question

J'ai vu cette même question pour VIM et c'est quelque chose que je voulais moi-même savoir comment faire pour Emacs.Dans ReSharper, j'utilise CTRL-D pour cette action.Quel est le nombre minimum de commandes pour effectuer cela dans Emacs ?

Était-ce utile?

La solution

j'utilise

C-a C-SPACE C-n M-w C-y

qui se décompose en

  • C-a: déplace le curseur au début de la ligne
  • C-SPACE: commence une sélection (" marque de repère ")
  • C-n: déplace le curseur sur la ligne suivante
  • M-w: région de copie
  • C-y: coller (" tirer ")

Ce qui précède

C-a C-k C-k C-y C-y

revient au même (TMTOWTDI)

  • C-k: déplace le curseur au début de la ligne
  • C-d: coupe (& "; tuez &") la ligne
  • delete-char: coupez la nouvelle ligne
  • C-c C-d: coller (" tirer & ") (nous sommes de retour à la case départ)
  • .emacs: collez à nouveau (nous avons maintenant deux copies de la ligne)

Celles-ci sont à la fois gênantes et embarrassantes par rapport à <=> dans votre éditeur, mais dans Emacs, il y a toujours une personnalisation. <=> est lié à <=> par défaut, alors que diriez-vous de <=>? Ajoutez simplement ce qui suit à votre <=>:

(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 liaisons de clé est modifiée.)

Attention: certains modes Emacs peuvent demander à <=> de faire autre chose.

Autres conseils

En plus des réponses précédentes, vous pouvez également définir votre propre fonction pour dupliquer une ligne. Par exemple, si vous insérez ce qui suit dans votre fichier .emacs, C-d 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 "C-d") 'duplicate-line)

Placez le curseur sur la ligne, sinon faites un CTRL - A , puis:

CTRL - K

CTRL - K

CTRL - Y

CTRL - Y

Ma version d'une fonction permettant de dupliquer une ligne qui fonctionne bien avec undo et ne joue pas avec la position du curseur. C’est le résultat d'un discussion dans gnu.emacs.sources à partir 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)

Au lieu de kill-line (C-k) comme dans C-a C-y kill-whole-line <=> <=> <=>, utilisez le <=> commande:

C-S-Backspace
C-y
C-y

Les avantages par rapport à <=> comprennent notamment le fait que l'emplacement du point importe peu (contrairement à <=> qui nécessite d'être au début de la ligne) et qu'il tue également la nouvelle ligne (encore une fois, <=> ne le fait pas ).

Voici encore une autre fonction pour le faire. Ma version ne touche pas l'anneau de mise à mort et le curseur se termine sur la nouvelle ligne où il se trouvait sur l'original. Elle dupliquera la région si elle est active (mode de marque transitoire) ou, par défaut, dupliquera la ligne. Il fera également plusieurs copies si un préfixe arg lui est attribué et commentera la ligne d'origine si un préfixe arg lui est attribué (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-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 devrait 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.

L’ajout de Nathan à votre fichier .emacs est la solution, mais il pourrait être légèrement simplifié en remplaçant

  (open-line 1)
  (next-line 1)

avec

  (newline)

cédant

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (newline)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)

Je ne me souviens pas très bien comment la duplication de lignes fonctionne ailleurs, mais en tant qu'ancien utilisateur de SciTE, j'aimais une chose à propos de SciTE-way: 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 ne sera réellement tué dans le processus, laissant intactes les marques et la sélection actuelle.

BTW, pourquoi êtes-vous si friands de faire virer le curseur quand il y a ce truc sympa et stupéfiant pour tuer toute la ligne (C-S-backspace)?

installez duplicate-thing depuis melpa:

M-x package-install RET duplicate-thing

et ajoutez cette liaison à fichier init :

(clé globale (kbd " M-c ")) 'chose en double »

parce que je ne sais pas, je vais commencer cette partie de golf avec un slowball:

ctrl-k, y, y

'J'ai écrit ma propre version de duplicate-line, parce que je ne veux pas bousiller l'anneau de la mort.

  (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 copy-from-above-command lié à une clé et utilisez-la.Il est fourni avec XEmacs, mais je ne connais pas GNU Emacs.

«Copy-from-Above-Command» est une fonction LISP compilée interactive
- Chargement à partir de "/usr/share/xemacs/21.4.15/lisp/misc.elc" (Copy-From-Aabove-Command & Arg facultatif)

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

C-a C-k C-k C-y C-y

Quelque chose que vous voudrez peut-être avoir dans votre .emacs est

(setq kill-whole-line t)

Ce qui tue la ligne entière plus la nouvelle ligne chaque fois que vous appelez kill-line (c.-à-d. via C-k). Ensuite, sans code supplémentaire, vous pouvez simplement faire C-a C-k C-y C-y 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 utilisez souvent cette méthode, une liaison de clé dédiée pourrait peut-être être une meilleure idée, mais l’avantage d’utiliser simplement Ca Ck Cy Cy est de pouvoir dupliquer la ligne ailleurs, plutôt que juste en dessous de la ligne actuelle.

Les valeurs par défaut 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 quand 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 aimé la version de FraGGod, à l'exception de 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 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)))))

Avec les récents emacs, vous pouvez utiliser M-w n'importe où dans la ligne pour le copier. Alors ça devient:

M-w C-a RET C-y

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)

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 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://i68.tinypic.com/24fk5eu.png

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

Lorsque vous appelez de manière interactive sans région active, COPY (M-w) à la place, une seule ligne:

(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)))))

Lorsque vous appelez de manière interactive sans région active, KILL (C-w) à 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)))))

En outre, 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)

ctrl - k , ctrl - k , (position vers le nouvel emplacement) ctrl - y

Ajoutez un ctrl - a si vous ne commencez pas au début de la ligne. Et le deuxième ctrl - k consiste à saisir le caractère de nouvelle ligne. Il peut être supprimé si vous voulez juste le texte.

J'en écris un à 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 en cours 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 autour du 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 cela,

(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 ceci

(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é à la méta + shift + d

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

Avec les 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 quelques lignes suivantes à 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 trouve souvent en train d'utiliser les deux, en utilisant une fonction wrapper pour changer le comportement de l'argument 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 le elisp ci-dessus à votre init.el, et vous obtenez maintenant la fonction de coupe / copie de 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.

C-a C-SPACE C-n M-w C-y

C'est la méthode par défaut prescrite par EMACS. À mon avis, il est préférable d'utiliser la norme. Je suis toujours attentif à la personnalisation de la 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 en avez l'habitude, vous pouvez faire vite et vous trouverez que c'est amusant!

Voici une fonction permettant de dupliquer la ligne en cours. Avec les arguments préfixés, la ligne sera dupliquée plusieurs fois. Par exemple, C-3 C-S-o va dupliquer la ligne en cours trois fois. Ne change pas le kill ring.

(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)

Je ne peux pas croire toutes ces solutions compliquées. Ce sont deux frappes:

<C-S-backspace> lance la commande kill-whole-line

C-/ exécute la commande undo

Donc <C-S-backspace> C-/ vers " copier " une ligne entière (tuer et annuler).

Vous pouvez bien sûr combiner cela avec des arguments numériques et négatifs pour supprimer plusieurs lignes en avant ou en arrière.

Cela semble plus naturel en ce qui concerne la réponse choisie par Chris Conway.

(clé globale & "; \ Cc \ Cd &"; & "\ Ca \ C- \ Cn \ Mw \ Cy \ Cp \ Ce &";)

Ceci vous permet de dupliquer une ligne plusieurs fois en répétant simplement les touches \ C-c \ C-d.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top