Как автоматически прописать вторую букву слова?

13

Когда мне приходится набирать много текста, я часто держу палец нажатым, shiftкогда пишу первую букву предложения, которое часто дает:

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

Здесь Eиз NEwдолжна быть в нижнем регистре. Затем я пытаюсь создать функцию, которая бы определяла, является ли вторая буква первого слова в набираемом мной предложении прописной буквой, а какая - строчной. Важной частью будет то, что исправление должно быть сделано автоматически, пока я печатаю конец моего предложения.

До сих пор я пытался поиграть с событием автокоманды, 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: как его можно улучшить?
statox
источник

Ответы:

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

Я думаю, что это не полное решение, но я подумал, что попробую другой подход и посмотрю, вызвало ли оно что-нибудь для вас. :)

Tumbler41
источник
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'

Редактировать: я не знаю, есть ли разница (с точки зрения производительности) между этими двумя синтаксисами: :let myvar = test ? new_value : old_valueи :if test | let myvar = new_value | endif.

Однажды я прочитал, что когда вы хотите оптимизировать свой код, вы должны использовать как можно меньше Ex-команд. Поэтому , возможно, второй синтаксис (который может быть расценен как 3 команды Ex: :if, :let, :endif) происходит медленнее , чем 1 - ый, я не знаю.

Но если это так, вы можете заменить autocmd на:

autocmd InsertCharPre * let v:char = (v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c') ? tolower(v:char) : v:char
user9433424
источник
1
Теперь это элегантное решение! По моим первым тестам это работает хорошо. Я должен использовать это в течение некоторого времени, чтобы быть уверенным, что это надежно. Мне нравится, как вы изменили v:charэту идею, которую я упустил с первой попытки.
statox
1

Другой способ сделать это (не такой автоматический и не такой универсальный; просто более короткий):

  • так как вы пишете предложения / прозу, а не код, Vim активирует проверку орфографии в ваших текстовых буферах
  • создать комбинированный ключ режима быстрой вставки, который возвращает к последним орфографическим ошибкам, исправляет их, а затем восстанавливает положение / состояние; например:

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

Итак, скажем, вы начинаете писать

"THis is a mistake|"

... а ты просто осознаешь ошибку - что делать? - просто нажмите <C-s>и продолжайте писать предложение.

VanLaser
источник