2012-01-24 5 views
21

私は追加のパラメータを取る新しい演算子をVimでマップすることを検討していました。パラメータを使って新しいVim演算子を定義する

は例えば、私たちは、私がciwのような動きを取りますが、必要となる(例えば、sのために)置き換えるためにカスタムアクションをしている探しています何を、ciwは「内部の単語をカット」し、挿入モードにあなたを置くことを知っています余分なパラメータ。そうよう*と最初の単語を囲むことになる

Given a line in a text file 

通常モードで実行する(最初の列にカーソルを与えられる)siw*

簡単な例であろう

*Given* a line in a text file 

私は知っている、これは最も優れたsurround.vimプラグインがするものです。しかし、私はここで例を挙げているだけで、上記の作業ができるようにマッピングを取得する方法についての答えを探しています。

私はonoremapと​​で試してみましたが、私が望むように再生できないようです。

これは、モーションと演算子保留マッピングの組み合わせです。

+1

面白い質問:) – Rook

+1

これはサラウンドの機能ですから、サラウンドのコードを見ましたか? – romainl

+0

これは、 'y'、 'd'、' c'のようなVimアクションの後にモーションを追加する点を除いて、サラウンドの動作と似ています。繰り返しますが、私は例を挙げています。サラウンドを書き直したいと言っているわけではありません。そして、はい、私はサラウンドのソースを見ました。 – alfredodeza

答えて

12

説明のために、質問 で説明されているコマンドの実装例です。

nnoremap <silent> s :set opfunc=Surround<cr>[email protected] 
vnoremap <silent> s :<c-u>call Surround(visualmode(), 1)<cr> 
function! Surround(vt, ...) 
    let s = InputChar() 
    if s =~ "\<esc>" || s =~ "\<c-c>" 
     return 
    endif 
    let [sl, sc] = getpos(a:0 ? "'<" : "'[")[1:2] 
    let [el, ec] = getpos(a:0 ? "'>" : "']")[1:2] 
    if a:vt == 'line' || a:vt == 'V' 
     call append(el, s) 
     call append(sl-1, s) 
    elseif a:vt == 'block' || a:vt == "\<c-v>" 
     exe sl.','.el 's/\%'.sc.'c\|\%'.ec.'c.\zs/\=s/g|norm!``' 
    else 
     exe el 's/\%'.ec.'c.\zs/\=s/|norm!``' 
     exe sl 's/\%'.sc.'c/\=s/|norm!``' 
    endif 
endfunction 

ユーザー入力を取得するには、機能InputChar()は 必要な引数が単一の文字であると仮定すると、使用されています。それは文字列引数を受け入れることが必要である場合

function! InputChar() 
    let c = getchar() 
    return type(c) == type(0) ? nr2char(c) : c 
endfunction 

、代わりに InputChar()input()呼び出します。

7

質問のタイトルが誤解の原因になることがあります。あなたがしたいのは、ydcのような新しい演算子を定義することです。動きもテキストオブジェクトもそうではありませんか? :help :map-operatorには、新しい演算子を定義する方法が記述されています。サラウンドプラグインのようなパラメータを使用するには、'operatorfunc'getchar()を使用してください。

:help :map-operatorが基本について説明していますが、'operatorfunc'に渡される引数を処理するのは面倒です。 vim-operator-userを使用すると、引数の処理を簡素化できます。あなたが本当にあなた自身のテキストオブジェクトを定義したい場合は、vim-textobj-userをご検討ください

function! OperatorSurround(motion_wise) 
    let _c = getchar() 
    let c = type(_c) == type(0) ? nr2char(_c) : _c 
    if c ==# "\<Esc>" || c == "\<C-c>" 
    return 
    endif 

    let bp = getpos("'[") 
    let ep = getpos("']") 
    if a:motion_wise ==# 'char' 
    call setpos('.', ep) 
    execute "normal! \"=c\<Return>p" 
    call setpos('.', bp) 
    execute "normal! \"=c\<Return>P" 
    elseif a:motion_wise ==# 'line' 
    let indent = matchstr(getline('.'), '^\s*') 
    call append(ep[1], indent . c) 
    call append(bp[1] - 1, indent . c) 
    elseif a:motion_wise ==# 'block' 
    execute bp[1].','.ep[1].'substitute/\%'.ep[2].'c.\zs/\=c/' 
    execute bp[1].','.ep[1].'substitute/\%'.bp[2].'c\zs/\=c/' 
    call setpos('.', bp) 
    else 
    endif 
endfunction 
call operator#user#define('surround', 'OperatorSurround') 
map s <Plug>(operator-surround) 

:次のようにこのプラグインでは、サラウンドのようなオペレータを書き込むことができます。

+0

誰かが実際にどのようにこの具体的な例を与えてくれれば幸いですか?私はすべてを試しました。たとえば、どのコマンドが何をしますか?ありがとう! –

関連する問題