当我不得不输入大量文本时,当我写一个句子的第一个字母时常常会经常按住手指以换档:

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


这里ENEw应该为小写。然后,我试图创建一个函数来检测我键入的句子的第一个单词的第二个字母是否为大写字母,而将其为小写字母。重要的是,当我键入句子的结尾时,更正应自动完成。

到目前为止,我已经尝试过使用自动命令事件InsertCharPre,然后才意识到文本可以不能被此事件触发的函数修改。

什么是好的解决方案?

请注意,到目前为止,我不需要关注诸如此类的边缘情况。首字母缩写词应该是大写字母或类似的东西。

EDIT我做了这个,这不是一个完美的解决方法:

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:如何改进?


#1 楼

这里有些东西很快就熟了。我认为它不那么健壮,但也更轻巧。也许您可以将其合并到您的产品中以使其更快?有时间的时候,我可能会对此做些修改。

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
我认为这不是一个完整的解决方案,但我想我会尝试一种不同的方法,看看是否能激发它任何适合您的东西。 :)

评论


重新映射的想法似乎很有趣,因为它减少了函数的调用次数。我也会尝试以这种方式工作!

–statox♦
16年5月25日在15:02

#2 楼

我不知道它的可靠性如何,但是您可以尝试以下方法:

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'



编辑:我不知道是否有区别(性能-明智的选择)在这两种语法之间::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


评论


现在,这是一个优雅的解决方案!根据我的首次测试,它运作良好。我将不得不使用一段时间以确保它的健壮性。我喜欢您如何修改v:char的想法,因为我在第一次尝试时就没有这个想法。

–statox♦
16年5月25日在15:18



#3 楼

做到这一点的另一种方法(不是那么自动,也不是那么通用;只是更短):


因为您是在写句子/散文,而不是代码,所以让Vim激活文本中的拼写检查缓冲区

创建一个快速插入模式组合键,该键可以返回到最后的拼写错误,进行修复,然后恢复位置/状态;例如:

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



所以现在,说你开始写

"THis is a mistake|"


...而您只是意识到错误-怎么办? -只需按<C-s>,然后继续写句子即可。