直前の単語境界からカーソル位置までを大文字にする

THIS_IS_A_CONSTANT_NAME のような、すべて大文字からなる定数名の入力を多少楽にする方法について。

補完がきく状況であれば補完すれば済む話ですが、新規に定数を定義する場合や、定数名が補完候補としてキャッシュされていない場合などは、どうしても自分で名前をタイプする必要があります。Shiftキーを押下した状態で長い名前をタイプするのは非常に苦痛なので、通常は

  1. capslock on/off
  2. 挿入モードから抜けた後 gUiw とか

といった方法が採られると思いますが、自分は以下のように設定しています。

id:thincaさんによる改訂版(コメ欄より)
inoremap <C-g><C-u> <ESC>gUiw`]a 
自作版*1

inoremap <expr> <C-g><C-u> <SID>upcase_word_before_cursor()

function! s:upcase_word_before_cursor()
  let cmdstr = "\<Space>\<Esc>bgUeelx"
  if col(".") == col("$")
    let cmdstr .= "a"
  else
    let cmdstr .= "i"
  endif
  return cmdstr
endfunction


これで例えば

THIS_IS_A_CONSTANT_NAME = value

と入力したい場合は、挿入モードで

this_is_a_constant_name = value

とタイプします。 で直前の単語境界から現在のカーソル位置までを大文字にし、そのまま挿入モードでの入力を続行できます。

capslock の状態を気にしないでいい*2のと、gUiw などを使うために挿入モードから抜けた後で大文字にしたい単語へ再度移動しないでいいので便利です。

ただ、関数の定義キーマップを見てもらえばわかるように、実際には一度挿入モードを抜けているので、この後 . による挿入の繰り返しを行った場合、期待した動作にならないという問題があります。

追記

関数を呼び出す形式にしたのは、挿入モードに再度戻るに際し、カーソル位置が行末かどうかで ia を使い分ける必要があったからです。この辺はもっとうまいやり方があるような気がするのですが…… ツッコミあればお願いします。

追記2

↑のように書いたところ、投稿から数時間で早速 id:thincaさんよりツッコミが寄せられ、シンプルに inoremap 1行で完結してしまいました。挿入モードを抜けた位置からの再開`]a でできるというのは目から鱗*3でした。感謝。
 ↑

']  `]                  To the last character of the previously changed or
                        yanked text.

なので「挿入モードを抜けた位置から」ではなく、「iw で選択された単語の語末から」でした。訂正します。

*1:恥ずかしいので打ち消し線でごまかすw

*2:capslock を on にしたまま挿入モードから抜けてパニック、というのも起こりません (^^;

*3:これをどうやるかで散々悩んだ経緯ありw