aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenichi Handa1998-02-04 11:25:47 +0000
committerKenichi Handa1998-02-04 11:25:47 +0000
commit1375754c3426086758a8050c2ed2bdb55c45d82e (patch)
tree03b7c369a46efba8d02c75b496e9f5acb987c962
parent27463edec5045d1b178abbdd5617994cfad08c60 (diff)
downloademacs-1375754c3426086758a8050c2ed2bdb55c45d82e.tar.gz
emacs-1375754c3426086758a8050c2ed2bdb55c45d82e.zip
Many codes re-written to adjust for
character-base positioning and for speed up by using with-temp-file, with-temp-buffer, and princ.
-rw-r--r--lisp/international/titdic-cnv.el381
1 files changed, 177 insertions, 204 deletions
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index ce5890f34ae..450400af021 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -96,8 +96,8 @@
96 (concat (file-name-nondirectory (substring filename 0 -4)) ".el") 96 (concat (file-name-nondirectory (substring filename 0 -4)) ".el")
97 dirname)) 97 dirname))
98 98
99;; This value is t if we are processing phrase dictionary. 99;; This value is nil if we are processing phrase dictionary.
100(defvar tit-phrase nil) 100(defconst tit-dictionary t)
101(defvar tit-encode nil) 101(defvar tit-encode nil)
102(defvar tit-default-encode "GB") 102(defvar tit-default-encode "GB")
103 103
@@ -106,18 +106,22 @@
106(defun tit-generate-key-bindings (keys function-symbol) 106(defun tit-generate-key-bindings (keys function-symbol)
107 (let ((len (length keys)) 107 (let ((len (length keys))
108 (i 0) 108 (i 0)
109 (first t)
109 key) 110 key)
110 (while (< i len) 111 (while (< i len)
112 (or first (princ "\n "))
111 (setq key (aref keys i)) 113 (setq key (aref keys i))
112 (indent-to 3) 114 (if (if (< key ?\ )
113 (if (< key ?\ ) 115 (eq (lookup-key quail-translation-keymap
114 (if (eq (lookup-key quail-translation-keymap (char-to-string key)) 116 (char-to-string key))
115 'quail-execute-non-quail-command) 117 'quail-execute-non-quail-command)
116 (insert (format "(\"\\C-%c\" . %s)\n" 118 (<= key 127))
117 (+ key ?@) function-symbol))) 119 (progn
118 (if (< key 127) 120 (princ (cons (cond ((< key ?\ ) (format "\"\\C-%c\"" (+ key ?@)))
119 (insert (format "(\"%c\" . %s)\n" key function-symbol)) 121 ((< key 127) (format "\"%c\"" key))
120 (insert (format "(\"\\C-?\" . %s)\n" function-symbol)))) 122 (t "\"\\C-?\""))
123 function-symbol))
124 (setq first nil)))
121 (setq i (1+ i))))) 125 (setq i (1+ i)))))
122 126
123;; Analyze header part of TIT dictionary and generate an appropriate 127;; Analyze header part of TIT dictionary and generate an appropriate
@@ -126,7 +130,13 @@
126 (message "Processing header part...") 130 (message "Processing header part...")
127 (goto-char (point-min)) 131 (goto-char (point-min))
128 132
129 (let (;; TIT keywords and the corresponding default values. 133 ;; At first, generate header part of the Quail package while
134 ;; collecting information from the original header.
135 (let ((package (concat
136 "chinese-"
137 (substring (downcase (file-name-nondirectory filename))
138 0 -4)))
139 ;; TIT keywords and the corresponding default values.
130 (tit-multichoice t) 140 (tit-multichoice t)
131 (tit-prompt "") 141 (tit-prompt "")
132 (tit-comments nil) 142 (tit-comments nil)
@@ -135,18 +145,24 @@
135 (tit-moveright ".>") 145 (tit-moveright ".>")
136 (tit-moveleft ",<") 146 (tit-moveleft ",<")
137 (tit-keyprompt nil)) 147 (tit-keyprompt nil))
138 ;; At first, collect information from the header. 148
149 (princ ";; Quail package `")
150 (princ package)
151 (princ "' generated by the command `titdic-convert'\n;;\tDate: ")
152 (princ (current-time-string))
153 (princ "\n;;\tOriginal TIT dictionary file: ")
154 (princ (file-name-nondirectory filename))
155 (princ "\n\n;;; Comment:\n\n")
156 (princ ";; Do byte-compile this file again after any modification.\n\n")
157 (princ ";;; Start of the header of original TIT dictionary.\n\n")
158
139 (while (not (eobp)) 159 (while (not (eobp))
140 (insert ";; ") 160 (let ((ch (following-char))
141 (let ((ch (following-char))) 161 (pos (point)))
142 (cond ((= ch ?C) ; COMMENT 162 (cond ((= ch ?C) ; COMMENT
143 (cond ((looking-at "COMMENT") 163 (cond ((looking-at "COMMENT")
144 (let ((pos (match-end 0))) 164 (let ((pos (match-end 0)))
145 (end-of-line) 165 (end-of-line)
146 (while (re-search-backward "[\"\\]" pos t)
147 (insert "\\")
148 (forward-char -1))
149 (end-of-line)
150 (setq tit-comments (cons (buffer-substring pos (point)) 166 (setq tit-comments (cons (buffer-substring pos (point))
151 tit-comments)))))) 167 tit-comments))))))
152 ((= ch ?M) ; MULTICHOICE, MOVERIGHT, MOVELEFT 168 ((= ch ?M) ; MULTICHOICE, MOVERIGHT, MOVELEFT
@@ -169,9 +185,9 @@
169 (goto-char (match-end 0)) 185 (goto-char (match-end 0))
170 (setq tit-backspace (tit-read-key-value))) 186 (setq tit-backspace (tit-read-key-value)))
171 ((looking-at "BEGINDICTIONARY") 187 ((looking-at "BEGINDICTIONARY")
172 (setq tit-phrase nil)) 188 (setq tit-dictionary t))
173 ((looking-at "BEGINPHRASE") 189 ((looking-at "BEGINPHRASE")
174 (setq tit-phrase t)))) 190 (setq tit-dictionary nil))))
175 ((= ch ?K) ; KEYPROMPT 191 ((= ch ?K) ; KEYPROMPT
176 (cond ((looking-at "KEYPROMPT(\\(.*\\)):[ \t]*") 192 (cond ((looking-at "KEYPROMPT(\\(.*\\)):[ \t]*")
177 (let ((key-char (match-string 1))) 193 (let ((key-char (match-string 1)))
@@ -182,162 +198,132 @@
182 key-char))))) 198 key-char)))))
183 (setq tit-keyprompt 199 (setq tit-keyprompt
184 (cons (cons key-char (tit-read-key-value)) 200 (cons (cons key-char (tit-read-key-value))
185 tit-keyprompt)))))))) 201 tit-keyprompt)))))))
186 (forward-line 1)) 202 (end-of-line)
203 (princ ";; ")
204 (princ (buffer-substring pos (point)))
205 (princ "\n")
206 (forward-line 1)))
187 207
188 ;; Then, generate header part of the Quail package. 208 (princ "\n;;; End of the header of original TIT dictionary.\n\n")
189 (goto-char (point-min)) 209 (princ ";;; Code:\n\n(require 'quail)\n\n")
190 (let ((package 210
191 (concat 211 (princ "(quail-define-package ")
192 "chinese-" 212 ;; Args NAME, LANGUAGE, TITLE
193 (substring (downcase (file-name-nondirectory buffer-file-name)) 213 (let ((title (cdr (assoc package quail-cxterm-package-title-alist))))
194 0 -3)))) 214 (princ "\"")
195 (insert ";; Quail package `" 215 (princ package)
196 package 216 (princ "\" \"")
197 "' generated by the command `titdic-convert'\n" 217 (princ (nth 2 (assoc tit-encode tit-encode-list)))
198 ";;\tDate: " (current-time-string) "\n" 218 (princ "\" \"")
199 ";;\tOriginal TIT dictionary file: " 219 (princ (or title
200 (file-name-nondirectory filename) 220 (if (string-match "[:$A!K$(0!(!J(B]+\\([^:$A!K$(0!(!K(B]+\\)" tit-prompt)
201 "\n\n" 221 (substring tit-prompt (match-beginning 1) (match-end 1))
202 ";;; Comment:\n\n" 222 tit-prompt)))
203 ";; Do byte-compile this file again after any modification.\n\n" 223 (princ "\"\n"))
204 ";;; Start of the header of original TIT dictionary.\n\n")
205
206 (goto-char (point-max))
207 (insert "\n"
208 ";;; End of the header of original TIT dictionary.\n\n"
209 ";;; Code:\n\n"
210 "(require 'quail)\n\n")
211
212 (insert "(quail-define-package ")
213 ;; Args NAME, LANGUAGE, TITLE
214 (let ((title (cdr (assoc package quail-cxterm-package-title-alist))))
215 (insert
216 "\""
217 package
218 "\" \"" (nth 2 (assoc tit-encode tit-encode-list))
219 "\" \""
220 (or title
221 (if (string-match "[:$A!K$(0!(!J(B]+\\([^:$A!K$(0!(!K(B]+\\)" tit-prompt)
222 (substring tit-prompt (match-beginning 1) (match-end 1))
223 tit-prompt))
224 "\"\n"))
225 )
226 224
227 ;; Arg GUIDANCE 225 ;; Arg GUIDANCE
228 (if tit-keyprompt 226 (if tit-keyprompt
229 (progn 227 (progn
230 (insert " '(") 228 (princ " '(")
231 (while tit-keyprompt 229 (while tit-keyprompt
232 (indent-to 3) 230 (princ " ")
233 (insert (format "(%d . \"%s\")\n" 231 (princ (format "(%d . \"%s\")\n"
234 (string-to-char (car (car tit-keyprompt))) 232 (string-to-char (car (car tit-keyprompt)))
235 (cdr (car tit-keyprompt)))) 233 (cdr (car tit-keyprompt))))
236 (setq tit-keyprompt (cdr tit-keyprompt))) 234 (setq tit-keyprompt (cdr tit-keyprompt)))
237 (forward-char -1) 235 (princ ")"))
238 (insert ")") 236 (princ " t\n"))
239 (forward-char 1))
240 (insert " t\n"))
241 237
242 ;; Arg DOCSTRING 238 ;; Arg DOCSTRING
243 (insert "\"" tit-prompt "\n") 239 (prin1
244 (let ((l (nreverse tit-comments))) 240 (mapconcat 'identity (cons tit-prompt (nreverse tit-comments)) "\n"))
245 (while l 241 (terpri)
246 (insert (format "%s\n" (car l)))
247 (setq l (cdr l))))
248 (insert "\"\n")
249 242
250 ;; Arg KEY-BINDINGS 243 ;; Arg KEY-BINDINGS
251 (insert " '(") 244 (princ " '(")
252 (tit-generate-key-bindings tit-backspace 'quail-delete-last-char) 245 (tit-generate-key-bindings tit-backspace 'quail-delete-last-char)
246 (princ "\n ")
253 (tit-generate-key-bindings tit-deleteall 'quail-abort-translation) 247 (tit-generate-key-bindings tit-deleteall 'quail-abort-translation)
248 (princ "\n ")
254 (tit-generate-key-bindings tit-moveright 'quail-next-translation) 249 (tit-generate-key-bindings tit-moveright 'quail-next-translation)
250 (princ "\n ")
255 (tit-generate-key-bindings tit-moveleft 'quail-prev-translation) 251 (tit-generate-key-bindings tit-moveleft 'quail-prev-translation)
256 (forward-char -1) 252 (princ ")\n")
257 (insert ")")
258 (forward-char 1)
259 253
260 ;; Args FORGET-TRANSLATION, DETERMINISTIC, KBD-TRANSLATE, SHOW-LAYOUT. 254 ;; Args FORGET-TRANSLATION, DETERMINISTIC, KBD-TRANSLATE, SHOW-LAYOUT.
261 ;; The remaining args are all nil. 255 ;; The remaining args are all nil.
262 (insert " nil" 256 (princ " nil")
263 (if tit-multichoice " nil" " t") 257 (princ (if tit-multichoice " nil" " t"))
264 (if tit-keyprompt " t t)\n\n" " nil nil)\n\n"))) 258 (princ (if tit-keyprompt " t t)\n\n" " nil nil)\n\n"))))
265 259
266 ;; Return the position of end of the header. 260(defsubst tit-flush-translations (key translations)
267 (point-max)) 261 (if (string-match "\\\\[0-9][0-9][0-9]" key)
262 (let ((newkey (concat (substring key 0 (match-beginning 0))
263 (car (read-from-string
264 (concat "\"" (match-string 0 key) "\"")))))
265 (idx (match-end 0)))
266 (while (string-match "\\\\[0-9][0-9][0-9]" key idx)
267 (setq newkey (concat
268 newkey
269 (substring key idx (match-beginning 0))
270 (car (read-from-string
271 (concat "\"" (match-string 0 key) "\"")))))
272 (setq idx (match-end 0)))
273 (setq key (concat newkey (substring key idx)))))
274 (prin1 (list key (if tit-dictionary translations
275 (vconcat (nreverse translations)))))
276 (princ "\n"))
268 277
269;; Convert body part of TIT dictionary into `quail-define-rules' 278;; Convert body part of TIT dictionary into `quail-define-rules'
270;; function call. 279;; function call.
271(defun tit-process-body () 280(defun tit-process-body ()
272 (message "Formatting translation rules...") 281 (message "Formatting translation rules...")
273 (let ((keyseq "\000") 282 (let* ((template (list nil nil))
274 pos) 283 (second (cdr template))
275 (insert "(quail-define-rules\n") 284 (prev-key "")
285 ch key translations pos)
286 (princ "(quail-define-rules\n")
276 (while (null (eobp)) 287 (while (null (eobp))
277 (if (or (= (following-char) ?#) (= (following-char) ?\n)) 288 (setq ch (following-char))
278 (progn 289 (if (or (= ch ?#) (= ch ?\n))
279 (insert ";; ") 290 (forward-line 1)
280 (forward-line 1))
281 (insert "(\"")
282 (setq pos (point)) 291 (setq pos (point))
283 (skip-chars-forward "^ \t") 292 (skip-chars-forward "^ \t\n")
284 (setq keyseq 293 (setq key (buffer-substring pos (point)))
285 (concat (regexp-quote (buffer-substring pos (point))) "[ \t]+"))
286 (save-excursion
287 ;; Escape `"' and `\' which is not used for quoting the
288 ;; following octal digits.
289 (while (re-search-backward "\"\\|\\\\[^0-9]" pos t)
290 (insert "\\")
291 (forward-char -1)))
292 (insert "\"")
293 (skip-chars-forward " \t") 294 (skip-chars-forward " \t")
294 295 (setq ch (following-char))
295 ;; Now point is at the start of translations. Remember it in 296 (if (or (= ch ?#) (= ch ?\n))
296 ;; POS and combine lines of the same key sequence while
297 ;; deleting trailing white spaces and comments (start with
298 ;; '#'). POS doesn't has to be a marker because we never
299 ;; modify region before POS.
300 (setq pos (point))
301 (if (looking-at "[^ \t]*\\([ \t]*#.*\\)")
302 (delete-region (match-beginning 1) (match-end 1)))
303 (while (and (= (forward-line 1) 0)
304 (looking-at keyseq))
305 (let ((p (match-end 0)))
306 (skip-chars-backward " \t\n")
307 (delete-region (point) p)
308 (if tit-phrase (insert " "))
309 (if (looking-at "[^ \t]*\\([ \t]*#.*\\)")
310 (delete-region (match-beginning 1) (match-end 1)))
311 ))
312
313 (goto-char pos)
314 (if (eolp)
315 ;; This entry contains no translations. Let's ignore it. 297 ;; This entry contains no translations. Let's ignore it.
316 (progn 298 (forward-line 1)
317 (beginning-of-line) 299 (or (string= key prev-key)
318 (setq pos (point))
319 (forward-line 1)
320 (delete-region pos (point)))
321
322 ;; Modify the current line to meet the syntax of Quail package.
323 (if tit-phrase
324 (progn 300 (progn
325 ;; PHRASE1 PHRASE2 ... => ["PHRASE1" "PHRASE2" ...] 301 (if translations
326 (insert "[") 302 (tit-flush-translations prev-key translations))
327 (skip-chars-forward " \t") 303 (setq translations nil
328 (while (not (eolp)) 304 prev-key key)))
329 (insert "\"") 305 (if tit-dictionary
330 (skip-chars-forward "^ \t\n") 306 (progn
331 (insert "\"") 307 (setq pos (point))
332 (skip-chars-forward " \t")) 308 (skip-chars-forward "^ \t#\n")
333 (insert "])")) 309 (setq translations
334 ;; TRANSLATIONS => "TRANSLATIONS" 310 (if translations
335 (insert "\"") 311 (concat translations
336 (end-of-line) 312 (buffer-substring pos (point)))
337 (skip-chars-backward " \t") 313 (buffer-substring pos (point)))))
338 (insert "\")")) 314 (while (not (eolp))
315 (setq pos (point))
316 (skip-chars-forward "^ \t\n")
317 (setq translations (cons (buffer-substring pos (point))
318 translations))
319 (skip-chars-forward " \t")
320 (setq ch (following-char))
321 (if (= ch ?#) (end-of-line))))
339 (forward-line 1)))) 322 (forward-line 1))))
340 (insert ")\n"))) 323
324 (if translations
325 (tit-flush-translations prev-key translations))
326 (princ ")\n")))
341 327
342;;;###autoload 328;;;###autoload
343(defun titdic-convert (filename &optional dirname) 329(defun titdic-convert (filename &optional dirname)
@@ -345,63 +331,50 @@
345Optional argument DIRNAME if specified is the directory name under which 331Optional argument DIRNAME if specified is the directory name under which
346the generated Quail package is saved." 332the generated Quail package is saved."
347 (interactive "FTIT dictionary file: ") 333 (interactive "FTIT dictionary file: ")
348 (let ((buf (get-buffer-create "*tit-work*"))) 334 (with-temp-file (tit-make-quail-package-file-name filename dirname)
349 (save-excursion 335 (set-buffer-file-coding-system 'iso-2022-7bit)
350 ;; Setup the buffer. 336 (let ((standard-output (current-buffer)))
351 (set-buffer buf) 337 (with-temp-buffer
352 (erase-buffer) 338 (let ((coding-system-for-read 'no-conversion))
353 (let ((coding-system-for-read 'no-conversion)) 339 (insert-file-contents (expand-file-name filename)))
354 (insert-file-contents (expand-file-name filename))) 340 (setq enable-multibyte-characters t)
355 (set-visited-file-name 341
356 (tit-make-quail-package-file-name filename dirname) t) 342 ;; Decode the buffer contents from the encoding specified by a
357 (setq enable-multibyte-characters t) 343 ;; value of the key "ENCODE:".
358 (set-buffer-file-coding-system 'iso-2022-7bit) 344 (if (not (search-forward "\nBEGIN" nil t))
359 345 (error "TIT dictionary doesn't have body part"))
360 ;; Decode the buffer contents from the encoding specified by a 346 (let ((limit (point))
361 ;; value of the key "ENCODE:". 347 coding-system slot)
362 (let (coding-system) 348 (goto-char (point-min))
363 (save-excursion 349 (if (re-search-forward "^ENCODE:[ \t]*" limit t)
364 (if (search-forward "\nBEGIN" nil t) 350 (progn
365 (let ((limit (point)) 351 (goto-char (match-end 0))
366 slot) 352 (setq tit-encode (tit-read-key-value)))
367 (goto-char 1) 353 (setq tit-encode tit-default-encode))
368 (if (re-search-forward "^ENCODE:[ \t]*" limit t) 354 (setq slot (assoc tit-encode tit-encode-list))
369 (progn 355 (if (not slot)
370 (goto-char (match-end 0)) 356 (error "Invalid ENCODE: value in TIT dictionary"))
371 (setq tit-encode (tit-read-key-value))) 357 (setq coding-system (nth 1 slot))
372 (setq tit-encode tit-default-encode)) 358 (message "Decoding by %s..." coding-system)
373 (setq slot (assoc tit-encode tit-encode-list)) 359 (goto-char (point-min))
374 (if slot 360 (decode-coding-region (point-min) (point-max) coding-system))
375 (setq coding-system (nth 1 slot)) 361
376 (error "Invalid ENCODE: value in TIT dictionary"))) 362 ;; Set point the starting position of the body part.
377 (error "TIT dictionary doesn't have body part"))) 363 (goto-char (point-min))
378 (message "Decoding %s..." coding-system) 364 (if (not (search-forward "\nBEGIN" nil t))
379 (goto-char 1) 365 (error "TIT dictionary can't be decoded correctly"))
380 (decode-coding-region 1 (point-max) coding-system)) 366
381 367 ;; Process the header part.
382 ;; Set point the starting position of the body part. 368 (forward-line 1)
383 (goto-char 1) 369 (narrow-to-region (point-min) (point))
384 (if (search-forward "\nBEGIN" nil t) 370 (tit-process-header filename)
385 (forward-line 1) 371 (widen)
386 (error "TIT dictionary can't be decoded correctly")) 372
387 373 ;; Process the body part. For speed, we turn off multibyte facility.
388 ;; Now process the header and body parts. 374 (with-current-buffer standard-output
389 (goto-char 375 (set-buffer-multibyte nil))
390 (save-excursion 376 (set-buffer-multibyte nil)
391 (save-restriction 377 (tit-process-body)))))
392 (narrow-to-region 1 (point))
393 (tit-process-header filename))))
394 (tit-process-body))
395
396 (if noninteractive
397 ;; Save the Quail package file.
398 (save-excursion
399 (set-buffer buf)
400 (save-buffer 0))
401 ;; Show the Quail package just generated.
402 (switch-to-buffer buf)
403 (goto-char 1)
404 (message "Save this buffer after you make any modification"))))
405 378
406;;;###autoload 379;;;###autoload
407(defun batch-titdic-convert (&optional force) 380(defun batch-titdic-convert (&optional force)