単語の2番目の文字を自動的に小文字にする方法は?


13

たくさんのテキストを入力しなければならないshiftとき、私はしばしば次のような文の最初の文字を書くときに指を押し続ける傾向があります。

[...]end of sentence. NEw sentence[...]

ここで、Eof NEwは小文字でなければなりません。次に、入力する文の最初の単語の2番目の文字が大文字かどうかを検出し、小文字にする関数を作成しようとしています。重要な部分は、文章の終わりを入力している間に修正が自動的に行われることです。

これまでのところInsertCharPre、このイベントによってトリガーされる関数によってテキストを変更できないことに気付く前に、オートコマンドイベントを試してみました。

良い解決策は何でしょうか?

これまでのところ、頭字語のような大文字の場合や、このようなことをする必要があるエッジケースに焦点を合わせる必要はありません。

編集私はこれを作成しましたが、これは完璧な回避策ではありません:

autocmd CursorMovedI * call RemoveUnwantedUpper()

function! RemoveUnwantedUpper()
    " Get the current sentence
    " Based on http://stackoverflow.com/a/23315227/4194289
    let l:save_clipboard = &clipboard
    set clipboard= " Avoid clobbering the selection and clipboard registers.
    let l:save_reg = getreg('"')
    let l:save_regmode = getregtype('"')

    normal! y(
    normal! ``

    let l:sentence =getreg('"') 

    call setreg('"', l:save_reg, l:save_regmode)
    let &clipboard = l:save_clipboard

    " Check that we entered a new word (space inserted)
    if l:sentence[len(l:sentence)-1] != " "
       return
    endif 

    " Check if the word is the first one of the sentence
    let l:size = len(split(l:sentence, " "))
    if l:size > 1 
        return
    endif

    " If the last char entered is a space (new word) remove the unwanted Upper case
   normal! bl
   normal! vu
   normal! ``

endfunction

挿入モードで最初に入力した文字が行末に移動するため問題がありますが、修正できると思います。

今、私の質問はコードレビューの質問になると思います

  • 挿入された最初の文字を動かす副作用を取り除くにはどうすればよいですか?
  • それは可能な最良の方法ですか?
  • この方法はVimを遅くするようです:どうすれば改善できますか?

回答:


6

ここに、ちょっと速いものが少しあります。堅牢性は低いと思いますが、はるかに軽量です。たぶんあなたはそれをあなたのものに組み込んでそれをより速くすることができますか?時間があれば、おそらく少し修正するでしょう。

inoremap <Space> <C-o>:call CheckCase()<CR><Space>

function! CheckCase()
   normal! may2b
   let l:words = getreg('"')
   if l:words[0] == '.'
      normal! wlvu
   endif
   normal! `a
endfunction

完全な解決策ではないと思いますが、別のアプローチを試してみて、それがあなたに何かを刺激したかどうかを確認すると思いました。:)


4
再マッピングのアイデアは<Space>、関数の呼び出し回数を減らすため、非常に興味深いようです。私もこの方法で作業しようとします!
statox

4

私はそれがどれほど信頼できるかわかりませんが、あなたはこれを試すことができます:

augroup FixDoubleUppercase
    autocmd!
    autocmd InsertCharPre * if v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c' | let v:char = tolower(v:char) | endif
augroup END

文字を挿入する前に次のコマンドを実行するautocmdをインストールします。

if v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c' | let v:char = tolower(v:char) | endif

挿入しようとしている文字は内部変数に保存されv:char、テストが次の場合:

v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c'

...成功し、その後、autocmdは、新しい値を代入v:charしています、tolower(v:char)

このテストでは、大文字(v:char =~ '\u')を挿入しようとしているかどうか、カーソルが文の最初の単語の最初の文字の後にあるかどうかを確認します。

getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c'

編集:これらの2つの構文の違い(パフォーマンス面)があるかどうかはわかりません: :let myvar = test ? new_value : old_value:if test | let myvar = new_value | endif

コードを最適化する場合、使用するExコマンドはできるだけ少なくする必要があることを一度読んだことがあります。そのため、おそらく(3つのEXコマンドとしてカウントすることができます:第二構文は:if:let:endif)第一のものよりも遅いですが、私は知りません。

ただし、この場合は、autocmdを次のように置き換えることができます。

autocmd InsertCharPre * let v:char = (v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c') ? tolower(v:char) : v:char

1
これがエレガントなソリューションです!私の最初のテストによると、うまく機能しています。堅牢であることを確認するには、しばらく使用する必要があります。v:char私が最初の試みで欠けていたアイデアをどのように修正したかが好きです。
statox

1

それを行う別の方法(それほど自動化されておらず、あまり一般的でもありません;短くなっています):

  • コードではなく文章/プローゼを書いているので、Vimにテキストバッファーのスペルチェックを有効にさせる
  • 最後のスペルミスに戻って修正し、位置/状態を再開する高速挿入モードコンボキーを作成します。例えば:

    inoremap <C-s> <Esc>[s1z=gi
    

だから今、あなたが書き始めると言います

"THis is a mistake|"

...そして、あなたは間違いに気付いた-何をすべきか?-単にヒット<C-s>して、文章を書き続けます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.