Исправление двойных столиц при вводе

23

У меня немного медленного мизинца. Поскольку мои другие пальцы становятся все быстрее и быстрее при наборе текста, мой мизинец просто не успевает. Это часто приводит меня к вводу предложений, первое слово которых начинается с двух заглавных букв. Вот короткий пример.

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

Обычно то , что я делаю , это удар M-b M-c(предполагая , что я обнаружить его сразу), но я получаю немного устал от этого.

Как я могу заставить Emacs исправить это автоматически?

То есть я бы хотел, чтобы Emacs обнаруживал, когда я набираю слово, начинающееся с двух заглавных букв, за которыми следует хотя бы одна строчная буква, и исправлял это автоматически.

Malabarba
источник

Ответы:

19

Вот функция, которая преобразует DOuble CApitals в Single Capitals. Изначально я предлагал добавить его в post-self-insert-hook, но ниже представлен вариант для прославленного второстепенного режима, так что вы добавляете этот крючок только тогда, когда вы действительно этого хотите:

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

И определение второстепенного режима:

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

Для чего это стоит, используя эту версию:

  • это просто: просто включите / выключите его вручную или в режиме ловушки;
  • не требует никаких изменений в привязках клавиш, поэтому вы не теряете никакой другой функциональности.

Даже когда вы добавляете его post-self-insert-hook, накладные расходы почти не существуют, по крайней мере, согласно некоторому простому сравнительному тестированию. На моей машине вот что я получаю с 10 000 повторений, каждая из которых имеет смехотворно простую форму и dcaps-to-scapsфункцию:

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

Так что, да, это медленнее, чем сложение 1 + 1, но в абсолютном выражении вы никогда не заметите.

Дэн
источник
Вы можете использовать looking-at-p, который вообще не устанавливает данные о совпадении (это нормально, так как вам это не нужно или не используйте это здесь).
YoungFrog
Еще несколько замечаний, в основном , неважно (но я предпочитаю свой ответ , так что я хочу внести свой вклад, р): использование forward-wordне будет хорошо работать с subword-modeиспользования (char-syntax (char-before))будет (я думаю) игнорировать любой класс синтаксиса набор со свойствами (альтернативным решением: (syntax-after (1- (point))) и (что не менее важно) регулярное выражение не найдет буквы с акцентом (например, «ÉMincer», по-французски)
YoungFrog
@YoungFrog: обновлен, чтобы справиться с forward-wordпроблемой, и изменил регулярное выражение для работы с ударными столицами.
Дан
Есть ли причина предпочесть andболее when, в частности , в первую очередь?
Климент
@ Clément: andкороткое замыкание, поэтому логика работает как whenздесь. Я не уверен, есть ли лучшие практики использования одного против другого, но кажется, что это сделало бы хороший вопрос на этом сайте (я все равно поддержал бы).
Дан
8

Я предпочитаю просто создать новую функцию, которая делает то, что обычно self-insert-commandделает, плюс больше .

Вот несколько причин:

  • Более точный контроль, в каких основных режимах должна быть возможность автокоррекции. В этом случае это могут быть только текстовые режимы, например org-mode, text-modeи т. Д.
  • Для типа исправления, запрошенного в вопросе, пользователь обычно нажимает клавишу SPCили RETили .после слова. Поэтому использование чего-то подобного post-self-insert-hookможет быть излишним, и мы выполняем эту дополнительную обработку каждый раз, когда нажимаем любую клавишу.

Таким образом, предложенное ниже решение связывает эту функцию только с SPCключом org-mode-map(игнорируя угловой случай, когда слово может быть последним словом в строке). При необходимости пользователь может связать похожие функции-оболочки с несколькими клавишами.

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

Это интересное упражнение elisp :)

Я лично не хотел бы связывать это с тем, RETкак тогда я потеряю привязки по умолчанию в org-modeи, возможно, другие основные режимы тоже. Но это было интересно узнать о eltи 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))))
Каушал Моди
источник
Ах, да, ограничить его текстовыми режимами - определенно хорошая идея. :)
Малабарба
@ Malabarba вы не хотите, чтобы это поведение в строках для режимов, полученных из prog-mode?
YoungFrog
Конечно, @YoungFrog, но тогда он должен проверить, что он на самом деле внутри строки, иначе он просто мешает.
Малабарба
0

Возможно, этот ответ не дает ожидаемого решения (интерактивное исправление слов при вводе), я хотел бы поделиться своими способами борьбы с такими проблемами.

Прежде всего, мне не нравятся вещи, которые молча меняют мой текст (пишите с заглавной буквы и т. Д., Что, если вы хотите ввести слово IBuffer, я думаю, что такой «корректор» является неправильным), поэтому я советую две вещи:

Сначала попробуйте включить функцию «Sticky Keys». Поначалу это может показаться странным, но я пользуюсь им постоянно. Эта функция доступна на уровне среды ОС / рабочего стола, это не Emacs. Когда эта функция включена, вы сначала нажимаете, ⇧ Shiftа затем нажимаете другую клавишу, которую хотите использовать с заглавной буквы. Таким образом, ваша проблема даже не может возникнуть, в этом последовательном подходе заглавная буква только одна! Это также уменьшает работу, которую ваши руки должны выполнять, удерживая ⇧ Shiftключ. Я думаю, что теперь легче печатать.

Во-вторых, теперь вы все еще можете использовать ⇧ Shiftключ как обычно (удерживая его), когда считаете, что это необходимо, но я бы хотел предложить вам пакет Emacs под названием Fix Word . Даже если вам не нравятся «Липкие ключи», вы можете легко исправить слова в правильные формы и исправить несколько слов подряд без лишних движений курсора. Попробуйте, я использую все время. (По-прежнему сложно что-то исправить, если вы ввели несколько слов, а слово, которое нужно использовать с заглавной буквы, находится где-то посередине.)

Марк Карпов
источник