diff options
-rw-r--r-- | GPL | 340 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | README | 353 | ||||
-rw-r--r-- | connection.el | 169 | ||||
-rwxr-xr-x | deb/README.debian | 14 | ||||
-rwxr-xr-x | deb/changelog | 158 | ||||
-rwxr-xr-x | deb/control | 18 | ||||
-rwxr-xr-x | deb/copyright | 13 | ||||
-rwxr-xr-x | deb/dirs | 5 | ||||
-rwxr-xr-x | deb/install.debian | 30 | ||||
-rwxr-xr-x | deb/postinst | 6 | ||||
-rwxr-xr-x | deb/prerm | 5 | ||||
-rwxr-xr-x | deb/remove.debian | 17 | ||||
-rwxr-xr-x | deb/rules | 53 | ||||
-rwxr-xr-x | dictionary-init.el | 24 | ||||
-rw-r--r-- | dictionary.el | 844 | ||||
-rwxr-xr-x | install-package.el | 7 | ||||
-rw-r--r-- | link.el | 120 | ||||
-rw-r--r-- | lpath.el | 4 |
19 files changed, 2185 insertions, 0 deletions
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..05f9096 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +EMACS=emacs + +all: + $(EMACS) -q -no-site-file -no-init-file -batch -l lpath.el \ + -f batch-byte-compile dictionary.el link.el connection.el @@ -0,0 +1,353 @@ +Emacs package for talking to a dictionary server + +Introduction + +Recently I installed the dictd server, which can be used to access several +dictionaries using a simple protocol as defined in RFC 2229 (Text Version). + +As my primary working environment is XEmacs 20.4, I decided to write an +Emacs-Lisp package for accessing this dictionary server. The older +webster.el didn't worked with the newer protocol. After starting the +implementation I was pointed to an already existing implementation, but this +was basically a wrapper to the dict client program and didn't have all the +features I wanted. + +If you didn't received this file from its original location you can visit it +at http://www.in-berlin.de/User/myrkr/dictionary.html + +Features + +The dictionary mode provides the following features: + + * looking up word definitions in all dictionaries + * search for matching word + * words/phrases marked with { } in the dictionary definitions are + recognized as hyper links and browseable + * easy selection of dictionary and search strategy + * backward moving through the visited definitions + +Here is a sample screenshot showing the dictionary mode in action within a +XEmacs buffer: + +[Image] + +This buffer shows the result of searching the definition for Emacs. Two +entries have been found. The bold text on the top are buttons for selecting +action using the mouse or keyboard, the blue words are hyper links that +points to the definitions of these words. + +Installation + +Download and Requirements + +I have tested the package with a native GNU Emacs 19.34.1 and XEmacs 20.4. I +implemented some hacks to work with the very very old custom.el file in the +above GNU Emacs. Please update to the current version whenever possible. + + * Current version (1.2.1) of this package + * Version 1.1 of this package + * Version 1.0 of this package + +I you want to know more about the differences please look at the ChangeLog. + +You will need the custom package to use this package. For full support +please check if your system knows the defface function, if not please +download the current version. + +For best usuability I suggest using the mouse, but it provide good keyboard +support as well. + +Unpacking the archive + +The package is distributed as tar.gz file. You unpack it using: + +gunzip dictionary-1.2.1.tar.gz | tar xf - + +or + +tar -xzf dictionary-1.2.1.tar.gz + +(with the version number subject to change) depending on whether you are +using GNU tar which support the z flag for compression. After unpacking the +archive a directory dictionary-1.2.1 has been created containing the +necessary files. + +Byte compiling + +For faster loading and executing of the package I strongly suggest that you +bytecompile the files. Emacs user please call make within the create +subdirectory, XEmacs user has to specifiy there favorite tool using make +EMACS=xemacs. If your custom package is not up-to-date expect some warnings +about free variables. + +Installing the files + +To install the files into your GNU Emacs/XEmacs installation please copy the +*.elc files into a directory being in your load-path variable. On most +installations /usr/lib/emacs/site-lisp or /usr/local/lib/emacs/site-lisp are +suitable locations. + +Loading the package + +You have to insert some instructions into your .emacs file to load the +dictionary package whenever needed. I suggest using the following lines: + +(autoload 'dictionary-search "dictionary" + "Ask for a word and search it in all dictionaries" t) +(autoload 'dictionary-match-words "dictionary" + "Ask for a word and search all matching words in the dictionaries" t) +(autoload 'dictionary "dictionary" + "Create a new dictionary buffer" t) + +In addition, some keybindings for faster access can be useful. I use the +following ones in my installation: + +(global-set-key [(control c) ?s] 'dictionary-search) +(global-set-key [(control c) ?m] 'dictionary-match-words) + +I will describe the user-callable functions and the keybindings within +dictionary mode later in this document. + +Using the package + +Glossary + +Before I start describing how you use this package, please let me explain +some words as they are used in this text: + +word + This is a word you want to lookup in the dictionaries verbatim. +pattern + This is used for looking up matching words. A pattern can be as simple + as a single word but also as complex as a POSIX regular expression. The + meaning of a pattern depends on the strategy used for matching words. +dictionary + The server can handle serveral distinct dictionaries. You can select + specific dictionaries or ask the server to search in all dictionaries + or until matches or definitions are found. To search in all + dictionaries the special name * is used, the special name ! requests to + search until definitions are found. For more details please take a look + at the standards definition. +definition + A dictionary entry that can be the result of a word search. +search + The operation of looking up a word in the dictionaries. +match + The operation of comparing a pattern to all words in the dictionary. +strategy + While matching in a dictionary serveral methods for comparing words can + be used. These methods are named strategies and include exact match, + regualare expression match, and soundex match. The available strategies + depends on the server, but a special name . can be used to denote a + server-default strategy. + +Invoking + +There are four different (documented) ways of invoking the package. By +calling dictionary you can start a new dictionary buffer waiting for your +commands. If you want to create multiple buffers for searching the +dictionary, you can run this function muliple times. dictionary-search will +ask for a word a search defaulting to the word at point and present all +definitions found. + +If you want to lookup the word near the point without further confirmation +use the dictionary-lookup-definition function. The last one is +dictionary-match-words which will ask for a pattern and display all matching +words. + +If you get an error message that the server could not be contacted, please +check the values of the variables dictionary-server and dictionary-port. The +port should usually be 2628, the default server as distributed is dict.org. + +You can have multiple independent dictionary buffer. If the above functions +are called from within dictionary mode they reuse the existing buffer. +Otherwise they create a new buffer. + +If you encounter emacs blocking forever while searching an entry and you are +using MULE you should check the value of the connection-broken-end-of-line +variable, which can be set to t in this case. + +Quitting + +Once a dictionary buffer is created you can close it by simply typing q +(dictionary-close). Another, more cruel, way is to use the kill-buffer +function which is handled correctly. + +The dictionary mode save the window configuration on startup and try to +reestablish it when the buffer is being closed. + +Using the buffer + +After a successful search the buffer is devided into two sections. The first +one is the button area at the top, the other one is the text buffer +displaying the result. By pressing the buttons you can select some functions +that are otherwise inaccessible with the mouse. + +In the text are each definition is introduced by the name of the database +that contains it. In the default configuration this text is in italic face. +The definition itself can contains hyperlinks that are marked using blue +foreground and both sensitive to clicking with the mouse and pressing return +while being within the link. + +Each link selection or otherwise selected new search or match will create a +new buffer showing the new result. You can use the Back button on the top or +the l key (dictionary-previous) to return the previous buffer contents. + +Pressing Meta while clicking on a link to start the search will extent the +search to all dictionaries (dictionary-default-dictionary to be more +precisly). + +If you prefer using the keyboard it can be very frustrating to use the +cursor key to position the point before pressing return to visit the link is +possible. Therefore, I defined the Tab and the n keys to jump to the next +link (dictionary-next-link) and the Shift-Tab and p keys to jump to the +previous one (dictionary-prev-link). + +Searching + +The search operation can be invoked by using the Search Definition button on +the top or by pressing s (dictionary-search). It will ask for a word to +search and will default to the word near point. This allows you to edit the +word before starting the search. The found definitions will be displayed +inside the buffer. If no entries could not be found an error message will be +displayed. + +If you want to quickly lookup the word at the point without further +confirmation use the d key (dictionary-lookup-definition). Except for not +allowing to edit the search word before asking the server it behaves the +same way as the normal search operation. + +Matching + +The match operation is started upon pressing the Matching Words button or +pressing the m key (dictionary-match-words). It will use the current +database and the current strategy and list matching words for the one you +entered at the prompt. The output is grouped by dictionary and each found +word can be looked up by clicking the word or pressing return. Please note +that in some cases not only the requested definition but some similiar +definitions are shown. This behaviour is caused by the keyword lookup in the +server. E.g., when you ask for the definition of from in Webster you will +presented with the definitions of from and Thrust, the latter includes the +phrase To thrust away or from which causes the display. + +Selecting dictionary + +By default all dictionaries (special name is "*") are searched for a word +definition or for matching words. You can select a specific word for both +modi by pressing the Select Default Dictionary button or the D key +(dictionary-select-dictionary). You will get a message about successful +selection. + +If you hold Meta while selecting a dictionary you will get more information +displayed instead. + +If you want to restore the original behaviour select All dictionaries. The +first matching dictionary is a special dictionary (named "!") where the +search will stop at the first dictionary with found definitions or matching +words. + +Selection search strategy + +While searching matching words to the pattern you entered the server can use +different comparison algorithm (aka search strategy). Every server provides +a default strategy which is internally known as ".". + +After pressing the Select Match Strategy button or pressing the M key +(dictionary-select-strategy) all available strategies on this server are +presented. As in the "select dictionary" mode you can select it by pressing +the mouse button 2 or typing return. + +Going backward + +If you visited a link and want to go back to the previous definition, simply +choose the Back button or press the l key (dictionary-previous). The buffer +contents and cursor position will be restored. If you intented to go beyond +the first definition an error message will appear. + +Getting Help + +If you are totally confused what all the keys do in your dictionary buffer +some help will displayed by pressing the h key. Press q to make the help go +away. This help buffer will display the default key bindings only as I had +problems with displaying multiple bindings for a single function (e.g., both +button2 and return select a link). Any suggestions are welcome. + +Customizing + +If you have an sufficient recent custom version installed (e.g., the one +provided in XEmacs 20.4) you can use the customize-group with the dictionary +group to customize this package. For using the customize buffer please refer +to its online help. + +Of course you can set all the variables and hooks you want in the startup +file. Here is a little example that I use for selecting the server on my +local machine and for binding some function to the user-reserved keys +starting from C-c a to C-c z. + +(global-set-key [(control c) ?s] 'dictionary-search) +(global-set-key [(control c) ?m] 'dictionary-match-words) +(setq dictionary-server "localhost") + +Thanks + +I want to thank Sam Steingold, Baoqiu Cui, and Bruce Ravel for their +valuable suggestions (including patches) for improving this package. + +License + +This file 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, or (at your option) any later +version. + +This file 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 version 2 +along with this package; see the file GPL. + +ChangeLogs + +Version 1.2 - 1.2.1 + + * Corrected dictionary command to draw the button bar. + * Improved documentation on dictionary to explicitly mention the use of + multiple buffers. + +Version 1.1.1 - 1.2 + + * Some users reported problems with GNU Emacs 20.3 and MULE. So I + introduced a new variable connection-broken-end-of-line which controls + whether a line is ended by \n or by \r\n. You can use the + customize-group command on dictionary to change the setting of the + variable. + +Version 1.1 - 1.1.1 + + * dictionary-search now allows editing the word to search for + * dictionary-search-word-near-point has been removed, you can use + dictionary-lookup-definition instead. It behaves like dictionary-search + but don't allow the search word to be edited (to speed up looking up + words). + +Version 1.0 - 1.1 + + * all dictionary buffers now share a single connection + * added kill-all-local-variables + * use cons instead of list where possible + * dictionary-search now: + o use word as point as default (implementing + dictionary-search-word-near-point too) + o asks for dictionary with prefix argument + * added help-echo tags which are used in XEmacs + * mark has been replaced by generic marker + * added messages for communications to the dictionary server that may + take a while + * fixed bug with going to the previous link + * replaced word-at-point by current-word + + ------------------------------------------------------------------------ +Torsten Hilbrich +Last modified: Sun May 7 11:06:16 CEST 2000 diff --git a/connection.el b/connection.el new file mode 100644 index 0000000..c83be81 --- /dev/null +++ b/connection.el @@ -0,0 +1,169 @@ +;;; connection.el -- handling a tcp based connection + +;; Author: Torsten Hilbrich <Torsten.Hilbrich@gmx.net> +;; Keywords: network +;; $Id: connection.el,v 1.6 2000/04/16 08:45:21 torsten Exp $ + +;; This file 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, or (at your option) +;; any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +(eval-when-compile + (require 'cl)) + +(defcustom connection-broken-end-of-line + nil + "Set to t (on) if you use a MULE Emacsen and have problems while connecting. +Usually for the dict protocol, the end of line characters are \\r\\n. +However, some users reported problems with using Emacs 20.3 and MULE +which seems to convert the \\r\\n to \\n while inserting the text into +the buffer. If you encounter these problems please set the value to t +and try again. +" + :group 'dictionary + :type 'boolean) + +(defmacro connection-p (connection) + "Returns non-nil if `connection' is a connection object" + (list 'get connection ''connection)) + +(defmacro connection-read-point (connection) + "Return the read point of the connection object." + (list 'get connection ''connection-read-point)) + +(defmacro connection-process (connection) + "Return the process of the connection object." + (list 'get connection ''connection-process)) + +(defmacro connection-buffer (connection) + "Return the buffer of the connection object." + (list 'get connection ''connection-buffer)) + +(defmacro connection-set-read-point (connection point) + "Set the read-point for `connection' to `point'." + (list 'put connection ''connection-read-point point)) + +(defmacro connection-set-process (connection process) + "Set the process for `connection' to `process'." + (list 'put connection ''connection-process process)) + +(defmacro connection-set-buffer (connection buffer) + "Set the buffer for `connection' to `buffer'." + (list 'put connection ''connection-buffer buffer)) + +(defun connection-create-data (buffer process point) + "Create a new connection data based on `buffer', `process', and `point'." + (let ((connection (make-symbol "connection"))) + (put connection 'connection t) + (connection-set-read-point connection point) + (connection-set-process connection process) + (connection-set-buffer connection buffer) + connection)) + +(defun connection-open (server port) + "Open a connection to `server' and `port'. +A data structure identifing the connection is returned" + + (let ((process-buffer (generate-new-buffer (format " connection to %s:%s" + server + port))) + (process)) + (save-excursion + (set-buffer process-buffer) + (setq process (open-network-stream "connection" process-buffer + server port)) + (connection-create-data process-buffer process (point-min))))) + +(defun connection-status (connection) + "Return the status of the connection. +Possible return values are the symbols: +nil: argument is no connection object +'none: argument has no connection +'up: connection is open and buffer is existing +'down: connection is closed +'alone: connection is not associated with a buffer" + (if (connection-p connection) + (let ((process (connection-process connection)) + (buffer (connection-buffer connection))) + (if (not process) + 'none + (if (not (buffer-live-p buffer)) + 'alone + (if (not (eq (process-status process) 'open)) + 'down + 'up)))) + nil)) + +(defun connection-close (connection) + "Force closing of the connection." + (if (connection-p connection) + (progn + (let ((buffer (connection-buffer connection)) + (process (connection-process connection))) + (if process + (delete-process process)) + (if buffer + (kill-buffer buffer)) + + (connection-set-process connection nil) + (connection-set-buffer connection nil))))) + +(defun connection-send (connection data) + "Send `data' to the process." + (unless (eq (connection-status connection) 'up) + (error "Connection is not up")) + (save-excursion + (set-buffer (connection-buffer connection)) + (goto-char (point-max)) + (connection-set-read-point connection (point)) + (process-send-string (connection-process connection) data))) + +(defun connection-send-crlf (connection data) + "Send `data' together with CRLF to the process." + (connection-send connection (concat data "\r\n"))) + +(defun connection-read (connection delimiter) + "Read data until `delimiter' is found inside the buffer." + (unless (eq (connection-status connection) 'up) + (error "Connection is not up")) + (let ((case-fold-search nil) + match-end) + (save-excursion + (set-buffer (connection-buffer connection)) + (goto-char (connection-read-point connection)) + ;; Wait until there is enough data + (while (not (search-forward delimiter nil t)) + (accept-process-output (connection-process connection) 3) + (goto-char (connection-read-point connection))) + (setq match-end (point)) + ;; Return the result + (let ((result (buffer-substring (connection-read-point connection) + match-end))) + (connection-set-read-point connection match-end) + result)))) + +(defun connection-read-crlf (connection) + "Read until a line is completedx with CRLF" + (connection-read connection (if connection-broken-end-of-line + "\n" + "\r\n"))) + +(defun connection-read-to-point (connection) + "Read until a line is consisting of a single point" + (connection-read connection (if connection-broken-end-of-line + "\n.\n" + "\r\n.\r\n"))) + + +(provide 'connection)
\ No newline at end of file diff --git a/deb/README.debian b/deb/README.debian new file mode 100755 index 0000000..d5bf0de --- /dev/null +++ b/deb/README.debian @@ -0,0 +1,14 @@ +dictionary for Debian +---------------------- + +This is an unofficial debian package for the dictionary client found +at http://www.myrkr.in-berlin.de/dictionary.html. + +A official package named 'dictionary-el' is now maintained by Aaron +M. Ucko <ucko@debian.org>, as debian user you probably should use this +package. + +Instructions on using this package can be found in the +/usr/share/doc/dictionary/README.gz file or in the above location. + +Torsten Hilbrich <dictionary@myrkr.in-berlin.de>, Sun, 13 May 2001 09:55:20 +0200 diff --git a/deb/changelog b/deb/changelog new file mode 100755 index 0000000..2c6d6d2 --- /dev/null +++ b/deb/changelog @@ -0,0 +1,158 @@ +dictionary (1.8.7-1) unstable; urgency=low + + * fixed decoding problem when selecting dictionary (problem reported by + Kuno Strassmann) + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 2 Oct 2004 08:05:37 +0200 + +dictionary (1.8.6-1) unstable; urgency=low + + * added patch fixing the wrong display of dictionary description + (provided by Sergei Pokrovsky) + * added dictionary-description-open-delimiter and + dictionary-description-close-delimiter (suggested by Sergei Pokrovsky) + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 25 Sep 2004 17:05:51 +0200 + +dictionary (1.8.5-1) unstable; urgency=low + + * added variable dictionary-use-single-buffer to allow selecting + between single/multiple buffers for dictionary access + * added tooltip support for XEmacs based on balloon-help + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 21 Jun 2003 18:55:54 +0200 + +dictionary (1.8.4-1) unstable; urgency=low + + * install-pkg was missing in the last tarball + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 12 Oct 2002 11:58:32 +0200 + +dictionary (1.8.3-1) unstable; urgency=low + + * Fixed multiple defined function in dictionary.el + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 20 Sep 2002 22:19:06 +0200 + +dictionary (1.8.2-1) unstable; urgency=low + + * fixed Makefile + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 14 Jun 2002 19:31:53 +0200 + +dictionary (1.8-1) unstable; urgency=low + + * added search for similiar words when the searched word is not found. + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Wed, 20 Mar 2002 21:27:54 +0100 + +dictionary (1.7.4-1) unstable; urgency=low + + * dictionary.el (dictionary-do-matching): removed quotes around + dictionary name and match strategy + + * dictionary.el (dictionary-do-search): removed quotes around dictionary + name + + * dictionary.el (dictionary-display-more-info): removed quotes around + dictionary name + + This problem (occurring with jdictd) was reported by E C Vijil + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 15 Mar 2002 21:19:23 +0100 + +dictionary (1.7.3-1) unstable; urgency=low + + * dictionary.el (dictionary-default-popup-strategy): added this + variable and changed dictionary-popup-matching-words to use + this as matching strategy (suggested by Renaud Pons) + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Tue, 29 Jan 2002 10:27:49 +0100 + +dictionary (1.7.2-1) unstable; urgency=low + + * link.el (link-initialize-keymap): fixed keybinding bug (reported by + David A. Panariti) + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Fri, 21 Dec 2001 18:50:20 +0100 + +dictionary (1.7.1-1) unstable; urgency=low + + * Fixed bug in dictionary-coding-system, the detection of non-mule + Emacsen was not correct + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sat, 15 Dec 2001 14:29:29 +0100 + +dictionary (1.7-1) unstable; urgency=low + + * Added first support for dictionaries with different encodings than + utf-8. + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Sun, 9 Dec 2001 14:21:57 +0100 + +dictionary (1.6-1) unstable; urgency=low + + * added HTTP proxy support using the CONNECT request type + + -- Torsten Hilbrich <dictionary@myrkr.in-berlin.de> Tue, 4 Dec 2001 20:22:03 +0100 + +dictionary (1.5.3-1) unstable; urgency=low + + * changed name of "select dictionary" button + * "select dictionary" and "select matching strategie" now has a better + feedback (by returning to the previous state) + * added support for non-colored display, the links are surrounded by + braces + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 14 Oct 2001 16:08:12 +0200 + +dictionary (1.5.2-1) unstable; urgency=low + + * popup menu now correctly records the selected window + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 2 Sep 2001 10:40:59 +0200 + +dictionary (1.5.1-1) unstable; urgency=low + + * corrected bug with dictionary-previous (found by Rui Zhu) + * corrected key bindings in link.el + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Tue, 17 Jul 2001 20:47:58 +0200 + +dictionary (1.5-1) unstable; urgency=low + + * added tooltip support for emacs + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 8 Jul 2001 21:01:12 +0200 + +dictionary (1.4.1-1) unstable; urgency=low + + * changed recognition of utf-8 support (suggested by Enrico Scholz) + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Fri, 6 Jul 2001 23:08:48 +0200 + +dictionary (1.4-1) unstable; urgency=low + + * support for popup menus + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Fri, 6 Jul 2001 19:54:54 +0200 + +dictionary (1.3.3-1) unstable; urgency=low + + * added support for xemacs 21 packages (no changes for debian) + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Wed, 27 Jun 2001 17:56:44 +0200 + +dictionary (1.3.2-1) unstable; urgency=low + + * removed use of set-text-properties in link.el + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Fri, 22 Jun 2001 21:39:47 +0200 + +dictionary (1.3.1-1) unstable; urgency=low + + * Initial release. + + -- Torsten Hilbrich <Torsten.Hilbrich@gmx.net> Sun, 13 May 2001 09:55:20 +0200 + + diff --git a/deb/control b/deb/control new file mode 100755 index 0000000..fed4dd5 --- /dev/null +++ b/deb/control @@ -0,0 +1,18 @@ +Source: dictionary +Section: unofficial +Priority: optional +Maintainer: Torsten Hilbrich <dictionary@myrkr.in-berlin.de> +Build-Depends: dpkg-dev, debmake +Standards-Version: 3.2.1 + +Package: dictionary +Architecture: all +Depends: emacsen +Description: dictionary client for emacs + This dictionary client provides access to a dictionary server + (as defined in RFC 2229) from within Emacs or XEmacs. + . + It supports utf-8 (currently available in Emacs 21) and allows + to follow links (marked by {braces}) within the definitions. + . + This is an unofficial debian package. diff --git a/deb/copyright b/deb/copyright new file mode 100755 index 0000000..b82cc97 --- /dev/null +++ b/deb/copyright @@ -0,0 +1,13 @@ +This package was debianized by Torsten Hilbrich <dictionary@myrkr.in-berlin.de> on Sun, 13 May 2001 09:55:20 +0200. + +It was downloaded from http://www.myrkr.in-berlin.de/dictionary.html + +Copyright: + +dictionary is licensed under the GNU General Public License version 2 or +higher. + +On Debian systems the full text of this licence can be found +in /usr/share/common-licenses/GPL. + + diff --git a/deb/dirs b/deb/dirs new file mode 100755 index 0000000..9d129ef --- /dev/null +++ b/deb/dirs @@ -0,0 +1,5 @@ +usr/lib/emacsen-common/packages/install +usr/lib/emacsen-common/packages/remove +usr/share/doc/dictionary +usr/share/emacs/site-lisp + diff --git a/deb/install.debian b/deb/install.debian new file mode 100755 index 0000000..ad76efb --- /dev/null +++ b/deb/install.debian @@ -0,0 +1,30 @@ +#!/bin/sh + +PACKAGE=dictionary +FLAVOUR=$1 +ELDIR=/usr/share/emacs/site-lisp/ +ELCDIR=/usr/share/$FLAVOUR/site-lisp/ +EFLAGS="-batch -q -l lpath.el -f batch-byte-compile" +CONFFILE=${ELDIR}/${PACKAGE}-init.el +CONFDIR=/etc/$FLAVOUR/site-start.d/ + +SOURCES="dictionary.el connection.el link.el" + +case "$FLAVOUR" in + emacs) echo "install/$PACKAGE: Ignoring emacs";; + *) echo -n "install/$PACKAGE: Byte-compiling for $FLAVOUR..." + install -m 755 -d $ELCDIR + for i in $SOURCES; do cp $ELDIR/$i $ELCDIR; done + (cd $ELCDIR && \ + echo '(setq load-path (cons "." load-path))' > lpath.el + $FLAVOUR $EFLAGS $SOURCES 2>/dev/null + rm lpath.el ) + cp ${CONFFILE} ${CONFDIR}/50${PACKAGE}.el + cd $ELCDIR + for i in $SOURCES; do rm -f $ELCDIR/*.el; done + echo " done." + ;; +esac + + + diff --git a/deb/postinst b/deb/postinst new file mode 100755 index 0000000..2333df3 --- /dev/null +++ b/deb/postinst @@ -0,0 +1,6 @@ +#!/bin/sh + +PACKAGE=dictionary + +/usr/lib/emacsen-common/emacs-package-install $PACKAGE + diff --git a/deb/prerm b/deb/prerm new file mode 100755 index 0000000..bc7ec08 --- /dev/null +++ b/deb/prerm @@ -0,0 +1,5 @@ +#!/bin/sh + +PACKAGE=dictionary + +/usr/lib/emacsen-common/emacs-package-remove $PACKAGE diff --git a/deb/remove.debian b/deb/remove.debian new file mode 100755 index 0000000..991d208 --- /dev/null +++ b/deb/remove.debian @@ -0,0 +1,17 @@ +#!/bin/sh +PACKAGE=dictionary +FLAVOUR=$1 +ELCDIR=/usr/share/$FLAVOUR/site-lisp/ + +SOURCE="connection.el dictionary.el link.el" +CONFFILE=/etc/$FLAVOUR/site-start.d/50${PACKAGE}.el + +case "$FLAVOUR" in + emacs) echo "install/$PACKAGE: Ignoring emacs";; + *) echo -n "remove/$PACKAGE: Removing for $FLAVOUR..." + cd $ELCDIR + for i in $SOURCE; do rm -f ${i}c; done + rm ${CONFFILE} + echo " done." + ;; +esac diff --git a/deb/rules b/deb/rules new file mode 100755 index 0000000..1a67696 --- /dev/null +++ b/deb/rules @@ -0,0 +1,53 @@ +#!/usr/bin/make -f +# Made with the aid of debmake, by Christoph Lameter, +# based on the sample debian/rules file for GNU hello by Ian Jackson. + +package=dictionary + +build: + $(checkdir) + + touch build + +clean: + $(checkdir) + -rm -f build + -rm -f `find . -name "*~"` + -rm -rf debian/tmp debian/files* core debian/substvars + +binary-indep: checkroot build + $(checkdir) +# There are no architecture-independent files to be uploaded +# generated by this package. If there were any they would be +# made here. + +binary-arch: checkroot build + $(checkdir) + -rm -rf debian/tmp + install -d debian/tmp + cd debian/tmp && install -d `cat ../dirs` + + cp dictionary.el connection.el link.el dictionary-init.el \ + debian/tmp/usr/share/emacs/site-lisp + cp debian/install.debian debian/tmp/usr/lib/emacsen-common/packages/install/dictionary + chmod 755 debian/tmp/usr/lib/emacsen-common/packages/install/dictionary + cp debian/remove.debian debian/tmp/usr/lib/emacsen-common/packages/remove/dictionary + chmod 755 debian/tmp/usr/lib/emacsen-common/packages/remove/dictionary + + debstd README + dpkg-gencontrol -isp + chown -R root.root debian/tmp + chmod -R go=rX debian/tmp + dpkg --build debian/tmp .. + +define checkdir + test -f debian/rules +endef + +binary: binary-indep binary-arch + +checkroot: + $(checkdir) + test root = "`whoami`" + +.PHONY: binary binary-arch binary-indep clean checkroot diff --git a/dictionary-init.el b/dictionary-init.el new file mode 100755 index 0000000..540dfc3 --- /dev/null +++ b/dictionary-init.el @@ -0,0 +1,24 @@ +;; $Id: dictionary-init.el,v 1.7 2003/06/21 17:55:15 torsten Exp $ +;; This file contains the autoload definitions that are used by the +;; debian package and can also be used in a standalone installation +;; The XEmacs package has some other means to create the autoload +;; information. + +(autoload 'dictionary-search "dictionary" + "Ask for a word and search it in all dictionaries" t) +(autoload 'dictionary-match-words "dictionary" + "Ask for a word and search all matching words in the dictionaries" t) +(autoload 'dictionary-lookup-definition "dictionary" + "Unconditionally lookup the word at point." t) +(autoload 'dictionary "dictionary" + "Create a new dictionary buffer" t) +(autoload 'dictionary-mouse-popup-matching-words "dictionary" + "Display entries matching the word at the cursor" t) +(autoload 'dictionary-popup-matching-words "dictionary" + "Display entries matching the word at the point" t) +(autoload 'dictionary-tooltip-mode "dictionary" + "Display tooltips for the current word" t) +(unless (boundp 'running-xemacs) + (autoload 'global-dictionary-tooltip-mode "dictionary" + "Enable/disable dictionary-tooltip-mode for all buffers" t)) + diff --git a/dictionary.el b/dictionary.el new file mode 100644 index 0000000..7fba27e --- /dev/null +++ b/dictionary.el @@ -0,0 +1,844 @@ +;; dictionary.el -- an interface to RFC 2229 dictionary server + +;; Author: Torsten Hilbrich <Torsten.Hilbrich@gmx.net> +;; Keywords: interface, dictionary +;; $Id: dictionary.el,v 1.16 2000/05/07 08:56:50 torsten Exp $ + +;; This file 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, or (at your option) +;; any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +(eval-when-compile + (require 'cl)) + +(require 'custom) +(require 'connection) +(require 'link) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Stuff for customizing. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(eval-when-compile + (unless (fboundp 'defface) + (message "Please update your custom.el file: %s" + "http://www.dina.kvl.dk/~abraham/custom/")) + + (unless (fboundp 'defgroup) + (defmacro defgroup (&rest ignored)) + (defmacro defcustom (var value doc &rest ignored) + (list 'defvar var value doc)))) + +(defgroup dictionary nil + "Client for accessing the dictd server based dictionaries" + :group 'help + :group 'hypermedia) + +(defcustom dictionary-server + "dict.org" + "This server is contacted for searching the dictionary" + :group 'dictionary + :type 'string) + +(defcustom dictionary-port + 2628 + "The port of the dictionary server. +This port is propably always 2628 so there should be no need to modify it." + :group 'dictionary + :type 'number) + +(defcustom dictionary-identification + "dictionary.el emacs lisp dictionary client" + "This is the identification string that will be send to the server." + :group 'dictionary + :type 'number) + +(defcustom dictionary-default-dictionary + "*" + "The dictionary which is used for searching definitions and matching. +* and ! have a special meaning, * search all dictionaries, ! search until +one dictionary yields matches." + :group 'dictionary + :type 'string) + +(defcustom dictionary-default-strategy + "." + "The default strategy for listing matching words." + :group 'dictionary + :type 'string) + +(defcustom dictionary-create-buttons + t + "Create some clickable buttons on top of the window if non-nil" + :group 'dictionary + :type 'boolean) + +(defcustom dictionary-mode-hook + nil + "Hook run in dictionary mode buffers." + :group 'dictionary + :type 'hook) + +(if (fboundp 'defface) + (progn + +(defface dictionary-word-entry-face + '((((type x)) + (:italic t)) + (((type tty) (class color)) + (:foreground "green")) + (t + (:inverse t))) + "The face that is used for displaying the initial word entry line." + :group 'dictionary) + +(defface dictionary-button-face + '((t + (:bold t))) + "The face that is used for displaying buttons." + :group 'dictionary) + +(defface dictionary-reference-face + '((((type x) + (class color) + (background dark)) + (:foreground "yellow")) + (((type tty) + (class color) + (background dark)) + (:foreground "brightyellow")) + (((class color) + (background light)) + (:foreground "blue")) + (t + (:underline t))) + + "The face that is used for displaying a reference word." + :group 'dictionary) + +) + +;; else +(copy-face 'italic 'dictionary-word-entry-face) +(copy-face 'bold 'dictionary-button-face) +(copy-face 'default 'dictionary-reference-face) +(set-face-foreground 'dictionary-reference-face "blue")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Buffer local variables for storing the current state +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defvar dictionary-window-configuration + nil + "The window configuration to be restored upon closing the buffer") + +(defvar dictionary-position-stack + nil + "The history buffer for point and window position") + +(defvar dictionary-data-stack + nil + "The history buffer for functions and arguments") + +(defvar dictionary-positions + nil + "The current positions") + +(defvar dictionary-current-data + nil + "The item that will be placed on stack next time") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Global variables +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar dictionary-mode-map + nil + "Keymap for dictionary mode") + +(defvar dictionary-connection + nil + "The current network connection") + +(defvar dictionary-instances + 0 + "The number of open dictionary buffers") + +(defvar dictionary-marker + nil + "Stores the point position while buffer display.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Basic function providing startup actions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun dictionary-mode () + "This is a mode for searching a dictionary server implementing +the protocol defined in RFC 2229. + +This is a quick reference to this mode describing the default key bindings: + +* q close the dictionary buffer +* h display this help information +* s ask for a new word to search +* d search the word at point +* n or Tab place point to the next link +* p or S-Tab place point to the prev link + +* m ask for a pattern and list all matching words. +* D select the default dictionary +* M select the default search strategy + +* Return or Button2 visit that link +* M-Return or M-Button2 search the word beneath link in all dictionaries +" + + (unless (eq major-mode 'dictionary-mode) + (incf dictionary-instances)) + + (kill-all-local-variables) + (buffer-disable-undo) + (use-local-map dictionary-mode-map) + (setq major-mode 'dictionary-mode) + (setq mode-name "Dictionary") + + (make-local-variable 'dictionary-data-stack) + (setq dictionary-data-stack nil) + (make-local-variable 'dictionary-position-stack) + (setq dictionary-position-stack nil) + + (make-local-variable 'dictionary-current-data) + (make-local-variable 'dictionary-positions) + + (make-local-variable 'dictionary-default-dictionary) + (make-local-variable 'dictionary-default-strategy) + + (make-local-hook 'kill-buffer-hook) + (add-hook 'kill-buffer-hook 'dictionary-close t t) + (run-hooks 'dictionary-mode-hook)) + +(defun dictionary () + "Create a new dictonary buffer and install dictionary-mode" + (interactive) + + (let ((buffer (generate-new-buffer "*Dictionary buffer*")) + (window-configuration (current-window-configuration))) + (switch-to-buffer-other-window buffer) + (dictionary-mode) + + (make-local-variable 'dictionary-window-configuration) + (setq dictionary-window-configuration window-configuration) + (dictionary-check-connection) + (dictionary-pre-buffer) + (dictionary-post-buffer))) + +(unless dictionary-mode-map + (setq dictionary-mode-map (make-sparse-keymap)) + (suppress-keymap dictionary-mode-map) + + (define-key dictionary-mode-map "q" 'dictionary-close) + (define-key dictionary-mode-map "h" 'dictionary-help) + (define-key dictionary-mode-map "s" 'dictionary-search) + (define-key dictionary-mode-map "d" 'dictionary-lookup-definition) + (define-key dictionary-mode-map "D" 'dictionary-select-dictionary) + (define-key dictionary-mode-map "M" 'dictionary-select-strategy) + (define-key dictionary-mode-map "m" 'dictionary-match-words) + (define-key dictionary-mode-map "l" 'dictionary-previous) + + (define-key dictionary-mode-map [tab] 'dictionary-next-link) + (define-key dictionary-mode-map "n" 'dictionary-next-link) + (define-key dictionary-mode-map [(shift tab)] 'dictionary-prev-link) + (define-key dictionary-mode-map "p" 'dictionary-prev-link) + + (define-key dictionary-mode-map " " 'scroll-up) + (define-key dictionary-mode-map [(meta space)] 'scroll-down) + + (link-initialize-keymap dictionary-mode-map)) + +(defun dictionary-check-connection () + "Check if there is already a connection open" + (if (not (and dictionary-connection + (eq (connection-status dictionary-connection) 'up))) + (progn + (message "Opening connection to %s:%s" dictionary-server + dictionary-port) + (connection-close dictionary-connection) + (setq dictionary-connection + (connection-open dictionary-server dictionary-port)) + (dictionary-check-initial-reply) + (dictionary-send-command (concat "client " dictionary-identification)) + (let ((reply (dictionary-read-reply-and-split))) + (message nil) + (unless (dictionary-check-reply reply 250) + (error "Unknown server answer: %s" (dictionary-reply reply))))))) +(defun dictionary-mode-p () + "Return non-nil if current buffer has dictionary-mode" + (eq major-mode 'dictionary-mode)) + +(defun dictionary-ensure-buffer () + "If current buffer is not a dictionary buffer, create a new one." + (unless (dictionary-mode-p) + (dictionary))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dealing with closing the buffer +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun dictionary-close () + "Close the current dictionary buffer and its connection" + (interactive) + (if (eq major-mode 'dictionary-mode) + (progn + (setq major-mode nil) + (if (<= (decf dictionary-instances) 0) + (connection-close dictionary-connection)) + (let ((configuration dictionary-window-configuration)) + (kill-buffer (current-buffer)) + (set-window-configuration configuration))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Helpful functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun dictionary-send-command (string) + "Send the command `string' to the network connection." + (dictionary-check-connection) + (connection-send-crlf dictionary-connection string)) + +(defun dictionary-read-reply () + "Read the reply line from the server" + (let ((answer (connection-read-crlf dictionary-connection))) + (if (string-match "\r" answer) + (substring answer 0 (match-beginning 0)) + answer))) + +(defun dictionary-split-string (string) + "Split the `string' constiting of space separated words into elements. +This function knows about the special meaning of quotes (\")" + (let ((list)) + (while (and string (> (length string) 0)) + (let ((search "\\(\\s-+\\)") + (start 0)) + (if (= (aref string 0) ?\") + (setq search "\\(\"\\)\\s-*" + start 1)) + (if (string-match search string start) + (progn + (setq list (cons (substring string start (- (match-end 1) 1)) list) + string (substring string (match-end 0)))) + (setq list (cons string list) + string nil)))) + (nreverse list))) + +(defun dictionary-read-reply-and-split () + "Read the reply, split it into words and return it" + (let ((answer (make-symbol "reply-data")) + (reply (dictionary-read-reply))) + (let ((reply-list (dictionary-split-string reply))) + (put answer 'reply reply) + (put answer 'reply-list reply-list) + (put answer 'reply-code (string-to-number (car reply-list))) + answer))) + +(defmacro dictionary-reply-code (reply) + "Return the reply code stored in `reply'." + (list 'get reply ''reply-code)) + +(defmacro dictionary-reply (reply) + "Return the string reply stored in `reply'." + (list 'get reply ''reply)) + +(defmacro dictionary-reply-list (reply) + "Return the reply list stored in `reply'." + (list 'get reply ''reply-list)) + +(defun dictionary-read-answer () + "Read an answer delimited by a . on a single line" + (let ((answer (connection-read-to-point dictionary-connection)) + (start 0)) + (while (string-match "^\\." answer start) + (setq answer (replace-match "" t t answer)) + (setq start (match-end 0))) + (setq start 0) + (while (string-match "\r\n" answer start) + (setq answer (replace-match "\n" t t answer)) + (setq start (1- (match-end 0)))) + answer)) + +(defun dictionary-check-reply (reply code) + "Check if the reply in `reply' has the `code'." + (let ((number (dictionary-reply-code reply))) + (and (numberp number) + (= number code)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Communication functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun dictionary-check-initial-reply () + "Read the first reply from server and check it." + (let ((reply (dictionary-read-reply-and-split))) + (unless (dictionary-check-reply reply 220) + (connection-close dictionary-connection) + (error "Server returned: %s" (dictionary-reply reply))))) + +;; Store the current state +(defun dictionary-store-state (function data) + "Stores the current state of operation for later restore." + + (if dictionary-current-data + (progn + (push dictionary-current-data dictionary-data-stack) + (unless dictionary-positions + (error "dictionary-store-state called before dictionary-store-positions")) + (push dictionary-positions dictionary-position-stack))) + (setq dictionary-current-data + (cons function data))) + +(defun dictionary-store-positions () + "Stores the current positions for later restore." + + (setq dictionary-positions (cons (point) (window-start)))) + +;; Restore the previous state +(defun dictionary-restore-state (&rest ignored) + "Restore the state just before the last operation" + (let ((position (pop dictionary-position-stack)) + (data (pop dictionary-data-stack))) + (unless position + (error "Already at begin of history")) + (apply (car data) (cdr data)) + (set-window-start (selected-window) (cdr position)) + (goto-char (car position)) + (setq dictionary-current-data data))) + + +;; The normal search + +(defun dictionary-new-search (args &optional all) + "Save the current state and start a new search" + (dictionary-store-positions) + (dictionary-ensure-buffer) + (let ((word (car args)) + (dictionary (cdr args))) + + (if all + (setq dictionary dictionary-default-dictionary)) + (dictionary-do-search word dictionary) + (dictionary-store-state 'dictionary-do-search (list word dictionary)))) + +(defun dictionary-do-search (word dictionary) + "The workhorse for doing the search" + + (message "Searching for %s in %s" word dictionary) + (dictionary-send-command (concat "define \"" dictionary "\" \"" + word "\"")) + (message nil) + (dictionary-pre-buffer) + (let ((reply (dictionary-read-reply-and-split))) + (if (dictionary-check-reply reply 552) + (error "Word \"%s\" in dictionary \"%s\" not found" + word dictionary) + (if (dictionary-check-reply reply 550) + (error "Dictionary \"%s\" is unknown, please select an existing one." + dictionary) + (unless (dictionary-check-reply reply 150) + (error "Unknown server answer: %s" (dictionary-reply reply))) + (dictionary-display-search-result reply))))) + +(defun dictionary-pre-buffer () + "These commands are executed at the begin of a new buffer" + (toggle-read-only 0) + (erase-buffer) + (if dictionary-create-buttons + (progn + (link-insert-link "[Back]" 'dictionary-button-face + 'dictionary-restore-state nil + "Mouse-2 to go backwards in history") + (insert " ") + (link-insert-link "[Search Definition]" + 'dictionary-button-face + 'dictionary-search nil + "Mouse-2 to look up a new word") + + (insert " ") + (link-insert-link "[Matching words]" + 'dictionary-button-face + 'dictionary-match-words nil + "Mouse-2 to find matches for a pattern") + (insert "\n ") + (link-insert-link "[Select Default Dictionary]" + 'dictionary-button-face + 'dictionary-select-dictionary nil + "Mouse-2 to select dictionary for future searches") + (insert " ") + (link-insert-link "[Select Match Strategy]" + 'dictionary-button-face + 'dictionary-select-strategy nil + "Mouse-2 to select matching algorithm") + (insert "\n\n"))) + (setq dictionary-marker (point-marker))) + +(defun dictionary-post-buffer () + "These commands are executed at the end of a new buffer" + (goto-char dictionary-marker) + (set-buffer-modified-p nil) + (toggle-read-only 1)) + +(defun dictionary-display-search-result (reply) + "This function starts displaying the result starting with the `reply'." + + (let ((number (nth 1 (dictionary-reply-list reply)))) + (insert number (if (equal number "1") + " definition" + " definitions") + " found\n\n") + (setq reply (dictionary-read-reply-and-split)) + (while (dictionary-check-reply reply 151) + (let* ((reply-list (dictionary-reply-list reply)) + (dictionary (nth 2 reply-list)) + (description (nth 3 reply-list)) + (word (nth 1 reply-list))) + (dictionary-display-word-entry word dictionary description) + (setq reply (dictionary-read-answer)) + (dictionary-display-word-definition reply word dictionary) + (setq reply (dictionary-read-reply-and-split)))) + (dictionary-post-buffer))) + +(defun dictionary-display-word-entry (word dictionary description) + "Insert an explanation for the current definition." + (let ((start (point))) + (insert "From " description "[" dictionary "]:\n\n") + (put-text-property start (point) 'face 'dictionary-word-entry-face))) + +(defun dictionary-display-word-definition (reply word dictionary) + "Insert the definition for the current word" + (let ((start (point))) + (insert reply) + (let ((regexp "\\({+\\)\\([^}]+\\)\\(}+\\)")) + (goto-char start) + (while (< (point) (point-max)) + (if (search-forward-regexp regexp nil t) + (progn + (replace-match "\\2") + ;; Compensate for the replacement + (let* ((brace-match-length (- (match-end 1) + (match-beginning 1))) + (match-start (- (match-beginning 2) + brace-match-length)) + (match-end (- (match-end 2) + brace-match-length))) + (dictionary-mark-reference match-start match-end + 'dictionary-new-search + word dictionary))) + (goto-char (point-max))))))) + +(defun dictionary-mark-reference (start end call displayed-word dictionary) + "Format the area from `start' to `end' as link calling `call'. +The word is taken from the buffer, the `dictionary' is given as argument." + (let ((word (buffer-substring-no-properties start end))) + (while (string-match "\n\\s-*" word) + (setq word (replace-match " " t t word))) + (while (string-match "[*\"]" word) + (setq word (replace-match "" t t word))) + + (unless (equal word displayed-word) + (link-create-link start end 'dictionary-reference-face + call (cons word dictionary) + (concat "Press Mouse-2 to lookup \"" + word "\" in \"" dictionary "\""))))) + +(defun dictionary-select-dictionary (&rest ignored) + "Save the current state and start a dictionary selection" + (interactive) + (dictionary-ensure-buffer) + (dictionary-store-positions) + (dictionary-do-select-dictionary) + (dictionary-store-state 'dictionary-do-select-dictionary nil)) + +(defun dictionary-do-select-dictionary (&rest ignored) + "The workhorse for doing the dictionary selection." + + (message "Looking up databases and descriptions") + (dictionary-send-command "show db") + + (let ((reply (dictionary-read-reply-and-split))) + (message nil) + (if (dictionary-check-reply reply 554) + (error "No dictionary present") + (unless (dictionary-check-reply reply 110) + (error "Unknown server answer: %s" + (dictionary-reply reply))) + (dictionary-display-dictionarys reply)))) + +(defun dictionary-simple-split-string (string &optional pattern) + "Return a list of substrings of STRING which are separated by PATTERN. +If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"." + (or pattern + (setq pattern "[ \f\t\n\r\v]+")) + ;; The FSF version of this function takes care not to cons in case + ;; of infloop. Maybe we should synch? + (let (parts (start 0)) + (while (string-match pattern string start) + (setq parts (cons (substring string start (match-beginning 0)) parts) + start (match-end 0))) + (nreverse (cons (substring string start) parts)))) + +(defun dictionary-display-dictionarys (reply) + "Handle the display of all dictionaries existing on the server" + (dictionary-pre-buffer) + (insert "Please select your default dictionary:\n\n") + (dictionary-display-dictionary-line "* \"All dictionaries\"") + (dictionary-display-dictionary-line "! \"The first matching dictionary\"") + (let* ((reply (dictionary-read-answer)) + (list (dictionary-simple-split-string reply "\n+"))) + (mapcar 'dictionary-display-dictionary-line list)) + (dictionary-post-buffer)) + +(defun dictionary-display-dictionary-line (string) + "Display a single dictionary" + (let* ((list (dictionary-split-string string)) + (dictionary (car list)) + (description (cadr list))) + (if dictionary + (progn + (link-insert-link description 'dictionary-reference-face + 'dictionary-set-dictionary + (cons dictionary description) + "Mouse-2 to select this dictionary") + (insert "\n"))))) + +(defun dictionary-set-dictionary (param &optional more) + "Select this dictionary as new default" + + (if more + (dictionary-display-more-info param) + (let ((dictionary (car param))) + (setq dictionary-default-dictionary dictionary) + (message "Dictionary %s has been selected" dictionary)))) + +(defun dictionary-display-more-info (param) + "Display the available information on the dictionary" + + (let ((dictionary (car param)) + (description (cdr param))) + (unless (or (equal dictionary "*") + (equal dictionary "!")) + (dictionary-store-positions) + (message "Requesting more information on %s" dictionary) + (dictionary-send-command (concat "show info \"" dictionary "\"")) + (let ((reply (dictionary-read-reply-and-split))) + (message nil) + (if (dictionary-check-reply reply 550) + (error "Dictionary \"%s\" not existing" dictionary) + (unless (dictionary-check-reply reply 112) + (error "Unknown server answer: %s" (dictionary-reply reply))) + (dictionary-pre-buffer) + (insert "Information on dictionary: ") + (link-insert-link description 'dictionary-reference-face + 'dictionary-set-dictionary + (cons dictionary description) + "Mouse-2 to select this dictionary") + (insert "\n\n") + (setq reply (dictionary-read-answer)) + (insert reply) + (dictionary-post-buffer))) + + (dictionary-store-state 'dictionary-display-more-info dictionary)))) + +(defun dictionary-select-strategy (&rest ignored) + "Save the current state and start a strategy selection" + (interactive) + (dictionary-ensure-buffer) + (dictionary-store-positions) + (dictionary-do-select-strategy) + (dictionary-store-state 'dictionary-do-select-strategy nil)) + +(defun dictionary-do-select-strategy () + "The workhorse for doing the strategy selection." + + (message "Request existing matching algorithm") + (dictionary-send-command "show strat") + + (let ((reply (dictionary-read-reply-and-split))) + (message nil) + (if (dictionary-check-reply reply 555) + (error "No strategies available") + (unless (dictionary-check-reply reply 111) + (error "Unknown server answer: %s" + (dictionary-reply reply))) + (dictionary-display-strategies reply)))) + +(defun dictionary-display-strategies (reply) + "Handle the display of all strategies existing on the server" + (dictionary-pre-buffer) + (insert "Please select your default search strategy:\n\n") + (dictionary-display-strategy-line ". \"The servers default\"") + (let* ((reply (dictionary-read-answer)) + (list (dictionary-simple-split-string reply "\n+"))) + (mapcar 'dictionary-display-strategy-line list)) + (dictionary-post-buffer)) + +(defun dictionary-display-strategy-line (string) + "Display a single strategy" + (let* ((list (dictionary-split-string string)) + (strategy (car list)) + (description (cadr list))) + (if strategy + (progn + (link-insert-link description 'dictionary-reference-face + 'dictionary-set-strategy strategy + "Mouse-2 to select this matching algorithm") + (insert "\n"))))) + +(defun dictionary-set-strategy (strategy &rest ignored) + "Select this strategy as new default" + (setq dictionary-default-strategy strategy) + (message "Strategy %s has been selected" strategy)) + +(defun dictionary-new-matching (word) + "Run a new matching search on `word'." + (dictionary-ensure-buffer) + (dictionary-store-positions) + (dictionary-do-matching word dictionary-default-dictionary + dictionary-default-strategy) + (dictionary-store-state 'dictionary-do-matching + (list word dictionary-default-dictionary + dictionary-default-strategy))) + +(defun dictionary-do-matching (word dictionary strategy) + "Ask the server about matches to `word' and display it." + + (message "Lookup matching words for %s in %s using %s" + word dictionary strategy) + (dictionary-send-command + (concat "match \"" dictionary "\" \"" + strategy "\" \"" word "\"")) + (let ((reply (dictionary-read-reply-and-split))) + (message nil) + (if (dictionary-check-reply reply 550) + (error "Dictionary \"%s\" is invalid" dictionary)) + (if (dictionary-check-reply reply 551) + (error "Strategy \"%s\" is invalid" strategy)) + (if (dictionary-check-reply reply 552) + (error (concat + "No match for \"%s\" with strategy \"%s\" in " + "dictionary \"%s\".") + word strategy dictionary)) + (unless (dictionary-check-reply reply 152) + (error "Unknown server answer: %s" (dictionary-reply reply))) + (dictionary-display-match-result reply))) + +(defun dictionary-display-match-result (reply) + "Display the results from the current matches." + (dictionary-pre-buffer) + + (let ((number (nth 1 (dictionary-reply-list reply))) + (list (dictionary-simple-split-string (dictionary-read-answer) "\n+"))) + (insert number " matching word" (if (equal number "1") "" "s") + " found\n\n") + (let ((result nil)) + (mapcar (lambda (item) + (let* ((list (dictionary-split-string item)) + (dictionary (car list)) + (word (cadr list)) + (hash (assoc dictionary result))) + (if dictionary + (if hash + (setcdr hash (cons word (cdr hash))) + (setq result (cons + (cons dictionary (list word)) + result)))))) + list) + (dictionary-display-match-lines (reverse result)))) + (dictionary-post-buffer)) + +(defun dictionary-display-match-lines (list) + "Display the match lines." + (mapcar (lambda (item) + (let ((dictionary (car item)) + (word-list (cdr item))) + (insert "Matches from " dictionary ":\n") + (mapcar (lambda (word) + (insert " ") + (link-insert-link word 'dictionary-reference-face + 'dictionary-new-search + (cons word dictionary) + "Mouse-2 to lookup word") + (insert "\n")) (reverse word-list)) + (insert "\n"))) + list)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; User callable commands +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun dictionary-search (word &optional dictionary) + "Search the `word' in `dictionary' if given or in all if nil. +It presents the word at point as default input and allows editing it." + (interactive + (list (read-string "Search word: " (current-word)) + (if current-prefix-arg + (read-string "Dictionary: " dictionary-default-dictionary) + dictionary-default-dictionary))) + + ;; if called by pressing the button + (unless word + (setq word (read-string "Search word: "))) + ;; just in case non-interactivly called + (unless dictionary + (setq dictionary dictionary-default-dictionary)) + (dictionary-new-search (cons word dictionary))) + +(defun dictionary-lookup-definition () + "Unconditionally lookup the word at point." + (interactive) + (dictionary-new-search (cons (current-word) dictionary-default-dictionary))) + +(defun dictionary-previous () + "Go to the previous location in the current buffer" + (interactive) + (unless (dictionary-mode-p) + (error "Current buffer is no dictionary buffer")) + (dictionary-restore-state)) + +(defun dictionary-next-link () + "Place the cursor to the next link." + (interactive) + (let ((pos (link-next-link))) + (if pos + (goto-char pos) + (error "There is no next link")))) + +(defun dictionary-prev-link () + "Place the cursor to the previous link." + (interactive) + (let ((pos (link-prev-link))) + (if pos + (goto-char pos) + (error "There is no previous link")))) + +(defun dictionary-help () + "Display a little help" + (interactive) + (describe-function 'dictionary-mode)) + +(defun dictionary-match-words (&optional pattern &rest ignored) + "Search `pattern' in current default dictionary using default strategy." + (interactive) + ;; can't use interactive because of mouse events + (or pattern + (setq pattern (read-string "Search pattern: "))) + (dictionary-new-matching pattern)) + +(provide 'dictionary)
\ No newline at end of file diff --git a/install-package.el b/install-package.el new file mode 100755 index 0000000..5b0474e --- /dev/null +++ b/install-package.el @@ -0,0 +1,7 @@ +(defun install-package () + (interactive) + (let ((filename (apply 'concat command-line-args-left))) + (message (concat "Installing package " filename)) + (package-admin-add-binary-package filename) + (set-buffer "*Package Output*") + (message (buffer-substring (point-min) (point-max))))) @@ -0,0 +1,120 @@ +;;; link.el -- putting clickable links into the buffer + +;; Author: Torsten Hilbrich <Torsten.Hilbrich@gmx.net> +;; Keywords: interface, hypermedia +;; $Id: link.el,v 1.5 1999/01/08 18:36:50 torsten Exp $ + +;; This file 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, or (at your option) +;; any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; Commentary: + +;; This file contains functions for using links in buffers. A link is +;; a part of the buffer marked with a special face, beeing +;; hightlighted while the mouse points to it and beeing activated when +;; pressing return or clicking the button2. + +;; Which each link a function and some data are associated. Upon +;; clicking the function is called with the data as only argument. + +(eval-when-compile + (require 'cl)) + +(defun link-create-link (start end face function &optional data help) + "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 `(face ,face + mouse-face highlight + link t + link-data ,data + help-echo ,help + link-function ,function))) + (set-text-properties start end properties))) + +(defun link-insert-link (text face function &optional data help) + "Insert the `text' at point to be formatted as link. +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 ((start (point))) + (insert text) + (link-create-link start (point) face function data help))) + +(defun link-selected (&optional all) + "Is called upon clicking or otherwise visiting the link." + (interactive) + + (let* ((properties (text-properties-at (point))) + (function (plist-get properties 'link-function)) + (data (plist-get properties 'link-data))) + (if function + (funcall function data all)))) + +(defun link-selected-all () + "Called for meta clicking the link" + (interactive) + (link-selected 'all)) + +(defun link-mouse-click (event &optional all) + "Is called upon clicking the link." + (interactive "@e") + + (mouse-set-point event) + (link-selected)) + +(defun link-mouse-click-all (event) + "Is called upon meta clicking the link." + (interactive "@e") + + (mouse-set-point event) + (link-selected-all)) + +(defun link-next-link () + "Return the position of the next link or nil if there is none" + (let* ((pos (point)) + (pos (next-single-property-change pos 'link))) + (if pos + (if (text-property-any pos (min (1+ pos) (point-max)) 'link t) + pos + (next-single-property-change pos 'link)) + nil))) + + +(defun link-prev-link () + "Return the position of the previous link or nil if there is none" + (let* ((pos (point)) + (pos (previous-single-property-change pos 'link))) + (if pos + (if (text-property-any pos (1+ pos) 'link t) + pos + (let ((val (previous-single-property-change pos 'link))) + (if val + val + (text-property-any (point-min) (1+ (point-min)) 'link t)))) + nil))) + +(defun link-initialize-keymap (keymap) + "Defines the necessary bindings inside keymap" + + (if (and (boundp 'running-xemacs) running-xemacs) + (progn + (define-key keymap [button2] 'link-mouse-click) + (define-key keymap [(meta button2)] 'link-mouse-click-all)) + (define-key keymap [mouse-2] 'link-mouse-click) + (define-key keymap [M-mouse-2] 'link-mouse-click-all)) + (define-key keymap [return] 'link-selected) + (define-key keymap [(meta return)] 'link-selected-all)) + +(provide 'link)
\ No newline at end of file diff --git a/lpath.el b/lpath.el new file mode 100644 index 0000000..858179f --- /dev/null +++ b/lpath.el @@ -0,0 +1,4 @@ +;; Shut up. + +(setq load-path (cons "." load-path)) + |