UPD: перепост старой заметки в новый блог, планирую обновлять и поддерживать в актуальном состоянии
Последнее обновление: Среда, 10. Март 2010
<p>Описание проблемы: при переключении на не-латинскую раскладку клавиатуры в Emacs не работают горячие клавиши. Также не запоминается своя раскладка для каждого буфера Emacs.</p>
<p>Варианты решения проблемы:
<ul>
<li>Продублировать все горячие клавиши для нужной раскладки и отказаться от
отдельной для каждого буфера раскладки (плохой выход из ситуации).</li>
<li>Использовать встроенную в Emacs переключалку (то, что нам нужно).</li>
</ul>
</p>
<!--more-->
<p>По умолчанию цикличное переключение раскладок в Emacs работает по комбинации C-\<br />
Очевидно, вы пожелаете настроить в Emacs клавиатурное сочетание для переключения раскладок как в xorg, и тут появляется проблема номер 2:</p>
<p>Xorg не передает приложению нажатие клавиш, которыми он переключает раскладку. К тому же нет возможности настроить игнорирование иксорговской переключалкой конкретного приложения. Для решения этой проблемы ранее предлагали использовать патченный xxkb, который переключал раскладку в окне Emacs всегда на латиницу и передавал окну нужные клавиатурные сочетания. Как показала практика - работает это решение не всегда и глючит, поэтому появились следующие, более корректные решения этой проблемы:</p>
<p>
<ul>
<li>Хороший человек с псевдонимом Akshaal написал программку, а другой хороший
человек с псевдонимом Bzek доработал её. К сожалению, все ссылки на описание
этого метода померли, поэтому я переношу эту информацию сюда (см. ниже). Этот
метод имеет свои недостатки, но я пользуюсь именно им. Суть метода сводится к
переключению раскладок сторонней программой, которая сама определяет окно Emacs
и отправляет ему нужное сочетание клавиш вместо переключения раскладки.</li>
<li>Использовать для переключения языков альтернативный метод ввода
ibus (scim). Достаточно отключить его в Emacs и клавиатурные сочетания, которые вы
настроили в ibus (scim), будут обрабатываться в Emacs. Описание тоже ниже.</li>
</ul>
</p>
<p><h3>Настраиваем ibus (scim)</h3></p>
<p>
<ol>
<li>Устанавливаем scim, scim-m17n и scim-tables (для ibus сами определяйтесь, не
пользуюсь им). Последние два включают в себя
приличное количество раскладок клавиатуры для различных языков.</li>
<li>Прописываем в профиль переменные среды:
Для scim:
<pre><code>
export XMODIFIERS=@im=SCIM
export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim
</code></pre>
Для ibus видимо будет как-то так:
<pre><code>
export GTK_IM_MODULE=ibu
export QT_IM_MODULE=ibu
</code></pre>
</li>
<li>Отключаем ibus (scim) в Emas, для этого пишем в .Xdefaults:
<pre><code>Emacs*useXIM:false</code></pre>
(не знаю правда, как тут с ibus; если кто-то знает - пишите мне)
</li>
<li>Запускаем scim-setup и настраиваем всё что нужно. Останавливаться на этом не
буду - если не разберетесь, то можете спросить в xmpp-конференции
emacs@conference.jabber.ru.</li>
<li>Настраиваем в Emacs обработку этих сочетаний клавиш. Например так:
{% highlight cl %}
(global-set-key (kbd “C-1”)
(lambda ()
(inactivate-input-method)))
(global-set-key (kbd “C-2”)
(lambda ()
(set-input-method 'russian-computer)))
{% endhighlight %}
</li>
</ol></p>
<p>Вы можете добавить сюда переключение словаря flyspell, например. Или настроить
цикличное переключение, в этом вам поможет функция toggle-input-method.</p>
<p><h3>Использование emxkb</h3></p>
<p>Замечание к этому методу: с его помощью нельзя настроить раскладку на цикличное
переключение (хотя, можно просто модифицировать программу). У меня, например,
группа "us" включается по нажатию C-1, а "ru" - C-2.</p>
<p>Первое, что нам понадобится - программа emxkb. Её нужно <a href="http://paul.elms.pro/files/emxkb.c">скачать</a> и скомпилировать
вот так:</p>
<p><pre><code>
gcc -L/usr/X11R6/lib -lX11 -o emxkb emxkb.c
</code></pre></p>
<p>При выполнении emxkb 0 раскладка переключается на первую группу, emxkb 1 -
вторую и т.д. Если же значение WM_CLASS текущего окна равно "emacs", то вместо
переключения групп emxkb шлёт нажатие виртуальных клавиш F31, F32, F33 и
т.д. Остается только обрабатывать эти нажатия в emacs.</p>
<p>Итак, вы уже настроили в своём wm (или xbindkeys) какие-либо сочетания клавиш на
выполнение комманд emxkb 0 и emxkb 1. Но ещё не все готово для настройки
emacs. Дело в том, что клавиш F31, F32 и т.д. не существует и нужно их виртуально
"создать" с помощью xmodmap:</p>
<p><pre><code>
keycode 431=F31
keycode 432=F32
keycode 433=F33
</code></pre></p>
<p>431, 432, 433 можно заменить на любые другие свободные кейкоды.</p>
<p>Теперь можно настраивать emacs:</p>
<p>{% highlight cl %}
(defun reset-flyspell-with-new-dict (dict)
“Set new dictionary and restart flyspell”
(unless (equal dict ispell-local-dictionary)
(setq ispell-local-dictionary dict)
(when flyspell-mode
(flyspell-mode)
(flyspell-mode)))
(when flyspell-mode
(save-excursion
(flyspell-region (window-start) (window-end))))
(message nil))
(global-set-key [(f31)]
(lambda ()
(interactive)
;; (reset-flyspell-with-new-dict "american")
(inactivate-input-method)))
(global-set-key [(f32)]
(lambda ()
(interactive)
;; (reset-flyspell-with-new-dict "russian")
(set-input-method 'russian-computer)))
(global-set-key [(f33)]
(lambda ()
(interactive)
;; (reset-flyspell-with-new-dict "italian")
(set-input-method 'italian-keyboard)))
(defun toggle-specified-isearch-input-method (new-input-method)
“Toggle specified input method in interactive search.”
(interactive)
(let ((overriding-terminal-local-map nil)))
(if (eq new-input-method ‘default-method)
(inactivate-input-method)
(set-input-method new-input-method))
(setq isearch-input-method-function input-method-function
isearch-input-method-local-p t)
(setq input-method-function nil)
(isearch-update))
(add-hook ‘isearch-mode-hook
(lambda ()
(define-key isearch-mode-map (kbd "<f31>")
(lambda ()
(interactive)
(toggle-specified-isearch-input-method 'default-method)))
(define-key isearch-mode-map (kbd "<f32>")
(lambda ()
(interactive)
(toggle-specified-isearch-input-method 'russian-computer)))
(define-key isearch-mode-map (kbd "<f33>")
(lambda ()
(interactive)
(toggle-specified-isearch-input-method 'italian-keyboard)))))
{% endhighlight %}</p>
<p>Внимательно (или не очень) изучите приведенный кусок кода на elisp и настройте
его под свои нужды.</p>
<p>P.S. Если у вас что-то не получилось, <strike>вы можете найти меня в конференции
emacs@conference.jabber.ru</strike>. Приветствуются любые дополнения и правки к статье.<br />
P.P.S. Для консольной версии Emacs проблема всё ещё актуальна.</p>