Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

repeat.vim support #18

Closed
thinca opened this issue May 11, 2013 · 26 comments
Closed

repeat.vim support #18

thinca opened this issue May 11, 2013 · 26 comments

Comments

@thinca
Copy link

thinca commented May 11, 2013

. でコメントアウト操作を繰り返したいです。

@deris
Copy link

deris commented Jul 6, 2013

+1

@thinca
Copy link
Author

thinca commented Jul 11, 2014

wktk

@tyru
Copy link
Owner

tyru commented Jul 11, 2014

repeat.vimのAPIは触った事ないんですよねぇ。
帰ったら見てみようかな…

wktk


Reply to this email directly or view it on GitHub
#18 (comment).

@toshi32tony3
Copy link

+1

repeat.vimのAPIは触った事ないんですよねぇ。
帰ったら見てみようかな…

リピートしたい処理の最後でsilent! call repeat#set("(リピートしたい処理のマッピング)", 1)するだけで良いはずです...

@tyru
Copy link
Owner

tyru commented Mar 27, 2016

PR! PR!

@tyru
Copy link
Owner

tyru commented Apr 8, 2016

#59 で実装しました (masterにもマージ済みです)。

@tyru tyru added release/1.0 and removed next labels Apr 8, 2016
@toshi32tony3
Copy link

repeat.vimのAPIは触った事ないんですよねぇ。
帰ったら見てみようかな…

リピートしたい処理の最後でsilent! call repeat#set("(リピートしたい処理のマッピング)", 1)するだけで良いはずです...

対応ありがとうございます...早速試してみました。operatorで指定範囲をコメントトグルした後にdotrepeatすると1行にしか適用されなかったので対応を考える必要がありそう

Lingrの方でコメントしてしまいましたが、範囲指定を含めてrepeatするにはこれだけじゃダメでした。

        let lastmap = printf("`[V`]\<Plug>(caw:%s:%s)", a:action, a:method)

こんな対応で良いかなと思ったけどさすがにダメでした。んー。

@toshi32tony3
Copy link

let lastmap = printf("[V](caw:%s:%s)", a:action, a:method)
こんな対応で良いかなと思ったけどさすがにダメでした。んー。

例えばgciしてコメントアウトした行の位置はmark([, ])が覚えてるけれど、その後に移動してdotrepeatすると現在のカーソル位置~markの位置に適用してしまう。3行に適用したとか、そういう単位で覚えてdotrepeatさせないといけない。

            let lines = line("']") - line("'[")
            let prefix = lines ? printf('V%dj', lines) : ''
            let lastmap = prefix
                  \ . printf("\<Plug>(caw:%s:%s)", a:action, a:method)
            call repeat#set(lastmap)

とりあえず、これで動く気がする。あれ?バッファ開いた直後って行頭と行末にmark([, ])が記憶されてるのかな?バッファ開いた直後だと誤爆する。

と思ったら最初のgciで変更行が記憶されてないのがおかしい。何故だ…。何かをトリガに記憶されるようになっているので自分の環境に問題がありそう。

@tyru tyru reopened this Apr 9, 2016
@tyru
Copy link
Owner

tyru commented Apr 9, 2016

ビジュアルモード確認してませんでした…ありがとうございます。
repeat#set() の第2引数に count 指定すれば行けるかと思いましたが違いますか? (今ちょっとすぐ試せないですが)

@toshi32tony3
Copy link

repeat#set() の第2引数に count 指定すれば行けるかと思いましたが違いますか? (今ちょっとすぐ試せないですが)

↑ですが繰り返し回数指定のcountだったような気がします。確認しますね。

https://github.com/kana/vim-repeat/blob/master/autoload/repeat.vim

repeat#set() の第2引数のcountはnormalの前に前置するだけぽいですね。

@toshi32tony3
Copy link

と思ったら最初のgciで変更行が記憶されてないのがおかしい。何故だ…。何かをトリガに記憶されるようになっているので自分の環境に問題がありそう。

