pax_global_header00006660000000000000000000000064120162323470014512gustar00rootroot0000000000000052 comment=2381385898693aaac2fa681e31d74fd06a37bc42 dictem-1.0.4/000077500000000000000000000000001201623234700127615ustar00rootroot00000000000000dictem-1.0.4/AUTHORS000066400000000000000000000001241201623234700140260ustar00rootroot00000000000000Mon, 20 Oct 2003 20:40:46 +0300 DictEm was written by Aleksey Cheusov dictem-1.0.4/COPYING000066400000000000000000000001401201623234700140070ustar00rootroot00000000000000GNU GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html http://opensource.org/licenses/gpl-2.0.php dictem-1.0.4/NEWS000066400000000000000000000227001201623234700134610ustar00rootroot00000000000000Version 1.0.4, Sat, 25 Aug 2012 23:23:24 +0300 - Flag (interactive) was removed from the following functions: dictem-select-strategy, dictem-select-database, dictem-read-query and dictem-run. This fixes Debian bug #564251. Version 1.0.3, Sun, 22 Jul 2012 13:12:00 +0300 - fix: "dictem-get-matches" function returns dictionary names without ":" in the end. - fix. insertion of text produced by "dict" client of by user's database is always made IN THE END of dictem buffer. This fixes the problems with hightlighting in match/define mixed results. - Fix failure when dictem-use-user-databases-only is t. The problem was that dictem-last-database variable was initialized incorrectly. Version 1.0.2, Sun, 22 Mar 2009 17:20:12 +0200 Another fix in dictem-postprocess-definition-remove-header. Version 1.0.1, Fri, 20 Mar 2009 12:43:15 +0200 - fix in dictem-postprocess-definition-remove-header. It wrongly deleted extra line Version 1.0.0, Sat, 11 Oct 2008 18:59:15 +0300 - Running dictem-initialize everytime your network/internet is up (if case you have no permanent connection to Internet, e.g. dial-up, adsl etc.) is a bit annoying. To avoid this dictem is (re)initialized (if needed) automatically from dictem-select-strategy and dictem-select-database functions. As a result, running dictem-initialize in .emacs becomes unnecessary - New function (dictem-reinitialize-err) added - Minor fix in dictem-initialize-databases-alist function. Now it returns error data in case of failure, not nil. (just like dictem-initialize-strategies-alist) Version 0.82, Mon, 28 Jan 2008 22:59:07 +0200 - FIX for emacs-22 (insert-string is replaced with insert) - Minor fixes in README Version 0.81, Sat, 22 Jul 2006 15:45:53 +0300 - dictem-server variable can be equal to nil, in this case 'dict' command line tool will be called without -h option, i.e. default _list of servers_ specified in .dictrc (or dict.conf) will be used. dict:///dictionary_name (in dictem-user-databases-alist) also means that default server list will be used, see Ex.4 for the sample of use. - dictem-server variable now defaults to nil, old value was "dict.org". dictem-strategy-alist and dictem-database-alist also defaults to nil. Version 0.8, Mon, Sun, 28 May 2006 00:23:43 +0300 - removed: ./configure / make / make install See installation section in README if you are in trouble - added: dictem-exclude-databases variable to disable some databases from autocompletion menu, see example 15 in README file. example for those who uses dict://dict.org: (setq dictem-exclude-databases '("tur-" "afr-" "ara-" "cro-" "cze-" "dan-" "hin-" "hun-" "iri-" "ita-" "kha-" "lat-" "nld-" "por-" "sco-" "scr-" "slo-" "swa-" "swe-" "tur-" "rom-" "wel-" "-tur" "-afr" "-ara" "-cro" "-cze" "-dan" "-hin" "-hun" "-iri" "-ita" "-kha" "-lat" "-nld" "-por" "-sco" "-scr" "-slo" "-swa" "-swe" "-tur" "-rom" "-wel")) - errors messages obtained from 'dict' command are printed in case initialization failure but the constant string. Version 0.7, Mon, 3 Apr 2006 15:11:57 +0300 - DICTEM can handle dictionaries defined by user. This allows to use dictem not only for accessing DICT servers, but also for accesing user's databases. See Ex.14 in README file for a simple example. - added: dictem-client-prog-args-list variable that keeps a list of additional arguments to the command line 'dict' client. This may be helpful in case you use 'dict' wrappers (having additional options) or new versions of 'dict' program. - added: dictem-option-mime variable. If `t' the OPTION MIME command (see RFC-2229 for details) will be sent to the DICT server. i.e. 'dict' program will be run with '-M' option. As a result server's response will be prepanded with MIME header followed by a blank line. Because of bugs in dict -M (dict version < 1.10.3), dict-1.10.3 or later is STRONGLY recommended. MIME-ized content can be postprocessed by functions called from dictem-postprocess-xxxx hooks. Because the current version of dictem doesn't contain such kind of functions, this variable should be used by those who program in Emacs. Suggestions and code are welcomed as always. Have a lot of fun ;-) - added: dictem-run-show-strategies function, similar to dictem-run-show-databases. - more complete dictem-mode's help string (documentation for dictem mode) - new examples of dictem usage in Ex.9 section - minor fixes in documentation and README Version 0.0.5, Wed, 8 Jun 2005 19:56:56 +0300 - new examples in README file: Ex.12-13 - `dictem-postprocess-collect-hyperlinks' function (when added to `dictem-postprocess-definition-hook', `dictem-postprocess-show-info-hook' or `dictem-postprocess-show-server-hook' hooks) collects hyperlinks in the variable `dictem-hyperlinks-alist'. This variable is used by the function `dictem-hyperlinks-menu' which implements the autocompletion-based menu the same way `Info-menu' does. "e" is assigned to call the function `dictem-hyperlinks-menu'. The variable `dictem-hyperlinks-alist' is local to buffer. - If `dictem-use-existing-buffer' variable is `t' and dictem-use-content-history is not nil, the entire buffer content and (point) is stored in `dictem-content-history' variable when you click on hyperlink and thus you can easily return to the previous buffer by pressing "l" (`dictem-last' function). "l" is assigned to function `dictem-last'. It works just like the button in the WEB browsers. - added: `dictem-postprocess-definition-remove-header', function for postprocessing DEFINE buffer. It is intended to remove header `XXX definition[s] found' at the beginning of dict's output and can be added to the hook `dictem-postprocess-definition-hook'. - fixes: `dictem-kill-all-buffers' has been reimplemented for using `dolist' macros instead of recursion. Recursion-bases implementation causes dictem to fail when lots of buffers exist. Thanks to Juri Linkov for bug reports and lots of suggestions. - String that begins hyperlink is stored in the variable `dictem-hyperlink-beginning', defaults to "{" String that ends hyperlink is stored in the variable `dictem-hyperlink-end, defaults to "}" Function that is called when hyperlink "define" is activated is stored in the variable `dictem-hyperlink-define-func', defaults to `dictem-base-define' All this stuff may be useful for more complex buffer postprocessing. Hyperlinks are not always enclosed in '{' and '}' braces. Version 0.0.4, Thu, 24 Feb 2005 19:40:24 +0200 dictem-default-database (dictem-default-strategy) variables override value of dictem-last-database (dictem-last-strategy) variable, i.e. when dictem-default-xxx is set to non-nil this database (strategy) is always used by default, otherwise the last used database (strategy) is used. All examples in README file are know numbered. New examples #10 and #11 in README file. By default dictem uses the default query as an initial input, this may be very useful. To disable this behaviour set `dictem-empty-initial-input' to `t'. See (describe-variable 'dictem-empty-initial-input) and REAME example #11. FIXED: `dictem-last-database' keeps "low-level" database name but the user's virtual one. As a result virtual dictionary could not be the default one (kept in dictem-last-database or dictem-default-database variable ). Version 0.0.3, Tue, 14 Dec 2004 20:43:34 +0200 DictEm has been ported to XEmacs Virtual dictionaries can access databases from different DICT servers (setq dictem-user-databases-alist '(("_translate" . ("dict://mova.org/mueller7" "dict://dict.org:2628/web1913")) ("_ru-ru" . ("beslov" "dict://mova.org:2628/religion")) )) See README file for more information. The following commands can be run non-interactively. `dictem-run-show-info', `dictem-run-search' and `dictem-run-define' `dictem-next-link' and `dictem-previous-link' skip hyperlinks on database names. Renamed: `dictem-url' to `dictem-make-url' `link-create-link' to `dictem-create-link' DictEm's prompt looks like this: ` []:' New default faces Lots of README updates. A few fixes Version 0.0.2, Tue, 30 Nov 2004 16:40:00 +0200 added: new function `dictem-kill-all-buffers' killing all dictem buffers. The key "x" press in dictem buffer use it. dictem-postprocess-definition-hyperlinks function: When a substring {foo|bar} is encountered in a definition, `foo' is used for highlighting and `bar' is used for subsearch. new functions: `dictem-next-link' and `dictem-previous-link' which set pointer to the next (or previous) hyper link \M-n and \M-p key are assigned to `dictem-next-link' and `dictem-previous-link' When pressing RET (C-m) key on hyper link, subsearch DICT server is sent a DEFINE command added: new customizable variable: `dictem-use-existing-buffer' which can be used to use existing dictem buffer instead of creating a new one for subsearches. This variable is local to buffer. Documentation update Version 0.0.1, Thu, 08 Jul 2004 13:58:59 +0300 first publicly available release dictem-1.0.4/README000066400000000000000000000406231201623234700136460ustar00rootroot00000000000000DictEm is a Dictionary protocol client for GNU Emacs. It uses a console dict client (http://sf.net/projects/dict) and implements all functions of the client part of DICT protocol (RFC-2229, www.dict.org), i.e. looking up words and definitions, obtaining information about available strategies, provided databases, information about DICT server etc. Unlike dictionary.el (http://www.myrkr.in-berlin.de/dictionary/index.html) DictEm widely uses autocompletion that is used for selecting dictionary and search strategy. Moreover, DictEm provides several hooks which may be used for buffer postprocessing. For example, inbuilt hyperlinking and highlighting mechanisms are based on this possibility. Another example is that information obtained from DICT server that is in HTML, ROFF or INFO format can be easily viewed by Emacs+DictEm if the user supplies appropriate conversion functions. Of course DictEm can be differently configured for different Emacs modes (major, minor or buffer oriented), that allows modularized access to all data serviced by DICT servers. This makes it ideal tool for translating articles between a series of foreign languages, browsing manuals and other tasks depending on Emacs mode user currently works with. Additionally DictEm supports accessing so called virtual dictionaries (a set of dictionaries provided by DICT server that user prefers to treat as a single one). Yet another feature DictEm provides is a set of useful functions with a help of which user can extend DictEm functionality such as to define new search strategies or even provide new functionality such as to use another sources of data other than DICT servers. See below for a set of example configuration and extensions. Also DictEm uses customization mechanism provided by Emacs that helps Emacs users to easily configure DictEm. COPYING ============ See the file COPYING DOWNLOAD ======== Latest sources can be downloaded from http://sourceforge.net/projects/dictem or http://freshmeat.net/projects/dictem INSTALLATION ============ * In order to uncompress dictem tarball run the following. tar xfv dictem-x.y.z.tar.gz If you read this file, you probably have already done this. * Change your current directory to dictem. cd dictem-x.y.z * Copy *.el file to the directory you want. cp *.el /path/to/emacs/el/files * Make sure that DICT client named dict (available at http://sf.net/projects/dict) is installed on your system. Console dict client is used by DictEm for accessing the DICT server. dict-1.9.14 or later is strongly recommended. If you'll set dictem-option-mime variable to t (read below), dict-1.10.3 or later MUST be used. REPORTING BUGS ============== Please send all bug reports and suggestions directly to Aleksey Cheusov . Reporting bugs at sf.net is also good. Also note that there exists dict-beta@dict.org mailing list (low traffic) where you can ask questions about DICT protocol and software. CONFIGURING ============= Customization group ------------------- Take note, that DictEm defines customization group "dictem". So, it may be easier for you to customize DictEm by running M-x customize-group dictem Manual Configuration -------------------- Ex.1 The easiest configuration of dictem may look like this ; Add to load-path variable a new directory with files of dictem (add-to-list 'load-path "/path/you/installed/dictem/to") ; Loading dictem functions (require 'dictem) ; Setting the dictionary server hostname. ; This part is optional, if dictem-server is nil (the default value) ; "dict" command line utility will use its ows config file ; ~/.dictrc or PREFIX/etc/dict.conf. ; Keeping dictem-server variable unset is recomended because ; this allows to try _list of_ servers until connection is made, ; see dict(1) for details. ;(setq dictem-server "localhost") ;(setq dictem-server "dict.org") ; Setting the dictionary server port. ; Setting dictem-port is usually not necessary because ; most DICT servers use the default port 2628. ;(setq dictem-port "2628") ; Code necessary to obtain database and strategy list from DICT ; server. As of version 0.90, dictem runs this function from ; dictem-select-database and dictem-select-strategy if an ; initialization was not completed or failed previously, that is ; running dictem-initialize is optional (dictem-initialize) ; Assigning hot keys for accessing DICT server ; SEARCH = MATCH + DEFINE ; Ask for word, database and search strategy ; and show definitions found (global-set-key "\C-cs" 'dictem-run-search) ; MATCH ; Ask for word, database and search strategy ; and show matches found (global-set-key "\C-cm" 'dictem-run-match) ; DEFINE ; Ask for word and database name ; and show definitions found (global-set-key "\C-cd" 'dictem-run-define) ; SHOW SERVER ; Show information about DICT server (global-set-key "\C-c\M-r" 'dictem-run-show-server) ; SHOW INFO ; Show information about the database (global-set-key "\C-c\M-i" 'dictem-run-show-info) ; SHOW DB ; Show a list of databases provided by DICT server (global-set-key "\C-c\M-b" 'dictem-run-show-databases) ------- Ex.2 There are a few functions that can make dictem look a bit nicer and be more functional. They should be added to special hooks like the following. ; For creating hyperlinks on database names ; and found matches. ; Click on them with mouse-2 (add-hook 'dictem-postprocess-match-hook 'dictem-postprocess-match) ; For highlighting the separator between the definitions found. ; This also creates hyperlink on database names. (add-hook 'dictem-postprocess-definition-hook 'dictem-postprocess-definition-separator) ; For creating hyperlinks in dictem buffer ; that contains definitions. (add-hook 'dictem-postprocess-definition-hook 'dictem-postprocess-definition-hyperlinks) ; For creating hyperlinks in dictem buffer ; that contains information about a database. (add-hook 'dictem-postprocess-show-info-hook 'dictem-postprocess-definition-hyperlinks) ------- Ex.3 If you want to combine some databases in you own "virtual" dictionary, create them like this (setq dictem-user-databases-alist '(("_en-ru" . ("mueller7" "korolew_en-ru")) ("_en-en" . ("foldoc" "gcide" "wn")) ("_ru-ru" . ("beslov" "ushakov" "ozhegov" "brok_and_efr")) ("_unidoc" . ("susv3" "man" "info" "howto" "rfc")) )) As a result four new special database collections will be created and new names will appear when dictem-run function will ask you about database name. ------- Ex.4 You can even create virtual dictionaries which consist of databases from different DICT server. The dict url form dict:///religion means 'dict' command line tool will be called without -h option, i.e. a list of dictionary servers from .dictrc (or dict.conf) will be used. (setq dictem-user-databases-alist '(("_en-ru" . ("dict://mova.org/mueller7" "dict://dict.org:2628/web1913")) ("_ru-ru" . ("beslov" "dict:///religion")) )) another example: (setq dictem-user-databases-alist `(("en-en" . ("dict://dict.org:2628/english")) ("en-ru" . ("dict:///en-ru" "dict://dict.org:2628/eng-rus" )) )) ------- Ex.5 If your DICT server provides too many databases and most of which are of no interest for you, you can disable them and use only those specified in dictem-user-databases-alist variable. (setq dictem-use-user-databases-only t) ------- Ex.6 Of course, you can assign your own key bindings in dictem buffer (define-key dictem-mode-map [tab] 'dictem-next-link) (define-key dictem-mode-map [(backtab)] 'dictem-previous-link) ------- Ex.7 You are not limited to the default DICT server only. The following code will allow you to access any server you want. You'll be asked for host and port. ; DEFINE (global-set-key "\C-c\M-d" '(lambda () (interactive) (save-dictem (let* ((dictem-server (read-string "server: " dictem-server nil "dict.org")) (dictem-port (read-string "port: " (dictem-get-port) nil "2628"))) (dictem-initialize) (call-interactively 'dictem-run-define))))) ; MATCH (global-set-key "\C-c\M-m" '(lambda () (interactive) (save-dictem (let* ((dictem-server (read-string "server: " dictem-server nil "dict.org")) (dictem-port (read-string "port: " (dictem-get-port) nil "2628"))) (dictem-initialize) (call-interactively 'dictem-run-match))))) ; SEARCH = MATCH+DEFINE (global-set-key "\C-c\M-s" '(lambda () (interactive) (save-dictem (let* ((dictem-server (read-string "server: " dictem-server nil "dict.org")) (dictem-port (read-string "port: " (dictem-get-port) nil "2628"))) (dictem-initialize) (call-interactively 'dictem-run-search))))) ; SHOW INFO (global-set-key "\C-c\M-i" '(lambda () (interactive) (save-dictem (let* ((dictem-server (read-string "server: " dictem-server nil "dict.org")) (dictem-port (read-string "port: " (dictem-get-port) nil "2628"))) (dictem-initialize) (call-interactively 'dictem-run-show-info))))) ; SHOW SERVER (global-set-key "\C-c\M-r" '(lambda () (interactive) (save-dictem (let* ((dictem-server (read-string "server: " dictem-server nil "dict.org")) (dictem-port (read-string "port: " (dictem-get-port) nil "2628"))) (dictem-initialize) (call-interactively 'dictem-run-show-server))))) ------- Ex.8 Some databases may have specially formatted definitions, for example, HTML, MIME, DICF or ROFF formats. It is easy to postprocess them. ; All functions from dictem-postprocess-each-definition-hook ; will be run for each definition which in turn will be narrowed. ; Current database name is kept in dictem-current-dbname variable. ; The following code demonstrates how to highlight SUSV3 and ROFF ; definitions. (add-hook 'dictem-postprocess-definition-hook 'dictem-postprocess-each-definition) ; Function for highlighting definition from the database "susv3". (defun dictem-highlight-susv3-definition () (cond ((string= "susv3" dictem-current-dbname) (goto-char (point-min)) (while (search-forward-regexp "^ *[QWERTYUIOPASDFGHJKLZXCVBNM ]+$" nil t) (put-text-property (match-beginning 0) (match-end 0) 'face 'bold) )))) ; Function to show roff-formatted text from the database "man". (require 'woman) (defun dictem-highlight-man-definition () (cond ((string= "man" dictem-current-dbname) (goto-char (point-min)) (while (search-forward-regexp "^ " nil t) (replace-match "")) (goto-char (point-min)) (forward-line 2) (woman-decode-region (point) (point-max)) ))) (add-hook 'dictem-postprocess-each-definition-hook 'dictem-highlight-susv3-definition) (add-hook 'dictem-postprocess-each-definition-hook 'dictem-highlight-man-definition) ------- Ex.9 ; The dictem's top level function is 'dictem-run'. ; By using it more advanced ELISP programmers ; can create their own search scenaria. Look at this code. (dictem-run 'dictem-base-search "gcide" "apple" "lev") (dictem-run 'dictem-base-match "dict://mova.org/mueller7" "apple" "exact") (dictem-run 'dictem-base-define '("dict://mova.org/mueller7" "dict://dict.org/gcide") "apple" "exact") (dictem-run 'dictem-base-show-info "dict://dict.org/gcide") (let ((dictem-server "localhost")) (dictem-run '(lambda (a b c) (dictem-base-show-strategies nil nil nil) (dictem-base-show-databases nil nil nil) (dictem-base-show-server nil nil nil) ))) (dictem-run '(lambda (a b c) (dictem-base-define '("man" "susv3") (dictem-read-query (thing-at-point 'word)) nil )) nil nil) (let ((query (dictem-read-query (thing-at-point 'word)))) (dictem-run `((lambda (a b c) (dictem-base-match '("gcide" "wn") ,query "exact")) (lambda (a b c) (dictem-base-search '("mueller7" "korolew_en-ru") ,query "word"))))) ------- Ex.10 By default dictem remembers the database name and strategy that was used last time. The dictem-select-database and dictem-select-strategy functions will use these values as a default in the minibuffer. If you dislike this behaviour, set variables dictem-default-database and/or dictem-default-strategy. (add-hook 'c-mode-common-hook '(lambda () (interactive) (make-local-variable 'dictem-default-database) (setq dictem-default-database "man") )) The example above sets default database to "man" in C buffers. ------- Ex.11 As of dictem-0.0.4 dictem-empty-initial-input customizable variable tells dictem-read-query whether to leave initial input empty or not. It is `nil' by default. For emulating behaviour of older releases, set it to `t'. (setq dictem-empty-initial-input t) ------- Ex. 12 By default dictem-postprocess-definition-hyperlinks function assumes that hyperlinks have the following form: {foo} or {foo|bar}. Sometimes "{" and "}" characters are general characters in definitions. The following code changes "{" and "}" for "{link-beg " and " link-end" respectively inside definitions obtained from the databases "^infopage-..." ; new function is used for creating hyperlinks ; which works differently depending on database name (defun my-dictem-postprocess-definition-hyperlinks () "Creating hyperlinks according to database name" (interactive) (cond ( ((string-match "^infopage-" dictem-current-dbname) (let ((dictem-hyperlink-beginning "{link-beg ") (dictem-hyperlink-end " link-end}") ) (dictem-postprocess-definition-hyperlinks))) (t (dictem-postprocess-definition-hyperlinks))))) ; definitions from each database are processed separately (add-hook 'dictem-postprocess-definition-hook 'dictem-postprocess-each-definition) (add-hook 'dictem-postprocess-each-definition-hook 'my-dictem-postprocess-definition-hyperlinks) ------- Ex. 13 You may want to remove "XXX definition[s] found" header from the DEFINE buffers. It may be done with a help of dictem-postprocess-definition-remove-header function. (add-hook 'dictem-postprocess-definition-hook 'dictem-postprocess-definition-remove-header) ------- Ex. 14 As of version 0.7 dictem can handle dictionaries defined by user. This allows to use dictem not only for accessing DICT servers, but also for accesing users' databases. ; DEFINE function for the database "mysuperdb" (defun dictem-mysuperdb-DEFINE (query) (cond ((string= query "apple") '("Apples grow on the trees" "Apple may be green, yellow or red")) ((string= query "potato") '("Potato is a vegetable" "Potato is a traditional Belarusian food")) (t (dictem-make-error 20 (format "No definitions for %s" query))) )) ; MATCH function for the database "mysuperdb" (defun dictem-mysuperdb-MATCH (query strategy) ; the name of strategy is ignored (let ((apple (string-match query "apple")) (potato (string-match query "potato"))) (cond ((and (string= strategy "exact") (string= query "apple")) '("apple")) ((and (string= strategy "exact") (string= query "potato")) '("potato")) ((and apple potato) '("apple" "potato")) (apple '("apple")) (potato '("potato")) (t (dictem-make-error 20 (format "No matches for %s/%s" query strategy))) ))) ; Initializing a list of user-defined databases (setq dictem-user-databases-alist `(("_en-en" . ("foldoc" "gcide" "wn")) ("_ru-ru" . ("beslov" "ushakov" "ozhegov" "brok_and_efr")) ,(dictem-make-userdb ; the name of the database "mysuperdb" ; short description "My super database" ; MATCH function (symbol-function 'dictem-mysuperdb-MATCH) ; DEFINE function (symbol-function 'dictem-mysuperdb-DEFINE)) )) ------- Ex. 15 Last years many dictionary servers provide too many bilingual dictionaries, most of which may be not very interesting for you. DictEm allows to exclude such dictionaries from an autocompletion menu by setting a list of regular expressions in dictem-exclude-databases variable. If, for example, you don't speak french and german and use dict://dict.org server, your config may look like this (setq dictem-server "dict.org") (setq dictem-exclude-databases '("ger-" "-ger" "fra-" "-fra")) (dictem-initialize) Note that, (dictem-initialize) is placed after initializing dictem-exclude-databases variable. ------- If you have read to this point and all the examples above seem easy, you are probably a ELISP Guru. So, I have nothing more to tell you ;-) Feel free to inspect the code, and I hope you'll find DictEm useful. Dict'em All! ;-) dictem-1.0.4/TODO000066400000000000000000000001001201623234700134400ustar00rootroot00000000000000Do you have ideas, want new features, see bugs? Let me know ;-) dictem-1.0.4/dictem-elisp.el000066400000000000000000000057751201623234700157000ustar00rootroot00000000000000(require 'dictem) (defun dictem-elisp-variable-documentation (func) (let* ((help-buffer "*Help*") (temp-buffer-show-function (lambda (b) ())) ) (if (boundp func) (save-excursion (describe-variable func) (set-buffer help-buffer) (prog1 (buffer-substring (point-min) (point-max)) (kill-this-buffer help-buffer)) ) nil))) (defun dictem-elisp-function-documentation (func) (let* ((help-buffer "*Help*") (temp-buffer-show-function (lambda (b) ())) ) (if (functionp func) (save-excursion (describe-function func) (set-buffer help-buffer) (prog1 (buffer-substring (point-min) (point-max)) (kill-this-buffer)) ) nil))) (defun dictem-elisp-DEFINE (query) (let ((sym (intern-soft query)) (doc nil)) ; (ret (if (and sym (functionp sym)) ; (documentation sym) ; nil))) (cond ((null sym) (dictem-make-error 20 (format "SYmbol '%s is not defined" query))) ((functionp sym) (setq doc (dictem-elisp-function-documentation sym)) (if doc doc (dictem-make-error 20 (format "'%s is not documented as a function" query)))) (t (setq doc (dictem-elisp-function-documentation sym)) (if doc doc (dictem-make-error 20 (format "'%s is documented as neither function not variable" query))) )))) ; (documentation sym)) ; (t (dictem-make-error ; 20 (format "There is no function '%s" query)))))) (defun dictem-string-match-prefix (pattern string) (eq 0 (string-match (regexp-quote pattern) string))) (defun dictem-string-match-substring (pattern string) (string-match (regexp-quote pattern) string)) (defun dictem-string-match-suffix (pattern string) (string-match (regexp-quote pattern) string) (= (length string) (match-end 0))) (defun dictem-string-match-word (pattern string) (string-match (concat "\\b\\(" (regexp-quote pattern) "\\)\\b") string)) (defun dictem-elisp-MATCH-UNI (query fun) (let ((i 0) (l nil) ; (re (regexp-quote query)) (item nil)) (while (< i (length obarray)) (progn (setq item (symbol-name (elt obarray i))) (if (funcall fun (regexp-quote query) item) (setq l (cons item l))) (setq i (+ i 1)))) l)) (defun dictem-elisp-MATCH (query strategy) (let ((l (dictem-elisp-MATCH-UNI query (cond ((string= strategy "exact") (symbol-function 'string=)) ((string= strategy "word") (symbol-function 'dictem-string-match-word)) ((string= strategy "prefix") (symbol-function 'dictem-string-match-prefix)) ((string= strategy "suffix") (symbol-function 'dictem-string-match-suffix)) ((string= strategy "substring") (symbol-function 'dictem-string-match-substring)))))) (if l l (dictem-make-error 20 (format "No matches for %s/%s" query strategy))))) ;(dictem-elisp-MATCH "at" "word") ;(dictem-elisp-MATCH "file" "suffix") ;(dictem-elisp-MATCH "dictem" "prefix") ;(dictem-elisp-MATCH "s-s" "substring") ;(dictem-elisp-MATCH "pike" "substring") (provide 'dictem-elisp) dictem-1.0.4/dictem-lingvo-dsl.el000066400000000000000000000035161201623234700166310ustar00rootroot00000000000000;; -*- coding: utf-8; -*- (require 'dictem) (defun dictem-lingvo-dsl-highlight () ; trn/ex/com/* (goto-char (point-min)) (while (search-forward-regexp "\\[/?trn\\]\\|\\[/?p\\]\\|\\[/?c\\]\\|\\[/?com\\]\\|\\[/?[*]\\]\\|\\[/?b\\]\\|\\[/?i\\]\\|\\[/?m[0-9]?\\]\\|\\[/?ex\\]" nil t) (replace-match "" t t)) ; [ex] [/ex] ; (goto-char (point-min)) ; (while (search-forward-regexp "\\[ex\\]\\([][]*\\)\\[/ex\\]" nil t) ; (add-text-properties (match-beginning 0) (match-end 0) ; '(face dictem-lingvo-dsl-example-face)) ; (let* ((beg (match-beginning 1)) ; (end (match-end 1)) ; (repl (buffer-substring beg end))) ; (replace-match repl 1 1))) ; <<>> (goto-char (point-min)) (while (search-forward-regexp "\\(<<\\|\\[ref\\]\\)\\([^\n]*\\)\\(>>\\|\\[/ref\\]\\)" nil t) (let* ((beg (match-beginning 2)) (end (match-end 2)) (repl (buffer-substring beg end))) (replace-match (concat "{" repl "}") t t))) ; hyperlinks (dictem-postprocess-definition-hyperlinks) ) (progn (set-buffer "*dsl-buffer*") (dictem-lingvo-dsl-highlight)) (defface dictem-lingvo-dsl-italic-face '((((background light)) (:italic true)) (((background dark)) (:italic true))) "Face for italic" ) (defface dictem-lingvo-dsl-color-face '((((background light)) (:italic true)) (((background dark)) (:italic true))) "Face for color" ) (defface dictem-lingvo-dsl-example-face '((((background light)) (:italic true)) (((background dark)) (:italic true))) "Face for color" ) (defface dictem-lingvo-dsl-bold-face '((((background light)) (:bold true)) (((background dark)) (:bold true))) "Face for bold" ) (defface dictem-lingvo-dsl-trn-face '((((background light)) (:bold true :italic true)) (((background dark)) (:bold true :italic true))) "Face for trn" ) (provide 'dictem-lingvo-dsl) dictem-1.0.4/dictem.el000066400000000000000000001574121201623234700145620ustar00rootroot00000000000000; dictem.el - DICT protocol client (rfc-2229) for [X]Emacs ; This code was initially based on ; dictionary.el written by Torsten Hilbrich ; but now probably doesn't contain original code. ; Most of the code has been written ; from scratch by Aleksey Cheusov , 2004-2008. ; ; DictEm 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 2 of the License, or ; (at your option) any later version. ; ; DictEm 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 this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ; 02111-1307, USA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; NOTE! Documentation is in README file. ; ; Latest information about dictem project and sources ; are available at ; ; http://freshmeat.net/projects/dictem ; http://sourceforge.net/projects/dictem ; http://mova.org/~cheusov/pub/dictem ; (require 'cl) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; Custom Things ;;;;; (defgroup dictem nil "Client for accessing the DICT server." :tag "DictEm" :group 'help :group 'hypermedia) (defgroup dictem-faces nil "Face options for dictem DICT client." :tag "DictEm faces" :group 'dictem :group 'faces) (defcustom dictem-server nil "The DICT server" :group 'dictem :type '(restricted-sexp :match-alternatives (stringp 'nil))) (defcustom dictem-port 2628 "The port of the DICT server" :group 'dictem :type 'number) (defcustom dictem-client-prog "dict" "The command line DICT client. dictem accesses DICT server through this executable. dict-1.9.14 or later (or compatible) is strongly recomented." :group 'dictem :type 'string) (defcustom dictem-client-prog-args-list nil "A list of additional arguments (strings) passed to dict client. For example '(\"--some-option\")." :group 'dictem :type 'list) (defcustom dictem-option-mime nil "If `t' the OPTION MIME command (see RFC-2229 for details) will be sent to the DICT server. i.e. \"dict\" program will be run with \"-M\" option. As a result server's response will be prepanded with MIME header followed by a blank line. Because of bugs in dict -M (version < 1.10.3) utility, dict-1.10.3 or later is strongly recommended " :group 'dictem :type 'boolean) (defcustom dictem-default-strategy nil "The default search strategy." :group 'dictem :type 'string) (defcustom dictem-default-database nil "The default database name." :group 'dictem :type 'string) (defcustom dictem-user-databases-alist nil "ALIST of user's \"virtual\"databases. Valid value looks like this: '((\"en-ru\" . (\"mueller7\" \"korolew_en-ru\")) ((\"en-en\" . (\"foldoc\" \"gcide\" \"wn\"))) ((\"gazetteer\" . \"gaz\"))) " :group 'dictem :type '(alist :key-type string)) (defcustom dictem-exclude-databases nil "ALIST of regexps for databases that will not appear in autocompletion list. " :group 'dictem :type '(alist :key-type string)) (defcustom dictem-use-user-databases-only nil "If `t', only user's dictionaries from dictem-user-databases-alist will be used by dictem-select-database" :group 'dictem :type 'boolean) (defcustom dictem-mode-hook nil "Hook run in dictem mode buffers." :group 'dictem :type 'hook) (defcustom dictem-use-existing-buffer nil "If `t' the `dictem-run' function will not create new *dictem* buffer. Instead, existing buffer will be erased and used to show results. " :group 'dictem :type 'boolean) (defcustom dictem-empty-initial-input nil "If `t' the `dictem-read-query' leave initial input empty" :group 'dictem :type 'boolean) (defcustom dictem-use-content-history t "If not nil and dictem-use-existing-buffer is also not nil, buffer content and (point) is saved in dictem-content-history variable when DEFINE hyperlinks are accessed. It is restored by dictem-last function. On slow machines it may better to set this variable to nil" :group 'dictem) ;;;;; Faces ;;;;; (defface dictem-reference-definition-face '((((background light)) (:foreground "blue")) (((background dark)) (:foreground "cyan"))) "The face that is used for displaying a reference to a phrase in a DEFINE search." :group 'dictem-faces) (defface dictem-reference-m1-face '((((background light)) (:foreground "darkgreen")) (((background dark)) (:foreground "lightblue"))) "The face that is used for displaying a reference to a phrase in a MATCH search." :group 'dictem-faces) (defface dictem-reference-m2-face '((((background light)) (:foreground "blue")) (((background dark)) (:bold true :foreground "gray"))) "The face that is used for displaying a reference to a single word in a MATCH search." :group 'dictem-faces) (defface dictem-reference-dbname-face '((((background light)) (:foreground "darkgreen")) (((background dark)) (:bold t :foreground "white"))) "The face that is used for displaying a reference to database" :group 'dictem-faces) (defface dictem-database-description-face '((((background light)) (:bold t :foreground "darkblue")) (((background dark)) (:bold t :foreground "white"))) "The face that is used for displaying a database description" :group 'dictem-faces) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; Variables ;;;;; (defconst dictem-version "1.0.4" "DictEm version information.") (defvar dictem-strategy-alist nil "ALIST of search strategies") (defvar dictem-database-alist nil "ALIST of databases") (defvar dictem-strategy-history nil "List of strategies entered from minibuffer") (defvar dictem-database-history nil "List of database names entered from minibuffer") (defvar dictem-query-history nil "List of queries entered from minibuffer") (defvar dictem-last-database "*" "Last used database name") (defvar dictem-last-strategy "." "Last used strategy name") (defvar dictem-mode-map nil "Keymap for dictem mode") (defvar dictem-temp-buffer-name "*dict-temp*" "Temporary dictem buffer name") (defvar dictem-current-dbname nil "This variable keeps a database name of the definition currently processed by functions run from dictem-postprocess-each-definition-hook.") (defvar dictem-error-messages nil "A list of error messages collected by dictem-run") (defvar dictem-hyperlinks-alist nil "ALIST of hyperlinks collected from dictem buffer by the function dictem-postprocess-collect-hyperlinks (add this function to the hook dictem-postprocess-definition-hook). This variable is local to buffer") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-prepand-special-strats (l) (cons '(".") l)) (defun dictem-prepand-special-dbs (l) (cons '("*") (cons '("!") l))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; Functions ;;;;;; (defmacro save-dictem (&rest funs) `(let ((dictem-port 2628) (dictem-server nil) (dictem-database-alist nil) (dictem-strategy-alist nil) (dictem-use-user-databases-only nil) (dictem-user-databases-alist nil) ) (progn ,@funs) )) (defun dictem-client-text () "Returns a portion of text sent to the server for identifying a client" (concat "dictem " dictem-version ", DICT client for emacs")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Functions related to userdb ;; (defun dictem-make-userdb (name short-name match define) "Make user database object" (list name 'dictem-userdb short-name match define)) (defun dictem-userdb-p (obj) "Returns t if obj is the dictem error object" (and obj (listp obj) (cdr obj) (listp (cdr obj)) (eq (cadr obj) 'dictem-userdb))) (defun dictem-userdb-member (obj name) "Extract member from userdb object by its name" (cond ((dictem-userdb-p obj) (nth (cdr (assoc name '(("name" . 0) ("short-name" . 2) ("match" . 3) ("define" . 4)))) obj)) (t (error "Invalid type of argument")))) (defun dictem-userdb-DEFINE (buffer db query host port) (let* ((fun (dictem-userdb-member db "define")) (name (dictem-userdb-member db "name")) (sname (dictem-userdb-member db "short-name")) (ret (save-excursion (funcall fun query))) (buf (dictem-get-buffer buffer))) (save-excursion (set-buffer buf) (cond ((dictem-error-p ret) ; (insert "From " sname " [" name "]:\n\n" ; (dictem-error-message ret) "\n\n") ; (insert (dictem-error-message ret) "\n") (insert (dictem-error-message ret) "\n") (dictem-error-status ret)) ((null ret) (insert "No matches found" "\n") 20) ((listp ret) (dolist (definition ret) (insert "From " sname " [" name "]:\n\n" (dictem-indent-string definition) "\n\n")) 0) ((stringp ret) (insert "From " sname " [" name "]:\n\n" (dictem-indent-string ret) "\n\n") 0) (t (error "Invalid type of returned value1")))))) (defun dictem-userdb-MATCH (buffer db query strat host port) (let* ((fun (dictem-userdb-member db "match")) (name (dictem-userdb-member db "name")) (ret (save-excursion (funcall fun query strat))) (buf (dictem-get-buffer buffer))) (save-excursion (set-buffer buf) (cond ((dictem-error-p ret) (insert (dictem-error-message ret) "\n") (dictem-error-status ret)) ((listp ret) (insert (concat name ":\n")) (dolist (match ret); (insert (car db) ":\n" )) (progn (insert " " match "\n")) ) 0) (t (error "Invalid type of returned value2")))))) (defun dictem-userdb-SEARCH (buffer db query strat host port) (let* ((funm (dictem-userdb-member db "match")) (name (dictem-userdb-member db "name")) (sname (dictem-userdb-member db "short-name")) (sname nil) (ret (funcall funm query strat)) (buf (dictem-get-buffer buffer))) (save-excursion (set-buffer buf) (cond ((dictem-error-p ret) (insert (dictem-error-message ret) "\n") (dictem-error-status ret)) ((listp ret) (dolist (match ret) (dictem-userdb-DEFINE buffer db match host port)) 0) (t (error "Something strange happened")) )))) (defun dictem-userdb-SHOW-INFO (buffer db host port) (let ((sname (dictem-userdb-member db "short-name")) (buf (dictem-get-buffer buffer))) (save-excursion (set-buffer buf) (cond ((dictem-error-p sname) (insert (dictem-error-message sname) "\n") (dictem-error-status sname)) ((stringp sname) (insert sname) 0) (t (error "Something strange happened")) )))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Functions related to error object ;; (defun dictem-make-error (error_status &optional buffer-or-string) "Creates dictem error object" (cond ((stringp buffer-or-string) (list 'dictem-error error_status buffer-or-string)) ((bufferp buffer-or-string) (dictem-make-error error_status (save-excursion (set-buffer buffer-or-string) (goto-char (point-min)) (dictem-get-line) ))) ((eq nil buffer-or-string) (list 'dictem-error error_status buffer-or-string)) (t (error "Invalid type of argument")) )) (defun dictem-error-p (OBJECT) "Returns t if OBJECT is the dictem error object" (and (not (null OBJECT)) (listp OBJECT) (eq (car OBJECT) 'dictem-error) )) (defun dictem-error-message (err) "Extract error message from dictem error object" (cond ((dictem-error-p err) (nth 2 err)) (t (error "Invalid type of argument")) )) (defun dictem-error-status (err) "Extract error status from dictem error object" (cond ((dictem-error-p err) (nth 1 err)) (t (error "Invalid type of argument")) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-collect-matches () ; nreverse, setcar and nconc are used to reduce a number of cons (goto-char (point-min)) (let ((dictem-temp nil)) (loop (let ((line (dictem-get-line))) (if (string-match "^[^ ]+:" line) (progn (if (consp dictem-temp) (setcar (cdar dictem-temp) (nreverse (cadar dictem-temp)))) (setq dictem-temp (cons (list (substring line (match-beginning 0) (- (match-end 0) 1)) (nreverse (dictem-tokenize (substring line (match-end 0))))) dictem-temp))) (if (consp dictem-temp) (setcar (cdar dictem-temp) (nconc (nreverse (dictem-tokenize line)) (cadar dictem-temp)) )) )) (if (or (> (forward-line 1) 0) (> (current-column) 0)) (return (nreverse dictem-temp))) ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-get-buffer (buf) (cond ((bufferp buf) buf) (buf (current-buffer)) (t (get-buffer-create dictem-temp-buffer-name)) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; call-process functions (defun dictem-local-dict-basic-option (host port option-mime) (let ((server-host (if host host (dictem-get-server)))) (append (list "-P" "-" "--client" (dictem-client-text)) (if server-host (list "-h" server-host "-p" (dictem-get-port port))) (if option-mime '("-M")) dictem-client-prog-args-list ))) (defun dictem-call-process-SHOW-SERVER (buffer host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port nil) "-I"))) (defun dictem-call-process-SHOW-INFO (buffer db host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port nil) "-i" ,db))) (defun dictem-call-process-SHOW-STRAT (buffer host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port nil) "-S"))) (defun dictem-call-process-SHOW-DB (buffer host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port nil) "-D"))) (defun dictem-call-process-MATCH (buffer db query strat host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port nil) "-m" "-d" ,(if db db "*") "-s" ,(if strat strat ".") ,query))) (defun dictem-call-process-DEFINE (buffer db query host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port dictem-option-mime) "-d" ,(if db db "*") ,query))) (defun dictem-call-process-SEARCH (buffer db query strat host port) (apply 'call-process `(,dictem-client-prog nil ,(dictem-get-buffer buffer) nil ,@(dictem-local-dict-basic-option host port dictem-option-mime) "-d" ,(if db db "*") "-s" ,(if strat strat ".") ,query))) ;;;;; GET Functions ;;;;; (defun dictem-get-matches (query &optional database strategy server port) "Returns ALIST of matches" (let ((exit_status (dictem-call-process-MATCH nil database query strategy server port) )) (cond ((= exit_status 20) ;20 means "no matches found", See dict(1) (kill-buffer dictem-temp-buffer-name) nil) ((= exit_status 0) (progn (save-excursion (set-buffer dictem-temp-buffer-name) (let ((matches (dictem-collect-matches))) (kill-buffer dictem-temp-buffer-name) matches)))) (t (let ((err (dictem-make-error exit_status (get-buffer dictem-temp-buffer-name)))) (kill-buffer dictem-temp-buffer-name) err)) ))) (defun dictem-get-strategies (&optional server port) "Obtains strategy ALIST from a DICT server and returns alist containing strategies and their descriptions" (let ((exit_status (dictem-call-process-SHOW-STRAT nil server port) )) (cond ((= exit_status 0) (save-excursion (set-buffer dictem-temp-buffer-name) (goto-char (point-min)) (let ((regexp "^ \\([^ ]+\\) +\\(.*\\)$") (l nil)) (while (search-forward-regexp regexp nil t) (setq l (cons (list (buffer-substring-no-properties (match-beginning 1) (match-end 1)) (buffer-substring-no-properties (match-beginning 2) (match-end 2))) l))) (kill-buffer dictem-temp-buffer-name) l))) (t (let ((err (dictem-make-error exit_status (get-buffer dictem-temp-buffer-name)))) (kill-buffer dictem-temp-buffer-name) err)) ))) (defun dictem-get-databases (&optional server port) "Obtains database ALIST from a DICT server and returns alist containing database names and descriptions" (let ((exit_status (dictem-call-process-SHOW-DB nil server port) )) (cond ((= exit_status 0) (save-excursion (set-buffer dictem-temp-buffer-name) (goto-char (point-min)) (let ((regexp "^ \\([^ ]+\\) +\\(.*\\)$") (l nil)) (while (search-forward-regexp regexp nil t) (let ((dbname (buffer-substring-no-properties (match-beginning 1) (match-end 1))) (dbdescr (buffer-substring-no-properties (match-beginning 2) (match-end 2)))) (if (not (string= "--exit--" dbname)) (setq l (cons (list dbname dbdescr) l))))) (kill-buffer dictem-temp-buffer-name) l))) (t (let ((err (dictem-make-error exit_status (get-buffer dictem-temp-buffer-name)))) (kill-buffer dictem-temp-buffer-name) err)) ))) (defun dictem-get-default-strategy (&optional def-strat) "Gets the default search strategy" (if def-strat def-strat (if dictem-default-strategy dictem-default-strategy (if dictem-last-strategy dictem-last-strategy ".")))) (defun dictem-extract-dbname (database) (cond ((consp database) (dictem-extract-dbname (car database))) ((stringp database) database) (t (error "The database should be either stringp or consp")) )) (defun dictem-get-default-database (&optional def-db) "Returns the default database" (if def-db (dictem-extract-dbname def-db) (if dictem-default-database (dictem-extract-dbname dictem-default-database) (if dictem-last-database (dictem-extract-dbname dictem-last-database) "*")))) ;;;;; Low Level Functions ;;;;; (defun dictem-db-should-be-excluded (dbname) "Returns t if a dbname should is not interesting for user. See dictem-exclude-databases variable" (let ((ret nil)) (dolist (re dictem-exclude-databases) (if (string-match re dbname) (setq ret t))) ret)) (defun dictem-delete-alist-predicate (l pred) "makes a copy of l with no items for which (pred item) is true" (let ((ret nil)) (dolist (item l) (if (not (funcall pred (car item))) (setq ret (cons item ret)))) ret)) (defun dictem-get-line () "Replacement for (thing-at-point 'line)" (save-excursion (buffer-substring-no-properties (progn (beginning-of-line) (point)) (progn (end-of-line) (point))))) (defun dictem-list2alist (l) (cond ((null l) nil) (t (cons (list (car l) nil) (dictem-list2alist (cdr l)))))) (defun dictem-indent-string (str) (let ((start 0)) (while (string-match "\n" str start) (progn (setq start ( + 2 (match-end 0))) (setq str (replace-match "\n " t t str))))) (concat " " str)) (defun dictem-replace-spaces (str) (while (string-match "[ \n][ \n]+" str) (setq str (replace-match " " t t str))) (if (string-match "^ +" str) (setq str (replace-match "" t t str))) (if (string-match " +$" str) (setq str (replace-match "" t t str))) str) (defun dictem-remove-value-from-alist (l) (let ((ret nil)) (dolist (i l) (setq ret (cons (list (car i)) ret))) (reverse ret) )) ;(defun dictem-remove-value-from-alist (l) ; (cond ; ((symbolp l) l) ; (t (cons (list (caar l)) ; (dictem-remove-value-from-alist (cdr l)))))) (defun dictem-select (prompt alist default history) (let* ((completion-ignore-case t) (str (completing-read (concat prompt " [" default "]: ") alist nil t nil history default)) (str-cons (assoc str alist))) (cond ((and str-cons (consp str-cons) (cdr str-cons)) str-cons) ((and str-cons (consp str-cons)) (car str-cons)) (t nil)))) (defun dictem-tokenize (s) (if (string-match "\"[^\"]+\"\\|[^ \"]+" s ) ; (substring s (match-beginning 0) (match-end 0)) (cons (substring s (match-beginning 0) (match-end 0)) (dictem-tokenize (substring s (match-end 0)))) nil)) ;(defun dictem-search-forward-regexp-cs (REGEXP &optional BOUND NOERROR COUNT) ; "Case-sensitive variant for search-forward-regexp" ; (let ((case-replace nil) ; (case-fold-search nil)) ; (search-forward-regexp REGEXP BOUND NOERROR COUNT))) ;(defun dictem-replace-match-cs (NEWTEXT &optional FIXEDCASE LITERAL STRING SUBEXP) ; "Case-sensitive variant for replace-match" ; (let ((case-replace nil) ; (case-fold-search nil)) ; (replace-match NEWTEXT FIXEDCASE LITERAL STRING SUBEXP))) (defun dictem-get-port (&optional port) (let ((p (if port port dictem-port))) (cond ((and (stringp p) (string= "" p)) 2628) ((null p) 2628) ((stringp p) p) ((numberp p) (number-to-string p)) (t (error "The value of dictem-port variable should be \ either a string or a number")) ))) (defun dictem-get-server () (cond ((and (stringp dictem-server) (string= "" dictem-server)) nil) ((stringp dictem-server) dictem-server) ((null dictem-server) nil) (t (error "The value of dictem-server variable should be \ either a string or a nil")) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; Main Functions ;;;;; ;;;;;; Functions for Initializing ;;;;;; (defun dictem-initialize-strategies-alist (&optional server port) "Obtain strategy ALIST from a DICT server and sets dictem-strategy-alist variable." (interactive) (setq dictem-strategy-alist (dictem-get-strategies server (dictem-get-port port)))) (defun dictem-initialize-databases-alist (&optional server port) "Obtain database ALIST from a DICT server and sets dictem-database-alist variable." (interactive) (setq dictem-database-alist (dictem-get-databases server (dictem-get-port port))) (if (dictem-error-p dictem-database-alist) dictem-database-alist (setq dictem-database-alist (dictem-delete-alist-predicate dictem-database-alist 'dictem-db-should-be-excluded)))) (defun dictem-initialize () "Initializes dictem, i.e. obtains a list of available databases and strategiss from DICT server and makes other tasks." (interactive) (let ((dbs (dictem-initialize-databases-alist)) (strats (dictem-initialize-strategies-alist))) (if (dictem-error-p dbs) dbs strats))) (defun dictem-reinitialize-err () "Initializes dictem if it is not initialized yet and run (error ...) if an initialization fails" (interactive) (if (or (dictem-error-p dictem-database-alist) (null dictem-database-alist)) (if (dictem-error-p (dictem-initialize)) (error (dictem-error-message dictem-database-alist))))) ;;; Functions related to Minibuffer ;;;; (defun dictem-select-strategy (&optional default-strat) "Switches to minibuffer and asks the user to enter a search strategy." (dictem-reinitialize-err) (dictem-select "strategy" (dictem-prepand-special-strats (dictem-remove-value-from-alist dictem-strategy-alist)) (dictem-get-default-strategy default-strat) 'dictem-strategy-history)) (defun dictem-select-database (spec-dbs user-dbs &optional default-db) "Switches to minibuffer and asks user to enter a database name." (dictem-reinitialize-err) (let* ((dbs (dictem-remove-value-from-alist dictem-database-alist)) (dbs2 (if user-dbs (if dictem-use-user-databases-only dictem-user-databases-alist (append dictem-user-databases-alist dbs) ) dbs))) (dictem-select "db" (if spec-dbs (dictem-prepand-special-dbs dbs2) dbs2) (dictem-get-default-database default-db) 'dictem-database-history))) (defun dictem-read-query (&optional default-query) "Switches to minibuffer and asks user to enter a query." (if (featurep 'xemacs) (read-string (concat "query [" default-query "]: ") nil 'dictem-query-history default-query) (read-string (concat "query [" default-query "]: ") (if dictem-empty-initial-input nil default-query) 'dictem-query-history default-query t))) ;;;;;;;; Hooks ;;;;;;;; (defcustom dictem-postprocess-definition-hook nil "Hook run in dictem mode buffers containing DEFINE result." :group 'dictem :type 'hook :options '(dictem-postprocess-definition-separator dictem-postprocess-definition-hyperlinks dictem-postprocess-each-definition dictem-postprocess-definition-remove-header dictem-postprocess-collect-hyperlinks)) (defcustom dictem-postprocess-match-hook nil "Hook run in dictem mode buffers containing MATCH result." :group 'dictem :type 'hook :options '(dictem-postprocess-match)) (defcustom dictem-postprocess-show-info-hook nil "Hook run in dictem mode buffers containing SHOW INFO result." :group 'dictem :type 'hook :options '(dictem-postprocess-definition-hyperlinks dictem-postprocess-collect-hyperlinks)) (defcustom dictem-postprocess-show-server-hook nil "Hook run in dictem mode buffers containing SHOW SERVER result." :group 'dictem :type 'hook) ;;;;;;;; Search Functions ;;;;;;; (defun dictem-call-dict-internal (fun databases) (let ((exit-status -1)) (cond ((null databases) 0) ((stringp databases) (dictem-call-dict-internal fun (list databases))) ((listp databases) (dolist (db databases) (let ((ex_st (funcall fun db))) (cond ((= ex_st 0) (setq exit-status 0)) (t (if (/= 0 exit-status) (setq exit-status ex_st))) ))) (if (= exit-status -1) 0 exit-status) ) (t (error "wrong type of argument")) ) )) ;(defun dictem-call-dict-internal (fun databases) ; (dolist (db databases) ; (funcall fun db))) ; (funcall fun databases)) (defun dictem-make-url (host port database cmd_sign query &optional strategy) "Returns dict:// URL" (concat "dict://" host ":" (dictem-get-port (if port port "2628")) "/" cmd_sign ":" query ":" database (if strategy (concat ":" (if strategy strategy "."))) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-base-do-selector (cmd hook &optional database &rest args) (let* ((splitted-url nil) (databases nil) (user-db (assoc database dictem-user-databases-alist)) ) (goto-char (point-max)) (cond ((dictem-userdb-p database) (apply 'dictem-base-do-default-server (append (list cmd hook database) args))) ((and database (listp database)) (dictem-call-dict-internal `(lambda (db) (apply 'dictem-base-do-selector (append (list ,cmd hook db) args))) (cdr database)) (setq dictem-last-database (car database))) ((and database (stringp database) (setq splitted-url (dictem-parse-url database))) (apply 'dictem-base-do-foreign-server (append (list cmd hook (nth 1 splitted-url) (dictem-get-port (nth 2 splitted-url)) (nth 3 splitted-url)) args))) (user-db (let ((exit_status (apply 'dictem-base-do-selector (append (list cmd hook user-db) args)))) (progn (setq dictem-last-database database) exit_status) )) (t (apply 'dictem-base-do-default-server (append (list cmd hook database) args))) ))) (defun dictem-base-do-foreign-server (cmd hook server port database &rest args) (let ((dictem-last-database nil) (dictem-last-strategy nil)) (save-dictem (setq dictem-server server) (setq dictem-port port) (setq database database) (dictem-initialize) (apply 'dictem-base-do-default-server (append (list cmd hook database) args)) ))) (defun dictem-base-do-default-server (cmd hook &optional database query strategy) (let* ((beg (point)) (fun (if (dictem-userdb-p database) (dictem-cmd2userdb cmd) (dictem-cmd2function cmd))) (exit_status (save-excursion (apply fun (append (list t) (if database (list database)) (if query (list query)) (if strategy (list strategy)) (list nil) (list nil)))) )) (cond ((= 0 exit_status) (save-excursion (narrow-to-region beg (point-max)) (run-hooks hook) (widen))) ((= 21 exit_status) (save-excursion (narrow-to-region beg (point-max)) (run-hooks 'dictem-postprocess-match-hook) (widen))) (t (if (/= beg (point)) (setq dictem-error-messages (append (list (dictem-make-url (dictem-get-server) (dictem-get-port) database "?" query) (buffer-substring-no-properties beg (point))) dictem-error-messages))) (kill-region beg (point)))) (if database (setq dictem-last-database database)) (if strategy (setq dictem-last-strategy strategy)) exit_status )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-base-search (databases query strategy) "MATCH + DEFINE commands" (dictem-base-do-selector "search" 'dictem-postprocess-definition-hook databases query strategy)) (defun dictem-base-define (databases query c) "DEFINE command" (dictem-base-do-selector "define" 'dictem-postprocess-definition-hook databases query)) (defun dictem-base-match (databases query strategy) "MATCH command" (dictem-base-do-selector "match" 'dictem-postprocess-match-hook databases query strategy)) (defun dictem-base-show-databases (a b c) "SHOW DB command" (dictem-base-do-selector "show-db" nil)) (defun dictem-base-show-strategies (a b c) "SHOW STRAT command" (dictem-base-do-selector "show-strat" nil)) (defun dictem-base-show-info (databases b c) "SHOW INFO command" (dictem-base-do-selector "show-info" 'dictem-postprocess-show-info-hook databases)) (defun dictem-base-show-server (a b c) "SHOW SERVER command" (dictem-base-do-selector "show-server" 'dictem-postprocess-show-server-hook)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-get-error-message (exit_status) (cond ((= exit_status 0) "All is fine") ((= exit_status 20) "No matches found") ((= exit_status 21) "Approximate matches found") ((= exit_status 22) "No databases available") ((= exit_status 23) "No strategies available") ((= exit_status 30) "Unexpected response code from server") ((= exit_status 31) "Server is temporarily unavailable") ((= exit_status 32) "Server is shutting down") ((= exit_status 33) "Syntax error, command not recognized") ((= exit_status 34) "Syntax error, illegal parameters") ((= exit_status 35) "Command not implemented") ((= exit_status 36) "Command parameter not implemented") ((= exit_status 37) "Access denied") ((= exit_status 38) "Authentication failed") ((= exit_status 39) "Invalid database name") ((= exit_status 40) "Invalid strategy name") ((= exit_status 41) "Connection to server failed") (t (concat "Ooops!" (number-to-string exit_status))) )) (defun dictem-local-internal (err-msgs exit_status) (if err-msgs (concat (car err-msgs) "\n" (cadr err-msgs) "\n" (dictem-local-internal (cddr err-msgs) nil) ) (if exit_status (dictem-get-error-message exit_status) nil))) (defun dictem-generate-full-error-message (exit_status) (concat "Error messages:\n\n" (dictem-local-internal dictem-error-messages exit_status))) (defun dictem-run (search-fun &optional database query strategy) "Creates new *dictem* buffer and run search-fun" (let ((ex_status -1)) (defun dictem-local-run-functions (funs database query strategy) (cond ((functionp funs) (let ((ex_st (funcall funs database query strategy))) (if (/= ex_status 0) (setq ex_status ex_st)))) ((and (consp funs) (functionp (car funs))) (dictem-local-run-functions (car funs) database query strategy) (dictem-local-run-functions (cdr funs) database query strategy)) ((null funs) nil) (t (error "wrong argument type")) ) ex_status) (let ((coding-system nil)) (if (and (functionp 'coding-system-list) (member 'utf-8 (coding-system-list))) (setq coding-system 'utf-8)) (let ((selected-window (frame-selected-window)) (coding-system-for-read coding-system) (coding-system-for-write coding-system) ; here we remember values of variables local to buffer (server dictem-server) (port dictem-port) (dbs dictem-database-alist) (strats dictem-strategy-alist) (user-dbs dictem-user-databases-alist) (user-only dictem-use-user-databases-only) (use-existing-buf dictem-use-existing-buffer) ; (option-mime dictem-option-mime) (dict-buf nil) ) (if dictem-use-existing-buffer (dictem-ensure-buffer) (dictem)) (setq dict-buf (buffer-name)) ; (set-buffer-file-coding-system coding-system) (make-local-variable 'dictem-default-strategy) (make-local-variable 'dictem-default-database) (make-local-variable 'case-replace) (make-local-variable 'case-fold-search) ; the following lines are to inherit values local to buffer (set (make-local-variable 'dictem-server) server) (set (make-local-variable 'dictem-port) port) (set (make-local-variable 'dictem-database-alist) dbs) (set (make-local-variable 'dictem-strategy-alist) strats) (set (make-local-variable 'dictem-user-databases-alist) user-dbs) (set (make-local-variable 'dictem-use-user-databases-only) user-only) (set (make-local-variable 'dictem-use-existing-buffer) use-existing-buf) ; (set (make-local-variable 'dictem-option-mime) option-mime) (set (make-local-variable 'dictem-hyperlinks-alist) nil) ;;;;;;;;;;;;;; (setq case-replace nil) (setq case-fold-search nil) (setq dictem-error-messages nil) (dictem-local-run-functions search-fun database query strategy) (switch-to-buffer dict-buf) (if (and (not (equal ex_status 0)) (= (point-min) (point-max))) (insert (dictem-generate-full-error-message ex_status))) (goto-char (point-min)) (setq buffer-read-only t) ex_status )))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-next-section () "Move point to the next definition" (interactive) (forward-char) (if (search-forward-regexp "^From " nil t) (beginning-of-line) (goto-char (point-max)))) (defun dictem-previous-section () "Move point to the previous definition" (interactive) (backward-char) (if (search-backward-regexp "^From " nil t) (beginning-of-line) (goto-char (point-min)))) (defun dictem-hyperlinks-menu () "Hyperlinks menu with autocompletion" (interactive) (let ((link (completing-read "Go to:" dictem-hyperlinks-alist))) (if (and link (setq link (assoc link dictem-hyperlinks-alist))) (dictem-run-define (cadr link) dictem-last-database)) )) (defun dictem-next-link () "Move point to the next hyperlink" (interactive) (let ((pt nil) (limit (point-max))) (if (and (setq pt (next-single-property-change (point) 'link nil limit)) (/= limit pt)) (if (get-char-property pt 'link) (goto-char pt) (goto-char (next-single-property-change pt 'link nil limit)))) )) (defun dictem-previous-link () "Move point to the previous hyperlink" (interactive) (let ((pt nil) (limit (point-min))) (if (and (setq pt (previous-single-property-change (point) 'link nil limit)) (/= limit pt)) (if (get-char-property pt 'link) (goto-char pt) (goto-char (previous-single-property-change pt 'link nil limit)))) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-help () "Display a dictem help" (interactive) (describe-function 'dictem-mode)) (defun dictem-mode () "This is a mode for dict client implementing the protocol defined in RFC 2229. The following basic commands are available in the buffer. \\[dictem-help] display the help information \\[dictem-kill] kill the dictem buffer \\[dictem-kill-all-buffers] kill all dictem buffers \\[dictem-quit] bury the dictem buffer \\[dictem-last] restore content of the previously visited dictem buffer \\[dictem-run-search] make a new SEARCH, i.e. ask for a database, strategy and query and show definitions \\[dictem-run-match] make a new MATCH, i.e. ask for database, strategy and query and show matches \\[dictem-run-define] make a new DEFINE, i.e. ask for a database and query and show definitions \\[dictem-run-show-server] show information about DICT server \\[dictem-run-show-info] ask for a database and show information about it \\[dictem-run-show-databases] show databases DICT server provides \\[dictem-run-show-strategies] show search strategies DICT server provides \\[dictem-next-section] move point to the next definition \\[dictem-previous-section] move point to the previous definition \\[dictem-next-link] move point to the next hyper link \\[dictem-previous-link] move point to the previous hyper link \\[dictem-hyperlinks-menu] display the menu with hyperlinks \\[scroll-up] scroll dictem buffer up \\[scroll-down] scroll dictem buffer down \\[dictem-define-on-click] or \\[dictem-define-on-press] visit a link (DEFINE using all dictionaries) Also some advanced commands are available. \\[dictem-initialize] Initializes dictem, i.e. obtains a list of available databases and strategiss from DICT server and makes other tasks \\[dictem-initialize-strategies-alist] Obtain strategy ALIST from a DICT server and sets dictem-strategy-alist variable \\[dictem-initialize-databases-alist] Obtain database ALIST from a DICT server and sets dictem-database-alist variable The following key bindings are currently in effect in the buffer: \\{dictem-mode-map} " (interactive) (kill-all-local-variables) (buffer-disable-undo) (use-local-map dictem-mode-map) (setq major-mode 'dictem-mode) (setq mode-name "dictem") (add-hook 'kill-buffer-hook 'dictem-kill t t) (run-hooks 'dictem-mode-hook) ) (defvar dictem-window-configuration nil "The window configuration to be restored upon closing the buffer") (defvar dictem-selected-window nil "The currently selected window") (defvar dictem-content-history nil "A list of lists (buffer_content point)") (defconst dictem-buffer-name "*dictem buffer*") (defconst dictem-url-regexp "^\\(dict\\)://\\([^/:]*\\)\\(:\\([0-9]+\\)\\)?/\\(.*\\)$") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defconst dictem-cmd2function-alist '(("show-server" dictem-call-process-SHOW-SERVER) ("show-info" dictem-call-process-SHOW-INFO) ("show-strat" dictem-call-process-SHOW-STRAT) ("show-db" dictem-call-process-SHOW-DB) ("match" dictem-call-process-MATCH) ("define" dictem-call-process-DEFINE) ("search" dictem-call-process-SEARCH) )) (defconst dictem-cmd2userdb-alist '(("match" dictem-userdb-MATCH) ("define" dictem-userdb-DEFINE) ("search" dictem-userdb-SEARCH) ("show-info" dictem-userdb-SHOW-INFO) )) (defun dictem-cmd2xxx (cmd alist) (let ((fun (assoc cmd alist))) (if fun (symbol-function (cadr fun)) (error "Unknown command \"%s\"" cmd) ) )) (defun dictem-cmd2function (cmd) (dictem-cmd2xxx cmd dictem-cmd2function-alist)) (defun dictem-cmd2userdb (cmd) (dictem-cmd2xxx cmd dictem-cmd2userdb-alist)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun dictem-parse-url (url) "Parses string like dict://dict.org:2628/foldoc and returns a list containing protocol, server, port and path on nil if fails" (if (string-match dictem-url-regexp url) (list (match-string 1 url) ; protocol (match-string 2 url) ; host (match-string 4 url) ; port (match-string 5 url) ; path (database name for dict://) ) nil)) (defun dictem () "Create a new dictem buffer and install dictem-mode" (interactive) (let ( (buffer (generate-new-buffer dictem-buffer-name)) (window-configuration (current-window-configuration)) (selected-window (frame-selected-window))) (switch-to-buffer-other-window buffer) (dictem-mode) (make-local-variable 'dictem-window-configuration) (make-local-variable 'dictem-selected-window) (make-local-variable 'dictem-content-history) (setq dictem-window-configuration window-configuration) (setq dictem-selected-window selected-window) )) ;(unless dictem-mode-map (setq dictem-mode-map (make-sparse-keymap)) (suppress-keymap dictem-mode-map) ; Kill the buffer (define-key dictem-mode-map "k" 'dictem-kill) ; Kill all dictem buffers (define-key dictem-mode-map "x" 'dictem-kill-all-buffers) ; Bury the buffer (define-key dictem-mode-map "q" 'dictem-quit) ; LAST, works like in Info-mode (define-key dictem-mode-map "l" 'dictem-last) ; Show help message (define-key dictem-mode-map "h" 'dictem-help) ; SEARCH = MATCH + DEFINE (define-key dictem-mode-map "s" 'dictem-run-search) ; MATCH (define-key dictem-mode-map "m" 'dictem-run-match) ; DEFINE (define-key dictem-mode-map "d" 'dictem-run-define) ; SHOW SERVER (define-key dictem-mode-map "r" 'dictem-run-show-server) ; SHOW INFO (define-key dictem-mode-map "i" 'dictem-run-show-info) ; Move point to the next DEFINITION (define-key dictem-mode-map "n" 'dictem-next-section) ; Move point to the previous DEFINITION (define-key dictem-mode-map "p" 'dictem-previous-section) ; Move point to the next HYPER LINK (define-key dictem-mode-map "\M-n" 'dictem-next-link) ; Move point to the previous HYPER LINK (define-key dictem-mode-map "\M-p" 'dictem-previous-link) ; Hyperlinks menu (define-key dictem-mode-map "e" 'dictem-hyperlinks-menu) ; Scroll up dictem buffer (define-key dictem-mode-map " " 'scroll-up) ; Scroll down dictem buffer (define-key dictem-mode-map "\177" 'scroll-down) ; Define on click (if (featurep 'xemacs) (define-key dictem-mode-map [button2] 'dictem-define-on-click) (define-key dictem-mode-map [mouse-2] 'dictem-define-on-click)) (define-key dictem-mode-map "\C-m" 'dictem-define-on-press) (defun dictem-mode-p () "Return non-nil if current buffer has dictem-mode" (eq major-mode 'dictem-mode)) (defun dictem-ensure-buffer () "If current buffer is not a dictem buffer, create a new one." (if (dictem-mode-p) (progn (if dictem-use-content-history (setq dictem-content-history (cons (list (buffer-substring (point-min) (point-max)) (point)) dictem-content-history))) (setq buffer-read-only nil) (erase-buffer)) (dictem))) (defun dictem-quit () "Bury the current dictem buffer." (interactive) (if (featurep 'xemacs) (bury-buffer) (quit-window))) (defun dictem-kill () "Kill the current dictem buffer." (interactive) (if (eq major-mode 'dictem-mode) (progn (setq major-mode nil) (let ((configuration dictem-window-configuration) (selected-window dictem-selected-window)) (kill-buffer (current-buffer)) (if (window-live-p selected-window) (progn (select-window selected-window) (set-window-configuration configuration))))))) (defun dictem-last () "Go back to the last buffer visited visited." (interactive) (if (eq major-mode 'dictem-mode) (if dictem-content-history (progn (setq buffer-read-only nil) (delete-region (point-min) (point-max)) (insert (car (car dictem-content-history))) (goto-char (cadr (car dictem-content-history))) (setq dictem-content-history (cdr dictem-content-history)) ) ) )) (defun dictem-kill-all-buffers () "Kill all dictem buffers." (interactive) (dolist (buffer (buffer-list)) (let ((buf-name (buffer-name buffer))) (if (and (<= (length dictem-buffer-name) (length buf-name)) (string= dictem-buffer-name (substring buf-name 0 (length dictem-buffer-name)))) (kill-buffer buf-name)) ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; Top-level Functions ;;;;;; (defun dictem-run-match (query database strat) "Asks a user about database name, search strategy and query, creates new *dictem* buffer and shows matches in it." (interactive (list (dictem-read-query (thing-at-point 'word)) (dictem-select-database t t (dictem-get-default-database)) (dictem-select-strategy (dictem-get-default-strategy)))) (dictem-run 'dictem-base-match database query strat)) (defun dictem-run-define (query database) "Asks a user about database name and query, creates new *dictem* buffer and shows definitions in it." (interactive (list (dictem-read-query (thing-at-point 'word)) (dictem-select-database t t (dictem-get-default-database)))) (dictem-run 'dictem-base-define database query nil)) (defun dictem-run-search (query database strat) "Asks a user about database name, search strategy and query, creates new *dictem* buffer and shows definitions in it." (interactive (list (dictem-read-query (thing-at-point 'word)) (dictem-select-database t t (dictem-get-default-database)) (dictem-select-strategy (dictem-get-default-strategy)))) (dictem-run 'dictem-base-search database query strat)) (defun dictem-run-show-info (database) "Asks a user about database name creates new *dictem* buffer and shows information about it." (interactive (list (dictem-select-database nil nil (dictem-get-default-database)))) (dictem-run 'dictem-base-show-info database)) (defun dictem-run-show-server () "Creates new *dictem* buffer and shows information about DICT server in it." (interactive) (dictem-run 'dictem-base-show-server)) (defun dictem-run-show-databases () "Creates new *dictem* buffer and shows a list of databases provided by DICT." (interactive) (dictem-run 'dictem-base-show-databases)) (defun dictem-run-show-strategies () "Creates new *dictem* buffer and shows a list of search stratgeies provided by DICT." (interactive) (dictem-run 'dictem-base-show-strategies)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (easy-menu-define dictem-menu dictem-mode-map "DictEm Menu" `("DictEm" ["DictEm..." dictem-help t] "--" ["Next Section" dictem-next-section t] ["Previous Section" dictem-previous-section t] "--" ["Match" dictem-run-match t] ["Definition" dictem-run-define t] ["Search" dictem-run-search t] "--" ["Information about server" dictem-run-show-server t] ["Information about database" dictem-run-show-info t] ["A list of available databases" dictem-run-show-databases t] "--" ["Bury Dictem Buffer" dictem-quit t] ["Kill Dictem Buffer" dictem-kill t] )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; Optional Features ;;;;; (defun dictem-create-link (start end face function &optional data add-props) "Create a link in the current buffer starting from `start' going to `end'. The `face' is used for displaying, the `data' are stored together with the link. Upon clicking the `function' is called with `data' as argument." (let ((properties (append (list 'face face 'mouse-face 'highlight 'link-data data 'link-function function 'dictem-server dictem-server 'dictem-port dictem-port) add-props))) (remove-text-properties start end properties) (add-text-properties start end properties))) ;;;;;;; Postprocessing Functions ;;;;;;; (defun dictem-postprocess-definition-separator () (save-excursion (goto-char (point-min)) (let ((regexp "^\\(From\\)\\( [^\n]+\\)\\(\\[[^\n]+\\]\\)")) (while (search-forward-regexp regexp nil t) (let ((beg (match-beginning 1)) (end (match-end 1)) (beg-dbdescr (match-beginning 2)) (end-dbdescr (match-end 2)) (beg-dbname (match-beginning 3)) (end-dbname (match-end 3)) ) (put-text-property beg end 'face 'dictem-database-description-face) (put-text-property beg-dbdescr end-dbdescr 'face 'dictem-database-description-face) (setq dictem-current-dbname (dictem-replace-spaces (buffer-substring-no-properties (+ beg-dbname 1) (- end-dbname 1)))) (dictem-create-link beg-dbname end-dbname 'dictem-reference-dbname-face 'dictem-base-show-info (list (cons 'dbname dictem-current-dbname)))) )))) (defvar dictem-hyperlink-beginning "{" "String that begins hyperlink. This variable is used by the function 'dictem-postprocess-definition-hyperlinks'") (defvar dictem-hyperlink-end "}" "String that ends hyperlink. This variable is used by the function 'dictem-postprocess-definition-hyperlinks'") (defvar dictem-hyperlink-define-func 'dictem-base-define "Function called when user clicks on hyperlinks inside the definition. This variable is used by the function 'dictem-postprocess-definition-hyperlinks'") (defun dictem-postprocess-collect-hyperlinks () (save-excursion (goto-char (point-min)) (let ((regexp (concat "\\(" dictem-hyperlink-beginning "\\([^{}|]+\\)" dictem-hyperlink-end "\\|\\(" dictem-hyperlink-beginning "\\([^{}|\n]+\\)|\\([^{}|\n]+\\)" dictem-hyperlink-end "\\)\\)"))) (while (search-forward-regexp regexp nil t) (cond ((match-beginning 2) (let* ((word (dictem-replace-spaces (buffer-substring-no-properties (match-beginning 2) (match-end 2))))) (setq dictem-hyperlinks-alist (cons (list word word) dictem-hyperlinks-alist)) )) ((match-beginning 3) (let* ((word-beg (match-beginning 4)) (word-end (match-end 4)) (link-beg (match-beginning 5)) (link-end (match-end 5)) (word (dictem-replace-spaces (buffer-substring-no-properties word-beg word-end))) (link (dictem-replace-spaces (buffer-substring-no-properties link-beg link-end))) ) (setq dictem-hyperlinks-alist (cons (list word link) dictem-hyperlinks-alist)) ))))) )) (defun dictem-postprocess-definition-hyperlinks () (save-excursion (goto-char (point-min)) (let ((regexp (concat dictem-hyperlink-beginning "\\([^{}|]+\\)" dictem-hyperlink-end "\\|" "^From [^\n]+\\[\\([^\n]+\\)\\]" "\\|" "\\(" dictem-hyperlink-beginning "\\([^{}|\n]+\\)|\\([^{}|\n]+\\)" dictem-hyperlink-end "\\)"))) (while (search-forward-regexp regexp nil t) (cond ((match-beginning 1) (let* ((beg (match-beginning 1)) (end (match-end 1)) (match-beg (match-beginning 0)) (word (buffer-substring-no-properties beg end))) (replace-match word t t) (dictem-create-link match-beg (+ match-beg (length word)) 'dictem-reference-definition-face dictem-hyperlink-define-func (list (cons 'word (dictem-replace-spaces word)) (cons 'dbname dictem-current-dbname)) '(link t)) )) ((match-beginning 2) (if (null dictem-current-dbname) (setq dictem-current-dbname (dictem-replace-spaces (buffer-substring-no-properties (match-beginning 2) (match-end 2)))))) ((match-beginning 3) (let* ((beg (match-beginning 5)) (end (match-end 5)) (match-beg (match-beginning 3)) (repl-beg (match-beginning 4)) (repl-end (match-end 4)) (repl (buffer-substring-no-properties repl-beg repl-end)) (word (buffer-substring-no-properties beg end))) (replace-match repl t t) (dictem-create-link match-beg (+ match-beg (length repl)) 'dictem-reference-definition-face dictem-hyperlink-define-func (list (cons 'word (dictem-replace-spaces word)) (cons 'dbname dictem-current-dbname)) '(link t)))) ))))) (defun dictem-postprocess-match () (save-excursion (goto-char (point-min)) (let ((last-database dictem-last-database) (regexp "\\(\"[^\"\n]+\"\\)\\|\\([^ \"\n]+\\)")) (while (search-forward-regexp regexp nil t) (let* ((beg (match-beginning 0)) (end (match-end 0)) (first-char (buffer-substring-no-properties beg beg))) (cond ((save-excursion (goto-char beg) (= 0 (current-column))) (setq last-database (dictem-replace-spaces (buffer-substring-no-properties beg (- end 1)))) (dictem-create-link beg (- end 1) 'dictem-reference-dbname-face 'dictem-base-show-info (list (cons 'dbname last-database)))) ((match-beginning 1) (dictem-create-link beg end 'dictem-reference-m1-face 'dictem-base-define (list (cons 'word (dictem-replace-spaces (buffer-substring-no-properties (+ beg 1) (- end 1)))) (cons 'dbname last-database)))) (t (dictem-create-link beg end 'dictem-reference-m2-face 'dictem-base-define (list (cons 'word (dictem-replace-spaces (buffer-substring-no-properties beg end ))) (cons 'dbname last-database)))) )))))) (defun dictem-postprocess-definition-remove-header () (save-excursion (goto-char (point-min)) (end-of-line) (let (eol (point)) (goto-char (point-min)) (if (search-forward-regexp "[0-9] definitions? found" eol t) (progn (goto-char (point-min)) (let ((kill-whole-line t)) (kill-line 1)) ))))) ;;;;; On-Click Functions ;;;;; (defun dictem-define-on-press () "Is called upon pressing Enter." (interactive) (let* ( (properties (text-properties-at (point))) (data (plist-get properties 'link-data)) (fun (plist-get properties 'link-function)) (dictem-server (plist-get properties 'dictem-server)) (dictem-port (plist-get properties 'dictem-port)) (word (assq 'word data)) (dbname (assq 'dbname data)) ) (if (or word dbname) (dictem-run fun (if dbname (cdr dbname) dictem-last-database) (if word (cdr word) nil) nil)))) (defun dictem-define-on-click (event) "Is called upon clicking the link." (interactive "@e") (mouse-set-point event) (dictem-define-on-press)) ;(defun dictem-define-with-db-on-click (event) ; "Is called upon clicking the link." ; (interactive "@e") ; ; (mouse-set-point event) ; (let* ( ; (properties (text-properties-at (point))) ; (word (plist-get properties 'link-data))) ; (if word ; (dictem-run 'dictem-base-define (dictem-select-database) word nil)))) ;(define-key dictem-mode-map [C-down-mouse-2] ; 'dictem-define-with-db-on-click) ;;; Function for "narrowing" definitions ;;;;; (defcustom dictem-postprocess-each-definition-hook nil "Hook run in dictem mode buffers containing SHOW SERVER result." :group 'dictem :type 'hook :options '(dictem-postprocess-definition-separator dictem-postprocess-definition-hyperlinks)) (defun dictem-postprocess-each-definition () (save-excursion (goto-char (point-min)) (let ((regexp-from-dbname "^From [^\n]+\\[\\([^\n]+\\)\\]") (beg nil) (end (make-marker)) (dbname nil)) (if (search-forward-regexp regexp-from-dbname nil t) (let ((dictem-current-dbname (buffer-substring-no-properties (match-beginning 1) (match-end 1)))) (setq beg (match-beginning 0)) (while (search-forward-regexp regexp-from-dbname nil t) (set-marker end (match-beginning 0)) ; (set-marker marker (match-end 0)) (setq dbname (buffer-substring-no-properties (match-beginning 1) (match-end 1))) (save-excursion (narrow-to-region beg (marker-position end)) (run-hooks 'dictem-postprocess-each-definition-hook) (widen)) (setq dictem-current-dbname dbname) (goto-char end) (forward-char) (setq beg (marker-position end)) ) (save-excursion (narrow-to-region beg (point-max)) (run-hooks 'dictem-postprocess-each-definition-hook) (widen)) ))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (provide 'dictem)