選択した行を上下に移動


7

私はしばらくの間日食を使用しており、特にAlt + Up / Downを使用して長方形のラインの選択を上下に移動する機能など、いくつかのショートカットが非常に便利であることに気付きました。私はemacsでこの機能を探していました。これまでのところ、次のスクリプトを見つけました。

(defun move-text-internal (arg)
   (cond
    ((and mark-active transient-mark-mode)
     (if (> (point) (mark))
            (exchange-point-and-mark))
     (let ((column (current-column))
              (text (delete-and-extract-region (point) (mark))))
       (forward-line arg)
       (move-to-column column t)
       (set-mark (point))
       (insert text)
       (exchange-point-and-mark)
       (setq deactivate-mark nil)))
    (t
     (beginning-of-line)
     (when (or (> arg 0) (not (bobp)))
       (forward-line)
       (when (or (< arg 0) (not (eobp)))
            (transpose-lines arg))
       (forward-line -1)))))

(defun move-text-down (arg)
   "Move region (transient-mark-mode active) or current line
  arg lines down."
   (interactive "*p")
   (move-text-internal arg))

(defun move-text-up (arg)
   "Move region (transient-mark-mode active) or current line
  arg lines up."
   (interactive "*p")
   (move-text-internal (- arg)))

(global-set-key [\M-up] 'move-text-up)
(global-set-key [\M-down] 'move-text-down)

これは、選択を移動するという事実を除いて機能します。代わりに、選択に含まれるすべての行(末尾の改行を含む)を移動します。これを実現する方法はありますか?


stackoverflowに関する関連質問:stackoverflow.com/q/2423834
名前

それは私がコードを入手した場所です。その解決策が満足できるものではなかったので、もう一度尋ねました。
hfhc2 2015

回答:


14

drag-stuff

drag-stuffパッケージをチェックしてください(Melpaでも入手可能)。

次に、リージョンを選択し、drag-stuff-up/ drag-stuff-downを使用してそのリージョンを上下に移動できます。


ラインをドラッグするときの代替動作

デフォルトでは、drag-stuffコマンドはその上にあるラインもドラッグしますpoint(ポイントが最初の列にある場合でも)。選択したい場合は、を実行して2行全体C-a C-SPC C-n C-nとすると、選択は次のようになります。

 line 1
▯line 2
 line 3
▮line 4 
 line 5

ここでは、4行目はなく、2行目と3行目だけを移動することに注意してください。ただしdrag-stuff、デフォルトではその3行目も移動します。

それは私の不満だった(そしておそらく他の誰にも当てはまらない)ので、私はソリューションのパッケージ開発者要求しました。このデフォルトの動作を望まない場合は、必要な後にemacs構成に追加できるハックを次にdrag-stuff示します。ポイントが列0(最初の列)にある場合、ハックは現在の行を移動しません。

;; https://github.com/kaushalmodi/.emacs.d/blob/master/setup-files/setup-drag-stuff.el
;; https://github.com/rejeep/drag-stuff.el/issues/4
(defvar modi/drag-stuff--point-adjusted nil)
(defvar modi/drag-stuff--point-mark-exchanged nil)

(defun modi/drag-stuff--adj-pt-pre-drag ()
  "If a region is selected AND the `point' is in the first column, move
back the point by one char so that it ends up on the previous line. If the
point is above the mark, exchange the point and mark temporarily."
  (when (region-active-p)
    (when (< (point) (mark)) ; selection is done starting from bottom to up
      (exchange-point-and-mark)
      (setq modi/drag-stuff--point-mark-exchanged t))
    (if (zerop (current-column))
        (progn
          (backward-char 1)
          (setq modi/drag-stuff--point-adjusted t))
      ;; If point did not end up being on the first column after the
      ;; point/mark exchange, revert that exchange.
      (when modi/drag-stuff--point-mark-exchanged
        (exchange-point-and-mark) ; restore the original point and mark loc
        (setq modi/drag-stuff--point-mark-exchanged nil)))))

(defun modi/drag-stuff--rst-pt-post-drag ()
  "Restore the `point' to where it was by forwarding it by one char after
the vertical drag is done."
  (when modi/drag-stuff--point-adjusted
    (forward-char 1)
    (setq modi/drag-stuff--point-adjusted nil))
  (when modi/drag-stuff--point-mark-exchanged
    (exchange-point-and-mark) ; restore the original point and mark loc
    (setq modi/drag-stuff--point-mark-exchanged nil)))

(add-hook 'drag-stuff-before-drag-hook #'modi/drag-stuff--adj-pt-pre-drag)
(add-hook 'drag-stuff-after-drag-hook  #'modi/drag-stuff--rst-pt-post-drag)

上記のハックの前後に線をドラッグする方法のデモ

ハッキング前

 line 1                                      line 1
▯line 2                                      line 5
 line 3    --(M-x drag-stuff-down)-->       ▯line 2   MOVED LINE
▮line 4                                      line 3   MOVED LINE
 line 5                                     ▮line 4   MOVED LINE

ハック後

 line 1                                      line 1
▯line 2                                      line 4
 line 3    --(M-x drag-stuff-down)-->       ▯line 2   MOVED LINE
▮line 4                                      line 3   MOVED LINE
 line 5                                     ▮line 5

キーバインド

日食のような動作を実現するには、適切なキーバインディングを追加するだけです。

(global-set-key (kbd "M-<up>")   #'drag-stuff-up)
(global-set-key (kbd "M-<down>") #'drag-stuff-down)

うーん... 4行目を動かすのと同じくらい面倒ですが、それは間違いなくより一貫しています。たとえば、行を移動する場合、ポイントがEOLであった場合、新しい「ハッキング」動作は実際に非常に奇妙に見えます。
PythonNut 2015

@PythonNutええ、ポイントが列0にない場合、その行全体が移動します。しかし、これがハックである理由です。それは私のワークフローに適合します。行を移動するとき、私は、私は、全体のライン(選択する傾向があるので、私のポイントは、COL 0であり、私の領域選択の99%を信じている C-a C-SPC C-4 C-n)または段落全体( C-a C-SPC M-})。私は知っM-hていますが、まだそれに慣れていません。選択した段落次の行をドラッグしてしまうたびに、いらいらすることを想像してみてください。:)
Kaushal Modi 2015

ポイントがリージョンの最後ではなく最初にある場合、あなたのハックは間違ったことをしませんか?
Harald Hanche-Olsen 2015

@ HaraldHanche-Olsen正解です。驚いたことに、私はその方法で選択を行ったことがなく(下から上に向かって)、この問題をキャッチしたことはありません:)。これは修正されました(簡単な確認でわかるように)。これで問題が解決するかどうかお知らせください。これに気づいていただきありがとうございます。
Kaushal Modi 2015

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)

1
これは素晴らしいです、これを投稿してくれてありがとう、なぜあなたはこれ以上賛成票を持っていないのかわかりません!
iFunction

1

キーボードマクロを使用してこれを行う方法を次に示します。

  • C-x ( マクロの記録を開始します。
  • C-aSPCC-pSPCC-wC-pC-y 行をカットして、バッファの1行前に貼り付けます。
  • C-x ) マクロの記録を終了します。
  • C-x e 押した回数だけラインを上に移動します。

まあ、transpose-linesこのように機能する関数がありますが、これはあなたの提案がそうであるように単
一行で

@ hfhc2キーボードマクロはとにかくアドホックソリューションです。同じ速度で、1行以上移動させることができます(数値引数をに追加するだけC-pです)。
wvxvw 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.