Come minuscola automaticamente la seconda lettera di una parola?


13

Quando devo scrivere un sacco di testo tendo spesso a tenere il dito premuto shiftquando scrivo la prima lettera di una frase che spesso dà:

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

Qui il Edi NEwdovrebbe essere minuscolo. Sto quindi cercando di creare una funzione che rilevi se la seconda lettera della prima parola della frase che sto scrivendo è maiuscola e che la minuscola. La parte importante sarebbe che la correzione dovrebbe essere fatta automaticamente mentre sto scrivendo la fine della mia frase.

Finora ho provato a giocare con l'evento autocommand InsertCharPre prima di conto che il testo non può essere modificato da una funzione attivata da questo evento.

Quale sarebbe una buona soluzione?

Nota che finora non ho bisogno di concentrarmi su casi limite come gli acronimi che dovrebbero essere in maiuscolo o questo tipo di cose.

EDIT Ho fatto questo, che è una soluzione non perfetta:

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

Ha un problema poiché il primo carattere che inserisco in modalità inserimento viene spostato alla fine della riga, ma penso che possa essere corretto.

Immagino che ora la mia domanda diventi una domanda di revisione del codice :

  • Come posso eliminare l'effetto collaterale che sposta il primo personaggio inserito?
  • È il metodo migliore possibile?
  • Questo metodo sembra rallentare Vim: come potrebbe essere migliorato?

Risposte:


6

Ecco un po 'qualcosa che è stato preparato molto velocemente. È meno robusto penso, ma è anche molto più leggero. Forse potresti incorporarlo nel tuo per renderlo più veloce? Probabilmente lo rivedrò un po 'quando avrò tempo.

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

Penso che non sia una soluzione completa, ma ho pensato di provare un approccio diverso e vedere se ha scatenato qualcosa per te. :)


4
L'idea di rimappare <Space>sembra piuttosto interessante poiché riduce il numero di invocazioni delle funzioni. Proverò a lavorare anche in questo modo!
statox

4

Non so quanto sia affidabile, ma potresti provare questo:

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

Installa un autocmd che esegue il comando seguente prima di inserire un carattere:

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

Il carattere che stai per inserire è memorizzato nella variabile interna v:chare se il test:

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

... riesce, quindi autocmd assegna un nuovo valore a v:char, che è tolower(v:char).

Il test verifica se stavi per inserire una lettera maiuscola ( v:char =~ '\u') e il cursore si trova dopo il primo carattere della prima parola di una frase:

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

Modifica: non so se c'è una differenza (dal punto di vista delle prestazioni) tra queste 2 sintassi: :let myvar = test ? new_value : old_valuee :if test | let myvar = new_value | endif.

Una volta ho letto che quando si desidera ottimizzare il codice, è necessario utilizzare il minor numero possibile di comandi Ex. Così forse il 2 ° sintassi (che potrebbe essere contato come 3 comandi Ex: :if, :let,:endif ) è più lenta della prima, io non lo so.

Ma se questo è il caso, potresti sostituire autocmd con:

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

1
Questa è una soluzione elegante! Secondo i miei primi test funziona bene. Dovrò usarlo per qualche tempo per essere sicuro che sia robusto. Mi piace come hai modificato v:charl'idea che mi mancava al mio primo tentativo.
statox

1

Un altro modo per farlo (non così automatico e non così universale; solo più breve):

  • poiché stai scrivendo frasi / prosa, non codice, chiedi a Vim di attivare il controllo ortografico nei tuoi buffer di testo
  • creare un tasto combo in modalità inserimento rapido che risale agli ultimi errori di ortografia, lo corregge, quindi riprende posizione / stato; per esempio:

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

Quindi ora supponiamo che inizi a scrivere

"THis is a mistake|"

... e ti rendi conto dell'errore - cosa fare? - basta premere <C-s>e continuare a scrivere la frase.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.