branch: externals/greader
commit 04b464caac38e6b1a607df857021e11d3d45ad2a
Author: Michelangelo Rodriguez <michelangelo.rodrig...@gmail.com>
Commit: Michelangelo Rodriguez <michelangelo.rodrig...@gmail.com>

    First working draft of module "greader-dict.el".
    
    For more information about of how to use the greader's dictionary
    feature, please refer to the commentary of greader-dict.el, the
    documentation in "greader-mode", and in the documentation of the
    commands exposed by this module.
---
 greader-dict.el | 513 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 428 insertions(+), 85 deletions(-)

diff --git a/greader-dict.el b/greader-dict.el
index 0fdebc5632..a4d7b54bfe 100644
--- a/greader-dict.el
+++ b/greader-dict.el
@@ -1,28 +1,90 @@
-;; greader-dict.el - dictionary module for greader. -*- lexical-binding: t; -*-
+;;; greader-dict.el --- dictionary module for greader. -*- lexical-binding: t; 
-*-
 ;; 
 ;; Filename: greader-dict.el
-;; Description: 
+;; Description:
 ;; Author: Michelangelo Rodriguez
-;; Maintainer: 
+;; Maintainer:
 ;; Created: Lun Gen  8 09:52:58 2024 (+0100)
-;; Version: 
+;; Version:
 ;; Package-Requires: ()
-;; Last-Updated: 
-;;           By: 
+;; Last-Updated:
+;;           By:
 ;;     Update #: 0
-;; URL: 
-;; Doc URL: 
-;; Keywords: 
-;; Compatibility: 
-;; 
+;; URL:
+;; Doc URL:
+;; Keywords:
+;; Compatibility:
+;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; 
-;;; Commentary: 
+;;; Commentary:
 ;; dictionary module for greader.
 ;; This module gives greader the ability to define different wais Of
