view lisp/mule/viet-util.el @ 5882:bbe4146603db

Reduce regexp usage, now CL-oriented non-regexp code available, core Lisp lisp/ChangeLog addition: 2015-04-01 Aidan Kehoe <kehoea@parhasard.net> When calling #'string-match with a REGEXP without regular expression special characters, call #'search, #'mismatch, #'find, etc. instead, making our code less likely to side-effect other functions' match data and a little faster. * apropos.el (apropos-command): * apropos.el (apropos): Call (position ?\n ...) rather than (string-match "\n" ...) here. * buff-menu.el: * buff-menu.el (buffers-menu-omit-invisible-buffers): Don't fire up the regexp engine just to check if a string starts with a space. * buff-menu.el (select-buffers-tab-buffers-by-mode): Don't fire up the regexp engine just to compare mode basenames. * buff-menu.el (format-buffers-tab-line): * buff-menu.el (build-buffers-tab-internal): Moved to being a label within the following. * buff-menu.el (buffers-tab-items): Use the label. * bytecomp.el (byte-compile-log-1): Don't fire up the regexp engine just to look for a newline. * cus-edit.el (get): Ditto. * cus-edit.el (custom-variable-value-create): Ditto, but for a colon. * descr-text.el (describe-text-sexp): Ditto. * descr-text.el (describe-char-unicode-data): Use #'split-string-by-char given that we're just looking for a semicolon. * descr-text.el (describe-char): Don't fire up the regexp engine just to look for a newline. * disass.el (disassemble-internal): Ditto. * files.el (file-name-sans-extension): Implement this using #'position. * files.el (file-name-extension): Correct this function's docstring, implement it in terms of #'position. * files.el (insert-directory): Don't fire up the regexp engine to split a string by space; don't reverse the list of switches, this is actually a longstand bug as far as I can see. * gnuserv.el (gnuserv-process-filter): Use #'position here, instead of consing inside #'split-string needlessly. * gtk-file-dialog.el (gtk-file-dialog-update-dropdown): Use #'split-string-by-char here, don't fire up #'split-string for directory-sep-char. * gtk-font-menu.el (hack-font-truename): Implement this more cheaply in terms of #'find, #'split-string-by-char, #'equal, rather than #'string-match, #'split-string, #'string-equal. * hyper-apropos.el (hyper-apropos-grok-functions): * hyper-apropos.el (hyper-apropos-grok-variables): Look for a newline using #'position rather than #'string-match in these functions. * info.el (Info-insert-dir): * info.el (Info-insert-file-contents): * info.el (Info-follow-reference): * info.el (Info-extract-menu-node-name): * info.el (Info-menu): Look for fixed strings using #'position or #'search as appropriate in this file. * ldap.el (ldap-decode-string): * ldap.el (ldap-encode-string): #'encode-coding-string, #'decode-coding-string are always available, don't check if they're fboundp. * ldap.el (ldap-decode-address): * ldap.el (ldap-encode-address): Use #'split-string-by-char in these functions. * lisp-mnt.el (lm-creation-date): * lisp-mnt.el (lm-last-modified-date): Don't fire up the regexp engine just to look for spaces in this file. * menubar-items.el (default-menubar): Use (not (mismatch ...)) rather than #'string-match here, for simple regexp. Use (search "beta" ...) rather than (string-match "beta" ...) * menubar-items.el (sort-buffers-menu-alphabetically): * menubar-items.el (sort-buffers-menu-by-mode-then-alphabetically): * menubar-items.el (group-buffers-menu-by-mode-then-alphabetically): Don't fire up the regexp engine to check if a string starts with a space or an asterisk. Use the more fine-grained results of #'compare-strings; compare case-insensitively for the buffer menu. * menubar-items.el (list-all-buffers): * menubar-items.el (tutorials-menu-filter): Use #'equal rather than #'string-equal, which, in this context, has the drawback of not having a bytecode, and no redeeming features. * minibuf.el: * minibuf.el (un-substitute-in-file-name): Use #'count, rather than counting the occurences of $ using the regexp engine. * minibuf.el (read-file-name-internal-1): Don't fire up the regexp engine to search for ?=. * mouse.el (mouse-eval-sexp): Check for newline with #'find. * msw-font-menu.el (mswindows-reset-device-font-menus): Split a string by newline with #'split-string-by-char. * mule/japanese.el: * mule/japanese.el ("Japanese"): Use #'search rather than #'string-match; canoncase before comparing; fix a bug I had introduced where I had been making case insensitive comparisons where the case mattered. * mule/korea-util.el (default-korean-keyboard): Look for ?3 using #'find, not #'string-march. * mule/korea-util.el (quail-hangul-switch-hanja): Search for a fixed string using #'search. * mule/mule-cmds.el (set-locale-for-language-environment): #'position, #'substitute rather than #'string-match, #'replace-in-string. * newcomment.el (comment-make-extra-lines): Use #'search rather than #'string-match for a simple string. * package-get.el (package-get-remote-filename): Use #'position when looking for ?@ * process.el (setenv): * process.el (read-envvar-name): Use #'position when looking for ?=. * replace.el (map-query-replace-regexp): Use #'split-string-by-char instead of using an inline implementation of it. * select.el (select-convert-from-cf-text): * select.el (select-convert-from-cf-unicodetext): Use #'position rather than #'string-match in these functions. * setup-paths.el (paths-emacs-data-root-p): Use #'search when looking for simple string. * sound.el (load-sound-file): Use #'split-string-by-char rather than an inline reimplementation of same. * startup.el (splash-screen-window-body): * startup.el (splash-screen-tty-body): Search for simple strings using #'search. * version.el (emacs-version): Ditto. * x-font-menu.el (hack-font-truename): Implement this more cheaply in terms of #'find, #'split-string-by-char, #'equal, rather than #'string-match, #'split-string, #'string-equal. * x-font-menu.el (x-reset-device-font-menus-core): Use #'split-string-by-char here. * x-init.el (x-initialize-keyboard): Search for a simple string using #'search.
author Aidan Kehoe <kehoea@parhasard.net>
date Wed, 01 Apr 2015 14:28:20 +0100
parents ac37a5f7e5be
children
line wrap: on
line source

