Skip to content

Instantly share code, notes, and snippets.

@the9ball
Last active December 11, 2015 02:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save the9ball/4531333 to your computer and use it in GitHub Desktop.
Save the9ball/4531333 to your computer and use it in GitHub Desktop.
オレオレ貼り付け処理の実装

はじめに

この記事は Vim Advent Calendar 2012 の46日目の記事です。
45日目は @rbtnn さんの vim scriptで字句解析! でした。

宣伝

毎週土曜日 23時からここでvimrc読書会が開催されています。 他の人のvimrcの設定をパク^H^H参考にできます。
いろいろ捗るのでオススメです!
" と言いつつ後から参加せずに後からログを眺めることしかしてないですが。

CtrlP

本当はCtrlPのプラグインについて書けばいいやと気楽に考えていたのですが
すでに 書かれていたので
これについては自作プラグインの紹介だけしておきます。

ctrlp-verboselet

:verbose let の結果をctrlpに流すだけのプラグイン
https://github.com/the9ball/ctrlp-verboselet

ctrlp-gtags

gtags.vimを便利に使うための誰得プラグイン
https://github.com/the9ball/ctrlp-gtags

本題

いろいろ考えた結果、題目を思いつかないので
最近作ったショートカットの紹介でお茶を濁します。

まずはコードの紹介。

" 貼り付け時に \<\> の有無を選択できるように。.
function! s:pasteOriginal( word, head, foot ) 
  " 対象のレジスタの内容を取得
  echo ( ( 0 == a:word )? 'StringMode' : 'WordMode' ) . ':Register:'
  let l:register = nr2char( getchar() ) 
  if match( l:register, '[a-zA-Z0-9.%#:-\"/]' ) < 0 
    echo l:register . ' is Not Register Name'
    return ""
  endif
  let l:string = getreg( l:register ) 

  " \< \> を削除
  let l:string = substitute( l:string, '^\\<', '', '' ) 
  let l:string = substitute( l:string, '\\>$', '', '' ) 

  " 改めて単語単位なら \< \> で囲む
  if a:word
    let l:string = a:head . l:string . a:foot
  endif

  return l:string
endfunction
function! s:pasteOriginalHeadFoot()
  echo 'Head:'
  let l:head = nr2char( getchar() ) 
  echo 'Foot:'
  let l:foot = nr2char( getchar() ) 
  return s:pasteOriginal( 1, l:head, l:foot )
endfunction
" 単純に<C-r>でマップするとWinのgvimだと反応が悪かったので・・・。
inoremap <expr> <C-r><C-e> <SID>pasteOriginal( 0, '', '' ) 
inoremap <expr> <C-r><C-w> <SID>pasteOriginal( 1, '\<', '\>' ) 
" surround.vim と微妙に用途がかぶってる気がするけど多分気のせい。
inoremap <expr> <C-r><C-r> <SID>pasteOriginalHeadFoot()

動作内容

書いてあるとおりに動きます。(当たり前
<C-r><C-e> で\<\>がない状態でのペースト
<C-r><C-w> で\<\>がある状態でのペーストを行います。
<C-r><C-r> で好きなもの( "()"とかとか )で囲めます。
cnoremap辺りも用意したほうがいいかもしれませんが、
コマンドラインウィンドウを使っている限りはこれで問題ないので放置中です。

悩んだ点

はじめは inoremap を使っておらず、
inoremap <silent><C-r><C-e> <C-o>:<SID>... とした上で setreg して normal! p などとしておりました。
その場合、行末にカーソルがある場合に問題が起きます。
hoge() に reg0:; を入れようとして ) の右側にカーソルを置きましたが、
hoge(;) と改行文字の直前ではなく、
改行文字の前にある文字の直前に挿入されたのです!
まぁ、<C-o>をした時のカーソル位置を考えたらわかる話ですね。
" なんで行末文字にカーソルが合わないのかなぁ。

アドバイスを下さったujihisaさんとthincaさんには感謝です。
ちなみに

col('$') <= col('.')

でも判定できるそうですが、インサートモードのまま関数コールできるのでしょうか???

また、mattnさんからも

<expr> はそれはそれで難点があるので注意
<expr> はバッファを変更出来ない。
バッファを変更したいなら <c-r>=s:foo() が良い。

とのアドバイスをいただきました。
タイミングを逸してしまい言いそびれていましたが、
この場でお礼を申し上げます。ありがとうございました!

その時のログはこちら

明日

明日は @toyamarinyon さんです。お楽しみに。

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