; CYR.EL version 2.32, Feb 4, 1998 ; ; This is a ready-to-use cyrillic mode for emacs and xemacs. I wrote it ; for my own use, and if you think that it is cool and you can use it ; too, it's enough of a reward for me. It is NOT a part of emacs ; (*shudder*). You may use, modify and distribute it at your own ; risk. It works with emacs19 and *does* now work with xemacs, thanks to ; Tzvetan Stoyanov and Dima Barsky ; . Keyboard driver works with emacs18, but ; not transliterated display. Some versions of emacs19 have a bug ; causing bad display when the point is at end of buffer. Can be fixed ; by upgrading to 19.28. ; ; ; The term `cyrillics' below is used as synonymous to `KOI-8'. The whole ; stuff can be easily converted to use with any other encoding, exactly ; in the same way as you would convert any text file between, say, ; KOI and ALT. Keyboard bindings for Win 1251 encoding were added by ; Sam Steingold and Boris Veytsman. ; ; FEATURES: ; 1. Enter cyrillic characters without any external keyboard drivers ; (DOS) or xmodmap (UNIX/X11). You don't need X or any other windows ; either. Actually, all you need is emacs (well, it still has to ; be running on *something*). Use qwerty or jcuken keyboard. ; 2. Read cyrillic texts in transliterated form, if you don't have ; fonts. It is not a file conversion, the text you read and write ; is intrinsically cyrillic, it is only displayed by emacs in ; transliterated form. Or do convert portions of text from ; cyrillic to transliteratied text. ; 3. At last you can use the best transliteration -- your own. If ; you figure out how to customize this stuff, which should be ; kids' play... or math school kids' play. ; 4. In conjunction with hilit19, highlights transliterated cyrillics ; so that it's easy to tell it from true latin-alphabet characters. ; 5. Now allows you to work in either KOI or Win (1251) encodings ; ; INSTALLATION: ; 1. Save this file as, say, "cyr.el" ; 2. Put in your .emacs the following lines (without initial semicolons!): ; (autoload 'cyrillic-mode "cyr.el" "Cyrillic mode" t) ; (autoload 'cyrillic-translit-mode "cyr.el" "Toggle Translit display" t) ; (autoload 'cyrillic-minibuffer-mode "cyr.el" nil 'INTERACTIVE) ; (autoload 'cyrillic-translit-region "cyr.el" "Transliterate destructively" t) ; (autoload 'cyrillic-set-translit-table "~/el/cyr.el" nil 'INTERACTIVE) ; (NOTE: you should either save the file where emacs will find it, ; or specify the full path instead of plain "cyr.el") ; 3. Restart emacs, or reload .emacs, type "M-x cyrillic-mode RET" and/or ; "M-x cyrillic-translit-mode RET" and enjoy. ; 4. Info on customization see in help on variables (C-h C-v) ; `cyrillic-mode-key-bindings' (or just below), ; and `cyrillic-hilit-highlight-face'. ; See also help on functions (C-h C-f) `cyrillic-set-kbd', ; `cyrillic-set-jcuken-kbd', `cyrillic-set-latin-kbd', ; `cyrillic-translit-mode', `cyrillic-translit-region'. ; 5. If you want keyboard bindings for most useful commands, this should work in your ; .emacs: ; (global-set-key "\C-crr" 'cyrillic-mode) ; (global-set-key "\C-crv" 'cyrillic-translit-mode) ; (global-set-key "\C-crw" ; '(lambda () (interactive) ; (cyrillic-set-kbd cyrillic-mode-latin-cp1251-kbd) ; (cyrillic-set-translit-table cyrillic-translit-table-1251 't))) ; (global-set-key "\C-crk" ; '(lambda () (interactive) ; (cyrillic-set-kbd cyrillic-mode-latin-kbd) ; (cyrillic-set-translit-table cyrillic-translit-table-koi 't))) ; 6. direct your questions and comments to me, ; Dmitrii (Mitya) Manin ; ; I'm grateful to Ed Ponarin for extensive beta-testing and addition ; of Ukrainian letters. Many thanks to Leonid Delitsyn for testing ; this code and useful suggestions. Kudos to Tzvetan Stoyanov and Dima Barsky ; for figuring out how to adapt the code for xemacs and to Boris Veytsman for ; keyboard bindings and translit tables for the Win 1251 encoding. (defvar cyrillic-mode-key-bindings nil "*Customizable list of key bindings. Each entry is a cons cell: car is the key pressed, cdr is the desired result. It can be: - a string or a character that should be inserted - a symbol or lambda expression for a function to be called - a list of substitutions. This list, in turn, consists of cons cells. Car will be compared to what's there in the buffer before point, and if found it will be replaced by cdr. The last element should be a character or string, which is to be inserted if all other tries fail. Here's an example: (setq cyrillic-mode-key-bindings (list (cons \"a\" (list (cons \"ÃÙ\" \"ÔÓÑ\") (cons \"Ù\" \"Ñ\") (cons \"ù\" \"ñ\") \"Á\")) (cons \"b\" ?Â) (cons \"c\" 'insert-tse) (cons \"d\" (lambda () (interactive) (insert ?Ä)) ))) Here's what this means. If the \"a\" key is pressed, and there is the string \"ÃÙ\" before cursor, it will be replaced by \"ÔÓÑ\" (why? think about how \"ÃÙÁ\" could appear otherwise). The \"Ñ\" results from \"ya\", and \"ñ\" from \"Ya\". Otherwise the key maps to the Russian \"Á\". The key \"b\" maps to the ? character (question sign precedes a character constant in elisp) Pressing \"c\" calls a hypothetical function insert-tse. \"d\" key invokes the nameless explicit function written as a lambda expression (this actually works as expected). Four ready-to-use tables are provided in this file: `cyrillic-mode-latin-kbd' (default), `cyrillic-mode-jcuken-kbd', `cyrillic-mode-latin-cp1251-kbd' and `cyrillic-mode-jcuken-cp1251-kbd' (to switch between them use commands `cyrillic-set-latin-kbd', `cyrillic-set-jcuken-kbd', and the general one, `cyrillic-set-kbd'). You can customize either or all, or write your own table. In this case be sure to add it to the `cyrillic-kbd-list'.") (defvar cyrillic-mode-latin-kbd (list (cons "a" (list ; (cons "ÃÙ" "ÔÓÑ") (cons "Ù" "Ñ") (cons "ù" "ñ") "Á")) (cons "b" ?Â) (cons "c" ?Ã) (cons "d" ?Ä) (cons "e" ?Å) (cons "f" ?Æ) (cons "g" ?Ç) (cons "h" (list (cons "Ë" "È") (cons "ë" "è") (cons "Å" "Ü") (cons "å" "ü") (cons "Ú" "Ö") (cons "ú" "ö") (cons "Ó" "Û") (cons "ó" "û") (cons "ÛÃ" "Ý") (cons "Ã" "Þ") (cons "ûã" "ý") (cons "ã" "þ") "È")) (cons "i" (list (cons "Ù" "yÊ") (cons "i" "iÊ") "É")) (cons "j" ?Ê) (cons "k" ?Ë) (cons "l" ?Ì) (cons "m" ?Í) (cons "n" ?Î) (cons "o" (list (cons "Ù" "£") (cons "ù" "³") ?Ï)) (cons "p" ?Ð) (cons "q" (list (cons "Ó" "Ý") ?Ñ)) (cons "r" ?Ò) (cons "s" (list ; (cons "Ô" "Ã") ; (cons "ô" "ã") ?Ó)) (cons "t" ?Ô) (cons "u" (list (cons "Ù" "À") (cons "ù" "à") ?Õ)) (cons "v" ?×) (cons "w" ?Û) (cons "x" ?Ý) (cons "y" ?Ù) (cons "z" (list (cons "Ã" "Ý") ?Ú)) (cons "`" (list (cons "Ø" "ø") ?Ø)) (cons "~" (list (cons "ß" "ÿ") ?ß)) (cons "A" (list (cons "ù" "ñ") ?á)) (cons "B" ?â) (cons "C" ?ã) (cons "D" ?ä) (cons "E" ?å) (cons "F" ?æ) (cons "G" ?ç) (cons "H" (list (cons "ë" "è") (cons "å" "ü") (cons "ú" "ö") (cons "ó" "û") (cons "ûã" "ý") (cons "ã" "þ") "è")) (cons "I" (list (cons "ù" "Yê") (cons "I" "Iê") ?é)) (cons "J" ?ê) (cons "K" ?ë) (cons "L" ?ì) (cons "M" ?í) (cons "N" ?î) (cons "O" (list (cons "ù" "³") ?ï)) (cons "P" ?ð) (cons "Q" (list (cons "ó" "ý") ?ñ)) (cons "R" ?ò) (cons "S" (list ; (cons "ô" "ã") ?ó)) (cons "T" ?ô) (cons "U" (list (cons "ù" "à") ?õ)) (cons "V" ?÷) (cons "W" ?û) (cons "X" ?ý) (cons "Y" ?ù) (cons "Z" (list (cons "ã" "ý") ?ú))) "Keyboard layout for entering cyrillics on latin keyboard. See help on `cyrillic-mode-key-bindings'.") (defvar cyrillic-mode-latin-cp1251-kbd (list (cons "a" (list ; (cons "öû" "òñÿ") (cons "û" "ÿ") (cons "Û" "ß") "à")) (cons "b" ?á) (cons "c" ?ö) (cons "d" ?ä) (cons "e" ?å) (cons "f" ?ô) (cons "g" ?ã) (cons "h" (list (cons "ê" "õ") (cons "Ê" "Õ") (cons "å" "ý") (cons "Å" "Ý") (cons "ç" "æ") (cons "Ç" "Æ") (cons "ñ" "ø") (cons "Ñ" "Ø") (cons "øö" "ù") (cons "ö" "÷") (cons "ØÖ" "Ù") (cons "Ö" "×") "õ")) (cons "i" (list ; (cons "û" "yé") ; (cons "i" "ié") "è")) (cons "j" ?é) (cons "k" ?ê) (cons "l" ?ë) (cons "m" ?ì) (cons "n" ?í) (cons "o" (list (cons "û" "¸") (cons "Û" "¨") ?î)) (cons "p" ?ï) (cons "q" (list (cons "ñ" "ù") ?ÿ)) (cons "r" ?ð) (cons "s" (list ; (cons "ò" "ö") ; (cons "Ò" "Ö") ?ñ)) (cons "t" ?ò) (cons "u" (list (cons "û" "þ") (cons "Û" "Þ") ?ó)) (cons "v" ?â) (cons "w" ?ø) (cons "x" ?ù) (cons "y" ?û) (cons "z" (list (cons "ö" "ù") ?ç)) (cons "`" (list (cons "ü" "Ü") ?ü)) (cons "~" (list (cons "ú" "Ú") ?ú)) (cons "A" (list (cons "Û" "ß") ?À)) (cons "B" ?Á) (cons "C" ?Ö) (cons "D" ?Ä) (cons "E" ?Å) (cons "F" ?Ô) (cons "G" ?Ã) (cons "H" (list (cons "Ê" "Õ") (cons "Å" "Ý") (cons "Ç" "Æ") (cons "Ñ" "Ø") (cons "ØÖ" "Ù") (cons "Ö" "×") "Õ")) (cons "I" (list ; (cons "Û" "YÉ") ; (cons "I" "IÉ") ?È)) (cons "J" ?É) (cons "K" ?Ê) (cons "L" ?Ë) (cons "M" ?Ì) (cons "N" ?Í) (cons "O" (list (cons "Û" "¨") ?Î)) (cons "P" ?Ï) (cons "Q" (list (cons "Ñ" "Ù") ?ß)) (cons "R" ?Ð) (cons "S" (list ; (cons "Ò" "Ö") ?Ñ)) (cons "T" ?Ò) (cons "U" (list (cons "Û" "Þ") ?Ó)) (cons "V" ?Â) (cons "W" ?Ø) (cons "X" ?Ù) (cons "Y" ?Û) (cons "Z" (list (cons "Ö" "Ù") ?Ç)) ) "Keyboard layout for entering cyrillics in cp1251 encoding on latin keyboard. See help on `cyrillic-mode-key-bindings'." ) (defvar cyrillic-mode-jcuken-kbd (list (cons "@" ?") (cons "$" ?;) (cons "%" ?:) (cons "^" ?,) (cons "&" ?.) (cons "q" ?Ê) (cons "w" ?Ã) (cons "e" ?Õ) (cons "r" ?Ë) (cons "t" ?Å) (cons "y" ?Î) (cons "u" ?Ç) (cons "i" ?Û) (cons "o" ?Ý) (cons "p" ?Ú) (cons "[" ?È) (cons "]" ?ß) (cons "Q" ?ê) (cons "W" ?ã) (cons "E" ?õ) (cons "R" ?ë) (cons "T" ?å) (cons "Y" ?î) (cons "U" ?ç) (cons "I" ?û) (cons "O" ?ý) (cons "P" ?ú) (cons "{" ?è) (cons "}" ?ÿ) (cons "a" ?Æ) (cons "s" ?Ù) (cons "d" ?×) (cons "f" ?Á) (cons "g" ?Ð) (cons "h" ?Ò) (cons "j" ?Ï) (cons "k" ?Ì) (cons "l" ?Ä) (cons ";" ?Ö) (cons "'" ?Ü) (cons "\\" ?£) (cons "A" ?æ) (cons "S" ?ù) (cons "D" ?÷) (cons "F" ?á) (cons "G" ?ð) (cons "H" ?ò) (cons "J" ?ï) (cons "K" ?ì) (cons "L" ?ä) (cons ":" ?ö) (cons "\"" ?ü) (cons "|" ?³) (cons "z" ?Ñ) (cons "x" ?Þ) (cons "c" ?Ó) (cons "v" ?Í) (cons "b" ?É) (cons "n" ?Ô) (cons "m" ?Ø) (cons "," ?Â) (cons "." ?À) (cons "Z" ?ñ) (cons "X" ?þ) (cons "C" ?ó) (cons "V" ?í) (cons "B" ?é) (cons "N" ?ô) (cons "M" ?ø) (cons "<" ?â) (cons ">" ?à)) "Russian jcuken keyboard layout. See help on `cyrillic-mode-key-bindings'.") (defvar cyrillic-mode-jcuken-cp1251-kbd (list (cons "@" ?") (cons "$" ?;) (cons "%" ?:) (cons "^" ?,) (cons "&" ?.) (cons "q" ?é) (cons "w" ?ö) (cons "e" ?ó) (cons "r" ?ê) (cons "t" ?å) (cons "y" ?í) (cons "u" ?ã) (cons "i" ?ø) (cons "o" ?ù) (cons "p" ?ç) (cons "[" ?õ) (cons "]" ?ú) (cons "Q" ?É) (cons "W" ?Ö) (cons "E" ?Ó) (cons "R" ?Ê) (cons "T" ?Å) (cons "Y" ?Í) (cons "U" ?Ã) (cons "I" ?Ø) (cons "O" ?Ù) (cons "P" ?Ç) (cons "{" ?Õ) (cons "}" ?Ú) (cons "a" ?ô) (cons "s" ?û) (cons "d" ?â) (cons "f" ?à) (cons "g" ?ï) (cons "h" ?ð) (cons "j" ?î) (cons "k" ?ë) (cons "l" ?ä) (cons ";" ?æ) (cons "'" ?ý) (cons "\\" ?¸) (cons "A" ?Ô) (cons "S" ?Û) (cons "D" ?Â) (cons "F" ?À) (cons "G" ?Ï) (cons "H" ?Ð) (cons "J" ?Î) (cons "K" ?Ë) (cons "L" ?Ä) (cons ":" ?Æ) (cons "\"" ?Ý) (cons "|" ?¨) (cons "z" ?ÿ) (cons "x" ?÷) (cons "c" ?ñ) (cons "v" ?ì) (cons "b" ?è) (cons "n" ?ò) (cons "m" ?ü) (cons "," ?á) (cons "." ?þ) (cons "Z" ?ß) (cons "X" ?×) (cons "C" ?Ñ) (cons "V" ?Ì) (cons "B" ?È) (cons "N" ?Ò) (cons "M" ?Ü) (cons "<" ?Á) (cons ">" ?Þ) ) "Russian jcuken keyboard layout for cp1251 encoding. See help on `cyrillic-mode-key-bindings'." ) (defvar cyrillic-translit-table-koi (list (cons "a" ?Á) (cons "b" ?Â) (cons "v" ?×) (cons "g" ?Ç) (cons "d" ?Ä) (cons "e" ?Å) (cons "yo" ?£) (cons "yo" ?¿); alternative placement for this letter (cons "zh" ?Ö) (cons "z" ?Ú) (cons "i" ?É) (cons "j" ?Ê) (cons "k" ?Ë) (cons "l" ?Ì) (cons "m" ?Í) (cons "n" ?Î) (cons "o" ?Ï) (cons "p" ?Ð) (cons "r" ?Ò) (cons "s" ?Ó) (cons "t" ?Ô) (cons "u" ?Õ) (cons "f" ?Æ) (cons "h" ?È) (cons "c" ?Ã) (cons "ch" ?Þ) (cons "sh" ?Û) (cons "sch" ?Ý) (cons "~" ?ß) (cons "y" ?Ù) (cons "'" ?Ø) (cons "e" ?Ü) (cons "yu" ?À) (cons "ya" ?Ñ) (cons "A" ?á) (cons "B" ?â) (cons "V" ?÷) (cons "G" ?ç) (cons "D" ?ä) (cons "E" ?å) (cons "YO" ?³) (cons "ZH" ?ö) (cons "Z" ?ú) (cons "I" ?é) (cons "J" ?ê) (cons "K" ?ë) (cons "L" ?ì) (cons "M" ?í) (cons "N" ?î) (cons "O" ?ï) (cons "P" ?ð) (cons "R" ?ò) (cons "S" ?ó) (cons "T" ?ô) (cons "U" ?õ) (cons "F" ?æ) (cons "H" ?è) (cons "C" ?ã) (cons "CH" ?þ) (cons "SH" ?û) (cons "SCH" ?ý) (cons "~" ?ÿ) (cons "Y" ?ù) (cons "'" ?ø) (cons "E" ?ü) (cons "YU" ?à) (cons "YA" ?ñ) ; Ukrainian letters can be placed differently ; This portion is courtesy Ed Ponarin (cons "ye" ?¤) ; Mykola Sereda's placement (cons "ye" ?µ) ; Vadim Kurland's placement (cons "YE" ?´) (cons "yi" ?§) ; Mykola Sereda's placement (cons "yi" ?¹) ; Vadim Kurland's placement (cons "YI" ?·) ; Mykola Sereda's placement (cons "YI" ?¸) ; Vadim Kurland's placement (cons "I" ?¦) ; *small* i as in "nich" - MS placement (cons "I" ?·) ; *small* i as in "nich" - VK placement (cons "i" ?¶) ; *LARGE* I as in "Ivan" ) "Table showing emacs how to transliterate cyrillic characters when displaying it on screen. This may differ from the key sequence you'd need to _enter_ this character. Note also that although you see latin characters on screen, there's true cyrillic within emacs. For example, if you enter `Ö' as two keystrokes `zh', you'll see them as `zh' in translit mode, but _they _are _a _single _character. For example, to delete them (it) you'll need to hit DEL only once. And if you save, send, or post it, any person with koi-8 will see the `Ö' there (assuming that 8th bit is not stripped in the process). This same table is used for destructive transliteration with the function `cyrillic-translit-region'. Edit it as you please (car of every cons cell is the transliteration, cdr is the character).") (defvar cyrillic-translit-table-1251 (list (cons "a" ?à) (cons "b" ?á) (cons "v" ?â) (cons "g" ?ã) (cons "d" ?ä) (cons "e" ?å) (cons "yo" ?¸) (cons "zh" ?æ) (cons "z" ?ç) (cons "i" ?è) (cons "j" ?é) (cons "k" ?ê) (cons "l" ?ë) (cons "m" ?ì) (cons "n" ?í) (cons "o" ?î) (cons "p" ?ï) (cons "r" ?ð) (cons "s" ?ñ) (cons "t" ?ò) (cons "u" ?ó) (cons "f" ?ô) (cons "h" ?õ) (cons "c" ?ö) (cons "ch" ?÷) (cons "sh" ?ø) (cons "sch" ?ù) (cons "~" ?ú) (cons "y" ?û) (cons "'" ?ü) (cons "e" ?ý) (cons "yu" ?þ) (cons "ya" ?ÿ) (cons "A" ?À) (cons "B" ?Á) (cons "V" ?Â) (cons "G" ?Ã) (cons "D" ?Ä) (cons "E" ?Å) (cons "YO" ?¨) (cons "ZH" ?Æ) (cons "Z" ?Ç) (cons "I" ?È) (cons "J" ?Õ) (cons "K" ?Ê) (cons "L" ?Ë) (cons "M" ?Ì) (cons "N" ?Í) (cons "O" ?Î) (cons "P" ?Ï) (cons "R" ?Ð) (cons "S" ?Ñ) (cons "T" ?Ò) (cons "U" ?Ó) (cons "F" ?Ô) (cons "H" ?Õ) (cons "C" ?Ö) (cons "CH" ?×) (cons "SH" ?Ø) (cons "SCH" ?Ù) (cons "~" ?Ú) (cons "Y" ?Û) (cons "'" ?Ü) (cons "E" ?Ý) (cons "YU" ?Þ) (cons "YA" ?ß) ) "Table showing emacs how to transliterate cyrillic characters when displaying it on screen. This may differ from the key sequence you'd need to _enter_ this character. Note also that although you see latin characters on screen, there's true cyrillic within emacs. For example, if you enter `Ö' as two keystrokes `zh', you'll see them as `zh' in translit mode, but _they _are _a _single _character. For example, to delete them (it) you'll need to hit DEL only once. And if you save, send, or post it, any person with koi-8 will see the `Ö' there (assuming that 8th bit is not stripped in the process). This same table is used for destructive transliteration with the function `cyrillic-translit-region'. Edit it as you please (car of every cons cell is the transliteration, cdr is the character).") (defvar cyrillic-translit-table cyrillic-translit-table-koi) (defvar cyrillic-hilit-highlight-face nil "*If you use hilit.el or xemacs, you can set this variable to a face (such as 'DarkGreen, or 'firebrick-underline) or a pattern (like 'active-error or 'keyword) so you can tell latin text from screen transliteration. If you use font-lock, this variable must be a face (don't forget to turn on font-lock-mode, this package does not do it).") (defvar cyrillic-kbd-list (list (cons "jcuken (standard Russian)" 'cyrillic-mode-jcuken-kbd) (cons "latin (with transliteration)" 'cyrillic-mode-latin-kbd) (cons "jcuken-cp1251 (cp1251, standard Russian)" 'cyrillic-mode-jcuken-cpp1251-kbd) (cons "latin-cp1251 (cp1251, with transliteration)" 'cyrillic-mode-latin-cp1251-kbd)) "An associative list with names and symbols for keyboard mappings. Used by the function `cyrillic-set-kbd'. If you add a new keyboard (say, Ukrainian), append it to this list to allow users to choose it.") (defvar cyrillic-translit-table-list (list (cons "koi8" 'cyrillic-translit-table-koi) (cons "win" 'cyrillic-translit-table-1251)) "An associative list with names and symbols for translit tables. Used by the function `cyrillic-set-translit-table'. If you add a new table append it to this list to allow users to choose it.") ;;;;;;;;;;;; Don't change anything below unless ;;;;;;;;;;;; you know what you're doing (defvar running-x-emacs (let ((case-fold-search t)) (and (string-match "xemacs" (emacs-version)) (fboundp 'add-spec-to-specifier) ))) (defvar cyr-font-lock-entry '("[À-ÿ][À-ÿ ,.-]*" . cyr-face)) (defun ascii-layout (&optional start stop) (interactive) (let* ((art (if start start 32)) (op (if stop stop 255)) (c art)) (while (<= c op) (insert (format "%d\t%c\n" c c)) (setq c (1+ c))))) (defvar cyrillic-mode-map (make-keymap) "Keymap for entering cyrillic on latin keyboard") (make-variable-buffer-local 'cyrillic-mode-map) (fset 'cyrillic-mode-map cyrillic-mode-map) (defvar latin-mode-map nil "Backup for restoring previous keymap") (make-variable-buffer-local 'latin-mode-map) (defvar cyrillic-mode nil "Flag to know where we are. Buffer-local.") (make-variable-buffer-local 'cyrillic-mode) (defvar cyrillic-minibuffer-mode nil "A flag. See documentation on the corresponding command.") (defvar cyrillic-mode-with-minibuffer nil "A flag for mode-line display only. Buffer-local.") (make-variable-buffer-local 'cyrillic-mode-with-minibuffer) (defvar syntax-table-modified nil) (make-variable-buffer-local 'syntax-table-modified) (defvar cyrillic-translit-mode nil "Flag to know where we are") (make-variable-buffer-local 'cyrillic-translit-mode) (defun cyrillic-translit-mode (&optional arg) "Display cyrillic letters in this buffer as combinations of latin letters, specified by cyrillic-translit-table. This affects only the display; internally emacs deals with true cyrillic symbols anyway. The command `cyrillic-translit-mode' toggles this mode without argument, and turns it on/off with positive/negative argument." (interactive "P") (if (and (not (boundp 'buffer-display-table)) (not (boundp 'current-display-table))) (error "This version of emacs does not support display tables. Sorry.") (let ((target (if (null arg) (not cyrillic-translit-mode) (> (prefix-numeric-value arg) 0)))) (if (eq target cyrillic-translit-mode) nil ; do nothing, requested state is already there (if (not (setq cyrillic-translit-mode target)) (progn (setq buffer-display-table nil) (if running-x-emacs (progn (add-spec-to-specifier current-display-table nil (current-buffer)) (setq font-lock-keywords (delq cyr-font-lock-entry font-lock-keywords)) (if font-lock-mode (font-lock-fontify-buffer)) )) (if (and (boundp 'hilit-patterns-alist) cyrillic-hilit-highlight-face) (let (patterns (cyr-pat (list 'cyrillic-hilit-find-cyr 0 cyrillic-hilit-highlight-face))) (hilit-associate 'hilit-patterns-alist major-mode (delete cyr-pat (cdr (assq major-mode hilit-patterns-alist)))) (hilit-associate 'hilit-patterns-alist 'msg-header (delete cyr-pat (cdr (assq 'msg-header hilit-patterns-alist)))) (hilit-associate 'hilit-patterns-alist 'msg-body (delete cyr-pat (cdr (assq 'msg-body hilit-patterns-alist)))) ))) (setq buffer-display-table (make-display-table)) (looplist '(lambda (pair) (aset buffer-display-table (cdr pair) (vconcat (car pair))) ) cyrillic-translit-table) (if running-x-emacs (progn (add-spec-to-specifier current-display-table buffer-display-table (current-buffer)) (if cyrillic-hilit-highlight-face (copy-face cyrillic-hilit-highlight-face 'cyr-face)) (if (not (memq cyr-font-lock-entry font-lock-keywords)) (setq font-lock-keywords (cons cyr-font-lock-entry font-lock-keywords))) (if font-lock-mode (font-lock-fontify-buffer)) )) (if (and (boundp 'hilit-patterns-alist) cyrillic-hilit-highlight-face) (let ((cyr-pat (list (list 'cyrillic-hilit-find-cyr 0 cyrillic-hilit-highlight-face))) (patterns (cdr (assq major-mode hilit-patterns-alist)))) (hilit-associate 'hilit-patterns-alist major-mode (if patterns (append patterns cyr-pat) (cons nil cyr-pat))) (hilit-associate 'hilit-patterns-alist 'msg-header (append (cdr (assq 'msg-header hilit-patterns-alist)) cyr-pat)) (hilit-associate 'hilit-patterns-alist 'msg-body (append (cdr (assq 'msg-body hilit-patterns-alist)) cyr-pat)) )) ) (redraw-display))))) (defun cyrillic-hilit-find-cyr (dummy) (let ((start (re-search-forward "[¿-ÿ³-¹£-§]" nil t)) end) (prog1 (if (null start) nil (setq end (re-search-forward "[A-z]" nil t)) (cons (1- start) (if end (1- end) (goto-char (point-max))))) (if start (message "HILIT-CYR: found block at %d - %d" (1- start) (if end (1- end) (point-max))))))) (defun looplist (func list) (let ((e list)) (while (and e (funcall func (car e))) (setq e (cdr e))))) (defun non-self-insert-command () (interactive) "Should be bound to simple key pressings" (let ((to-insert (cdr (assoc (if (fboundp 'events-to-keys) (events-to-keys (this-command-keys)) (this-command-keys)) cyrillic-mode-key-bindings)))) (if (not to-insert) (self-insert-command 1)); (this-command-keys))) (if (char-or-string-p to-insert) (insert to-insert) (looplist 'insert-depending to-insert)))) (defun insert-depending (pair) (if (char-or-string-p pair) ; we got to the last element (insert pair) (let* ((curpos (point)) (len (length (car pair)))) (if (or (<= curpos len) (not (string= (buffer-substring (- curpos len) curpos) (car pair)))) t ; return continue to looplist (delete-backward-char len) (insert (cdr pair)) nil ; return stop to looplist )))) (defun define-cyrillic-mode-key (keyfunc) (let ((rhs (cdr keyfunc))) (if (or (symbolp rhs) (and (listp rhs) (eq (car rhs) 'lambda))) (define-key cyrillic-mode-map (car keyfunc) rhs) (define-key cyrillic-mode-map (car keyfunc) 'non-self-insert-command)))) (defun do-cyrillic-mode-bindings () (mapcar (function define-cyrillic-mode-key) cyrillic-mode-key-bindings)) (defun buffer-not-for-editing () (interactive) (let* ((map (or (current-local-map) (current-global-map))) (a (lookup-key map "a"))) (if (not a) (setq map (current-global-map) a (lookup-key map "a"))) (if (eq a 'self-insert-command) nil t))) (defun cyrillic-mode (&optional arg) "Edit cyrillic text in this buffer. Use command `cyrillic-set-latin-kbd' to enter cyrillic letters as keys or key combinations of latin keyboard (default), like `ya' for the last letter of Russian alphabet. The variable `cyrillic-mode-latin-kbd' controls the mapping. Command `cyrillic-set-jcuken-kbd' allows you to use the standard Russian keyboard layout. The command `cyrillic-mode' toggles this mode without argument, and turns it on/off with positive/negative argument. This minor mode is buffer-local, so you can have cyrillic and non-cyrillic buffers simultaneously. On the other hand, since minibuffer is also a buffer, you should turn another minor mode on to have cirillic input in minibuffer. See `cyrillic-minibuffer-mode'. This has nothing to do with the ability of your screen to _display_ cyrillics. However if your emacs does not display cyrillics, you may try to type: \"M-x set-default-font RET\" and specify the name of cyrillic font on your system. You might also need to type \"M-x standard-display-european RET\", if instead of cyrillics emacs shows escaped octal numbers. Finally, if there are no cyrillic fonts installed on your system, use translit mode (command `cyrillic-translit-mode')." (interactive "P") (if (and arg (eq (> (prefix-numeric-value arg) 0) cyrillic-mode)) nil ; do nothing, requested state is already there (set-buffer-modified-p (buffer-modified-p)) ;update mode line :( (if (and (not cyrillic-mode) (or buffer-read-only (buffer-not-for-editing))) (message "Buffer %s is read-only or not for editing!" (buffer-name)) (if cyrillic-mode (restore-latin-mode) (if syntax-table-modified nil (setq syntax-table-modified t) (looplist '(lambda (pair) (modify-syntax-entry (cdr pair) "w") t) cyrillic-translit-table)) (if (and (boundp 'standard-display-table) (null standard-display-table)) (standard-display-european 1)) (setq cyrillic-mode t cyrillic-mode-with-minibuffer cyrillic-minibuffer-mode))))) (defun cyrillic-minibuffer-mode (&optional arg) "Usually you don't need cyrillics in the minibuffer, because it is used to open files and issuing commands. However you'll need it sometimes, for example to search-and-replace. Minibuffer cyrillic mode is toggled by this function without argument; turned on with positive prefix argument, and off with negative prefix argument. When minibuffer cyrillics is on, every time you enter minibuffer it is set in the same state (with respect to cyrillic input and transliteration) as the buffer you're working in: cyrillic buffer -- cyrillic minibuffer. The \C-r key toggles cyrillic mode within the minibuffer (if you need to issue a command). Normally this key means incremental search backwards, which you hardly ever need in minibuffer. The reason why it is not turned on permanently (or even by default) is that it involves some overhead every time the minibuffer is used. When this mode is on, it is indicated in mode line by Cyr/MB for cyrillic buffers, and not indicated for non-cyrillic buffers, though \\C-r works in any case." (interactive "P") (if (and arg (eq (> (prefix-numeric-value arg) 0) cyrillic-minibuffer-mode)) nil ; do nothing, requested state is already there (if cyrillic-minibuffer-mode (setq minibuffer-setup-hook (delete 'cyrillic-minibuffer-on minibuffer-setup-hook) minibuffer-exit-hook (delete 'cyrillic-minibuffer-off minibuffer-exit-hook) cyrillic-minibuffer-mode nil cyrillic-mode-with-minibuffer nil) (add-hook 'minibuffer-setup-hook 'cyrillic-minibuffer-on 'APPEND) (add-hook 'minibuffer-exit-hook 'cyrillic-minibuffer-off 'APPEND) (setq cyrillic-minibuffer-mode t cyrillic-mode-with-minibuffer cyrillic-mode)))) (defvar cyrillic-minibuffer-default-ctrl-r nil) (defun cyrillic-minibuffer-on () (let ((translit nil) (cyr nil) (pos (point))) (save-excursion (set-buffer (car (cdr (buffer-list)))) (setq translit cyrillic-translit-mode cyr cyrillic-mode)) (setq cyrillic-minibuffer-default-ctrl-r (lookup-key (current-local-map) "\C-r")) (define-key (current-local-map) "\C-r" 'cyrillic-mode) (if cyr (cyrillic-mode 1)) (if translit (cyrillic-translit-mode 1)))) (defun cyrillic-minibuffer-off () (cyrillic-mode -1) (cyrillic-translit-mode -1) (define-key (current-local-map) "\C-r" cyrillic-minibuffer-default-ctrl-r)) (defun restore-latin-mode () (interactive) (setq cyrillic-mode nil cyrillic-mode-with-minibuffer nil)) (defun cyrillic-set-translit-koi () (interactive) (setq cyrillic-translit-table cyrillic-translit-table-koi)) (defun cyrillic-set-translit-win () (interactive) (setq cyrillic-translit-table cyrillic-translit-table-1251)) (defun cyrillic-set-translit-table (&optional tbl &optional aon) (interactive) "Set keyboard layout for cyrillic mode. Without argument, ask which keyboard to choose." (let ((on (or aon cyrillic-translit-mode))) (if tbl nil (setq tbl (completing-read "Which table? (hit SPC for options): " cyrillic-translit-table-list nil t)) (setq tbl (symbol-value (cdr (assoc tbl cyrillic-translit-table-list))))) (if on (cyrillic-translit-mode -1)) (setq cyrillic-translit-table tbl) (if on (cyrillic-translit-mode 1)))) (defun cyrillic-set-latin-kbd () (interactive) "Make emacs use the table `cyrillic-mode-latin-kbd' to translate your keystrokes into cyrillic characters. For example, to enter the 7th letter of Russian alphabet, type `yo' (or whatever the table contains)" (cyrillic-set-kbd cyrillic-mode-latin-kbd)) (defun cyrillic-set-jcuken-kbd () (interactive) "Make emacs use the table `cyrillic-mode-jcuken-kbd' to translate your keystrokes into cyrillic characters. For example, to enter the 7th letter of Russian alphabet, type backslash (or whatever key it is currently mapped to, according to the table)" (cyrillic-set-kbd cyrillic-mode-jcuken-kbd)) (defun cyrillic-set-kbd (&optional kbd) (interactive) "Set keyboard layout for cyrillic mode. Without argument, ask which keyboard to choose." (let ((on cyrillic-mode)) (if kbd nil (setq kbd (completing-read "Which keyboard? (hit SPC for options): " cyrillic-kbd-list nil t)) (setq kbd (symbol-value (cdr (assoc kbd cyrillic-kbd-list))))) (if on (cyrillic-mode -1)) (setq cyrillic-mode-key-bindings kbd) (do-cyrillic-mode-bindings) (if on (cyrillic-mode 1)))) (defun cyrillic-translit-region (BEG END) (interactive "r") "Destructively replace all cyrillic characters in the region with their transliteration, according to the variable `cyrillic-translit-table'. Leaves pointer at the end of region." (let (tr (e END)) (goto-char BEG) (while (< (point) e) (setq tr (rassq (char-after (point)) cyrillic-translit-table)) (if (null tr) (forward-char 1) (delete-char 1) (insert (car tr)) (setq e (+ e (1- (length (car tr)))))) ) (goto-char e))) (or (assq 'cyrillic-translit-mode minor-mode-alist) (setq minor-mode-alist (cons '(cyrillic-translit-mode " Translit") minor-mode-alist))) (or (assq 'cyrillic-mode-with-minibuffer minor-mode-alist) (setq minor-mode-alist (cons '(cyrillic-mode-with-minibuffer "/MB") minor-mode-alist))) (or (assq 'cyrillic-mode minor-mode-alist) (setq minor-mode-alist (cons '(cyrillic-mode " Cyr") minor-mode-alist))) (or (assq 'cyrillic-mode minor-mode-map-alist) (setq minor-mode-map-alist (cons '(cyrillic-mode . cyrillic-mode-map) minor-mode-map-alist))) (setq cyrillic-mode-key-bindings cyrillic-mode-latin-kbd) (do-cyrillic-mode-bindings)