Hatena::ブログ(Diary)

C++でゲームプログラミング

2014-05-24

[]Vim Advent Calendar 2013 175日目: 横幅が統一ではない矩形をヤンクしたり削除したりするプラグインをつくった

この記事は Vim Advent Calendar 2013 175日目の記事になります。


さて、以前、矩形なオブジェクトを対象とする textobj をつくりました。


上記で作った textobj は、

  : カーソル位置
  : 範囲

NeoBundle "Shougo/vimproc.vim"
NeoBundle "Shougo/unite.vim"
NeoBundle "Shougo/unite-outline"
NeoBundle "Shougo/vimfiler.vim"

の用に幅が同じオブジェクトに対しては有効なのですが、幅が違うオブジェクトの場合には対処できません。

" アカウント名のみヤンクしたい
NeoBundle "Shougo/unite.vim"
NeoBundle "t9md/vim-choosewin"
NeoBundle "thinca/vim-qfreplace"
NeoBundle "koron/codic-vim"
NeoBundle "anyakichi/vim-textobj-xbrackets"

このように矩形の対象としたいオブジェクトの幅が統一していない場合に操作するためのプラグインをつくりました。

最初に言っておくと operator を書いてありますが実際には operator ではなくて operator の機能をエミュレートしているので注意してください。


[プラグイン]

[設定例]

" 下の行に向かって入力した {motion} にマッチしなくなるまでの範囲を操作する
" -head は先頭が同じ列の場合のみマッチする

" ヤンク
nmap YY <Plug>(operator-blockwise-yank-head)
" 削除
nmap DD <Plug>(operator-blockwise-delete-head)
" 変更
nmap CC <Plug>(operator-blockwise-change-head)

[使い方]

<Plug>(operator-blockwise-yank)iw するとカーソル位置から下の行に向かって iw にマッチしなくなる範囲までを矩形選択でヤンクします。

ヤンク以外にも <Plug>(operator-blockwise-delete) で削除したり、<Plug>(operator-blockwise-change) 変更したりする事ができます。

他に

" 列に関係なくマッチ
<Plug>(operator-blockwise-yank)
" 先頭が同じ列の場合のみマッチ
<Plug>(operator-blockwise-yank-head)
" 末尾が同じ列の場合のみマッチ
<Plug>(operator-blockwise-yank-tail)

のようなマッピングもあります。

また、operator#blockwise#mapexpr() を使用することで任意の operator で操作することができます。


" operator-replace
" https://github.com/kana/vim-operator-replace
" マッチしたそれぞれのオブジェクトに operator-replace を適用する
nmap <expr> SS operator#blockwise#mapexpr_head("\<Plug>(operator-replace)")

[キャプチャ]

<Plug>(operator-blockwise-delete)i"

https://cloud.githubusercontent.com/assets/214488/3074723/8f568f68-e34f-11e3-84b5-340558aaa021.gif

<Plug>(operator-blockwise-change-head)iw

https://cloud.githubusercontent.com/assets/214488/3074722/7c37cbcc-e34f-11e3-96a4-dc01f5ec660d.gif


