Consertando CApitals DOuble enquanto digito

23

Eu tenho um pouco de mindinho lento. Enquanto meus outros dedos ficam cada vez mais rápidos na digitação, meu mindinho simplesmente não consegue acompanhar. Isso frequentemente me leva a digitar frases cuja primeira palavra começa com duas letras maiúsculas. Aqui está um pequeno exemplo.

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

Normalmente, o que faço é acertado M-b M-c(supondo que eu o localize imediatamente), mas estou ficando um pouco cansado disso.

Como o Emacs pode corrigir isso automaticamente para mim?

Ou seja, eu gostaria que o Emacs detectasse quando eu digitasse uma palavra que comece com duas letras maiúsculas seguida por pelo menos uma letra minúscula e corrija isso automaticamente.

Malabarba
fonte

Respostas:

19

Aqui está uma função que converterá DOuble CApitals em Single Capitals. Eu sugeri originalmente adicioná-lo a post-self-insert-hook, mas abaixo está uma opção para um modo menor glorificado, para que você só adicione esse gancho quando realmente quiser:

(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 a definição de modo secundário:

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

Para o que vale a pena, usando esta versão:

  • é simples: basta ligar / desligar manualmente ou em um gancho de modo;
  • não requer alterações nas ligações de teclas, para que você não perca nenhuma outra funcionalidade.

Mesmo quando você o adiciona post-self-insert-hook, a sobrecarga é quase inexistente, pelo menos de acordo com alguns testes comparativos simples. Na minha máquina, eis o que recebo com 10.000 repetições, cada uma de uma forma ridiculamente simples e da dcaps-to-scapsfunção:

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

Então, sim, é mais lento que adicionar 1 + 1, mas em termos absolutos, você nunca notará.

Dan
fonte
Você pode usar looking-at-p, que não define os dados da correspondência (tudo bem, pois você não precisa nem os usa aqui).
YoungFrog
Mais algumas observações, a maioria sem importância (mas eu prefiro a sua resposta assim que eu quero contribuir; p): o uso de forward-wordnão funcionar bem com subword-mode, usando (char-syntax (char-before))irá (eu acho) ignorar qualquer conjunto classe sintaxe com propriedades (solução alternativa: (syntax-after (1- (point))) , e (por último, mas não menos importante), a regexp não encontrará letras acentuadas (por exemplo, "ÉMincer", em francês)
YoungFrog 14/15/15
@YoungFrog: atualizado para lidar com o forward-wordproblema e alterou o regexp para lidar com maiúsculas acentuadas.
Dan
Existe uma razão para preferir andmais when, em particular, em primeira instância?
Clément
@ Clément: andestá em curto-circuito, então a lógica funciona como whenaqui. Não tenho certeza se existem práticas recomendadas sobre o uso de um contra o outro, mas parece que isso faria uma boa pergunta neste site (eu teria votado de qualquer maneira).
Dan
8

Minha preferência é simplesmente criar uma nova função que faça o que o habitual self-insert-commandfaria e mais .

Aqui estão algumas razões:

  • Controle mais preciso sobre quais modos principais devem ter esse recurso de correção automática. Para este caso de uso, pode ser modos somente de texto como org-mode, text-mode, etc.
  • Para o tipo de correção solicitada na pergunta, o usuário normalmente pressionava SPCou RETou pressionava a .tecla após a palavra. Portanto, usar algo como isso post-self-insert-hookpode ser um exagero e faríamos esse processamento extra sempre que pressionássemos qualquer tecla.

Portanto, a solução proposta abaixo vincula essa função apenas com a SPCtecla org-mode-map(ignorando a caixa de canto onde a palavra pode ser a última palavra em uma linha). Se necessário, o usuário pode vincular funções de wrapper semelhantes a mais chaves.

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

Este é um exercício interessante do elisp :)

Pessoalmente, não gostaria de vincular isso RET, pois perderia as vinculações padrão org-modee provavelmente outros modos principais também. Mas foi interessante aprender sobre 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))))
Kaushal Modi
fonte
Ah, sim, restringi-lo aos modos derivados de texto é definitivamente uma boa ideia. :)
Malabarba
@ Malabarba, você não quer esse comportamento em strings para modos derivados do modo prog?
YoungFrog
@YoungFrog, com certeza, mas seria preciso verificar se realmente está dentro de uma string, caso contrário, apenas atrapalharia.
Malabarba
0

Talvez essa resposta não forneça a solução que você espera (correção interativa de palavras enquanto digita), gostaria de compartilhar minhas maneiras de combater esses problemas.

Antes de tudo, não gosto de coisas que mudam silenciosamente meu texto (em maiúsculas etc.), e se você quiser digitar a palavra IBuffer, acho que esse "corretor" é um caminho errado), então aconselho duas coisas:

Primeiro, tente ativar o recurso "Teclas aderentes". Pode parecer estranho no começo, mas eu uso o tempo todo. Esse recurso está disponível no nível do ambiente OS / desktop, não é uma coisa do Emacs. Quando essa opção está ativada, você pressiona primeiro ⇧ Shifte depois pressiona outra tecla que deseja capitalizar. Dessa forma, seu problema nem pode surgir, apenas uma letra é maiúscula nessa abordagem seqüencial! Também reduz o trabalho que suas mãos precisam segurando a ⇧ Shifttecla. Eu acho que é mais fácil digitar agora.

Segundo, agora você ainda pode usar a ⇧ Shiftchave normalmente (mantendo-a) quando achar necessário, mas eu gostaria de propor um pacote do Emacs chamado Fix Word . Mesmo que você não goste de "Teclas de aderência", poderá corrigir as palavras em suas formas apropriadas facilmente e corrigir várias palavras seguidas sem movimentos inúteis do cursor. Experimente, eu uso o tempo todo. (Ainda é difícil corrigir as coisas se você digitou várias palavras e a palavra que você precisa colocar em maiúscula está em algum lugar no meio.)

Mark Karpov
fonte