-;; pronounce a given sequence of characters.
-
-;; 
+;; to pronounce a given sequence of characters.
+;;
+;;
+;; There are two types of items that you can add to
+;; the dictionary:
+;; `word'
+;; This is a substitution where the word to be replaced
+;; constitutes a word as a whole.
+;; For example, the word "dog" will be replaced only if it is
+;; surrounded by characters that do not constitute a word. (what is a
+;; word may change depending on the major-mode
+;; currently in use).
+;; `match'
+;; This is a "literal" substitution, that is, in which it is sufficient
+;; that the word to be replaced is a substring of a word.
+;; For example, if you add the match "dog", it will be replaced
+;; also in the words "dogs", "doggy", ETC.
+;; To add a word of type `word' simply execute the
+;; command `C-r d a" (greader-dict-add-entry).
+;; (when you launch the command, default values ​​will be proposed which
+;; you can consult with the arrow keys.
+;; The `greader-dict-add-entry' command includes  in its defaults
+;; already existing definitions.
+;; In this case, choosing one of these values ​​will change the
+;; replacement to be applied.
+;; To add a word like `match' run the command
+;; `greader-dict-add-entry' with the prefix.
+;; In this case, the proposed alternatives will only be those that
+;; in the dictionary they are classified, precisely, as match.
+;; The command is also useful when selecting text: in this
+;; case, it will be proposed to add a match that includes only the
+;; selected characters.
+;; Matches can also be regular expressions, through
+;; which you can create more refined filters than you can
+;; just do with simple strings.
+;;
+;; visibility of dictionary.
+;;
+;; In general, you can choose between three dictionary visibilities:
+;; `global'
+;; The default dictionary visibility.
+;; `mode'
+;; This visibility is shared by all buffers in which a particular mode is
+;; in effect.
+;; For example, if you are visiting the buffer "foo.txt" in text-mode,
+;; and you choose the visibility `mode', all the buffers in which
+;; `text-mode' is active and in which 'mode' visibility is set, those
+;; buffers all will refer to mode dictionary.
+;; `buffer'
+;; The most local visibility, in which the dictionary is valid only in
+;; the current buffer.
+;; You can set the dictionary visibility for each buffer.
+;; Use `C-r d c" (greader-dict-change-dictionary) to change the
+;; dictionary visibility in the current buffer.
+;; If you instead wish to set a particular visibility in a particular
+;; buffer or mode as default, you can add the following code snippet
+;; in your .emacs file:
+;; Suppose that you want to set dictionary `mode' visibility for
+;; `info-mode':
+;;Just copy the following snippet in your init file without quotes:
+;; "(add-hook 'info-mode-hook
+;; (lambda ()
+;; (greader-dict-mode 1)
+;; (greader-dict--set-file 'mode)))
+;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; 
 ;;; Change Log:
@@ -48,8 +110,8 @@
 ;; 
 ;;; Code:
 (require 'greader)
-(defvar greader-dictionary (make-hash-table :test 'equal))
-(defvar greader-dict-match-indicator "%\*"
+(defvar-local  greader-dictionary nil)
+(defvar greader-dict-match-indicator "\%\*"
   "Regexp that will be used for match delimiter.")
 
 ;; The following two functions deal, respectively, with
@@ -72,20 +134,29 @@
                           greader-dict-match-indicator match)))
     (save-excursion
       (goto-char (point-min))
-      (while (search-forward normalized-match nil t)
+      (while (re-search-forward normalized-match nil t)
        (replace-match (gethash match greader-dictionary))))))
 
 (defun greader-dict-substitute-word (match)
-  "substitute match only if it constitutes an entire word."
+  "Substitute MATCH only if it constitutes an entire word."
   (save-excursion
     (goto-char (point-min))
-    (let ((word (concat match "\\W")))
-      (while (re-search-forward word nil t)
-       (setq word (match-string 0))
-       (let ((replacement (concat (gethash match
-                                           greader-dictionary)
-                                  (char-to-string (aref word (1- (length 
word)))))))
-         (replace-match replacement))))))
+    (let ((word (concat "\\(\\W+\\)" "\\(" match "\\)" "\\(\\W+\\)"))
+         (alternative-word
+          (concat "\\(^\\)" "\\(" match "\\)" "\\(\\W+\\)"))
+         (end-word
+          (concat "\\(\\W+\\)" "\\(" match "\\)" "\\(\\W*$\\)")))
+      (while (or (re-search-forward word nil t) (re-search-forward
+                                                alternative-word nil
+                                                t)
+                (re-search-forward end-word nil t))
+       ;; (edebug)
+       (let ((replacement
+              (concat (match-string 1)
+                      (gethash match greader-dictionary)
+                      (match-string 3))))
+         (replace-match replacement))
+       (goto-char (point-min))))))
 
 ;; This function adds to the `greader-dictionary' variable the
 ;; key/value pair that you pass as arguments.
@@ -97,23 +168,40 @@ A value of 0 indicates saving immediately."
 (defun greader-dict-add (word replacement)
   "Add the WORD REPLACEMent pair to `greader-dictionary'.
 If you want to add a partial replacement, you should
-add `\*'to the end of WORD string parameter."
+add `\*'to the end of the WORD string parameter."
   (puthash (downcase word) replacement greader-dictionary)
+  (setq greader-dict--saved-flag nil)
   (cond
    ((> greader-dict-save-after-time 0)
     (when (timerp greader-dict--timer)
       (cancel-timer greader-dict--timer))
-    (run-with-idle-timer greader-dict-save-after-time nil 
#'greader-dict-write-file))
+    (run-with-idle-timer greader-dict-save-after-time nil
+                        #'greader-dict-write-file))
    ((= greader-dict-save-after-time 0)
-    (greader-dict-write-file))
+    (unless greader-dict--saved-flag
+      (greader-dict-write-file)))
    (t
+    (setq greader-dict--saved-flag t)
     nil)))
 
 ;; This function removes the association indicated by the key argument.
 (defun greader-dict-remove (key)
   "Remove the association specified by KEY from the variable
 `greader-dictionary'."
-  (remhash key greader-dictionary))
+  (remhash key greader-dictionary)
+  (setq greader-dict--saved-flag nil)
+  (cond
+   ((> greader-dict-save-after-time 0)
+    (when (timerp greader-dict--timer)
+      (cancel-timer greader-dict--timer))
+    (run-with-idle-timer greader-dict-save-after-time nil
+                        #'greader-dict-write-file))
+   ((= greader-dict-save-after-time 0)
+    (unless greader-dict--saved-flag
+      (greader-dict-write-file)))
+   (t
+    (setq greader-dict--saved-flag t)
+    nil)))
 
 (defun greader-dict-item-type (key)
   "Return the type of KEY.
@@ -133,11 +221,14 @@ Return nil if KEY is not present in `greader-dictionary'."
 
 (defun greader-dict--get-key-from-word (word)
   "Return key related to WORD, nil otherwise."
+  (setq word (string-trim word))
   (let ((key nil))
     (maphash (lambda (k v)
-              (when (string-search (string-remove-suffix
-                                    greader-dict-match-indicator k) word)
-                (setq key k))) greader-dictionary)
+              (when (string-match (string-remove-suffix
+                                   greader-dict-match-indicator k)
+                                  word)
+                (setq key k)))
+            greader-dictionary)
     key))
 
 ;; This function checks that, in the string you pass to it, there are
@@ -150,58 +241,88 @@ Return nil if KEY is not present in `greader-dictionary'."
   "Return the TEXT passed to it, eventually modified according to
 `greader-dictionary' and variants."
   (with-temp-buffer
+    (setq greader-dictionary (buffer-local-value 'greader-dictionary
+                                                
greader-dict--current-reading-buffer))
     (insert text)
     (goto-char (point-min))
-    (re-search-forward "\\w" nil t)
-    (while (not (eobp))
-      (let*
-         ((key (greader-dict--get-key-from-word (downcase
-                                                 (thing-at-point 'word))))
-          (modified-word (concat (downcase (thing-at-point 'word)) 
greader-dict-match-indicator)))
-       (cond
-        ((equal (greader-dict-item-type key) 'word)
-         (greader-dict-substitute-word (string-remove-suffix
-                                        greader-dict-match-indicator key)))
-        ((equal (greader-dict-item-type key) 'match)
-         (greader-dict-substitute-match key))
-        ((not (greader-dict-item-type key))
-         nil)))
-      (forward-word))
-    (buffer-string)))
+    (let ((inhibit-read-only t))
+      (re-search-forward "\\w" nil t)
+      (while (not (eobp))
+       (let*
+           ((key (greader-dict--get-key-from-word (downcase
+                                                   (thing-at-point
+                                                    'word))))
+            (modified-word
+             (concat (downcase (thing-at-point 'word))
+                     greader-dict-match-indicator)))
+         (cond
+          ((equal (greader-dict-item-type key) 'word)
+           (greader-dict-substitute-word (string-remove-suffix
+                                          greader-dict-match-indicator
+                                          key)))
+          ((equal (greader-dict-item-type key) 'match)
+           (greader-dict-substitute-match key))
+          ((not (greader-dict-item-type key))
+           nil)))
+       (re-search-forward "\\W*\\w" nil 1))
+      (buffer-string))))
 
 ;; This function saves the contents of the hash table.
-(defcustom greader-dict-directory (concat user-emacs-directory
-                                         ".greader-dict/"
-                                         (greader-get-language) "/")
-  "The directory containing greader-dict files."
-  :type 'directory)
-(defcustom greader-dict-filename "greader-dict.global"
-  "File name where dictionary definitions are stored."
-  :type 'string)
+(defvar greader-dict-directory (concat user-emacs-directory
+                                      ".greader-dict/")
+  "The directory containing greader-dict files.")
+(defvar-local greader-dict-filename "greader-dict.global"
+  "File name where dictionary definitions are stored.")
+(defvar greader-dict--current-reading-buffer (current-buffer))
+;; We use this variable to know if greader-dictionary is saved after
+;; the last modification.
+(defvar-local greader-dict--saved-flag t)
 
 (defun greader-dict-write-file ()
   "Save greader-dictionary stored in `greader-dict-filename'."
   (unless (file-exists-p greader-dict-directory)
     (make-directory greader-dict-directory t))
   (with-temp-buffer
+    (setq greader-dictionary (buffer-local-value 'greader-dictionary
+                                                
greader-dict--current-reading-buffer))
+    (setq greader-dict-filename (buffer-local-value
+                                'greader-dict-filename
+                                greader-dict--current-reading-buffer))
     (maphash
      (lambda (k v)
-       (insert (concat k "=" v "\n"))) greader-dictionary)
-    (write-file (concat greader-dict-directory
-                       greader-dict-filename))))
+       (insert (concat k "=" v "\n")))
+     greader-dictionary)
+    (write-region (point-min) (point-max)
+                 (greader-dict--get-file-name)))
+  (setq greader-dict--saved-flag t))
 
-(defun greader-dict-read-from-dict-file ()
+(defun greader-dict-read-from-dict-file (&optional force)
   "populate `greader-dictionary' with the contents of
-`greader-dict-filename'."
-  (when (file-exists-p (concat greader-dict-directory
-                              greader-dict-filename))
+`greader-dict-filename'.
+If FORCE is non-nil, reading happens even if there are definitions not
+  yet saved.
+If FORCE is nil \(the default\) then this function generates an
+  user-error and aborts the reading process."
+  ;; This code is to provide a variable
+  ;; `greader-dictionary' by default usable in the buffer
+  ;; temporary where the replacements defined in 
`greader-after-get-sentence-functions' occur.
+  (when (and (not greader-dict--saved-flag) (not force))
+    (user-error "Dictionary has been modified and not yet saved"))
+  (when (file-exists-p (greader-dict--get-file-name))
     (with-temp-buffer
-      (insert-file-contents (concat greader-dict-directory
-                                   greader-dict-filename))
-      (when-let ((lines (string-lines (buffer-string))))
+      (setq greader-dictionary (buffer-local-value 'greader-dictionary
+                                                  
greader-dict--current-reading-buffer))
+      (setq greader-dict-filename (buffer-local-value
+                                  'greader-dict-filename
+                                  greader-dict--current-reading-buffer))
+      (insert-file-contents (greader-dict--get-file-name))
+      (when-let ((lines (string-lines (buffer-string) t)))
        (dolist (line lines)
          (setq line (split-string line "="))
-         (greader-dict-add (car line) (car (cdr line))))))))
+         (let ((greader-dict-save-after-time -1))
+           (greader-dict-add (car line) (car (cdr line)))))
+       (setq greader-dict--saved-flag t))))
+  (add-hook 'buffer-list-update-hook #'greader-dict--update))
 
 ;; Command for saving interactively dictionary data.
 (defun greader-dict-save ()
@@ -227,36 +348,219 @@ to the dictionary."
 ;; In this last case, the word will be added to
 ;; `greader-dictionary' as "word", so it must constitute itself
 ;; a word to be replaced.
-(defun greader-dict-add-entry ()
-  (interactive)
+(defun greader-dict-add-entry (arg)
+  "Add an entry to the dictionary.
+If point is on a word, this function proposes to add that word as
+default.
+In this case, you can also use history commands to modify key already
+present in the dictionary.
+The word will be added as a word, but you can choice to add it as a
+match using history commands when in the minibuffer.
+If the region is active, and you have selected a word or a partial
+word, it will be added as a match.
+If neither the region is active nor point is on a word, simply asks
+for definition and substitution, without defaults.
+If called with prefix argument, ask for a match.
+In this case you can type a regular expression.
+You can use regular expressions to, for example, craft filters instead
+of pronunciation rules."
+  (interactive "P")
   (let (key value)
     (cond
+     (arg
+      (setq key (read-regexp "match to add or modify: "
+                            (greader-dict--get-matches 'match)))
+      (unless key
+       (user-error "Input is empty: aborting"))
+      (setq key (concat key greader-dict-match-indicator))
+      (setq value (read-string (concat "substitute regexp " key "with:
+")))
+      (greader-dict-add key value))
      ((region-active-p)
       (when (= (count-words(region-beginning) (region-end)) 1)
-       (setq key (concat (read-string "Original word to substitute:" nil nil
-                                      (thing-at-point 'word)) 
greader-dict-match-indicator))
+       (setq key (concat (read-string "Original word to substitute:"
+                                      nil nil
+                                      (buffer-substring
+                                       (region-beginning)
+                                       (region-end)))
+                         greader-dict-match-indicator))
        (setq value (read-string (concat "substitute match " key
                                         "with:")))
        (greader-dict-add key value)))
-     (t
-      (when-let ((default-word (thing-at-point 'word)))
-       (setq key (read-string "Original word to substitute:" nil nil
-                              default-word))
-       (setq value (read-string (concat "substitute word " key
-                                        "with:")))
+     ((not (region-active-p))
+      (if-let ((default-word (thing-at-point 'word)))
+         (progn
+           (setq key (read-string "Original word to substitute or
+modify: " nil
+nil
+(append (list default-word)(greader-dict--get-matches 'word))))
+           (setq value (read-string (concat "substitute word " key
+                                            " with:")))
+           (greader-dict-add key value))
+       (setq key (read-string "Word to add or modify: " nil nil
+                              (greader-dict--get-matches 'word)))
+       (setq value (read-string (concat "substitute " key " with:")))
        (greader-dict-add key value))))))
 
+(defun greader-dict-remove-entry (key)
+  "Remove KEY from the dictionary.
+If KEY is not present, signal an user-error."
+  (interactive
+   (list
+    (read-string "key to remove: "nil nil
+                (sort (hash-table-keys greader-dictionary)
+                      (lambda (s1 s2)
+                        (string-greaterp s2 s1))))))
+  (unless (greader-dict-remove key)
+    (user-error "Key not found.")))
+
+(defun greader-dict-clear ()
+  "Clean the definition table.
+It does'nt save cleaned table in the definitions file automatically,
+  instead you should save it manually if you want.
+Please use `greader-dict-save' for that purpose."
+  (interactive)
+  (clrhash greader-dictionary)
+  (setq greader-dict--saved-flag nil)
+  (message "Cleaned."))
+
 ;; greader-dict-mode.
 (defvar-keymap greader-dict-mode-map
   :doc "keymap for `greader-dict-mode'."
   "C-r d a" #'greader-dict-add-entry
+  "C-r d c" #'greader-dict-change-dictionary
   "C-r d s" #'greader-dict-save)
 (defun greader-dict--replace-wrapper (text)
   "Function to add to `greader-after-get-sentence-functions'.
 It simply calls `greader-dict-check-and-replace' with TEXT as its
 argument, only if `greader-dict-mode' is enabled."
+  (if greader-dict-mode
+      (greader-dict-check-and-replace text)
+    text))
+
+(defun greader-dict--get-file-name ()
+  "Return the absolute path of current dictionary file."
+  (concat greader-dict-directory (greader-get-language) "/"
+         (buffer-local-value 'greader-dict-filename
+                             greader-dict--current-reading-buffer)))
+
+(defun greader-dict--set-file (type)
+  "Set `greader-dict-filename' according to TYPE.
+TYPE Must be a symbol, and accepted symbols are:
+`buffer', `mode', and `global'.
+See also the documentation of `greader-dict--file-type' For
+technicalities."
+  (cond
+   ((not greader-dict--saved-flag)
+    (greader-dict-write-file)))
+  (cond
+   ;; We use `setq-local' only for clarity.
+   ((equal type 'buffer)
+    (setq-local greader-dict-filename (concat (buffer-name) ".dict")))
+   ((equal type 'mode)
+    (setq-local greader-dict-filename
+               (concat (symbol-name major-mode) ".dict")))
+   ((equal type 'global)
+    (setq-local greader-dict-filename "greader-dict.global"))
+   (t
+    (error (concat "type " (symbol-name type) " not valid as "
+                  (symbol-name (type-of type)))))))
+
+
+(defcustom greader-dict-ask-before-change t
+  "Ask before changing the dictionary in current buffer.
+If toggled on, when you attempt to change the dictionary and current
+  dictionary table as data not yet saved,
+  `greader-dict-change-dictionary will ask you if you want to save
+  the current dictionary first.
+If you answer no, you will loose that data.
+If you answer yes, instead, data will be saved in the current
+  dictionary before setting the dictionary at newone."
+  :type 'boolean)
+
+(defun greader-dict--file-type ()
+  "Return the file type of dictionary for the current buffer.
+The `file type' refers to the scope in a given context:
+`buffer'
+Means that it exists a file named `(concat buffer-file-name \".dict\")
+in `greader-dict-directory'.
+`mode'
+Means it exists a file called `(concat major-mode \".dict\")' in
+`greader-dict-directory'.
+`global'
+Means it exists a file called \"greader-dict.global\" in
+`greader-dict-directory'."
+  (let ((default-directory (concat greader-dict-directory
+                                  (greader-get-language) "/")))
+    (cond
+     ((string-equal (concat (buffer-name) ".dict")
+                   greader-dict-filename)
+      'buffer)
+     ((string-equal (concat (symbol-name major-mode) ".dict")
+                   greader-dict-filename)
+      'mode)
+     ((string-equal "greader-dict.global" greader-dict-filename)
+      'global)
+     (t 'global))))
+
+(defvar greader-dict--type-file-alternatives '(buffer mode global))
+(defun greader-dict--type-alternatives ()
+  "Return the list of currently valid alternatives for dictionary."
+  (let ((alternatives nil))
+    (dolist (alternative greader-dict--type-file-alternatives)
+      (unless (equal alternative (greader-dict--file-type))
+       (push (symbol-name alternative) alternatives)))
+    alternatives))
+
+(defun greader-dict-change-dictionary (new-dict)
+  "change the current dictionary.
+You can choose between the alternatives by using the arrow keys when
+asked."
+  (interactive
+   (list
+    (read-string (concat "Change dictionary from "
+                        (symbol-name
+                         (greader-dict--file-type))
+                        " to: ")
+                nil nil
+                (greader-dict--type-alternatives))))
+  (unless greader-dict-mode
+    (user-error "Please enable `greader-dict-mode' first."))
+  (let ((old-dict (greader-dict--file-type))
+       (response nil))
+    (unless (equal new-dict old-dict)
+      (cond
+       ((and greader-dict-ask-before-change (not
+                                            greader-dict--saved-flag))
+       (setq response (yes-or-no-p "There are definitions not yet
+  saved; Do you want to save them before changing?"))
+       (if response (greader-dict-write-file)
+         (setq
+          greader-dict--saved-flag
+          t))))
+      (clrhash greader-dictionary)
+      (greader-dict--set-file (intern new-dict))
+      (unless (file-exists-p (greader-dict--get-file-name))
+       (shell-command-to-string
+        (concat "touch " greader-dict-filename)))
+      (greader-dict-read-from-dict-file))))
+;; (remove-hook 'buffer-list-update-hook #'greader-dict--update)))))
+
+(defun greader-dict--update ()
   (when greader-dict-mode
-    (greader-dict-check-and-replace text)))
+    (setq greader-dict--current-reading-buffer (current-buffer))
+    (unless greader-dict--saved-flag
+      (greader-dict-write-file))
+    ;; I decided to keep the following code for historical reasons and
+    ;; memento.
+    ;;   Indeed it is superfluous as it is, because "buffer-locality", so
+    ;; the following conditional is not necessary.
+    (unless greader-reading-mode
+      (clrhash
+       (buffer-local-value 'greader-dictionary
+                          greader-dict--current-reading-buffer))
+      (greader-dict-read-from-dict-file t))))
+
 ;;;###autoload
 (define-minor-mode greader-dict-mode
   "Dictionary module for greader.
@@ -276,13 +580,52 @@ as a word definition."
   :lighter " gr-dictionary"
   (cond
    (greader-dict-mode
-    (when (hash-table-empty-p greader-dictionary)
-      (greader-dict-read-from-dict-file))
+    (setq greader-dictionary (make-hash-table :test 'equal))
+    (setq greader-dict--current-reading-buffer (current-buffer))
+    (greader-dict-read-from-dict-file)
     (add-hook 'greader-after-get-sentence-functions
-             #'greader-dict--replace-wrapper 1))
-   (t
-    (remove-hook 'greader-after-get-sentence-functions
-                #'greader-dict--replace-wrapper))))
+             #'greader-dict--replace-wrapper 1)
+                                       ; (add-hook 'greader-reading-mode-hook 
#'greader-dict--update))))
+
+    (add-hook 'buffer-list-update-hook #'greader-dict--update))))
+;; Questa funzione è solo di utilità e potrebbe essere rimossa o
+;; modificata in qualsiasi momento.
+(defun greader-dict-beep ()
+  (beep))
+
+(defun greader-dict-info ()
+  "Print some information about current dictionary."
+  (interactive)
+  (let ((message
+        (concat "Current dictionary is " (symbol-name 
(greader-dict--file-type))
+                " in file " greader-dict-filename " it has "
+                (number-to-string (hash-table-count
+                                   greader-dictionary)) " entries.")))
+    (message "%s" message)))
+
+(defun greader-dict--get-matches (type &optional decorate)
+  "Return a list with keys classified as TYPE.
+If TYPE is `all', all items in the current dictionary will be included."
+  (let ((matches nil))
+    (maphash
+     (lambda (k v)
+       (cond ((equal (greader-dict-item-type k) type)
+             (let ((match (string-remove-suffix
+                           greader-dict-match-indicator k)))
+               (when decorate
+                 (setq match (concat match " \(" (gethash k 
greader-dictionary) "\)")))
+               (push match matches)))
+            ((equal type 'all)
+             (let ((match (string-remove-suffix
+                           greader-dict-match-indicator k)))
+               (when decorate
+                 (setq match (concat match " \(" (gethash k 
greader-dictionary) "\)")))
+               (push match matches))))) greader-dictionary)
+    (sort
+     matches
+     (lambda (s1 s2)
+       (string-greaterp s2 s1)))))
+
 
 (provide 'greader-dict)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Reply via email to