ちなみに上記はoperatorとして使ってる分には問題無いです。自分はほとんどoperatorの方しか使ってないので実質問題にはならなそう。

@tyru
Copy link
Owner

tyru commented Apr 9, 2016

あ、operator の方は最初から手を入れてません。
operator-user が勝手にやってくれるので。

@toshi32tony3
Copy link

あ、operator の方は最初から手を入れてません。
operator-user が勝手にやってくれるので。

結果から言うと手を入れたつもりがなくても入ってしまってる状況だと思います。論拠は以下です。

対応ありがとうございます...早速試してみました。operatorで指定範囲をコメントトグルした後にdotrepeatすると1行にしか適用されなかったので対応を考える必要がありそう

operator-userの中身は読んでないのではっきりしたことは言えないのですが、やってることは:h g@を使って自分でoperatorを定義する手順をより簡単にするものだと思います。

そこでやってるのはmotionやtext-objects指定時に設定されるmark([, ])の範囲をvisualないしlinewise-visualで選択してから指定した関数を呼び出す、みたいな具合です。

    • 今回(caw:wrap:toggle)をvim-repeatでdotrepeatできるようにした
    • (caw-operator-wrap-toggle)を使うと(caw:wrap:toggle)が内部で呼び出されるのでdotrepeat候補が(caw:wrap:toggle)になってしまった
      • ↑により(caw-operator-wrap-toggle)の変更がdotrepeatできなくなった

間違ってたらすみません。

@toshi32tony3
Copy link

と思ったら最初のgciで変更行が記憶されてないのがおかしい。何故だ…。何かをトリガに記憶されるようになっているので自分の環境に問題がありそう。

ちなみに上記はoperatorとして使ってる分には問題無いです。自分はほとんどoperatorの方しか使ってないので実質問題にはならなそう。

以下でもgciした時に変更位置のmark([, ])が更新されなかったので、環境の問題ではなさそうです。手元(https://github.com/toshi32tony3/caw.vim) では暫定修正コード入れたけれど上記問題が解決しないとPRできない…

set encoding=utf-8

" filetype関連のファイルはruntimepathの登録が終わってから読み込むため, 一旦オフ
filetype plugin indent off

" 実は必要のないset nocompatible
" http://rbtnn.hateblo.jp/entry/2014/11/30/174749
if has('vim_starting')
  if &compatible | setglobal nocompatible | endif
    setglobal runtimepath+=~/.vim/bundle/neobundle.vim_673be4e
endif
call neobundle#begin(expand('~/.vim/bundle'))

NeoBundleLazy 'kana/vim-operator-user'

NeoBundleLazy 'toshi32tony3/caw.vim', {
      \   'depends' : ['kana/vim-operator-user'],
      \   'on_map'  : [['nx', '<Plug>', '<Plug>(operator']],
      \ }

call neobundle#end()

" filetype関連のファイルを読み込む
filetype plugin indent on

" シンタックスハイライトを有効化(on:現在の設定を破棄する, enable:破棄しない)
syntax enable

" コメントアウト/コメントアウト解除(caw.vim) {{{
if neobundle#tap('caw.vim')

  map gc    <Plug>(caw:prefix)
  map <A-c> <Plug>(operator-caw-wrap-toggle)

endif "}}}

@toshi32tony3
Copy link

setline()やsubstitute()あたりを使ってると変更履歴mark([, ])が更新されないので、これが原因ぽいです。

setline({lnum}, {text})                 *setline()*
        カレントバッファの{lnum}行目を{text}にする。行を挿入したい場合
        は |append()| を使う。
        {lnum}は|getline()|のときと同じように解釈される。
        {lnum}が最後の行の次の行の場合、新規行として{text}を追加する。
        成功したら0を返す。失敗したら(大抵{lnum}が無効な値のとき)1を返
        す。例: >
            :call setline(5, strftime("%c"))
<       {text}がリスト|List|の場合、{lnum}行目とそれ以降の行にリストの
        要素をセットする。例: >
            :call setline(5, ['aaa', 'bbb', 'ccc'])
<       上の例は次と同値である: >
            :for [n, l] in [[5, 'aaa'], [6, 'bbb'], [7, 'ccc']]
            :  call setline(n, l)
            :endfor
<       Note: マーク '[ と '] はセットされない。

