ラインをインターリーブしてブロックをマージする


15

これから渡すように、行をインターリーブすることで2つのテキストブロックをマージする専用の方法はありますか?

a1
a2
a3
a4
  b1
  b2
  b3
  b4

それに:

a1
  b1
a2
  b2
a3
  b3
a4
  b4

いくつかのコマンドで?

編集:私は本当に佐藤桂のソリューションが好きです、ここに私がそれを実装した方法があります:

function! Interleave()
    " retrieve last selected area position and size
    let start = line(".")
    execute "normal! gvo\<esc>"
    let end = line(".")
    let [start, end] = sort([start, end], "n")
    let size = (end - start + 1) / 2
    " and interleave!
    for i in range(size - 1)
        execute (start + size + i). 'm' .(start + 2 * i)
    endfor
endfunction

" Select your two contiguous, same-sized blocks, and use it to Interleave ;)
vnoremap <pickYourMap> <esc>:call Interleave()<CR>

今、私は興味があります-あなたのユースケースは何ですか?テレビシーズンの字幕のブロック名を変更していますか?
ヴァンレーザー

@VanLaserハハ、私は違います。ほとんどの場合、プログラムからの出力を目で解析します。作成の順序に関する一貫性をチェックし、オブジェクトの読み取りを遅らせる必要があります。ブロックをインターリーブすると、遅延出力ブロックの対応する行を簡単に一致させることができます。また、ログの記録やベンチマークのために、コードの行を繰り返し同じような命令でインターリーブする必要がある場合もあります。離れて:)偉大な感じ、この機能を持つキーストロークだけのカップルになりました実際のコードでそれらをインターリーブ、その後、マクロで簡単にそれらの命令をされている生成
イアーゴー-リト

1
@ lago-lito-答えてくれてありがとう!はい、Vimは非常に用途が広いです:)あなたの「目を解析する」という表現は、scroll-binding2つのVimウィンドウについても考えさせられました。
ヴァンレーザー

これの使用に問題がありますが、2つの連続したブロックをどのように選択していますか?それらは隣接している必要がありますか?
cbcoutinho

@cbcoutinhoはい、彼らは持っています:)私はあなたがそうでなければ両方を選択できるかどうかわかりません。示した例では、カーソルを(たとえば)に置き、b1ヒットvipしてチャンク全体を選択し、,itそれがになり<map-I've-Picked>ます。それはあなたの側で働いていませんか?
iago-lito

回答:


8

(私が知る限り)それを行うための専用の方法はありませんが、ええ、それはいくつかのコマンドで行うことができます:

function! Interleave(start, end, where)
    if a:start < a:where
        for i in range(0, a:end - a:start)
            execute a:start . 'm' . (a:where + i)
        endfor
    else
        for i in range(a:end - a:start, 0, -1)
            execute a:end . 'm' . (a:where + i)
        endfor
    endif
endfunction

で実行できます:call Interleave(5, 8, 1)。最初のパラメーターは移動する最初の行、2番目のパラメーターは最後の行、3番目のパラメーターはそれらを移動する場所です。行番号をオンにして、何をしているのかを確認したいでしょう(:set number)。

これは、ブロックがオーバーラップしないことを前提としています。関数がどのように機能するかを参照:help :move:help range()て理解してください。

おそらく、2つのブロックを選択するより良い方法があります。2つのブロックをスワップできるプラグインがあります。プラグインの名前を思い出せませんが、著者(おそらく有名なDr. Chip?)は、私よりもインターフェイスを見つけることにもっと考えました。:)


甘い!私は唯一の2つのブロックが連続しており、同じサイズを持っているので、二つの引数が必要になりますstartsize。選択からこれらの値を取得する自作機能を使用すると、完璧になります。私はそれに取り組んでいます。:)
iago-lito

興味深いクロスリンク?;)
iago-lito

13

別の代替手段を次に示します。

:g/^a/+4t .
:+,+5d 

最初に4行下の行を現在の行の後(:h :t)にコピーしてから、連続するb行を削除します(:h :d

さらに良いのはこのコマンドです:

 :g/^a//^\s*b/m .

つまり、最初の行で始まる行ごとに、「b」で始まる次の行を見つけて、現在の行の下に移動します。


1
2番目のコマンドで「E16:Invalid range」と表示されました。私は.+,$d代わりに試してみましたが、それはうまくいきました(そうでした.+,.+4d
ピーターレウェリン

なぜこれが起こるのかわからない
クリスチャンブラバンド

1
いいえ、そうではありません。:h:rangeを読むと、正規表現検索の代わりに常に直接番号付けを使用できます
クリスチャンブラバンド

2
@ iago-lito 2番目のトリックは常に機能しますが/^\s*b、別のトリックに変更する 必要があります:range。例:最初のブロックを選択して実行'<,'>g/^/'>+1m.
dedowsdi

1
@ iago-litoクリスチャンの答えと本質的に同じです。1番目のブロックを視覚的に選択した場合'>+1、2番目のブロックの開始を示すマークはハードコーディングされません。
dedowsdi

3

マクロとマークを少し楽しみたい場合は、次のようなものを試すことができます。

  • 最初にwith aを含む行にマーク(ここ)を置きますa1ma

  • を含む行に移動してb1、マークを付けますmb

  • 必要なレジスタ(ここではregister q)でマクロの記録を開始しますqq

  • マクロに次を挿入します。 ddmb'apjma'b

  • マクロの記録を停止します q

  • で、必要に応じて何度でもそれを再生するX@q場所X、それを再生するための時間の数です。

マクロの詳細:

dd mb 'a p j ma 'b
 |  |  | | |    |
 |  |  | | |    go back to line marked `b`
 |  |  | | |
 |  |  | | move of one line and replace the mark `a`
 |  |  | insert the deleted line under the line marked `a`
 |  |  go to line marked `a`
 |  mark the future line to move with `b`
 delete the line to move

編集 lago-litoがコメントで述べたように、このメソッドはマークとバッファを上書きします。

  • マークについては、それが本当の問題だとは思いません。バッファで26個すべてのマークを使用することはめったになく、ほとんどの場合、2個の無料マークが見つかると思います。

  • バッファの場合、一時変数に保存することができます。マクロを記録する前に:let saveReg=getreg('"')レジスタを保存し、アクションが完了:call setreg('"', saveReg)したら、レジスタを以前の状態に戻すために使用します。

とにかく、この解決策は簡単な回避策であり、最適ではないことを認めなければなりません:私の意見では、Christanの答えはバッファとマークを混乱させず、ユーザーに作成を強制しないため、受け入れられるべきですグローバルコマンドの機能を示します。


面白い。残念ながら、これはマークとレジスタの内容を上書きします。これは私が使用している可能性があります;)
iago-lito

@ lago-lito:確かにマークとバッファを上書きします。マークについては、バッファで26個すべてのマークを使用することはないので、それが実際に問題になるとは思わない。バッファの場合、それは問題になる可能性があります。未使用のバッファを見つけることができるか、実際に見つからない場合は、一時変数と関数getreg()を使用setreg()してバッファを保存します。しかし、私はそれが最適な解決策ではないことに同意します:-)
statox

1

私は別の同様の質問を見ましたが、解決策は次のとおりです:

中央のプラス1にジャンプします。

Mj

そして実行:

:,$g/./exe 'm' 2*line('.')-line('$')-1

興味深い:)ただし、選択した段落だけでなく、ファイル全体がインターリーブされることに注意してください!
iago-lito
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.