LINUX.ORG.RU

GNU Emacs: quale: символы старше Latin-1 на клавиатуре

 , , , ,


0

1

Добрых суток, ЛОР.

Хочется мне, допустим, в английской раскладке иметь на клавишах сперва английские кавычки, а в русской — на тех же клавишах сперва русские. В Иксах тут никаких проблем нет. В Емаксе на первый взгляд тоже ничего сложного:

(quail-define-package
 "test" "Test" "XX" nil
 ""
 nil t t nil t nil nil nil nil nil t)

(quail-define-rules
 ("«" ?‘)
 ("»" ?’)
 ("‘" ?«)
 ("“" ?„)
 ("’" ?»)
 ("”" ?“))

(set-input-method 'test)

Однако если в направлении « все работает, то « — и не думает.

Документация по «Квэйлу» как-то скудновата, но из собственно quail.el, а именно из quail-simple-translation-keymap [0] становится понятно, что символы дальше 255-го по-умолчанию просто не обрабатываются, а из quail-define-package [1] улавливается, что их должно быть можно включить в обработку вот так:

(quail-define-package
 "test" "Test" "XX" nil
 ""
 '(("‘" . quail-self-insert-command)
   ("’" . quail-self-insert-command)
   ("“" . quail-self-insert-command)
   ("”" . quail-self-insert-command))
 t t nil t nil nil nil nil '() t)

После этого еще раз (quail-define-rules ...) и (set-input-method 'test) — и однако нифига.

Чего я не понимаю?

-- Приложения --

[0]

(defvar quail-simple-translation-keymap
  (let ((map (make-keymap))
	(i 0))
    (while (< i ?\ )
      (define-key map (char-to-string i) 'quail-other-command)
      (setq i (1+ i)))
    (while (< i 127)
      (define-key map (char-to-string i) 'quail-self-insert-command)
      (setq i (1+ i)))
    (setq i 128)
    (while (< i 256)
      (define-key map (vector i) 'quail-self-insert-command)
      (setq i (1+ i)))
    (define-key map "\177" 'quail-delete-last-char)
    (define-key map [delete] 'quail-delete-last-char)
    (define-key map [backspace] 'quail-delete-last-char)
    ;;(let ((meta-map (make-sparse-keymap)))
    ;;(define-key map (char-to-string meta-prefix-char) meta-map)
    ;;(define-key map [escape] meta-map))
    map))

[1]

(defun quail-define-package (name language title
				  &optional guidance docstring translation-keys
				  forget-last-selection deterministic
				  kbd-translate show-layout create-decode-map
				  maximum-shortest overlay-plist
				  update-translation-function
				  conversion-keys simple)
  (let (translation-keymap conversion-keymap)
    (if deterministic (setq forget-last-selection t))
    (if translation-keys
	(progn
	  (setq translation-keymap (copy-keymap
				    (if simple quail-simple-translation-keymap
				      quail-translation-keymap)))
	  (dolist (trans translation-keys)
	    (define-key translation-keymap (car trans) (cdr trans))))
      (setq translation-keymap
	    (if simple quail-simple-translation-keymap
	      quail-translation-keymap)))
    (when conversion-keys
      (setq conversion-keymap (copy-keymap quail-conversion-keymap))
      (dolist (conv conversion-keys)
	(define-key conversion-keymap (car conv) (cdr conv))))
    (quail-add-package
     (list name title (list nil) guidance (or docstring "")
	   translation-keymap
	   forget-last-selection deterministic kbd-translate show-layout
	   (if create-decode-map (list 'decode-map) nil)
	   maximum-shortest overlay-plist update-translation-function
	   conversion-keymap simple))

    ;; Update input-method-alist.
    (let ((slot (assoc name input-method-alist))
	  (val (list language 'quail-use-package title docstring)))
      (if slot (setcdr slot val)
	(setq input-method-alist (cons (cons name val) input-method-alist)))))

  (quail-select-package name))

★★★★★

Да, пардон. Для того, чтобы это как-то ощутить, нужно, очевидно, мочь все эти кавычки ввести с клавиатуры. Если у вас не вводятся, то вот сценарий для временной минимальной настройки и возврата в исходное состояние:

#!/bin/bash

case "$1" in
    backup)
        xkbcomp "$DISPLAY" /tmp/xkb.bak
        ;;
    restore)
        xkbcomp /tmp/xkb.bak "$DISPLAY"
        ;;
    setup)
        xkbcomp - "$DISPLAY" <<EOF

xkb_keymap {
  xkb_keycodes { include "evdev+aliases(qwerty)" };

  xkb_types { include "complete" };

  xkb_compatibility { include "complete" };

  xkb_symbols {
    include "pc+us:1+ru:2+inet(evdev)"
    include "group(shift_caps_switch)"
    include "level3(ralt_switch)"

    key <AB08> {
        type[group1]= "FOUR_LEVEL",
        type[group2]= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [           comma,            less, leftsinglequotemark, leftdoublequotemark ],
        symbols[Group2]= [     Cyrillic_be,     Cyrillic_BE,   guillemotleft, doublelowquotemark ]
    };

    key <AB09> {
        type[group1]= "FOUR_LEVEL",
        type[group2]= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [          period,         greater, rightsinglequotemark, rightdoublequotemark ],
        symbols[Group2]= [     Cyrillic_yu,     Cyrillic_YU,  guillemotright, leftdoublequotemark ]
    };

  };
};

EOF
        ;;
    *)
        echo >&2 $"Usage: $0 { setup | backup | restore }"
        ;;
esac

Кавычки будут вводится по AltGr-, , AltGr-., AltGr-Shift-, AltGr-Shift-. (<правый альт>-<запятая> и так далее), раскладка переключается: Caps на американскую, Shift-Caps на русскую.

Zmicier ★★★★★
() автор топика
Последнее исправление: Zmicier (всего исправлений: 1)

Однако если в направлении « → ‘ все работает, то ‘ → « — и не думает.

Если честно, то ты очень много текста написал. И сущность проблемы становится туманной.

(quail-defrule "'" "«" "russian-computer")

При нажатии «'» в русской будет "«", а в английской «'».

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

то ты очень много текста написал

Прошу простить, но короче никак не получалось.

И сущность проблемы становится туманной.

Символы старше #xFF-го (все, что не ASCII и не Latin-1) игнорируются quail’ом.

При нажатии «'» в русской будет "«", а в английской «'».

Нисколько не сомневаюсь. ' — это же машинописная кавычка из аски-диапазона (#x27), а я говорю про полноценные: (#x2018) и (#x2019).

Zmicier ★★★★★
() автор топика
Ответ на: комментарий от Zmicier

Я не очень понимаю все равно. А как ты вводишь свои полноценные «полноценные» кавычки в emacs? Зачем ты это делаешь?

Вот я тебе показываю. У тебя есть клавиша «'». Ты ее жмешь, и в зависимости от языка у тебя то один вид кавычек, то другой.

Наверное, еще надо уточнить: ты какой переключалкой пользуешься, когда переключаешь языки в Emacs? Иксовой или емаксовской?

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

А как ты вводишь свои полноценные «полноценные» кавычки в emacs?

Английские — через третий уровень, а именно почти так же, как это позволит сделать минимальный конфиг, что я привел выше (за исключением того, что у меня третьеуровневый шифт на месте залипающего «супера», а не правого «альта», но это не важно). Для русского пока продоложаю пользоваться Вимом — там keymap работает с любыми символами без проблем.

Зачем ты это делаешь?

Ну, как минимум, XXI век на дворе — неприлично уже как-то ASCII обходиться. Да и семантически ‘foo’ и 'foo' — это все-таки разные вещи — подсвечиваются и не только, соответственно, по-разному.

Вот я тебе показываю. У тебя есть клавиша «'». Ты ее жмешь, и в зависимости от языка у тебя то один вид кавычек, то другой.

Пардон, не понимаю совсем. Кто-то из нас, кажется, не выспался. Во-первых, машинописная кавычка, очевидно, тоже нужна. А во-вторых, какой вообще от ее привязки толк — она же одна, тогда как настоящие кавычки таки парные.

когда переключаешь языки в Emacs? Иксовой или емаксовской?

Емаксовской, разумеется, если я говорю о «Квэйле». А что, можно как-то полноценно пользоваться иксовой?

Zmicier ★★★★★
() автор топика
Ответ на: комментарий от Zubok

Да и вовсе дело не только в одних кавычках — они из всего третьего-четвертого уровня выбраны только для наглядности, а там еще нужно много менее очевидных трансляций, например, ў.

Zmicier ★★★★★
() автор топика
Последнее исправление: Zmicier (всего исправлений: 1)
Ответ на: комментарий от Zmicier

Ну, как минимум, XXI век на дворе — неприлично уже как-то ASCII обходиться. Да и семантически ‘foo’ и 'foo' — это все-таки разные вещи — подсвечиваются и не только, соответственно, по-разному.

Ну я же говорю, что не понимает Emacs эти символы. Он позволяет тебе символ или последовательность символов с клавиатуры в контексте input-method переводить в не-ASCII. Можешь сделать свой input-method (типа третий уровень).

А когда ты пользуешься чем-то другим (в данном случае - третий уровень), то Emacs этого не понимает. Он и русские буквы не понимает. В правилах quial первый параметр - это не символ на экране, а keystroke. Для Emacs нет такой кнопки ‘, есть только '.

Тебе надо специально для Emacs придумывать, как ты будешь разные типы кавычек вводить через последовательности keystrokes.

Zubok ★★★★★
()
Ответ на: комментарий от Zmicier

Какой бы ты не выбрал input-method, у тебя кнопка с буквой «ы» все равно будет для quail как «s». То есть правило перевода «ы» -> «s» работать не будет. А вот правило «s» -> «ы» в контексте русского input-method (или тобою специально созданного) будет.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 3)
Ответ на: комментарий от Zubok

Ну я же говорю, что не понимает Emacs эти символы.

В каком смысле «не понимает»? Связать любой уникодный символ с функцией безусловно можно:

(local-set-key "€" (lambda () (interactive) (message "Euro!")))

Ограничение в 255 символов по-умолчанию в quail-simple-translation-keymap выглядит абсолютно искусственным. Более того, по всей видимости, предусмотрен и обход этого ограничения — параметр translation-keys в quail-define-package.

Однако скудность документации и полное отсутствие опыта в Елиспе не позволяет мне понять, как им правильно пользоваться.

Для Emacs нет такой кнопки , есть только '.

В том-то и фишка, что для Емакса вообще нет «кнопок», есть только символы. Умел бы он работать с «кнопками» — все эти костыли с «Квайлами» и «методами ввода» были бы не нужны.

К слову, если мне не изменяет память, лет пятнадцать назад с этим было попроще: в Иксах аккорды от раскладки не зависели: C-<AB02> вне зависимости от раскладки понималась C-x, а не как C-ч и соответственно работала. Потом, вероятно, унифицировали с терминалом.

специально для Emacs придумывать, как ты будешь разные типы кавычек вводить через последовательности keystrokes.

Нет уж, спасибо, костыль для костыля — это перебор.

Zmicier ★★★★★
() автор топика
Последнее исправление: Zmicier (всего исправлений: 1)
Ответ на: комментарий от Zubok

Какой бы ты не выбрал input-method, у тебя кнопка с буквой «ы» все равно будет для quail как «s».

Убедиться, что это неверно, более чем легко — выберите, к примеру, метод ukrainian-computer, переключите раскладку в Иксах на русскую и нажмите клавишу «s» / «ы» — полу́чите в Емаксе «ы», а не «і».

Zmicier ★★★★★
() автор топика
Ответ на: комментарий от Zubok

[quail] — это не то, что тебе нужно.

Учитывая, что это весьма навороченная система, специально предназначенная для составления методов ввода, позволю себе усомниться. Скорее всего, я ее просто пока не могу осилить.

Все-таки, если перейти к конкретике, вы, как человек (я так понимаю) с опытом в Елиспе, можете сказать, я вообще правильно заполнил аргумент translation-keys при определении нового метода ввода (я там какую-нибудь кавычку не пропустил?). И нет ли какого-нибудь метода отладки, какой тут можно применить?

А посмотри в сторону make-translation-table.

Посмотрел. По сути вы мне предлагаете написать свою упрощенную реализацию «Квайла» для строго детерминированных методов ввода. Вполне допускаю, что в итоге так придется сделать, но пока повременю.

Zmicier ★★★★★
() автор топика
Ответ на: комментарий от Zmicier

Ну так все верно. Символ «ы» в твоем случае пришел из иксов. Ты можешь хоть китайский ввод выбрать - нарисует «ы». Emacs работает со своей системой ввода, но не сопротивляется, если пришло что-то незнакомое. Но вся цепочка правил quail просто не будет работать. Emacs не понимает иксовый символ <Cyrillic_yeru>, он понимает символ «s» в контексте выбранной системы ввода. Вот так вот работает.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Вот так вот работает.

Я имею наглость считать, что на таком-то уровне я понимаю, как работает Квайл, когда я включаю russian-computer. А не понимаю я — как его несколько изменить, чтобы он транслировал отдельные символы старше #xFF-го. Мне все еще кажется, что здесь не просто не должно быть непреодолимых трудностей, а даже имеются прямо для этого предназначенные пользовательские интерфейсы — translation-keys, но я их как-то не так использую. Я неправ?

Zmicier ★★★★★
() автор топика
Последнее исправление: Zmicier (всего исправлений: 1)
Ответ на: комментарий от Zmicier

Я имею наглость считать, что на таком-то уровне я понимаю, как работает Квайл

Да он работает так, для чего его и делали:

;;; Commentary:

;; In Quail minor mode, you can input multilingual text easily.  By
;; defining a translation table (named Quail map) which maps ASCII key
;; string to multilingual character or string, you can input any text
;; from ASCII keyboard.

То есть это изначально не то, что тебе нужно.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Я имею в виду шестой аргумент функции quail-define-package. Открывая нить, я показал, что́ (и основываясь на чем), я попытался с ним с сделать. Но оно не возымело действия. Отсутствие всяческого опыта в Елиспе не позволяет мне понять, не допустил ли я какой-нибудь глупой ошибки, и как это отлаживать.

Zmicier ★★★★★
() автор топика
Ответ на: комментарий от Zmicier

тобы он транслировал отдельные символы старше #xFF-го.

А я не вижу, как ты их используешь в коде наверху. Ты транслируй не по кодам #xFF, а по названию символа. То есть [guillemotleft] и т . д. Это аналогично [escape], [home] и т . д.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

То есть [guillemotleft] и т . д.

guillemotleft-то («) и так работает, но я понял. Сейчас попробую.

Попробовал:

(quail-define-package
 "test" "Test" "XX" nil
 ""
 '(([leftsinglequotemark] . quail-self-insert-command)
   ([rightsinglequotemark] . quail-self-insert-command))
 t t nil t nil nil nil nil '() t)

(quail-define-rules
 ("«" ?‘)
 ("»" ?’)
 ([leftsinglequotemark] ?«)
 ([rightsinglequotemark] ?»))

(set-input-method 'test)

Ничего не изменилось.

Zmicier ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.