Come posso duplicare un'intera riga in Emacs?
Domanda
vidi questa stessa domanda per VIM ed è stata una cosa che io stesso volevo sapere come fare per Emacs.In ReSharper utilizzo CTRL-D per questa azione.Qual è il numero minimo di comandi per eseguire questa operazione in Emacs?
Soluzione
Io uso
C-a C-SPACE C-n M-w C-y
che si rompe in
C-a
:sposta il cursore all'inizio della rigaC-SPACE
:iniziare una selezione ("imposta contrassegno")C-n
:sposta il cursore sulla riga successivaM-w
:copia regioneC-y
:incolla ("strappa")
Il suddetto
C-a C-k C-k C-y C-y
equivale alla stessa cosa (TMTOWTDI)
C-a
:sposta il cursore all'inizio della rigaC-k
:tagliare ("uccidere") la lineaC-k
:tagliare la nuova rigaC-y
:incolla ("yank") (siamo tornati al punto di partenza)C-y
:incolla di nuovo (ora abbiamo due copie della riga)
Questi sono entrambi imbarazzantemente prolissi rispetto a C-d
nel tuo editor, ma in Emacs c'è sempre una personalizzazione. C-d
è obbligato a delete-char
per impostazione predefinita, quindi che ne dici di C-c C-d
?Basta aggiungere quanto segue al tuo .emacs
:
(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")
(@La versione elisp di Nathan è probabilmente preferibile, perché non si romperà se una qualsiasi delle associazioni dei tasti viene modificata.)
Attenzione:alcune modalità Emacs potrebbero recuperare C-c C-d
fare qualcos'altro.
Altri suggerimenti
Oltre alle risposte precedenti puoi anche definire la tua funzione per duplicare una linea.Ad esempio, inserendo quanto segue nel file .emacs, C-d duplicherà la riga corrente.
(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)
Posiziona il cursore sulla riga, se non all'inizio esegui a CTRL-UN, Poi:
CTRL-K
CTRL-K
CTRL-Y
CTRL-Y
La mia versione di una funzione per duplicare una riga che funziona bene con l'annullamento e non interferisce con la posizione del cursore.È stato il risultato di a discussione in gnu.emacs.sources del 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))
Quindi puoi definire CTRL-D per chiamare questa funzione:
(global-set-key (kbd "C-d") 'duplicate-line)
Invece di kill-line
(C-k
) come in C-a
C-k
C-k
C-y
C-y
Usa il kill-whole-line
comando:
C-S-Backspace
C-y
C-y
I vantaggi sopra C-k
includere che non importa dove si trova il punto sulla linea (a differenza di C-k
che richiede di essere all'inizio della riga) e uccide anche il ritorno a capo (di nuovo qualcosa C-k
non fa).
Ecco ancora un'altra funzione per fare questo.La mia versione non tocca il kill ring e il cursore finisce sulla nuova riga dove si trovava nell'originale.Duplicherà la regione se è attiva (modalità contrassegno transitorio) o altrimenti duplicherà automaticamente la linea.Farà anche più copie se gli viene dato un prefisso arg e commenterà la riga originale se gli viene dato un prefisso negativo arg (questo è utile per testare una versione diversa di un comando/istruzione mantenendo quella vecchia).
(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)))))
Sono obbligato a farlo C-c d
:
(global-set-key [?\C-c ?d] 'duplicate-line-or-region)
Questo non dovrebbe mai essere riassegnato da una modalità o altro perché C-c
seguito da una singola lettera (non modificata) è riservata alle associazioni dell'utente.
L'aggiunta di Nathan al tuo file .emacs è la strada da percorrere ma potrebbe essere leggermente semplificata sostituendola
(open-line 1)
(next-line 1)
con
(newline)
cedevole
(defun duplicate-line()
(interactive)
(move-beginning-of-line 1)
(kill-line)
(yank)
(newline)
(yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
Non ricordo bene come funzioni la duplicazione della linea da nessun'altra parte, ma come ex utente SciTE mi è piaciuta una cosa di SciTE-way:non tocca la posizione del cursore!Quindi tutte le ricette sopra non erano abbastanza buone per me, ecco la mia versione 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))))
Tieni presente che nulla viene effettivamente ucciso durante il processo, lasciando intatti i segni e la selezione corrente.
A proposito, perché a voi ragazzi piace così tanto muovere il cursore quando c'è questa cosa carina e pulita che uccide l'intera riga (C-S-backspace)?
installa duplicate-thing da melpa:
M-x package-install RET duplicate-thing
e aggiungi questa combinazione di tasti a file iniziale :
(global-set-key (kbd "M-c") 'oggetto duplicato)
perché non lo so, inizierò questa partita di golf con una palla lenta:
ctrl-k, y, y
' Ho scritto la mia versione di duplicate-line
, perché non voglio rovinare il giro degli omicidi.
(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)
Io ho copy-from-above-command
legato a una chiave e usarla.Viene fornito con XEmacs, ma non conosco GNU Emacs.
`copia-from-above-comand 'è una funzione LISP compilata interattiva
-Caricato da "/usr/share/xemacs/21.4.15/lisp/misc.elc" (Copy-from-above-command & opzionale Arg)Documentazione: Copia caratteri dalla linea non bianca precedente, iniziando appena sopra il punto.Copia i personaggi arg, ma non oltre la fine di quella linea.Se non viene fornito alcun argomento, copiare l'intero resto della linea.I personaggi copiati vengono inseriti nel buffer prima del punto.
C-a C-k C-k C-y C-y
qualcosa che potresti voler avere nel tuo .emacs lo è
(setq kill-whole-line t)
Che fondamentalmente uccide l'intera riga più la nuova riga ogni volta che invochi kill-line (cioètramite C-k).Quindi senza codice aggiuntivo, puoi semplicemente fare C-a C-k C-y C-y per duplicare la riga.Si rompe in
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.
Ma se lo usi spesso, forse un'associazione di tasti dedicata potrebbe essere un'idea migliore, ma il vantaggio di usare solo C-a C-k C-y C-y è che puoi duplicare la riga altrove, invece che appena sotto la riga corrente.
Le impostazioni predefinite sono orribili per questo.Tuttavia, puoi estendere Emacs affinché funzioni come SlickEdit e TextMate, ovvero copia/taglia la riga corrente quando non è selezionato testo:
(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)))))
Inserisci quanto sopra .emacs
.Quindi, per copiare una riga, M-w
.Per eliminare una riga, C-w
.Per duplicare una linea, C-a M-w C-y C-y C-y ...
.
Mi è piaciuta la versione di FraGGod, tranne che per due cose:(1) Non controlla se il buffer è già di sola lettura con (interactive "*")
, e (2) fallisce sull'ultima riga del buffer se l'ultima riga è vuota (poiché in quel caso non è possibile terminare la riga), lasciando il buffer di sola lettura.
Ho apportato le seguenti modifiche per risolvere il problema:
(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 recente, puoi usare M-w ovunque nella riga per copiarlo.Quindi diventa:
M-w C-a RET C-y
Ho visto soluzioni molto complesse, comunque...
(defun duplicate-line ()
"Duplicate current line"
(interactive)
(kill-whole-line)
(yank)
(yank))
(global-set-key (kbd "C-x M-d") 'duplicate-line)
C'è un pacchetto chiamato Avy Ha il comando avy-copy-line.Quando usi quel comando, ogni riga nella tua finestra riceve una combinazione di lettere.Quindi devi solo digitare la combinazione e ottieni quella riga.Questo funziona anche per la regione.Quindi devi solo digitare due combinazioni.
Qui puoi vedere l'interfaccia:
@[Kevin Conner]:Abbastanza vicino, per quanto ne so.L'unica altra cosa da considerare è l'accensione kill-whole-line
per includere il ritorno a capo nel C-k.
Quando chiamato in modo interattivo senza regione attiva, COPY (M-w) invece una singola riga:
(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)))))
Quando viene chiamato in modo interattivo senza una regione attiva, KILL (C-w) invece di una singola riga.
(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)))))
Inoltre, in una nota correlata:
(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, (posizione nella nuova posizione) Ctrl-sì
Aggiungere un Ctrl-UN se non inizi dall'inizio della riga.E il 2° Ctrl-K è prendere il carattere di nuova riga.Può essere rimosso se vuoi solo il testo.
Ne scrivo uno per mia preferenza.
(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)
Ma ho scoperto che questo avrebbe qualche problema quando la riga corrente contiene caratteri multibyte (ad es.caratteri CJK).Se riscontri questo problema, prova invece questo:
(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)
Questa funzionalità dovrebbe corrispondere all'implementazione di JetBrains in termini di duplicazione sia per linea che per regione e quindi di lasciare il punto e/o la regione attiva come previsto:
Solo un wrapper attorno al modulo interattivo:
(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)))
Che lo chiama,
(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 questo
(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))
E poi ho questo legato a meta+shift+d
(global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)
Con argomenti di prefisso e qual è (spero) un comportamento 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))))))
Il cursore rimarrà sull'ultima riga.In alternativa, potresti voler specificare un prefisso per duplicare le righe successive contemporaneamente:
(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))
Mi ritrovo a usarli entrambi spesso, utilizzando una funzione wrapper per cambiare il comportamento dell'argomento prefisso.
E una combinazione di tasti:(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.
aggiungi l'elisp sopra a init.el e ora ottieni la funzione taglia/copia l'intera riga, quindi puoi F3 F4 per duplicare una riga.
Il modo più semplice è il metodo di Chris Conway.
C-a C-SPACE C-n M-w C-y
Questo è il modo predefinito imposto da EMACS.Secondo me è meglio usare lo standard.Sono sempre attento alla personalizzazione della propria associazione di tasti in EMACS.EMACS è già abbastanza potente, penso che dovremmo fare del nostro meglio per adattarci alle sue associazioni di tasti.
Anche se è un po' lungo, ma quando ci sarai abituato, potrai farlo velocemente e scoprirai che è divertente!
Ecco una funzione per duplicare la linea corrente.Con argomenti prefisso, duplicherà la riga più volte.Per esempio., C-3 C-S-o
duplicherà la riga corrente tre volte.Non cambia il 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)
Non posso credere a tutte queste soluzioni complicate.Si tratta di due sequenze di tasti:
<C-S-backspace>
esegue il comando kill-whole-line
C-/
esegue il comando annulla
COSÌ <C-S-backspace> C-/
per "copiare" un'intera riga (uccidi e annulla).
Ovviamente puoi combinarlo con argomenti numerici e negativi per eliminare più righe in avanti o all'indietro.
Questo sembra più naturale, rispetto alla risposta selezionata da Chris Conway.
(chiave-insieme-globale "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y\C-p\C-e")
Ciò ti consente di duplicare una riga più volte semplicemente ripetendo i tasti \C-c\C-d.