Wie wird der zweite Buchstabe eines Wortes automatisch in Kleinbuchstaben geschrieben?

13

Wenn ich viel Text tippen muss, neige ich oft dazu, meinen Finger gedrückt zu halten, shiftwenn ich den ersten Buchstaben eines Satzes schreibe, der oft folgendes ergibt:

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

Hier wird die Evon noch NEwtiefer Fall sein. Ich versuche dann, eine Funktion zu erstellen, die erkennt, ob der zweite Buchstabe des ersten Wortes des Satzes, den ich tippe, Großbuchstaben und der zweite Buchstabe Kleinbuchstaben enthält. Der wichtige Teil wäre, dass die Korrektur automatisch durchgeführt wird, während ich das Ende meines Satzes schreibe.

Bisher habe ich versucht, mit dem Autocommand-Ereignis zu spielen, InsertCharPrebevor mir klar wurde, dass der Text nicht durch eine von diesem Ereignis ausgelöste Funktion geändert werden kann.

Was wäre eine gute Lösung?

Beachten Sie, dass ich mich bisher nicht auf Kantenfälle wie Akronyme konzentrieren muss, die in Großbuchstaben geschrieben werden sollten, oder auf solche Dinge.

BEARBEITEN Ich habe dies gemacht, was eine nicht perfekte Problemumgehung ist:

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

Es hat ein Problem, da das erste Zeichen, das ich im Einfügemodus eingebe, an das Ende der Zeile verschoben wird, aber ich denke, das kann korrigiert werden.

Ich denke jetzt wird meine Frage eine Codeüberprüfungsfrage :

  • Wie kann ich den Nebeneffekt beseitigen, der das erste eingefügte Zeichen bewegt?
  • Ist es die bestmögliche Methode?
  • Diese Methode scheint Vim zu verlangsamen: Wie könnte sie verbessert werden?
statox
quelle

Antworten:

6

Hier ist ein bisschen was ganz schnell gekocht. Ich denke, es ist weniger robust, aber es ist auch viel leichter. Vielleicht könntest du es in deine integrieren, um es schneller zu machen? Ich werde das wahrscheinlich ein wenig überarbeiten, wenn ich Zeit habe.

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

Ich denke, keine vollständige Lösung, aber ich dachte, ich würde einen anderen Ansatz ausprobieren und sehen, ob er etwas für Sie auslöste. :)

Tumbler41
quelle
4
Die Idee der Neuzuordnung <Space>scheint ziemlich interessant zu sein, da sie die Anzahl der Aufrufe der Funktionen verringert. Ich werde auch versuchen, auf diese Weise zu arbeiten!
statox
4

Ich weiß nicht, wie zuverlässig es ist, aber Sie könnten dies versuchen:

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

Es installiert eine autocmd, die den folgenden Befehl ausführt, bevor Sie ein Zeichen einfügen:

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

Das Zeichen, das Sie einfügen möchten, wird in der internen Variablen gespeichert v:char, und wenn der Test:

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

... gelingt, dann weist die autocmd einen neuen Wert zu v:char, nämlich tolower(v:char).

Der Test prüft, ob Sie im Begriff waren, einen Großbuchstaben ( v:char =~ '\u') einzufügen, und Ihr Cursor steht nach dem ersten Zeichen des ersten Wortes eines Satzes:

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

Bearbeiten: Ich weiß nicht, ob es einen Unterschied (in Bezug auf die Leistung) zwischen diesen beiden Syntaxen gibt: :let myvar = test ? new_value : old_valueund :if test | let myvar = new_value | endif.

Ich habe einmal gelesen, dass Sie zur Optimierung Ihres Codes so wenig Ex-Befehle wie möglich verwenden müssen. Also vielleicht die zweite Syntax (die als 3 Ex - Befehle gezählt werden konnte: :if, :let, :endif) ist langsamer als die erste ein, ich weiß es nicht.

Wenn dies jedoch der Fall ist, können Sie die autocmd ersetzen durch:

autocmd InsertCharPre * let v:char = (v:char =~ '\u' && getline('.') =~ '\v(\.\s+|^\s*)\u%' . col('.') . 'c') ? tolower(v:char) : v:char
user9433424
quelle
1
Das ist eine elegante Lösung! Nach meinen ersten Tests funktioniert es gut. Ich muss es für einige Zeit benutzen, um sicherzugehen, dass es robust ist. Es gefällt mir, wie Sie v:chardie Idee geändert haben , die mir bei meinem ersten Versuch gefehlt hat.
statox
1

Ein anderer Weg, es zu tun (nicht so automatisch und nicht so universell; nur kürzer):

  • Da Sie Sätze / Prosa und keinen Code schreiben, lassen Sie Vim die Rechtschreibprüfung in Ihren Textpuffern aktivieren
  • Erstellen Sie eine Kombinationstaste für den schnellen Einfügemodus, die auf die letzten Rechtschreibfehler zurückgreift, diese korrigiert und dann die Position / den Status wieder aufnimmt. z.B:

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

Sagen wir also, Sie fangen an zu schreiben

"THis is a mistake|"

... und Sie erkennen nur den Fehler - was zu tun ist? - Schlagen Sie einfach <C-s>und schreiben Sie Ihren Satz weiter.

VanLaser
quelle