Fixing DOuble CApitals während ich tippe

23

Ich habe ein bisschen einen langsamen kleinen Finger. Da meine anderen Finger beim Tippen immer schneller werden, kann mein kleiner Finger einfach nicht mithalten. Dies führt mich häufig dazu, Sätze einzugeben, deren erstes Wort mit zwei Großbuchstaben beginnt. Hier ist ein kurzes Beispiel.

THere's nothing in there. DEfinitely not a body.

Normalerweise ist das, was ich tue, ein Treffer M-b M-c(vorausgesetzt, ich sehe es sofort), aber ich bin es ein bisschen leid.

Wie kann ich Emacs veranlassen, dies automatisch für mich zu beheben?

Das heißt, ich möchte, dass Emacs erkennt, wenn ich ein Wort eingebe, das mit zwei Großbuchstaben gefolgt von mindestens einem Kleinbuchstaben beginnt, und das automatisch korrigiert.

Malabarba
quelle

Antworten:

19

Hier ist eine Funktion, die doppelte Großbuchstaben in einfache Großbuchstaben konvertiert. Ich hatte ursprünglich vorgeschlagen, es hinzuzufügen post-self-insert-hook, aber unten ist eine Option für einen verherrlichten Nebenmodus, so dass Sie diesen Haken nur dann hinzufügen, wenn Sie es wirklich wollen:

(defun dcaps-to-scaps ()
  "Convert word in DOuble CApitals to Single Capitals."
  (interactive)
  (and (= ?w (char-syntax (char-before)))
       (save-excursion
         (and (if (called-interactively-p)
                  (skip-syntax-backward "w")
                (= -3 (skip-syntax-backward "w")))
              (let (case-fold-search)
                (looking-at "\\b[[:upper:]]\\{2\\}[[:lower:]]"))
              (capitalize-word 1)))))

(add-hook 'post-self-insert-hook #'dcaps-to-scaps nil 'local)

Und die Definition des Nebenmodus:

(define-minor-mode dubcaps-mode
  "Toggle `dubcaps-mode'.  Converts words in DOuble CApitals to
Single Capitals as you type."
  :init-value nil
  :lighter (" DC")
  (if dubcaps-mode
      (add-hook 'post-self-insert-hook #'dcaps-to-scaps nil 'local)
    (remove-hook 'post-self-insert-hook #'dcaps-to-scaps 'local)))

Für was es sich lohnt, mit dieser Version:

  • Es ist ganz einfach: Schalten Sie es einfach manuell oder in einem Modus-Hook ein / aus.
  • erfordert keine Änderungen an den Tastenkombinationen, sodass Sie keine andere Funktionalität verlieren.

Selbst wenn Sie es hinzufügen, post-self-insert-hookist der Overhead fast nicht vorhanden, zumindest nach einem einfachen Benchmarking. Auf meiner Maschine erhalte ich mit 10.000 Wiederholungen jeweils eine lächerlich einfache Form und die dcaps-to-scapsFunktion:

(benchmark-run-compiled 10000 (+ 1 1))          ; => .001 to .003 -ish
(benchmark-run-compiled 10000 (dcaps-to-scaps)) ; => .003 to .006 -ish

Also, ja, es ist langsamer als das Hinzufügen von 1 + 1, aber in absoluten Zahlen werden Sie es nie bemerken.

Dan
quelle
Du looking-at-pkönntest verwenden , was die Match-Daten überhaupt nicht setzt (das ist in Ordnung, da du sie hier nicht brauchst oder verwendest).
YoungFrog
Noch ein paar Bemerkungen, meist unwichtig (aber ich ziehe deine Antwort so dass ich dazu beitragen will; p): die Verwendung von forward-wordmit nicht gut funktionieren subword-mode, indem (char-syntax (char-before))mit Eigenschaften jeden Syntax Klassensatz ignorieren (I guess) (alternative Lösung: (syntax-after (1- (point))) , und (last but not least) der reguläre Ausdruck findet keine akzentuierten Buchstaben (z. B. "ÉMincer", in Französisch)
YoungFrog
@YoungFrog: wurde aktualisiert, um das forward-wordProblem zu beheben, und der reguläre Ausdruck wurde geändert, um Großbuchstaben mit Akzenten zu behandeln.
Dan
Gibt es einen Grund zu bevorzugen andüber when, insbesondere in erster Linie?
Clément
@ Clément: andist kurzgeschlossen, also funktioniert die Logik wie whenhier. Ich bin mir nicht sicher, ob es Best Practices für die Verwendung von eins gegen das andere gibt, aber es scheint, als würde dies eine gute Frage auf dieser Website darstellen (ich würde es trotzdem positiv bewerten).
Dan
8

Ich bevorzuge es, einfach eine neue Funktion zu erstellen, die das tut, was das Übliche self-insert-commandtun würde, und noch mehr .

Hier sind einige Gründe:

  • Feinere Kontrolle darüber, welche Hauptmodi diese Fähigkeit zur automatischen Korrektur haben sollen. Für diesen Anwendungsfall könnte es Nur - Text-Modi wie sein org-mode, text-modeusw.
  • Für die Art der in der Frage angeforderten Korrektur würde der Benutzer normalerweise SPCoder REToder .nach dem Wort drücken. So etwas zu verwenden, post-self-insert-hookkönnte ein Overkill sein, und wir würden diese zusätzliche Verarbeitung jedes Mal durchführen, wenn wir eine Taste drücken.

Die unten vorgeschlagene Lösung bindet diese Funktion also nur mit der SPCTasteneingabe org-mode-map(wobei der Eckfall ignoriert wird, bei dem das Wort das letzte Wort in einer Zeile sein könnte). Bei Bedarf kann der Benutzer ähnliche Wrapper-Funktionen an mehrere Schlüssel binden.

(defun space-plus-more ()
  (interactive)
  (save-excursion
    (backward-word 1)
    (let ((case-fold-search))
      (when (looking-at-p "[A-Z]\\{2\\}.*?[a-z]+.*?\\b")
        (capitalize-word 1))))
  (self-insert-command 1))

(define-key org-mode-map (kbd "<SPC>") #'space-plus-more)

Dies ist eine interessante Elisp-Übung :)

Ich persönlich würde dies nicht binden wollen, RETda ich dann die Standardbindungen in org-modeund wahrscheinlich auch andere Hauptmodi verlieren würde . Aber es war interessant, über eltund zu lernen this-command-keys-vector.

(defun my/fix-double-caps ()
  (interactive)
  (save-excursion
    (backward-word 1)
    (let ((case-fold-search))
      (when (looking-at-p "[A-Z]\\{2\\}.*?[a-z]+.*?\\b")
        (capitalize-word 1))))
  (if (eq 13 (elt (this-command-keys-vector) 0)) ; detect RET
      (newline)
    (self-insert-command 1)))

(let ((maps-list (list org-mode-map
                       text-mode-map))
      (keys-list (list "<SPC>" "<RET>" ".")))
  (dolist (map maps-list)
    (dolist (key keys-list)
      (define-key map (kbd key) #'my/fix-double-caps))))
Kaushal Modi
quelle
Oh ja, es ist definitiv eine gute Idee, es auf von Text abgeleitete Modi zu beschränken. :)
Malabarba
@Malabarba Willst du dieses Verhalten nicht in Strings für Modi, die vom Prog-Modus abgeleitet sind?
YoungFrog
@YoungFrog sicher, aber dann müsste es überprüfen, ob es tatsächlich in einem String ist, sonst würde es nur in die Quere kommen.
Malabarba,
0

Vielleicht bietet diese Antwort keine Lösung, die Sie erwarten (interaktive Korrektur von Wörtern während der Eingabe). Ich möchte meine Möglichkeiten zur Bekämpfung solcher Probleme erläutern.

Erstens mag ich keine Dinge, die meinen Text stillschweigend ändern (Großschreibung usw., was, wenn Sie das Wort eingeben möchten IBuffer, ich denke, ein solcher "Korrektor" ist ein falscher Weg), also rate ich zwei Dinge:

Versuchen Sie zunächst, die Funktion "Sticky Keys" zu aktivieren. Es mag zunächst seltsam erscheinen, aber ich benutze es die ganze Zeit. Diese Funktion ist auf Betriebssystem- / Desktop-Umgebungsebene verfügbar. Es handelt sich nicht um Emacs-Inhalte. Wenn dieses Element aktiviert ist, drücken Sie zuerst ⇧ Shiftund dann eine andere Taste, die Sie großschreiben möchten. Auf diese Weise kann Ihr Problem nicht einmal entstehen, nur ein Buchstabe wird in diesem sequentiellen Ansatz großgeschrieben! Es reduziert auch die Arbeit, die Ihre Hände für das Halten des ⇧ ShiftSchlüssels benötigen . Ich denke, es ist jetzt einfacher zu tippen.

Zweitens können Sie die ⇧ ShiftTaste jetzt noch normal verwenden (halten), wenn Sie dies für erforderlich halten, aber ich möchte Ihnen ein Emacs-Paket mit dem Namen Fix Word vorschlagen . Auch wenn Sie "Sticky Keys" nicht mögen, können Sie Wörter einfach in die richtige Form bringen und mehrere Wörter hintereinander korrigieren, ohne den Cursor unnötig bewegen zu müssen. Probieren Sie es aus, ich benutze es die ganze Zeit. (Es ist immer noch schwierig, Dinge zu korrigieren, wenn Sie mehrere Wörter eingegeben haben und das Wort, das Sie großschreiben müssen, irgendwo in der Mitte liegt.)

Mark Karpov
quelle