From: Eshel Yaron Date: Sat, 6 May 2023 18:45:47 +0000 (+0300) Subject: Add initial documentation X-Git-Tag: v0.1.2 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=be0f59f5f9e977e9e1fbbb73f02473e873f6f86d;p=dict.git Add initial documentation --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d094410 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/README.org~ +/dict-autoloads.el +/dict-pkg.el +/dict.elc +/dict.info +/dict.texi diff --git a/README.org b/README.org new file mode 100644 index 0000000..a9f23f9 --- /dev/null +++ b/README.org @@ -0,0 +1,194 @@ +#+title: Dict: Display Word Definitions from RFC2229 Dictionary Servers +#+author: Eshel Yaron +#+email: me@eshelyaron.com +#+language: en +#+options: ':t toc:nil author:t email:t num:nil ^:{} +#+startup: content indent +#+export_file_name: dict.texi +#+texinfo_filename: dict.info +#+texinfo_dir_category: Emacs +#+texinfo_dir_title: Dict: (dict) +#+texinfo_dir_desc: Display Word Definitions from RFC2229 Dictionary Servers +#+texinfo_header: @set MAINTAINERSITE @uref{https://eshelyaron.com,maintainer webpage} +#+texinfo_header: @set MAINTAINER Eshel Yaron +#+texinfo_header: @set MAINTAINEREMAIL @email{me@eshelyaron.com} +#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:me@eshelyaron.com,contact the maintainer} + +This manual describes the Emacs package Dict (or =dict.el=), which provides an +interface for querying RFC2229 dictionary servers and displaying word +definitions. + +#+toc: headlines 8 insert TOC here, with eight headline levels + +* TODO Installation + +* Displaying Word Definitions +:PROPERTIES: +:CUSTOM_ID: word-definitions +:DESCRIPTION: Obtaining and displaying the word definitions +:ALT_TITLE: Word Definitions +:END: + +Dict defines a single autoloaded command for displaying the word definitions: + +- Command: dict-describe-word :: Prompt for a word and display its definition. + +This command prompts for a word in the minibuffer, obtains its definition from a +dictionary server, and displays it in a =*Help*= buffer. (See [[info:emacs#Help][Help]] in the Emacs +manual.) + +~dict-describe-word~ uses the word at point, if any, as the minibuffer's default +argument (see [[info:emacs#Basic Minibuffer][Basic Minibuffer]]). This means that you can display the definition +of the word at point by typing ~M-x dict-describe-word RET RET~. + +Dictionary servers usually support several dictionaries that you can query. +When Dict asks the dictionary server for a word definition, it needs to specify +in which dictionary the server should look. The dictionary Dict uses is +determined by the user option ~dict-dictionary~. By default this is set to +~nil~, which says to prompt for a supported dictionary the first time you invoke +~dict-describe-word~. + +Similarly, the user option ~dict-strategy~ specifies a dictionary matching +strategy for finding completion candidates. This is set to ~nil~ by default, +like ~dict-dictionary~, which means that ~dict-describe-word~ prompts also for a +supported matching strategy the first time you use it. + +You can customize ~dict-dictionary~ and ~dict-strategy~ to appropriate values +before calling ~dict-describe-word~ to inhibit these prompts on first use. +(Also see [[#customization][Customizing Dict]] for more customization options.) + +* Customizing Dict +:PROPERTIES: +:CUSTOM_ID: customization +:DESCRIPTION: Customization options for Dict +:ALT_TITLE: Customization +:END: + +The following user options affect the behavior of ~dict-describe-word~: + +- User Option: dict-server-host :: Host name or IP address of the + dictionary server to use. Defaults to ~nil~, which means to first + try "localhost", and if no local server is available then fallback + to the host specified by ~dict-default-server-host~. +- User Option: dict-default-server-host :: Remote dictionary server to + use when there is no local server and ~dict-server-host~ is ~nil~. + Defaults to "dict.org". +- User Option: dict-server-port :: Port number to use for connecting to the + dictionary server. Defaults to 2628. +- User Option: dict-dictionary :: Name of the dictionary to query, which must be + supported by the dictionary server. Default to ~nil~, which means to prompt + for a supported dictionary on the first invocation of ~dict-describe-word~. +- User Option: dict-dictionary-prompt :: Prompt string to use when prompting for + a dictionary. Defaults to "Set dictionary". +- User Option: dict-strategy :: Name of the dictionary matching strategy to use, + which must be supported by the dictionary server. Default to ~nil~, which + means to prompt for a supported strategy on the first invocation of + ~dict-describe-word~. +- User Option: dict-strategy-prompt :: Prompt string to use when prompting for a + matching strategy. Defaults to "Set matching strategy". +- User Option: dict-process-name :: Name to use for the dictionary server + connection process. Defaults to "dict". +- User Option: dict-process-buffer-name :: Name of the buffer to use for the + dictionary server connection process output. Defaults to "*​dict output*". + #+FINDEX: dict-display-definition-in-help-buffer +- User Option: dict-display-definition-function :: Function to use for + displaying word definitions. The function must take two string arguments, the + word and its definition, and display the definition to the user. Defaults to + the function ~dict-display-definition-in-help-buffer~, which displays the + definition in a =*Help*= buffer. + +* Extending Dict +:PROPERTIES: +:CUSTOM_ID: extending-dict +:DESCRIPTION: Defining bespoke extensions for Dict +:ALT_TITLE: Extending Dict +:END: + +The best way to extend Dict with bespoke commands for your workflow, is to +define wrappers around ~dict-describe-word~ that supply specific words or +locally bind some user options to specific values. For example, the following +command looks up the definition of the word at point in the WordNet dictionary +without prompting: + +#+begin_src emacs-lisp + (defun my/wordnet-definition-for-word-at-point (word) + (interactive (list (word-at-point))) + (let ((dict-dictionary "wn")) + (dict-describe-word word))) +#+end_src + +To create a command that displays definitions in the echo area (see [[info:emacs#Echo Area][Echo Area]]), +locally bind ~dict-display-definition-function~ to an appropriate function: + +#+begin_src emacs-lisp + (defun my/echo-word-definition (word) + (interactive (list (dict-read-word))) + (let ((dict-display-definition-function + (lambda (_word definition) + (message definition)))) + (dict-describe-word word))) +#+end_src + +#+FINDEX: dict-read-word +Note the use of the function ~dict-read-word~ in the above definition. +This helper function prompts for a word defined in dictionary, with +completion, using the word at point as the minibuffer's default +argument. This is also what ~dict-describe-word~ uses to prompt for a +word when you call it interactively. + +* TODO How Dict Compares to Other RFC2229 Client Packages +:PROPERTIES: +:CUSTOM_ID: alternatives +:DESCRIPTION: Comparison of Dict with other RFC2229 client packages +:ALT_TITLE: Alternatives +:END: + +** dictionary + +** define-word + +** DictEm + + +#+html: diff --git a/dict.el b/dict.el index 1582800..fa1b04a 100644 --- a/dict.el +++ b/dict.el @@ -5,8 +5,8 @@ ;; Author: Eshel Yaron ;; Keywords: help, comm ;; URL: https://git.eshelyaron.com/gitweb/dict.git -;; Package-Version: 0.1.0 -;; Package-Requires: ((emacs "29.1")) +;; Package-Version: 0.1.1 +;; Package-Requires: ((emacs "28.1")) ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ ;; Dict defines a single command that displays the definition of a ;; given word, as obtained from an RFC2229 dictionary server. To use -;; it, invoke \\[dict-describe-word]. +;; it, do M-x dict-describe-word (or bind it to a key). ;;; Code: @@ -33,6 +33,14 @@ "Access to RFC2229 dictionary servers." :group 'help) +(defcustom dict-strategy-prompt "Set matching strategy" + "Prompt to use for dictionary matching strategies selection." + :type 'string) + +(defcustom dict-dictionary-prompt "Set dictionary" + "Prompt to use for dictionary selection." + :type 'string) + (defcustom dict-process-buffer-name "*dict output*" "Buffer name for dictionary server output." :type 'string) @@ -41,9 +49,10 @@ "Process name for dictionary server connection." :type 'string) -(defcustom dict-server-host "dict.org" +(defcustom dict-server-host nil "Host or IP address of dictionary server." - :type 'string) + :type '(choice (const :tag "Try local server, fallback to `dict-default-server-host'" nil) + (string :tag "Select host"))) (defcustom dict-server-port 2628 "Port of dictionary server." @@ -64,12 +73,30 @@ "Function to use for displaying dictionary definitions." :type 'function) +(defcustom dict-default-server-host "dict.org" + "Remote server to use when there is no local server. +This is only considered when the user option `dict-server-host' +is nil." + :type 'string) + (defvar dict-process nil) (defvar dict-read-word-history nil) (defvar dict-match-cache nil) +(defun dict-server-host () + (or dict-server-host + (when-let ((proc (condition-case _ + (make-network-process + :name dict-process-name + :host "localhost" + :service dict-server-port) + (file-error nil)))) + (delete-process proc) + (setq dict-server-host "localhost")) + (setq dict-server-host dict-default-server-host))) + (defun dict-command (command parse) "Invoke a dictionary server command. COMMAND is an RFC2229 command in string format, without a newline. @@ -99,7 +126,7 @@ beginning of a buffer with the server's response." (setq dict-process (make-network-process :name dict-process-name - :host dict-server-host + :host (dict-server-host) :service dict-server-port :buffer buffer))))) (set-process-filter proc filter) @@ -156,8 +183,8 @@ beginning of a buffer with the server's response." result)) result))))) -(defun dict-read-strategy () - "Prompt for a matching strategy supported by the dictionary server." +(defun dict-read-strategy (prompt) + "Prompt with PROMPT for a matching strategy supported by the server." (let* ((strats (dict-get-strategies)) (len (apply #'max (mapcar #'length (mapcar #'car strats)))) (completion-extra-properties @@ -165,15 +192,19 @@ beginning of a buffer with the server's response." (lambda (key) (concat (make-string (1+ (- len (length key))) ?\s) (alist-get key strats nil nil #'string=)))))) - (completing-read "Strategy: " - strats nil t))) + (completing-read (format-prompt prompt dict-strategy) + strats nil t nil nil dict-strategy))) + +(defun dict-set-strategy () + "Prompt for a value and set the user option `dict-strategy'." + (setq dict-strategy (dict-read-strategy dict-strategy-prompt))) (defun dict-strategy () "Return the value of the user option `dict-strategy'. If its nil, prompt for a supported strategy and set the user option to it first." (or dict-strategy - (setq dict-strategy (dict-read-strategy)))) + (dict-set-strategy))) (defun dict-get-dictionaries () "Return the dictionary server's supported dictionaries." @@ -192,8 +223,8 @@ option to it first." result)) result))))) -(defun dict-read-dictionary () - "Prompt for dictionary server's supported by the dictionary server." +(defun dict-read-dictionary (prompt) + "Prompt with PROMPT for a dictionary supported by the server." (let* ((dicts (dict-get-dictionaries)) (len (apply #'max (mapcar #'length (mapcar #'car dicts)))) (completion-extra-properties @@ -201,18 +232,22 @@ option to it first." (lambda (key) (concat (make-string (1+ (- len (length key))) ?\s) (alist-get key dicts nil nil #'string=)))))) - (completing-read "Dictionary: " - dicts nil t))) + (completing-read (format-prompt prompt dict-dictionary) + dicts nil t nil nil dict-dictionary))) + +(defun dict-set-dictionary () + "Prompt for a value and set the user option `dict-dictionary'." + (setq dict-dictionary (dict-read-dictionary dict-dictionary-prompt))) (defun dict-dictionary () "Return the value of the user option `dict-dictionary'. If its nil, prompt for a supported dictionary and set the user option to it first." (or dict-dictionary - (setq dict-dictionary (dict-read-dictionary)))) + (dict-set-dictionary))) (defun dict-read-word () - "Prompt for a word known to the dictionary server." + "Prompt for a word defined in the dictionary server." (let* ((completion-ignore-case t) (word-at-point (thing-at-point 'word t)) (default (car (dict-match-word word-at-point))))