2010-12-02 4 views
3

視覚的なテキストブロックを取り、それをリストとして保存する単純なvimスクリプトがあります。関数VtoList()の問題点は、の後にを実行するということです。カーソルは、ビジュアルブロックの先頭に戻ります。このため、ビジュアルブロックが終了する行を取得する方法がありません。関数からビジュアルモードで現在の行を取得する

nn <F2> :call VtoList()<CR> 

func! VtoList() 
    firstline = line('v') " Gets the line where the visual block begins 
    lastline = line('.') " Gets the current line, but not the one I want. 
    mylist = getline(firstline, lastline) 
    echo mylist 
endfunc 

問題はline('.')です。カーソルの現在の行を返すはずですが、関数が呼び出される前に、カーソルはすでにビジュアルブロックの先頭に戻っています。したがって、私は一行の範囲の代わりに一行だけを取得しています。

私は一緒にユーザーがVを打つと、関数が呼び出される前に、別のマークを設定する毎回マークを設定するソリューションを置きます。私はline("'V")line("'Z")line('v')line('.')を置き換える場合

nnoremap V mV 
nnoremap <F2> mZ:call VtoList()<CR> 

機能が正常に動作しますが、私は私ができるならば、それはユーザーのマッピングと競合する可能性があるため、このソリューションを避けるためにします。

カーソルがビジュアルブロックの先頭に戻る前に、関数内でビジュアルブロックの現在の行を取得する方法はありますか?

答えて

4

<expr>を使用し、:を使用しないでください:

function! s:NumSort(a, b) 
    return a:a>a:b ? 1 : a:a==a:b ? 0 : -1 
endfunction 
func! VtoList() 
    let [firstline, lastline]=sort([line('v'), line('.')], 's:NumSort') 
    let mylist = getline(firstline, lastline) 
    echo mylist 
    return "" 
endfunc 
vnoremap <expr> <F2> VtoList() 

注その他の変更:let(あなたはそれを忘れてしまった)、sort(選択開始すると選択が終了した行の後かもしれライン)、vnoremapline("v")視覚モードでのみ動作します)、returnexprマッピングの戻り値が実行されますが、それは必要ありません。副作用のみが必要です)。あなたはあなたのソリューションが動作しない理由は:がマッピングで発生したとき、あなたはすぐにビジュアルモードを終了し、コマンドモードに入るということです

if mode()=~#"^[vV\<C-v>]" 
     let [firstline, lastline]=sort([line('v'), line('.')], 's:NumSort') 
    else 
     let [firstline, lastline]=sort([line("'<"), line("'>")], 's:NumSort') 
    endif 

との二行を置き換えることができます。 line("v")はビジュアルモードでのみ機能します。

その他の注意:vnoremap {lhs} :は、すでに'<,'>で満たされたコマンドラインを生成します。関数定義にrangeを追加し、let [firstline, lastline]=sort([a:firstline, a:lastline], 's:NumSort')を使用した可能性があります。しかし、あなたは:でビジュアルモードを終了します。

+0

ソートの問題はアルファベット順に並べ替えられているため、行5〜12の範囲にある場合は[12,5]から[firstline、lastline]に戻ります。 100sエッジ、1000sエッジなどをブリッジすると同じ問題が発生します。 – bobpaul

+0

@bobpaulありがとう。私は今この問題について知っていますが、ソートがこのように使われる場所はまだすべて見つけられていません。 – ZyX

関連する問題