Memperbaiki DOuble CApital saat saya mengetik

23

Saya memiliki sedikit pinky yang lambat. Saat jari-jari saya yang lain semakin cepat dan semakin cepat dalam mengetik, jari kelingking saya tidak bisa mengikuti. Ini sering membuat saya mengetik kalimat yang kata pertamanya dimulai dengan dua huruf besar. Ini contoh singkatnya.

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

Biasanya yang saya lakukan adalah memukul M-b M-c(dengan asumsi saya segera menemukannya), tetapi saya mulai bosan.

Bagaimana saya bisa membuat Emacs memperbaikinya secara otomatis untuk saya?

Yaitu, saya ingin Emacs mendeteksi ketika saya mengetik kata yang dimulai dengan dua huruf besar diikuti oleh setidaknya satu huruf kecil, dan memperbaikinya secara otomatis.

Malabarba
sumber

Jawaban:

19

Inilah fungsi yang akan mengonversi DOuble CApital ke Single Capitals. Saya awalnya menyarankan untuk menambahkannya post-self-insert-hook, tetapi di bawah ini adalah opsi untuk mode minor yang dimuliakan sehingga Anda hanya menambah kait itu ketika Anda benar-benar menginginkannya:

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

Dan definisi mode minor:

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

Untuk apa nilainya, menggunakan versi ini:

  • sederhana: cukup hidupkan / matikan secara manual atau dalam mode hook;
  • tidak memerlukan perubahan pada binding utama, sehingga Anda tidak kehilangan fungsionalitas lainnya.

Bahkan ketika Anda menambahkannya post-self-insert-hook, overhead hampir tidak ada, setidaknya menurut beberapa pembandingan sederhana. Di komputer saya, inilah yang saya dapatkan dengan 10.000 pengulangan masing-masing dari bentuk dan dcaps-to-scapsfungsi yang sangat sederhana :

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

Jadi, ya, ini lebih lambat daripada menambahkan 1 +1, tetapi secara absolut Anda tidak akan pernah melihat.

Dan
sumber
Anda dapat menggunakan looking-at-p, yang tidak mengatur data pertandingan sama sekali (tidak apa-apa karena Anda tidak perlu atau menggunakannya di sini).
YoungFrog
Beberapa komentar lagi, sebagian besar tidak penting (tapi aku lebih suka jawaban Anda jadi saya ingin berkontribusi; p): penggunaan forward-wordtidak akan bekerja dengan baik dengan subword-modemenggunakan (char-syntax (char-before))akan (saya kira) mengabaikan setiap set kelas sintaks dengan sifat (solusi alternatif: (syntax-after (1- (point))) , dan (last but not least) regexp tidak akan menemukan huruf beraksen (misalnya "ÉMincer", dalam bahasa Prancis)
YoungFrog
@YoungFrog: diperbarui untuk menangani forward-wordmasalah ini, dan mengubah regexp untuk berurusan dengan modal beraksen.
Dan
Apakah ada alasan untuk memilih andlebih when, khususnya pada contoh pertama?
Clément
@ Clément: anddihubung pendek, jadi logikanya bekerja seperti di whensini. Saya tidak yakin apakah ada praktik terbaik tentang menggunakan satu versus yang lain, tetapi sepertinya itu akan menjadi pertanyaan yang bagus di situs ini (toh saya akan merasa senang).
Dan
8

Preferensi saya adalah dengan hanya membuat fungsi baru yang melakukan apa yang biasa self-insert-commanddilakukan ditambah lagi .

Berikut ini beberapa alasan:

  • Kontrol yang lebih baik pada mode utama mana yang harus memiliki kemampuan koreksi otomatis ini. Untuk kasus penggunaan ini, bisa jadi mode teks saja seperti org-mode, text-mode, dll
  • Untuk jenis koreksi yang diminta dalam pertanyaan, pengguna biasanya akan menekan SPCatau RETatau .kunci setelah kata. Jadi menggunakan sesuatu seperti post-self-insert-hookmungkin merupakan kerja keras, dan kami akan melakukan pemrosesan ekstra setiap kali kami menekan tombol apa pun.

Jadi solusi yang diusulkan di bawah ini mengikat fungsi ini hanya dengan SPCkunci org-mode-map(mengabaikan kasus sudut di mana kata itu bisa menjadi kata terakhir dalam satu baris). Jika perlu, pengguna dapat mengikat fungsi pembungkus yang serupa ke lebih banyak tombol.

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

Ini adalah latihan yang sangat menarik :)

Saya pribadi tidak ingin mengikat ini RETkarena saya akan kehilangan ikatan default di org-modedan mungkin mode utama lainnya juga. Tapi itu menarik untuk dipelajari eltdan 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
sumber
Oh ya, membatasi ke mode turunan teks jelas merupakan ide yang bagus. :)
Malabarba
@ Malabarba tidak Anda inginkan perilaku ini dalam string untuk mode yang berasal dari prog-mode?
YoungFrog
@YoungFrog yakin, tapi kemudian harus memeriksa bahwa itu benar-benar di dalam sebuah string, kalau tidak itu hanya akan menghalangi.
Malabarba
0

Mungkin jawaban ini tidak memberikan solusi yang Anda harapkan (koreksi kata-kata interaktif saat Anda mengetik), saya ingin membagikan cara saya untuk mengatasi masalah tersebut.

Pertama-tama, saya tidak suka hal-hal yang secara diam-diam mengubah teks saya (huruf besar, dll., Bagaimana jika Anda ingin mengetik kata IBuffer, saya pikir "korektor" seperti itu adalah cara yang salah), jadi saya menyarankan dua hal:

Pertama, coba aktifkan fitur "Sticky Keys". Awalnya mungkin terasa aneh, tetapi saya menggunakannya sepanjang waktu. Fitur ini tersedia di level lingkungan OS / desktop, ini bukan Emacs. Ketika hal ini diaktifkan, Anda pertama kali menekan ⇧ Shiftdan kemudian Anda menekan tombol lain yang ingin Anda gunakan huruf besar. Dengan cara ini masalah Anda bahkan tidak dapat muncul, hanya satu huruf yang menggunakan huruf kapital dalam pendekatan sekuensial ini! Ini juga mengurangi pekerjaan yang perlu dilakukan tangan Anda dengan memegang ⇧ Shiftkunci. Saya pikir lebih mudah mengetik sekarang.

Kedua, sekarang Anda masih dapat menggunakan ⇧ Shiftkunci secara normal (memegangnya) ketika menurut Anda itu perlu, tetapi saya ingin mengusulkan Anda sebuah paket Emacs yang disebut Fix Word . Bahkan jika Anda tidak menyukai "Sticky Keys", Anda dapat dengan mudah mengoreksi kata-kata menjadi bentuk yang tepat, dan Anda dapat memperbaiki beberapa kata secara berturut-turut tanpa pergerakan kursor yang tidak berguna. Cobalah, saya menggunakannya setiap saat. (Masih sulit untuk memperbaiki hal-hal jika Anda memasukkan beberapa kata dan kata yang perlu Anda kapitalisasi adalah suatu tempat di tengah.)

Mark Karpov
sumber