言葉で説明するのは難しいので実際に使ってみてください(投げやり。

最初にも書きましたが、このプラグイン

"homu"
"mamimami"
"an"

みたいなテキストがある場合に簡単に "" 内のテキストを操作するためにつくったプラグインです。

なにか要望や不具合があったら Issues までお願いします。

kumakuma 2014/05/25 22:09 Neobundle でインストールして例の通りに設定、YYiwとすると以下のエラーが発生します。

function operator#blockwise#operator..<SNR>71_input_motion..<SNR>71_has_motion の処理中にエラーが検出されました:
行 1:
E117: 未知の関数です: textobj#multitextobj#region_from_textobj
E116: 関数の無効な引数です: empty(textobj#multitextobj#region_from_textobj(a:name)[1])
E15: 無効な式です: s:mapcheck_once(a:name, "o") || !empty(textobj#multitextobj#region_from_textobj(a:name)[1])

osyo-mangaosyo-manga 2014/05/25 22:22 報告ありがとうございます。修正しました。
プラグインを更新して試してみてください。

kumakuma 2014/05/26 00:02 修正確認しました。対応ありがとうございます。
が、別の不具合というか問題点なのですが
<Plug>(operator-blockwise-change-head)を使用した場合は問題ないのですが、<Plug>(operator-blockwise-change)を使用するとCCawでカーソルが行頭に移動してしまいます。
まあよく考えると短形編集を使用しているので行頭の違う部分を編集できるわけないのですが、もし何とかなるならうれしいです。

osyo-mangaosyo-manga 2014/05/26 05:10 >修正確認しました。対応ありがとうございます。
確認ありがとうございます。
><Plug>(operator-blockwise-change-head)を使用した場合は問題ないのですが、<Plug>(operator-blockwise-change)を使用するとCCawでカーソルが行頭に移動してしまいます。
これなのですがちょっと具体的にどういう不具合なのかよくわかりませんでした。
ただ、change のカーソル移動周りにバグがあったので修正しました。
もう少し具体的な例と手順を上げてもらえると助かります。
(複雑であれば github の Issues の方に報告してもらえるとよいかも。

kumakuma 2014/05/26 13:29 例えば#をマウスとして以下のような位置でCCiwddd<esc>とすると

a AAA#AA
b BBBBBBB
c CCCC

a ddd
b ddd
c ddd

となります。これを

a ddddd
b ddddddd
c dddd

とできるようになると便利なのですが、ここだけ別処理が必要になってしまいまけど

kumakuma 2014/05/26 13:32 ん?すいません連続した空白がまとめられてしまったみたいです。
訂正版

例えば#をマウスとして以下のような位置でCCiwddd<esc>とすると

a \ \ AAA#AA
b BBBBBBB
c \ \ \ CCCC

a \ \ ddd
b \ \ ddd
c \ \ ddd

となります。これを

a \ \ ddddd
b ddddddd
c \ \ \ dddd

とできるようになると便利なのですが、ここだけ別処理が必要になってしまいますね。

osyo-mangaosyo-manga 2014/05/26 16:59 あーなんとなくわかりました。
これって、『AAAAA』や『BBBBBBB』などを『特定の1文字(d)』で埋めたい、っていうようなことなんでしょうか。
そうでなければ、例えば CCiw123<esc> と入力した場合はどういう風な結果になることを期待しているのでしょうか。
これを対応するのであれば operator-blockwise ではなくて、それ用の operator を実装するのがよさそうな雰囲気ですねぇ。

kumakuma 2014/05/26 20:40 重ね重ねすいません。
a \ \ ddddd
b ddddddd
c \ \ \ dddd
これは
a \ \ ddd
b ddd
c \ \ \ ddd
の間違いです。つまりその例だと
a \ \ 123
b 123
c \ \ \ 123
となって欲しいのです。

osyo-mangaosyo-manga 2014/05/26 20:47 なるほど、把握しました。
確かにそっちの方が意図した挙動な気がしますが…実装はちょっと難しいかもしれませんねぇ…。

kumakuma 2018/03/30 13:28 お久しぶりです。
久しぶりに使用したところ以下のようにtextobj#blockwise#region_from_textobj()が見つからないとエラーが出ました。
依存関係変わりましたか?

function operator#blockwise#operator[6]..<SNR>137_operator_blockwise[4]..<SNR>137_blockwise_yank[6]..<SNR>137_blockwise[5]..<SNR>137_region の処理中にエラーが検出されました:
行 1:
E117: 未知の関数です: textobj#blockwise#region_from_textobj
E116: 関数の無効な引数です: get(textobj#blockwise#region_from_textobj(a:textobj), 1, [])
E15: 無効な式です: get(textobj#blockwise#region_from_textobj(a:textobj), 1, [])

osyo-mangaosyo-manga 2018/03/30 13:35 お手数ですが、github の方に報告して頂けると助かります。

kumakuma 2018/03/30 13:51 了解です。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/osyo-manga/20140524/1400943249