Налаштування українського середовища у (X)Emacs

Автор: Андрій Балагута <andrey.balaguta (гау!) gmail.com>

Деякий час я мав дуже обмежений доступ до мережи, то ж не було ніякої можливості забрати із потічної гілки CVS Emacs. То ж я залишився наодинці зі стареньким XEmacs 21.4.17.

Щоб редагувати україномовні та російскомовні тексти, мені було потрібно:

  • Оточення, здатне хочби на 70-80% обробляти Unicode.
  • Звичні методи вводу кирилиці. Для мене «звичні» -- це Windows-подібні методи вводу (на мою думку, вони звичні також і для більшості людей у нашому суспільстві).
  • Перевірка українського та російского правопису.

Налаштування оточення Unicode

Внутрішнє кодування символів у XEmacs є спорідненим (я не дуже впевен у цьому питанні) міжнародному кодуванню ISO-2022-2, що здатне кодувати символи будь-якої мови, та навіть надає можливість перемикатись з мови на мову у одному документі. То ж для кодування символів європейських мов XEmacs використовує набір кодувань ISO-8859-X. Нажаль, кодування ISO-8859-5, що призначене для кирилиці, не підтримує символ «Ґ», то ж можете одразу забути про цю літеру -- ви ніяким чином не зможете ввести чи прочитати її у старих Emacs'ах (проте, якщо ви редагуєте HTML чи Wiki, ви можете використовувати її Unicode-код -- Ґ).

Для налаштування Unicode нам знадобиться пакет Mule-UCS, що входить до поставки XEmacs. Щоб заставити цей пакет працювати на вас, треба у init.el ввести такі рядки:

