X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=ids-find.el;h=eb404b356120a895f36e8ce2b53f9cdf86d1ddc4;hb=f641879e4d25e23e8c63085a64cf5c83390f8737;hp=ad9ff9c4e947ab3cb1889cf52de8c2fc2e364590;hpb=a470b505b5753f9d1951923b233e31be13a9a467;p=chise%2Fids.git diff --git a/ids-find.el b/ids-find.el index ad9ff9c..eb404b3 100644 --- a/ids-find.el +++ b/ids-find.el @@ -1,11 +1,11 @@ ;;; ids-find.el --- search utility based on Ideographic-structures -;; Copyright (C) 2002 MORIOKA Tomohiko +;; Copyright (C) 2002,2003,2005,2006,2007,2017 MORIOKA Tomohiko ;; Author: MORIOKA Tomohiko -;; Keywords: Kanji, Ideographs, search, IDS +;; Keywords: Kanji, Ideographs, search, IDS, CHISE, UCS, Unicode -;; This file is a part of Tomoyo-Tools. +;; This file is a part of CHISE IDS. ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as @@ -24,6 +24,186 @@ ;;; Code: +(defun ids-index-store-char (product component) + (let ((ret (get-char-attribute component 'ideographic-products))) + (unless (memq product ret) + (put-char-attribute component 'ideographic-products + (cons product ret)) + (when (setq ret (char-feature component 'ideographic-structure)) + (ids-index-store-structure product ret))) + )) + +(defun ids-index-store-structure (product structure) + (let (ret) + (dolist (cell (cdr structure)) + (if (char-ref-p cell) + (setq cell (plist-get cell :char))) + (cond ((characterp cell) + (ids-index-store-char product cell)) + ((setq ret (assq 'ideographic-structure cell)) + (ids-index-store-structure product (cdr ret))) + ((setq ret (find-char cell)) + (ids-index-store-char product ret)) + )))) + +;;;###autoload +(defun ids-update-index () + (interactive) + (map-char-attribute + (lambda (c v) + (ids-index-store-structure c v) + nil) + 'ideographic-structure) + (save-char-attribute-table 'ideographic-products)) + + +(mount-char-attribute-table 'ideographic-products) + +;;;###autoload +(defun ids-find-all-products (char) + (let (dest) + (dolist (cell (char-feature char 'ideographic-products)) + (unless (memq cell dest) + (setq dest (cons cell dest))) + (setq dest (union dest (ids-find-all-products cell)))) + dest)) + +(defun of-component-features () + (let (dest) + (dolist (feature (char-attribute-list)) + (when (string-match "^<-.*[@/]component\\(/[^*/]+\\)*$" + (symbol-name feature)) + (push feature dest))) + (list* '<-mistakable '->mistakable + '<-formed '->formed + '<-same '->same + '<-original '->original + '<-ancient '->ancient + dest))) + +(defun to-component-features () + (let (dest) + (dolist (feature (char-attribute-list)) + (when (string-match "^->.*[@/]component\\(/[^*/]+\\)*$" + (symbol-name feature)) + (push feature dest))) + dest)) + +;;;###autoload +(defun char-component-variants (char) + (let ((dest (list char)) + ret uchr) + (dolist (feature (to-component-features)) + (if (setq ret (get-char-attribute char feature)) + (dolist (c ret) + (setq dest (union dest (char-component-variants c)))))) + (cond + ;; ((setq ret (some (lambda (feature) + ;; (get-char-attribute char feature)) + ;; (to-component-features))) + ;; (dolist (c ret) + ;; (setq dest (union dest (char-component-variants c)))) + ;; ) + ((setq ret (get-char-attribute char '->ucs-unified)) + (setq dest (cons char ret)) + (dolist (c dest) + (setq dest (union dest + (some (lambda (feature) + (get-char-attribute c feature)) + (of-component-features)) + ))) + ) + ((and (setq ret (get-char-attribute char '=>ucs)) + (setq uchr (decode-char '=ucs ret))) + (setq dest (cons uchr (char-variants uchr))) + (dolist (c dest) + (setq dest (union dest + (some (lambda (feature) + (get-char-attribute c feature)) + (of-component-features)) + ))) + ) + (t + (map-char-family + (lambda (c) + (unless (memq c dest) + (setq dest (cons c dest))) + (setq dest + (union dest + (some (lambda (feature) + (char-feature c feature)) + (of-component-features)) + )) + nil) + char) + )) + dest)) + +;;;###autoload +(defun ideographic-products-find (&rest components) + (if (stringp (car components)) + (setq components (string-to-char-list (car components)))) + (let (dest products) + (dolist (variant (char-component-variants (car components))) + (setq products + (union products + (get-char-attribute variant 'ideographic-products)))) + (setq dest products) + (while (and dest + (setq components (cdr components))) + (setq products nil) + (dolist (variant (char-component-variants (car components))) + (setq products + (union products + (get-char-attribute variant 'ideographic-products)))) + (setq dest (intersection dest products))) + dest)) + +(defun ideograph-find-products-with-variants (components &optional ignored-chars) + (if (stringp components) + (setq components (string-to-char-list components))) + (let (dest products) + (dolist (variant (char-component-variants (car components))) + (setq products + (union products + (set-difference + (get-char-attribute variant 'ideographic-products) + ignored-chars)))) + (setq dest products) + (while (and dest + (setq components (cdr components))) + (setq products nil) + (dolist (variant (char-component-variants (car components))) + (setq products + (union products + (set-difference + (get-char-attribute variant 'ideographic-products) + ignored-chars)))) + (setq dest (intersection dest products))) + dest)) + +(defun ideograph-find-products (components &optional ignored-chars) + (if (stringp components) + (setq components (string-to-char-list components))) + (let (dest products) + ;; (dolist (variant (char-component-variants (car components))) + ;; (setq products + ;; (union products + ;; (get-char-attribute variant 'ideographic-products)))) + ;; (setq dest products) + (setq dest (get-char-attribute (car components) 'ideographic-products)) + (while (and dest + (setq components (cdr components))) + ;; (setq products nil) + ;; (dolist (variant (char-component-variants (car components))) + ;; (setq products + ;; (union products + ;; (get-char-attribute variant 'ideographic-products)))) + (setq products (get-char-attribute (car components) 'ideographic-products)) + (setq dest (intersection dest products))) + dest)) + + (defun ideographic-structure-char= (c1 c2) (or (eq c1 c2) (and c1 c2 @@ -31,88 +211,200 @@ (m2 (char-ucs c2))) (or (and m1 m2 (eq m1 m2)) - (progn - (setq m1 (car (get-char-attribute c1 '<-radical)) - m2 (car (get-char-attribute c2 '<-radical))) - (unless (characterp m1) - (setq m1 (or (find-char m1)))) - (unless (characterp m2) - (setq m2 (find-char m2))) - (when (or m1 m2) - (ideographic-structure-char= m1 m2)))))))) - -(defun ideographic-structure-member-compare-parts (part s-part) + (memq c1 (char-component-variants c2))))))) + +(defun ideographic-structure-member-compare-components (component s-component) (let (ret) - (cond ((char-ref= part s-part #'ideographic-structure-char=)) - ((listp s-part) - (if (setq ret (assq 'ideographic-structure s-part)) - (ideographic-structure-member part (cdr ret)))) - ((setq ret (get-char-attribute s-part 'ideographic-structure)) - (ideographic-structure-member part ret))))) + (cond ((char-ref= component s-component #'ideographic-structure-char=)) + ((listp s-component) + (if (setq ret (assq 'ideographic-structure s-component)) + (ideographic-structure-member component (cdr ret)))) + ((setq ret (get-char-attribute s-component 'ideographic-structure)) + (ideographic-structure-member component ret))))) ;;;###autoload -(defun ideographic-structure-member (part structure) - "Return non-nil if PART is included in STRUCTURE." - (or (progn +(defun ideographic-structure-member (component structure) + "Return non-nil if COMPONENT is included in STRUCTURE." + (or (memq component structure) + (progn (setq structure (cdr structure)) - (ideographic-structure-member-compare-parts part (car structure))) + (ideographic-structure-member-compare-components + component (car structure))) (progn (setq structure (cdr structure)) - (ideographic-structure-member-compare-parts part (car structure))) + (ideographic-structure-member-compare-components + component (car structure))) (progn (setq structure (cdr structure)) (and (car structure) - (ideographic-structure-member-compare-parts - part (car structure)))))) + (ideographic-structure-member-compare-components + component (car structure)))))) ;;;###autoload -(defun ideographic-structure-repertoire-p (structure parts) - "Return non-nil if STRUCTURE can be constructed by a subset of PARTS." +(defun ideographic-structure-repertoire-p (structure components) + "Return non-nil if STRUCTURE can be constructed by a subset of COMPONENTS." (and structure - (let (ret s-part) + (let (ret s-component) (catch 'tag (while (setq structure (cdr structure)) - (setq s-part (car structure)) - (unless (characterp s-part) - (if (setq ret (find-char s-part)) - (setq s-part ret))) + (setq s-component (car structure)) + (unless (characterp s-component) + (if (setq ret (find-char s-component)) + (setq s-component ret))) (unless (cond - ((listp s-part) - (if (setq ret (assq 'ideographic-structure s-part)) + ((listp s-component) + (if (setq ret (assq 'ideographic-structure s-component)) (ideographic-structure-repertoire-p - (cdr ret) parts))) - ((member* s-part parts + (cdr ret) components))) + ((member* s-component components :test #'ideographic-structure-char=)) ((setq ret - (get-char-attribute s-part + (get-char-attribute s-component 'ideographic-structure)) - (ideographic-structure-repertoire-p ret parts))) + (ideographic-structure-repertoire-p ret components))) (throw 'tag nil))) t)))) + +(defvar ids-find-result-buffer "*ids-chars*") + +(defun ids-find-format-line (c v) + (format "%c\t%s\t%s\n" + c + (or (let ((ucs (or (char-ucs c) + (encode-char c 'ucs)))) + (if ucs + (cond ((<= ucs #xFFFF) + (format " U+%04X" ucs)) + ((<= ucs #x10FFFF) + (format "U-%08X" ucs))))) + " ") + (or (ideographic-structure-to-ids v) + v))) + +(defun ids-insert-chars-including-components* (components + &optional level ignored-chars) + (unless level + (setq level 0)) + (let (is i as bs) + (dolist (c (sort (copy-tree (ideograph-find-products components + ignored-chars)) + (lambda (a b) + (if (setq as (char-total-strokes a)) + (if (setq bs (char-total-strokes b)) + (if (= as bs) + (ideograph-char< a b) + (< as bs)) + t) + (ideograph-char< a b))))) + (unless (memq c ignored-chars) + (setq is (char-feature c 'ideographic-structure)) + (setq i 0) + (while (< i level) + (insert "\t") + (setq i (1+ i))) + (insert (ids-find-format-line c is)) + (setq ignored-chars + (ids-insert-chars-including-components* + (char-to-string c) (1+ level) + (cons c ignored-chars)))) + ) + ) + ignored-chars) + +(defun ids-insert-chars-including-components (components + &optional level ignored-chars) + (unless level + (setq level 0)) + (setq ignored-chars + (nreverse + (ids-insert-chars-including-components* components + level ignored-chars))) + (let (is i as bs) + (dolist (c ignored-chars) + (dolist (vc (char-component-variants c)) + (unless (memq vc ignored-chars) + (when (setq is (get-char-attribute vc 'ideographic-structure)) + (setq i 0) + (while (< i level) + (insert "\t") + (setq i (1+ i))) + (insert (ids-find-format-line vc is)) + (setq ignored-chars + (ids-insert-chars-including-components* + (char-to-string vc) (1+ level) + (cons vc ignored-chars))))))) + (dolist (c (sort (copy-tree (ideograph-find-products-with-variants + components ignored-chars)) + (lambda (a b) + (if (setq as (char-total-strokes a)) + (if (setq bs (char-total-strokes b)) + (if (= as bs) + (ideograph-char< a b) + (< as bs)) + t) + (ideograph-char< a b))))) + (unless (memq c ignored-chars) + (setq is (get-char-attribute c 'ideographic-structure)) + (setq i 0) + (while (< i level) + (insert "\t") + (setq i (1+ i))) + (insert (ids-find-format-line c is)) + (setq ignored-chars + (ids-insert-chars-including-components* + (char-to-string c) (1+ level) + (cons c ignored-chars)))) + ) + ) + ignored-chars) + +;;;###autoload +(defun ids-find-chars-including-components (components) + "Search Ideographs whose structures have COMPONENTS." + (interactive "sComponents : ") + (with-current-buffer (get-buffer-create ids-find-result-buffer) + (setq buffer-read-only nil) + (erase-buffer) + (ids-insert-chars-including-components components 0 nil) + ;; (let ((ignored-chars + ;; (nreverse + ;; (ids-insert-chars-including-components components 0 nil + ;; #'ideograph-find-products))) + ;; rest) + ;; (setq rest ignored-chars) + ;; ;; (dolist (c rest) + ;; ;; (setq ignored-chars + ;; ;; (union ignored-chars + ;; ;; (ids-insert-chars-including-components + ;; ;; (list c) 0 ignored-chars + ;; ;; #'ideograph-find-products-with-variants)))) + ;; (ids-insert-chars-including-components components 0 ignored-chars + ;; #'ideograph-find-products-with-variants)) + (goto-char (point-min))) + (view-buffer ids-find-result-buffer)) + +;;;###autoload +(define-obsolete-function-alias 'ideographic-structure-search-chars + 'ids-find-chars-including-components) + ;;;###autoload -(defun ideographic-structure-search-chars (parts) - "Search Ideographs by PARTS." - (interactive "sParts : ") - (with-current-buffer (get-buffer-create " *ids-chars*") +(defun ids-find-chars-covered-by-components (components) + "Search Ideographs which structures are consisted by subsets of COMPONENTS." + (interactive "sComponents: ") + (if (stringp components) + (setq components (string-to-char-list components))) + (with-current-buffer (get-buffer-create ids-find-result-buffer) (setq buffer-read-only nil) (erase-buffer) (map-char-attribute (lambda (c v) - (when (every - (lambda (p) - ;; (member* p v :test #'char-ref=) - (ideographic-structure-member p v)) - parts) - (insert (format "%c\t%s\n" - c - (or (ideographic-structure-to-ids v) - v)))) - nil) + (when (ideographic-structure-repertoire-p v components) + (insert (ids-find-format-line c v)))) 'ideographic-structure) (goto-char (point-min))) - (view-buffer " *ids-chars*")) + (view-buffer ids-find-result-buffer)) ;;; @ End.