¿Cómo minúscula automáticamente la segunda letra de una palabra?

13

Cuando tengo que escribir mucho texto, a menudo tiendo a mantener mi dedo presionado shiftcuando escribo la primera letra de una oración que a menudo me da:

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

Aquí el Ede NEwdebe ser minúscula. Luego estoy tratando de crear una función que detecte si la segunda letra de la primera palabra de la oración que estoy escribiendo es mayúscula y la minúscula. La parte importante sería que la corrección debe hacerse automáticamente mientras escribo el final de mi oración.

Hasta ahora he intentado jugar con el evento de autocomando InsertCharPreantes de darme cuenta de que el texto no puede ser modificado por una función activada por este evento.

¿Cuál sería una buena solución?

Tenga en cuenta que hasta ahora no necesito centrarme en casos de bordes como acrónimos que deberían estar en mayúsculas o este tipo de cosas.

EDITAR He hecho esto, que es una solución no perfecta:

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

Tiene un problema ya que el primer carácter que ingreso en el modo de inserción se mueve al final de la línea, pero creo que se puede corregir.

Supongo que ahora mi pregunta se convierte en una pregunta de revisión de código :

  • ¿Cómo puedo deshacerme del efecto secundario que mueve el primer personaje insertado?
  • ¿Es el mejor método posible?
  • Este método parece ralentizar Vim: ¿cómo podría mejorarse?
statox
fuente

Respuestas:

6

Aquí hay algo pequeño cocinado muy rápido. Creo que es menos robusto, pero también es mucho más ligero. ¿Quizás podrías incorporarlo al tuyo para hacerlo más rápido? Probablemente revisaré esto un poco cuando tenga tiempo.

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

Creo que no es una solución completa, pero pensé que probaría un enfoque diferente y vería si te provocaba algo. :)

Vaso41
fuente
44
La idea de la reasignación <Space>parece bastante interesante, ya que reduce el número de invocaciones de las funciones. ¡Intentaré trabajar de esta manera también!
statox
4

No sé qué tan confiable es, pero podrías intentar esto:

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

Instala un autocmd que ejecuta el siguiente comando antes de insertar un carácter:

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

El carácter que está a punto de insertar se almacena en la variable interna v:char, y si la prueba:

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

... tiene éxito, entonces el autocmd asigna un nuevo valor a v:char, que es tolower(v:char).

La prueba verifica si estaba a punto de insertar una letra mayúscula ( v:char =~ '\u') y si el cursor está después del primer carácter de la primera palabra de una oración:

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

Editar: No sé si hay una diferencia (en cuanto al rendimiento) entre estas 2 sintaxis: :let myvar = test ? new_value : old_valuey :if test | let myvar = new_value | endif.

Una vez leí que cuando quieres optimizar tu código, debes usar la menor cantidad posible de comandos Ex. Así que tal vez la segunda sintaxis (que podría ser considerado como 3 comandos Ex: :if, :let, :endif) es más lento que el primero uno, no sé.

Pero si este es el caso, puede reemplazar el autocmd con:

autocmd InsertCharPre * let v:char = (v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c') ? tolower(v:char) : v:char
usuario9433424
fuente
1
Ahora que es una solución elegante! Según mis primeras pruebas, funciona bien. Tendré que usarlo durante un tiempo para asegurarme de que sea robusto. Me gusta cómo modificó v:charesa idea que me faltaba en mi primer intento.
statox
1

Otra forma de hacerlo (no tan automático y no tan universal; solo más corto):

  • ya que está escribiendo oraciones / prosa, no código, haga que Vim active la corrección ortográfica en sus buffers de texto
  • cree una tecla combinada de modo de inserción rápida que regrese a los últimos errores ortográficos, la corrija y luego reanude la posición / estado; p.ej:

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

Entonces, digamos que empiezas a escribir

"THis is a mistake|"

... y te das cuenta del error: ¿qué hacer? - simplemente presiona <C-s>y continúa escribiendo tu oración.

VanLaser
fuente