osyo-manga / vital-over

18 stars 3 forks source link

ビジュアルモードから起動した時にビジュアルモードのハイライトを維持する #125

Open osyo-manga opened 9 years ago

osyo-manga commented 9 years ago

関連 : https://github.com/osyo-manga/vim-over/issues/41

Modules で実装したほうがよいかと思いこっちに立てました。

haya14busa commented 9 years ago

incsearch.vim では実装してるので必要だったらprします

osyo-manga commented 9 years ago

お、お願いします!

haya14busa commented 9 years ago

ただvisualモードで起動されてるかvital-over側で検知するのめんどいかも...? まぁ mode(1) 直接叩けばいいか

osyo-manga commented 9 years ago

どうなんですかね。 そこら辺はなんかいい感じに(適当。

haya14busa commented 9 years ago

あーこれよく思い返してみれば実は2段階問題があります.

普通にヴィジュアルモードの選択を維持する場合は

  1. <expr> マッピングなどを用いてコマンド(:)を経由しないようにする
  2. 関数内でヴィジュアルモードから起動された場合はnormal! gvする

のいづれかの方法を取れば可能です. これが問題の1段階目で,これはあんまりモジュールでやる問題でもなさそう(ヴィジュアルモードから起動したかどうかは引数とったりヴィジュアル用の関数を作らないとわからないため.<expr>じゃない場合は呼び出し先でmode(1) つかっても無理)

しかしこれだけでは2段階目の問題が浮上し,これはヴィジュアル選択範囲のハイライトがmatchadd()よりも必ず優先度が高いようなので,incsearch.vimやおそらくvim-overのハイライトがビジュアル選択ハイライトに負けます.

これをincsearch.vimではビジュアル選択ハイライトを一旦消して自前でハイライトすることで対応しており,モジュール化するとしたらおそらくこちらの方だと思いますがそういう認識でいいでしょうか? Retain highlight in visual mode という要望を応えるだけならnormal! gvでできる(vim-overがそれでエンバグする可能性はわからないですが).

あとかなり気軽にPRしましょうかと言ってしまいましたが,modeを引数として取らないと対応できない(かも)なので,vital-overのenter/leaveイベントあたりで対応するの意外とダルそうだということに気づいた...

osyo-manga commented 9 years ago

ふーむ、なるほど。

Retain highlight in visual mode という要望を応えるだけならnormal! gvでできる(vim-overがそれでエンバグする可能性はわからないですが).

確かにそれが一番手っ取り早そうな気がするんですが、set showmode=1 の時に normal! gv すると vital-over の出力が崩れてしまいますね。 あとカーソルのハイライトもおかしくなります。

これは incsearch.vim でも同様に再現します。 vital-over 側で対応するのがよいかなぁ…。

osyo-manga commented 9 years ago

うーん、ここら辺も含めてモジュール化してしまってもよさそうな気はします。

haya14busa commented 9 years ago

確かにそれが一番手っ取り早そうな気がするんですが、set showmode=1 の時に normal! gv すると vital-over の出力が崩れてしまいますね。 あとカーソルのハイライトもおかしくなります。

これ再現しない...と思ったらgvimで起動したら再現しました. あと正確には set showmode ですかね?

関係ないけどgvimかつヴィジュアルモードから起動したらめっちゃ遅いな...ターミナルだと普通の速度なのに

haya14busa commented 9 years ago

カーソルのハイライトがおかしくなる問題は :set noshowmode でも再現しそう

osyo-manga commented 9 years ago

カーソルのハイライトがおかしくなる問題は :set noshowmode でも再現しそう

ですね。 showmode とカーソルハイライトが残ったままになる2つの問題があるみたいです。

osyo-manga commented 9 years ago

とりあえず、normal! gv だと問題あるみたいなんで、matchadd() を使った版を実装してみました。


call vital#of("vital").unload()
let s:V = vital#of("vital")
let s:Highlight = s:V.import("Coaster.Highlight")
let s:cmdline = s:V.import("Over.Commandline").make_standard("> ")

let s:module = {
\   "name" : "HighlightVisualMode"
\}

function! s:module.__valid__()
    return 0
endfunction

function! s:module.on_enter(cmdline)
    if !self.__valid__(a:cmdline)
        return
    endif
    if &selection == "exclusive"
        let pat = '\%''<\|\%>''<.*\%<''>'
    else
        let pat = '\%''<\|\%>''<.*\%<''>\|\%''>'
    endif
    call s:Highlight.highlight("visualmode", "Visual", pat)
endfunction

function! s:module.on_leave(...)
    call s:Highlight.clear("visualmode")
endfunction

let s:hl_vmode = deepcopy(s:module)

" ユーザ側でハイライトする条件を定義
function! s:hl_vmode.__valid__(cmdline)
    return a:cmdline._visualmode
endfunction

call s:cmdline.connect(s:hl_vmode)

function! Test() range
    " 複数行選択されていた場合、visual mode にする
    " NOTE: 1行のみ選択されていた場合は有効にならない
    let s:cmdline._visualmode = (a:firstline != a:lastline)
    call s:cmdline.start()
endfunction

vnoremap <A-c> :call Test()<CR>
nnoremap <A-c> :call Test()<CR>

visual mode かどうかを判定するのはユーザ側で決定できるように実装しました。 いまは range の値で判定していますが、<expr> 時に mode() の値を渡してごにょごにょというような判定もできます。 暫定的な問題点として矩形選択した場合にちゃんとハイライトされないというのがあります。

osyo-manga commented 9 years ago

余計なコード混ざってたので修正