(require 'un-define)

(set-coding-priority-list '(utf-8))
(set-coding-category-system 'utf-8 'utf-8)

Після цього у списку кодувань повинні з'явитися Unicode-кодування.

Налаштування методів вводу

Поперше, невелика порада: ніколи не використовувайте методи вводу XKB (тобто стандартні методи вводу X Window System) у Emacs! Це дуже незручно. Наприклад, неможливо вводити M-x команди -- треба перемикатись на англійську. Є ще декілька аспектів. Найбільш вірний спосіб -- використовувати методи вводу Mule. Вони обслуговуються бібліотечкою Quail, що входить до кожної дистрибуції Emacs.

За методами вводу я звернувся до гілки CVS Emacs. Витягнув звідти файл quail/cyrillic.el, викусив метод russian-computer, після цього скопіював його та перейменував у ukrainian-computer, тому що звичайний ukrainian-computer був закодован у деяких дивних ESC-послідовностях, які мій XEmacs зовсім не хотів розуміти. Після чого я, звісно, відредагував цей метод (ы -> і, ъ -> ї, і тому подібне). Результат ви можете бачити (файл ~/.xemacs/input-methods.el):

;;; AB: taken from the CVS Emacs, just a piece...

(require 'quail)

(quail-define-package
 "russian-computer" "Russian" "RU" nil
 "ЙЦУКЕН Russian computer layout"
 nil t t t t nil nil nil nil nil t)

;;  1! 2" 3№ 4; 5% 6: 7? 8* 9( 0) -_ =+ ёЁ
;;   Й  Ц  У  К  Е  Н  Г  Ш  Щ  З  Х  Ъ
;;    Ф  Ы  В  А  П  Р  О  Л  Д  Ж  Э
;;     Я  Ч  С  М  И  Т  Ь  Б  Ю  .,

(quail-define-rules
 ("1" ?1)
 ("2" ?2)
 ("3" ?3)
 ("4" ?4)
 ("5" ?5)
 ("6" ?6)
 ("7" ?7)
 ("8" ?8)
 ("9" ?9)
 ("0" ?0)
 ("-" ?-)
 ("=" ?=)
 ("`" ?ё)
 ("q" ?й)
 ("w" ?ц)
 ("e" ?у)
 ("r" ?к)
 ("t" ?е)
 ("y" ?н)
 ("u" ?г)
 ("i" ?ш)
 ("o" ?щ)
 ("p" ?з)
 ("[" ?х)
 ("]" ?ъ)
 ("a" ?ф)
 ("s" ?ы)
 ("d" ?в)
 ("f" ?а)
 ("g" ?п)
 ("h" ?р)
 ("j" ?о)
 ("k" ?л)
 ("l" ?д)
 (";" ?ж)
 ("'" ?э)
 ("\\" ?\\)
 ("z" ?я)
 ("x" ?ч)
 ("c" ?с)
 ("v" ?м)
 ("b" ?и)
 ("n" ?т)
 ("m" ?ь)
 ("," ?б)
 ("." ?ю)
 ("/" ?.)
 ("!" ?!)
 ("@" ?\")
 ("#" ?№)
 ("$" ?\;)
 ("%" ?%)
 ("^" ?:)
 ("&" ??)
 ("*" ?*)
 ("(" ?()
 (")" ?))
 ("_" ?_)
 ("+" ?+)
 ("~" ?Ё)
 ("Q" ?Й)
 ("W" ?Ц)
 ("E" ?У)
 ("R" ?К)
 ("T" ?Е)
 ("Y" ?Н)
 ("U" ?Г)
 ("I" ?Ш)
 ("O" ?Щ)
 ("P" ?З)
 ("{" ?Х)
 ("}" ?Ъ)
 ("A" ?Ф)
 ("S" ?Ы)
 ("D" ?В)
 ("F" ?А)
 ("G" ?П)
 ("H" ?Р)
 ("J" ?О)
 ("K" ?Л)
 ("L" ?Д)
 (":" ?Ж)
 ("\"" ?Э)
 ("|" ?|)
 ("Z" ?Я)
 ("X" ?Ч)
 ("C" ?С)
 ("V" ?М)
 ("B" ?И)
 ("N" ?Т)
 ("M" ?Ь)
 ("<" ?Б)
 (">" ?Ю)
 ("?" ?,))

(quail-define-package
 "ukrainian-computer" "Ukrainian" "UK" nil
 "ЙЦУКЕН Ukrainian (Unicode-based for use with KOI8-U encoding)."
 nil t t t t nil nil nil nil nil t)

;; AB: Here is going my "modification" -- I just don't get all this ESC and (,
;; and xemacs doesn't eat that, so I just copypasted russian-computer and changed
;; it appropriately

;;  1! 2" 3№ 4; 5% 6: 7? 8* 9( 0) -_ =+ 'Ё (why I need Ё here? :)
;;   Й  Ц  У  К  Е  Н  Г  Ш  Щ  З  Х  Ї
;;    Ф  І  В  А  П  Р  О  Л  Д  Ж  Є
;;     Я  Ч  С  М  И  Т  Ь  Б  Ю  .,

(quail-define-rules
 ("1" ?1)
 ("2" ?2)
 ("3" ?3)
 ("4" ?4)
 ("5" ?5)
 ("6" ?6)
 ("7" ?7)
 ("8" ?8)
 ("9" ?9)
 ("0" ?0)
 ("-" ?-)
 ("=" ?=)
 ("`" ?')
 ("q" ?й)
 ("w" ?ц)
 ("e" ?у)
 ("r" ?к)
 ("t" ?е)
 ("y" ?н)
 ("u" ?г)
 ("i" ?ш)
 ("o" ?щ)
 ("p" ?з)
 ("[" ?х)
 ("]" ?ї)
 ("a" ?ф)
 ("s" ?і)
 ("d" ?в)
 ("f" ?а)
 ("g" ?п)
 ("h" ?р)
 ("j" ?о)
 ("k" ?л)
 ("l" ?д)
 (";" ?ж)
 ("'" ?є)
 ("\\" ?\\)
 ("z" ?я)
 ("x" ?ч)
 ("c" ?с)
 ("v" ?м)
 ("b" ?и)
 ("n" ?т)
 ("m" ?ь)
 ("," ?б)
 ("." ?ю)
 ("/" ?.)
 ("!" ?!)
 ("@" ?\")
 ("#" ?№)
 ("$" ?\;)
 ("%" ?%)
 ("^" ?:)
 ("&" ??)
 ("*" ?*)
 ("(" ?()
 (")" ?))
 ("_" ?_)
 ("+" ?+)
 ("~" ?Ё)
 ("Q" ?Й)
 ("W" ?Ц)
 ("E" ?У)
 ("R" ?К)
 ("T" ?Е)
 ("Y" ?Н)
 ("U" ?Г)
 ("I" ?Ш)
 ("O" ?Щ)
 ("P" ?З)
 ("{" ?Х)
 ("}" ?Ї)
 ("A" ?Ф)
 ("S" ?І)
 ("D" ?В)
 ("F" ?А)
 ("G" ?П)
 ("H" ?Р)
 ("J" ?О)
 ("K" ?Л)
 ("L" ?Д)
 (":" ?Ж)
 ("\"" ?Є)
 ("|" ?|)
 ("Z" ?Я)
 ("X" ?Ч)
 ("C" ?С)
 ("V" ?М)
 ("B" ?И)
 ("N" ?Т)
 ("M" ?Ь)
 ("<" ?Б)
 (">" ?Ю)
 ("?" ?,))

після цього треба просто завантажити цей файл (рядки з init.el):

(push (concat (getenv "HOME") "/.xemacs") load-path)

(load "input-methods")

Йдемо далі. Треба якимось чином усе це перемикати. Я ніколи не розумів цих перемикачів «на три позиції». На мій погляд, це дуже незручно, бо у звичайній ситуації потрібно перемикатися або rus-eng, або ukr-eng. То ж я вирішив зробити інакше. Було введено змінну, що містила т.з. «кільце методів вводу», у якому описувались усі потрібні нам методи вводу (у нашому прикладі -- два методи, російський та український). Кільце -- тому що з останнього метода ми перемикаємось на перший. Визначення змінної:

(defcustom input-methods-loop 
  '("russian-computer" "ukrainian-computer")
  "Define input methods switching loop."
  :type '(list string))

Далі я написав невеличку функцію, яка перемикає звичайний метод вводу (default-input-method) між методами у кільці. Треба зауважити, що ця функція адекватно реагує у разі ввімкненого поточного метода вводу -- вона перемикає його на новий метод вводу. Наприклад, якщо ви редагували текст російсьскою, та перемикаєтесь на українську, метод вводу відразу змінюється на українську, то ж ви не змушені вимикати та знову вмикати метод вводу, щоб отримати українську. Визначення функції:

(defun switch-default-input-method ()
  "Switch default input method to the next in `input-methods-loop'.
If it was the last input method in that list, then switch to first
(i.e. circulate through that list)."
  (interactive)
  (custom-set-variables 
   '(default-input-method 
      (let ((next (second (member default-input-method
                  input-methods-loop))))
    (if (null next) 
        (first input-methods-loop) 
      next))))
  (message "Selected input method: %s" default-input-method)
  (when (not (null current-input-method))
    (activate-input-method default-input-method)))

Тепер треба назначити цієї функції яку-небудь зручну комбінацію клавіш (я вибрав C-=):

(global-set-key '(control =) #'switch-default-input-method)

Також ми мусимо деяким чином встановити початкове значення для default-input-method:

(custom-set-variables
 '(default-input-method (first input-methods-loop)))

Таким чином, поточний метод вводу я перемикаю за допомогою C-=, а вмикаю/вимикаю -- стандартним C-\. Мені дуже зручно.

Багато чого залишилося

Досі я ще не налаштував деякі потрібні речі:

  • ispell ukrainian (тут великі незрозумілі проблеми з ispell.el)
  • словник (потрібен зручний й адекватний фейс до dict, та, мабуть, mova).
  • адекватну обробку Primary Selection та Cut-буферів у X-ах.
  • налаштування оточення koi8-u.
  • мабуть ще щось.

То ж, сподіваюсь, далі буде :-) Буду радий порадам та такому іншому, адреса електричної пошти зверху.