web-dev-qa-db-ja.com

Emacsで行全体を複製するにはどうすればよいですか?

VIMについてもこれと同じ質問 を見ましたが、それは私自身がEmacsのやり方を知りたかったことです。 ReSharperでは、このアクションにCTRL-Dを使用します。 Emacsでこれを実行するコマンドの最小数は何ですか?

146
Ray Vega

私が使う

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

に分解する

  • C-a:カーソルを行頭に移動
  • C-SPACE:選択を開始します(「マークを設定」)
  • C-n:カーソルを次の行に移動します
  • M-w:領域をコピー
  • C-y:貼り付け(「ヤンク」)

前述の

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

同じこと(TMTOWTDI)

  • C-a:カーソルを行頭に移動
  • C-k:行をカット(「殺す」)
  • C-k:改行を切る
  • C-y:paste( "yank")(正方形に戻りました)
  • C-y:もう一度貼り付けます(行のコピーが2つあります)

これらは両方とも、エディターのC-dと比べて恥ずかしいほど冗長ですが、Emacsには常にカスタマイズがあります。 C-dはデフォルトでdelete-charにバインドされていますが、C-c C-dはどうですか?次を.emacsに追加するだけです:

(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")

(@Nathanのelispバージョンは、キーバインディングのいずれかが変更されても壊れないため、おそらく望ましいでしょう。)

注意:一部のEmacsモードは、C-c C-dを再利用して他のことを行う場合があります。

140
Chris Conway

前の回答に加えて、独自の関数を定義して行を複製することもできます。たとえば、次を.emacsファイルに追加すると、C-dが現在の行を複製します。

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

行にカーソルを置きます。先頭にない場合は、 CTRL-A、その後:

CTRL-K

CTRL-K

CTRL-Y

CTRL-Y

61
epatel

行を複製する機能の私のバージョンは、元に戻すとうまく機能し、カーソル位置を混乱させません。これは 1997年11月からのgnu.emacs.sourcesでの議論 の結果でした。

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

次に、CTRL-Dを定義してこの関数を呼び出すことができます。

(global-set-key (kbd "C-d") 'duplicate-line)
52
pesche

kill-lineのようなC-kC-a)の代わりにC-kC-kC-yC-yを使用して、 kill-whole-line コマンド:

C-S-Backspace
C-y
C-y

C-kを超える利点には、ポイントが行のどこにあるかは関係なく(C-kとは異なり、行の先頭にいる必要があります)、改行も削除されます(再びC-kしません)。

44
Ray Vega

これを行うためのさらに別の関数を次に示します。私のバージョンはキルリングに触れず、カーソルは元の行の新しい行に移動します。リージョンがアクティブな場合はリージョンを複製し(一時マークモード)、そうでない場合はデフォルトで行を複製します。また、接頭辞引数を指定すると複数のコピーを作成し、負の接頭辞引数を指定すると元の行をコメントアウトします(これは、古いバージョンを保持しながら異なるバージョンのコマンド/ステートメントをテストする場合に便利です)。

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

C-c dにバインドしています:

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

C-cの後に単一の(変更されていない)文字が続くのはユーザーバインディング用に予約されているため、これはモードなどによって再割り当てされることはありません。

25
qmega

Nathanを.emacsファイルに追加する方法がありますが、これを置き換えることで少し単純化できます。

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

  (newline)

降伏

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

melpaから重複したものをインストールします。

M-xパッケージインストールRET複製物

そして、このキーバインディングを init file に追加します:

(global-set-key(kbd "M-c") '重複するもの)

5
user2626414

他の場所で行の複製がどのように機能するかはよく覚えていませんが、以前のSciTEユーザーとしては、SciTE-wayについて好きな点が1つありました。カーソル位置に触れないことです。したがって、上記のレシピはすべて私にとって十分ではありませんでした、ここに私のヒッピー版があります:

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

実際にプロセスで強制終了されるものはなく、マークと現在の選択はそのまま残ります。

ところで、なぜあなたはこのNice'n'cleanの全行削除(C-S-backspace)があるときにカーソルをぐいと動かすのが好きなのですか?

5
mk-fg

私は持っています copy-from-above-commandキーにバインドし、それを使用します。 XEmacsで提供されますが、GNU Emacsについては知りません。

`copy-from-above-command 'は、インタラクティブにコンパイルされたLISP関数です
-"/usr/share/xemacs/21.4.15/LISP/misc.elc"からロード(copy-from-above-command&optional ARG)

ドキュメント:直前の空白行から文字をコピー、ポイントのすぐ上から開始します。 ARG文字をコピーしますが、その行の終わりを超えてはコピーしません。引数が指定されていない場合、行全体をコピーします。コピーされた文字は、ポイントの前のバッファーに挿入されます。

4
Darron

私は知らないので、スローボールでこのゴルフのラウンドを始めます:

ctrl-k、y、y

4
Kevin Conner

'私はduplicate-lineの独自のバージョンを作成しました。キリングリングを台無しにしたくないからです。

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

最近のemacsでは、行のどこでもM-wを使用してコピーできます。したがって、次のようになります。

M-w C-a RET C-y
3
Louis Kottmann
C-a C-k C-k C-y C-y
3
sverrejoh

.emacsに入れたいものは

(setq kill-whole-line t)

これは基本的に、kill-lineを呼び出すたびに(つまりC-k経由で)行全体と改行を削除します。その後、余分なコードなしで、C-a C-k C-y C-yを実行するだけで行を複製できます。に分解する

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.

しかし、これを頻繁に使用する場合は、おそらく専用のキーバインディングがより良いアイデアかもしれませんが、C-a C-k C-y C-yを使用する利点は、現在の行のすぐ下ではなく、他の場所で行を複製できることです。

3
polyglot

FraGGodのバージョンは、次の2つの点を除いて気に入っています。(1)(interactive "*")でバッファが既に読み取り専用であるかどうかを確認せず、(2)最後の行でバッファの最後の行で失敗する(その場合、行を削除できないため)は空で、バッファーは読み取り専用のままです。

それを解決するために、次の変更を加えました。

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

これはデフォルトでは恐ろしいものです。ただし、SlickEditやTextMateのようにEmacsを拡張できます。つまり、テキストが選択されていないときに現在の行をコピー/カットできます。

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

上記を.emacsに配置します。次に、M-wという行をコピーします。行を削除するには、C-w。行を複製するには、C-a M-w C-y C-y C-y ...

3
Marius Andersen

とにかく非常に複雑なソリューションを見ました...

(defun duplicate-line ()
  "Duplicate current line"
  (interactive)
  (kill-whole-line)
  (yank)
  (yank))
(global-set-key (kbd "C-x M-d") 'duplicate-line)
3
user6581334

Avy というパッケージがあります。コマンドavy-copy-lineがあります。そのコマンドを使用すると、ウィンドウ内のすべての行に文字の組み合わせが適用されます。次に、組み合わせを入力するだけで、その行が表示されます。これは地域でも機能します。次に、2つの組み合わせを入力するだけです。

ここでインターフェイスを見ることができます:

http://i68.tinypic.com/24fk5eu.png

3
teksturi

@ [Kevin Conner]:私の知る限り、かなり近い。他に考慮すべきことは、kill-whole-lineをオンにして、改行をC-kに含めることです。

2
Allen

アクティブ領域なしで対話的に呼び出された場合、代わりに1行をコピー(M-w)します:

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

アクティブな領域なしで対話的に呼び出された場合、代わりに単一の行をKILL(C-w)します。

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

また、関連するメモ:

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

私の好みに合わせて書きます。

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

しかし、現在の行にマルチバイト文字(CJK文字など)が含まれている場合、これには問題があることがわかりました。この問題が発生した場合は、代わりにこれを試してください:

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

ctrl-k、 ctrl-k、(新しい場所への位置) ctrl-y

を追加 ctrl-a 行の先頭から開始していない場合。そして第2 ctrl-k 改行文字を取得することです。テキストだけが必要な場合は削除できます。

1
CJP

この機能は、JetBrainsの実装と一致する必要があります。線または領域の両方で複製し、ポイントおよび/またはアクティブな領域を期待どおりに残します。

インタラクティブなフォームのラッパー:

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

これを呼び出すと、

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

またはこれ

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

そして、これをmeta + shift + dにバインドします

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

M-cShift+Insertx2(または貼り付けのショートカット)が実行します。

0
Andrew Naguib
;; 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.

上記のelispをinit.elに追加すると、今度は行全体のカット/コピー機能が使用できます。F3F4で行を複製できます。

0
WisdomFusion

これは、Chris Conwayが選択した回答に関して、より自然に感じられます。

(グローバルセットキー "\ C-c\C-d" "\ C-a\C-\C-n\M-w\C-y\C-p\C-e")

これにより、\ C-c\C-dキーストロークを繰り返すだけで行を複数回複製できます。

0
Shim Kporku

以下は、現在の行を複製するための関数です。プレフィックス引数を使用すると、行が複数回複製されます。例:C-3 C-S-oは、現在の行を3回複製します。キルリングを変更しません。

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

他の回答で述べたように、キーストロークを別のキーストロークにバインドするよりも、キーストロークをLISPコードにバインドする方が適切です。 @mwの答えでは、コードは行を複製し、マークを新しい行の末尾に移動します。この変更により、新しい行の同じ列にマーク位置が保持されます。

fun duplicate-line ()
  (interactive)
  (let ((col (current-column)))
    (move-beginning-of-line 1)
    (kill-line)
    (yank)
    (newline)
    (yank)
    (move-to-column col)))
0
krsoni

これらすべての複雑なソリューションを信じることはできません。これは2つのキーストロークです。

<C-S-backspace>コマンドkill-whole-lineを実行します

C-/コマンドundoを実行します

そう <C-S-backspace> C-/行全体を「コピー」します(強制終了および取り消し)。

もちろん、これを数値および負の引数と組み合わせて、複数の行を前後にキルすることができます。

0
Andy

最も簡単な方法は、Chris Conwayの方法です。

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

これがEMACSで義務付けられているデフォルトの方法です。私の意見では、標準を使用する方が良いと思います。私は、EMACSで自分のキーバインドをカスタマイズすることに常に注意しています。 EMACSはすでに十分に強力です。独自のキーバインディングに適応するために最善を尽くす必要があると思います。

それは少し長いですが、あなたがそれに慣れているとき、あなたは速く行うことができ、これは楽しいことがわかります!

0
linbianxiaocao

プレフィックス引数を使用し、直感的な動作(希望)を指定します。

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

カーソルは最後の行に残ります。または、次の数行を一度に複製するプレフィックスを指定することもできます。

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

両方とも頻繁に使用し、ラッパー関数を使用してプレフィックス引数の動作を切り替えることに気付きました。

キーバインド:(global-set-key (kbd "C-S-d") 'duplicate-line)

0
Karthik