@machakann
Copy link
Contributor

変更位置のマークが更新されないのは setline() 関数か append() 関数で編集をしているためではないでしょうか。これらの関数は '[, '] マークを更新しません。

オペレータを使った場合は対象範囲をオペレータに渡すため Vim がこれらのマークを更新しますが、オペレータ以外のマッピングだと更新されないと思います。

@machakann
Copy link
Contributor

かぶってしまいました、すいません。

@toshi32tony3
Copy link

いえいえ、ちょうど同じ結論に達していました。ありがとうございます。マークの更新を見て処理分岐させるしかないですかね

@machakann
Copy link
Contributor

caw#keymapping_stub() 関数の冒頭で context に編集した行数を保存できませんかね?

それと、オペレータが repeat#set() を使うのは避けたほうがいいと思います。テキストオブジェクト/モーションが repeat#set() を使いたい場合にコンフリクトする恐れがあります。マイナーケースだと思いますが。

@toshi32tony3
Copy link

‘caw#keymapping_stub()関数の冒頭でcontext` に編集した行数を保存できませんかね?

変更の開始行と終了行をそれぞれ保持してるみたいなので、そっち使えば解決できる話でした。とりあえず試してみます。
→上に書いてた、こんな感じで…をlet lines = context.lastline - context.firstlineにすればいけました。

それと、オペレータが repeat#set() を使うのは避けたほうがいいと思います。テキストオブジェクト/モーションが repeat#set() を使いたい場合にコンフリクトする恐れがあります。マイナーケースだと思いますが。

確かにそうですね。operatorに登録するマッピングは分けた方がよさそう

@machakann
Copy link
Contributor

大変な話になるかもしれないので聞き流してもらって構わないんですが、基本のキーマッピングをオペレータを使って定義することで vim-repeat への依存もなくドットリピートできますね。

omap <SID>line :normal! v^og_<CR>
nmap gci <Plug>(operator-caw-hatpos-comment)<SID>line
xmap gci <Plug>(operator-caw-hatpos-comment)

operator-user への依存をなくす必要があるのですが。。。

@toshi32tony3
Copy link

大変な話になるかもしれないので聞き流してもらって構わないんですが、基本のキーマッピングをオペレータを使って定義することで vim-repeat への依存もなくドットリピートできますね。

あー・・・なるほど。

  • operatorがvisual-repeat可能だからvim-repeatに依存する必要が無い
  • 基本のキーマッピングにoperator化できない類のものはある?
    • それが無いなら、そもそも基本のキーマッピングが要らないのでは?

operator-user への依存をなくす必要があるのですが。。。

これはどういうことですかね。operator-userで定義したマッピングはvisual-repeatできるので変わらないような。operator-userに依存しないで実現するのが簡単なら、そもそも依存しなくていいじゃんという話にはなりそう。

@machakann
Copy link
Contributor

operator-user がないと caw.vim が使えなくなってしまうということが言いたかったのでした。言葉足らずでした。

@toshi32tony3
Copy link

operator-user がないと caw.vim が使えなくなってしまうということが言いたかったのでした。言葉足らずでした。

なるほど。当たり前ですが、そうですね…。caw.vimではなくvim-operator-○○の類になってしまう。

@machakann
Copy link
Contributor

覚えている限りでは operator-user がやっているのはマッピングの定義とカウント・レジスタをよしなに扱うことだったので、依存を切るのは難しくないと思います。ただ、それでも全体の作業は大変だと思います。

@tyru
Copy link
Owner

tyru commented Apr 9, 2016

お二人が内部に関する事まで色々議論して頂いてるのを感無量の思いで見ていました。ありがとうございます。
土日中に対応できるかは分かりませんが、PRの方も見て対応します。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants