Riparando DOpit CApitals mentre scrivo


23

Ho un po 'di mignolo lento. Mentre le altre dita diventano sempre più veloci durante la digitazione, il mio mignolo non riesce a tenere il passo. Questo spesso mi porta a digitare frasi la cui prima parola inizia con due lettere maiuscole. Ecco un breve esempio.

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

Di solito quello che faccio è colpito M-b M-c(supponendo che lo rilevo immediatamente), ma mi sto stancando un po '.

Come posso fare in modo che Emacs risolva automaticamente questo problema per me?

Cioè, vorrei che Emacs rilevasse quando digito una parola che inizia con due lettere maiuscole seguite da almeno una lettera minuscola e la aggiusto automaticamente.

Risposte:


19

Ecco una funzione che convertirà DOuble CApitals in Single Capitals. Inizialmente avevo suggerito di aggiungerlo a post-self-insert-hook, ma di seguito è un'opzione per una modalità minore glorificata in modo da aggiungere a quel gancio solo quando lo vuoi davvero:

(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)

E la definizione della modalità minore:

(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)))

Per quello che vale, usando questa versione:

  • è semplice: basta accenderlo / spegnerlo manualmente o in modalità hook;
  • non richiede modifiche ai collegamenti chiave, quindi non stai perdendo altre funzionalità.

Anche quando lo aggiungi post-self-insert-hook, l'overhead è quasi inesistente, almeno secondo alcuni semplici benchmark. Sulla mia macchina, ecco cosa ottengo con 10.000 ripetizioni ciascuna di una forma ridicolmente semplice e la dcaps-to-scapsfunzione:

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

Quindi, sì, è più lento dell'aggiunta di 1 + 1, ma in termini assoluti non lo noterai mai.


Potresti usare looking-at-p, che non imposta affatto i dati della partita (va bene perché non ti serve o non li usi qui).
YoungFrog,

Ancora qualche osservazioni, in gran parte poco importante (ma io preferisco la tua risposta così voglio contribuire; p): l'uso di forward-wordnon funzionano bene con subword-mode, utilizzando (char-syntax (char-before))sarà (credo) di ignorare qualsiasi insieme di classe sintassi con proprietà (soluzione alternativa: (syntax-after (1- (point))) e (ultimo ma non meno importante) il regexp non troverà lettere accentate (ad esempio "ÉMincer", in francese)
YoungFrog

@YoungFrog: aggiornato per risolvere il forward-wordproblema e modificato la regexp per gestire i capitali accentati.
Dan

C'è un motivo per preferire andrispetto when, in particolare in primo luogo?
Clément,

@ Clément: andè in corto circuito, quindi la logica funziona come whenqui. Non sono sicuro che ci siano le migliori pratiche sull'uso dell'una rispetto all'altra, ma sembra che farebbe una buona domanda su questo sito (vorrei comunque votare).
Dan

8

La mia preferenza è semplicemente creare una nuova funzione che faccia quello che self-insert-commandfarebbe il solito e molto altro .

Ecco alcuni motivi:

  • Controllo più preciso su quali modalità principali dovrebbero avere questa capacità di correzione automatica. Per questo caso d'uso, potrebbe essere le modalità di solo testo come org-mode, text-mode, etc.
  • Per il tipo di correzione richiesta nella domanda, l'utente in genere preme SPCo RETo digita .dopo la parola. Quindi usare qualcosa del genere post-self-insert-hookpotrebbe essere eccessivo e faremmo quell'elaborazione extra ogni volta che premiamo un tasto.

Quindi la soluzione proposta di seguito lega questa funzione semplicemente SPCinserendo il tasto org-mode-map(ignorando il caso d'angolo in cui la parola potrebbe essere l'ultima parola di una riga). Se necessario, l'utente può associare funzioni wrapper simili a più tasti.

(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)

Questo è un esercizio elisp interessante :)

Personalmente non vorrei associare questo a RETcome allora perderei i collegamenti predefiniti org-modee probabilmente anche altre modalità principali. Ma è stato interessante conoscere elte 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))))

Oh sì, limitarlo alle modalità derivate dal testo è sicuramente una buona idea. :)
Malabarba,

@Malabarba non vuoi questo comportamento nelle stringhe per le modalità derivate dalla modalità prog?
YoungFrog,

@YoungFrog certo, ma poi dovrebbe verificare che sia effettivamente all'interno di una stringa, altrimenti si metterebbe di mezzo.
Malabarba,

0

Forse questa risposta non fornisce la soluzione che ti aspetti (correzione interattiva delle parole durante la digitazione), vorrei condividere i miei modi per combattere tali problemi.

Prima di tutto, non mi piacciono le cose che cambiano silenziosamente il mio testo (lettere maiuscole, ecc. E se volessi digitare la parola IBuffer, penso che tale "correttore" sia un modo sbagliato), quindi consiglio due cose:

Innanzitutto, prova ad abilitare la funzione "Tasti permanenti". All'inizio può sembrare strano, ma lo uso sempre. Questa funzione è disponibile a livello di sistema operativo / desktop, non è roba di Emacs. Quando questa cosa è abilitata, premi prima ⇧ Shifte poi premi un altro tasto che vuoi mettere in maiuscolo. In questo modo il tuo problema non può nemmeno sorgere, solo una lettera è maiuscola in questo approccio sequenziale! Riduce anche il lavoro che le mani devono fare tenendo la ⇧ Shiftchiave. Penso che sia più facile digitare ora.

Secondo, ora puoi ancora usare la ⇧ Shiftchiave normalmente (tenendola) quando pensi che sia necessario, ma vorrei proporti un pacchetto Emacs chiamato Fix Word . Anche se non ti piacciono le "Sticky Keys", puoi correggere facilmente le parole nelle loro forme appropriate e puoi correggere diverse parole di fila senza inutili movimenti del cursore. Provalo, lo uso sempre. (È ancora difficile correggere le cose se hai inserito più parole e la parola che devi mettere in maiuscolo è da qualche parte nel mezzo.)

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.