;;; viet-util.el --- utilities for Vietnamese  -*- coding: iso-2022-7bit; -*-

;; Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
;; Copyright (C) 2002 Ben Wing.
;; Licensed to the Free Software Foundation.

;; Keywords: mule, multilingual, Vietnamese

;; This file is part of XEmacs.

;; XEmacs is free software: you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by the
;; Free Software Foundation, either version 3 of the License, or (at your
;; option) any later version.

;; XEmacs is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
;; for more details.

;; You should have received a copy of the GNU General Public License
;; along with XEmacs.  If not, see <http://www.gnu.org/licenses/>.

;;; Synched up with: Emacs 21.1 (language/viet-util.el).

;;; Commentary:

;; Vietnamese uses ASCII characters and additional 134 unique
;; characters (these are Latin alphabets with various diacritical and
;; tone marks).  As far as I know, Vietnamese now has 4 different ways
;; for representing these characters: VISCII, VSCII, VIQR, and
;; Unicode.  VISCII and VSCII are simple 1-byte code which assigns 134
;; unique characters in control-code area (0x00..0x1F) and right half
;; area (0x80..0xFF).  VIQR is a menmonic encoding specification
;; representing diacritical marks by following ASCII characters.

;;; Code:

;;;###autoload
(defun viet-encode-viscii-char (char)
  "Return VISCII character code of CHAR if appropriate."
  (check-argument-type #'characterp char)
  (if (eq char ?~)
      char
    (setq char (encode-coding-string char 'viscii))
    (if (and (eql 1 (length char))
	     (not (eql (aref char 0) ?~)))
	(aref char 0))))

;; VIQR is a menmonic encoding specification for Vietnamese.
;; It represents diacritical marks by ASCII characters as follows:
;; ------------+----------+--------
;;     mark    | mnemonic | example
;; ------------+----------+---------
;;    breve    |    (     | a( -> ,1e(B
;;  circumflex |    ^     | a^ -> ,1b(B
;;    horn     |    +     | o+ -> ,1=(B
;; ------------+----------+---------
;;    acute    |    '     | a' -> ,1a(B
;;    grave    |    `     | a` -> ,1`(B
;;  hook above |    ?     | a? -> ,1d(B
;;    tilde    |    ~     | a~ -> ,1c(B
;;   dot below |    .     | a. -> ,1U(B
;; ------------+----------+---------
;;    d bar    |   dd     | dd -> ,1p(B
;; ------------+----------+---------

(defvar viet-viqr-alist
  '(;; lowercase
    (?,1!(B . "a('")			; 161
    (?,1"(B . "a(`")			; 162
    (?,1#(B . "a(.")			; 163
    (?,1$(B . "a^'")			; 164
    (?,1%(B . "a^`")			; 165
    (?,1&(B . "a^?")			; 166
    (?,1'(B . "a^.")			; 167
    (?,1((B . "e~")				; 168
    (?,1)(B . "e.")				; 169
    (?,1*(B . "e^'")			; 170
    (?,1+(B . "e^`")			; 171
    (?,1,(B . "e^?")			; 172
    (?,1-(B . "e^~")			; 173
    (?,1.(B . "e^.")			; 174
    (?,1/(B . "o^'")			; 175
    (?,10(B . "o^`")			; 176
    (?,11(B . "o^?")			; 177
    (?,12(B . "o^~")			; 178
    (?,15(B . "o^.")			; 181
    (?,16(B . "o+`")			; 182
    (?,17(B . "o+?")			; 183
    (?,18(B . "i.")				; 184
    (?,1=(B . "o+")				; 189
    (?,1>(B . "o+'")			; 190
    (?,1F(B . "a(?")			; 198
    (?,1G(B . "a(~")			; 199
    (?,1O(B . "y`")				; 207
    (?,1Q(B . "u+'")			; 209
    (?,1U(B . "a.")				; 213
    (?,1V(B . "y?")				; 214
    (?,1W(B . "u+`")			; 215
    (?,1X(B . "u+?")			; 216
    (?,1[(B . "y~")				; 219
    (?,1\(B . "y.")				; 220
    (?,1^(B . "o+~")			; 222
    (?,1_(B . "u+")				; 223
    (?,1`(B . "a`")				; 224
    (?,1a(B . "a'")				; 225
    (?,1b(B . "a^")				; 226
    (?,1c(B . "a~")				; 227
    (?,1d(B . "a?")				; 228
    (?,1e(B . "a(")				; 229
    (?,1f(B . "u+~")			; 230
    (?,1g(B . "a^~")			; 231
    (?,1h(B . "e`")				; 232
    (?,1i(B . "e'")				; 233
    (?,1j(B . "e^")				; 234
    (?,1k(B . "e?")				; 235
    (?,1l(B . "i`")				; 236
    (?,1m(B . "i'")				; 237
    (?,1n(B . "i~")				; 238
    (?,1o(B . "i?")				; 239
    (?,1p(B . "dd")				; 240
    (?,1q(B . "u+.")			; 241
    (?,1r(B . "o`")				; 242
    (?,1s(B . "o'")				; 243
    (?,1t(B . "o^")				; 244
    (?,1u(B . "o~")				; 245
    (?,1v(B . "o?")				; 246
    (?,1w(B . "o.")				; 247
    (?,1x(B . "u.")				; 248
    (?,1y(B . "u`")				; 249
    (?,1z(B . "u'")				; 250
    (?,1{(B . "u~")				; 251
    (?,1|(B . "u?")				; 252
    (?,1}(B . "y'")				; 253
    (?,1~(B . "o+.")			; 254

    ;; upper case
    (?,2!(B . "A('")			; 161
    (?,2"(B . "A(`")			; 162
    (?,2#(B . "A(.")			; 163
    (?,2$(B . "A^'")			; 164
    (?,2%(B . "A^`")			; 165
    (?,2&(B . "A^?")			; 166
    (?,2'(B . "A^.")			; 167
    (?,2((B . "E~")				; 168
    (?,2)(B . "E.")				; 169
    (?,2*(B . "E^'")			; 170
    (?,2+(B . "E^`")			; 171
    (?,2,(B . "E^?")			; 172
    (?,2-(B . "E^~")			; 173
    (?,2.(B . "E^.")			; 174
    (?,2/(B . "O^'")			; 175
    (?,20(B . "O^`")			; 176
    (?,21(B . "O^?")			; 177
    (?,22(B . "O^~")			; 178
    (?,25(B . "O^.")			; 181
    (?,26(B . "O+`")			; 182
    (?,27(B . "O+?")			; 183
    (?,28(B . "I.")				; 184
    (?,2=(B . "O+")				; 189
    (?,2>(B . "O+'")			; 190
    (?,2F(B . "A(?")			; 198
    (?,2G(B . "A(~")			; 199
    (?,2O(B . "Y`")				; 207
    (?,2Q(B . "U+'")			; 209
    (?,2U(B . "A.")				; 213
    (?,2V(B . "Y?")				; 214
    (?,2W(B . "U+`")			; 215
    (?,2X(B . "U+?")			; 216
    (?,2[(B . "Y~")				; 219
    (?,2\(B . "Y.")				; 220
    (?,2^(B . "O+~")			; 222
    (?,2_(B . "U+")				; 223
    (?,2`(B . "A`")				; 224
    (?,2a(B . "A'")				; 225
    (?,2b(B . "A^")				; 226
    (?,2c(B . "A~")				; 227
    (?,2d(B . "A?")				; 228
    (?,2e(B . "A(")				; 229
    (?,2f(B . "U+~")			; 230
    (?,2g(B . "A^~")			; 231
    (?,2h(B . "E`")				; 232
    (?,2i(B . "E'")				; 233
    (?,2j(B . "E^")				; 234
    (?,2k(B . "E?")				; 235
    (?,2l(B . "I`")				; 236
    (?,2m(B . "I'")				; 237
    (?,2n(B . "I~")				; 238
    (?,2o(B . "I?")				; 239
    (?,2p(B . "DD")				; 240
    (?,2p(B . "dD")				; 240
    (?,2p(B . "Dd")				; 240
    (?,2q(B . "U+.")			; 241
    (?,2r(B . "O`")				; 242
    (?,2s(B . "O'")				; 243
    (?,2t(B . "O^")				; 244
    (?,2u(B . "O~")				; 245
    (?,2v(B . "O?")				; 246
    (?,2w(B . "O.")				; 247
    (?,2x(B . "U.")				; 248
    (?,2y(B . "U`")				; 249
    (?,2z(B . "U'")				; 250
    (?,2{(B . "U~")				; 251
    (?,2|(B . "U?")				; 252
    (?,2}(B . "Y'")				; 253
    (?,2~(B . "O+.")			; 254

    ;; escape from composition
    (?\( . "\\(")			; breve (left parenthesis)
    (?^ . "\\^")			; circumflex (caret)
    (?+ . "\\+")			; horn (plus sign)
    (?' . "\\'")			; acute (apostrophe)
    (?` . "\\`")			; grave (backquote)
    (?? . "\\?")			; hook above (question mark)
    (?~ . "\\~")			; tilde (tilde)
    (?. . "\\.")			; dot below (period)
    (?d . "\\d")			; d-bar (d)
    (?\\ . "\\\\")			; literal backslash
    )
  "Alist of Vietnamese characters vs corresponding `VIQR' string.")

;; Regular expression matching single Vietnamese character represented
;; by VIQR.
(defconst viqr-regexp
  "[aeiouyAEIOUY]\\([(^+]?['`?~.]\\|[(^+]\\)\\|[Dd][Dd]")

;;;###autoload
(defun viet-decode-viqr-region (from to)
  "Convert `VIQR' mnemonics of the current region to Vietnamese characters.
When called from a program, expects two arguments,
positions (integers or markers) specifying the stretch of the region."
  (interactive "r")
  (save-restriction
    (narrow-to-region from to)
    (goto-char (point-min))
    (while (re-search-forward viqr-regexp nil t)
      (let* ((viqr (buffer-substring (match-beginning 0) (match-end 0)))
	     (ch (car (rassoc viqr viet-viqr-alist))))
	(if ch
	    (progn
	      (delete-region (match-beginning 0) (match-end 0))
	      (insert ch)))))))

;;;###autoload
(defun viet-decode-viqr-buffer ()
  "Convert `VIQR' mnemonics of the current buffer to Vietnamese characters."
  (interactive)
  (viet-decode-viqr-region (point-min) (point-max)))

;;;###autoload
(defun viet-encode-viqr-region (from to)
  "Convert Vietnamese characters of the current region to `VIQR' mnemonics.
When called from a program, expects two arguments,
positions (integers or markers) specifying the stretch of the region."
  (interactive "r")
  (save-restriction
    (narrow-to-region from to)
    (goto-char (point-min))
    (while (re-search-forward "\\cv" nil t)
      (let* ((ch (preceding-char))
	     (viqr (cdr (assq ch viet-viqr-alist))))
	(if viqr
	    (progn
	      (delete-char -1)
	      (insert viqr)))))))

;;;###autoload
(defun viet-encode-viqr-buffer ()
  "Convert Vietnamese characters of the current buffer to `VIQR' mnemonics."
  (interactive)
  (viet-encode-viqr-region (point-min) (point-max)))

;;;###autoload
(defun viqr-post-read-conversion (len)
  (save-excursion
    (save-restriction
      (narrow-to-region (point) (+ (point) len))
      (let ((buffer-modified-p (buffer-modified-p)))
	(viet-decode-viqr-region (point-min) (point-max))
	(set-buffer-modified-p buffer-modified-p)
	(- (point-max) (point-min))))))

;;;###autoload
(defun viqr-pre-write-conversion (from to)
  (let ((old-buf (current-buffer)))
    (set-buffer (generate-new-buffer " *temp*"))
    (if (stringp from)
	(insert from)
      (insert-buffer-substring old-buf from to))
    (viet-encode-viqr-region (point-min) (point-max))
    ;; Should return nil as annotations.
    nil))

;;;
(provide 'viet-util)

;;; viet-util.el ends here