home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / interfaces / webster.el < prev    next >
Encoding:
Text File  |  1991-11-11  |  13.6 KB  |  411 lines

  1. ; Received: from dg-rtp by teton (5.4/rtp-s04)
  2. ;     id AA04130; Mon, 21 Oct 1991 01:54:11 -0400
  3. ; Received: from lucid.com by dg-rtp.dg.com (5.4/dg-rtp-proto)
  4. ;     id AA12962; Mon, 21 Oct 1991 01:54:02 -0400
  5. ; Received: from thalidomide ([192.31.212.116]) by heavens-gate.lucid.com id AA00571g; Sun, 20 Oct 91 22:53:20 PDT
  6. ; Received: by thalidomide id AA05286g; Sun, 20 Oct 91 22:54:00 PDT
  7. ; Date: Sun, 20 Oct 91 22:54:00 PDT
  8. ; X-Windows: Let it get in YOUR way.
  9. ; From: Jamie Zawinski <jwz%thalidomide@lucid.com>
  10. ; Subject: webster modes
  11. ; Content-Type: text
  12. ; Content-Length: 13262
  13. ; Status: RO
  14. ; Hi.  I've made some improvements to webster.el, you might want to archive this
  15. ; version.
  16. ; LCD Archive Entry:
  17. ; webster|Glasgow, Grunwald, Ram, Sill, Zawinski|jwz@lucid.com
  18. ; |Look up a word in Webster's 7th Ed.
  19. ; |91-09-14||~/interfaces/webster.el.Z|
  20.  
  21. ; ---------- slice 'n' dice ----------------------------------- file: webster.el
  22. ;; Copyright (C) 1989 Free Software Foundation
  23.  
  24. ;; This file is part of GNU Emacs.
  25.  
  26. ;; GNU Emacs is distributed in the hope that it will be useful,
  27. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  28. ;; accepts responsibility to anyone for the consequences of using it
  29. ;; or for whether it serves any particular purpose or works at all,
  30. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  31. ;; License for full details.
  32.  
  33. ;; Everyone is granted permission to copy, modify and redistribute
  34. ;; GNU Emacs, but only under the conditions described in the
  35. ;; GNU Emacs General Public License.   A copy of this license is
  36. ;; supposed to have been given to you along with GNU Emacs so you
  37. ;; can know your rights and responsibilities.  It should be in a
  38. ;; file named COPYING.  Among other things, the copyright notice
  39. ;; and this notice must be preserved on all copies.
  40. ;;
  41. ;; Author Jason R. Glasgow (glasgow@cs.yale.edu)
  42. ;; Modified from telnet.el by William F. Schelter
  43. ;; But almost entirely different.
  44. ;;
  45. ;; Modified by Dirk Grunwald to maintain an open connection.
  46. ;;
  47. ;; 3/18/89 Ashwin Ram <Ram-Ashwin@yale.edu>
  48. ;; Added webster-mode.
  49. ;; Fixed documentation.
  50. ;;
  51. ;; 3/20/89 Dirk Grunwald <grunwald@flute.cs.uiuc.edu>
  52. ;; Merged Rams changes with new additions: smarter window placement,
  53. ;; correctly handles un-exposed webster windows, minor cleanups.
  54. ;; Also, ``webster-word'', akin to ``spell-word''.
  55. ;;
  56. ;; To use this, you might want to add this line to your .emacs file:
  57. ;;
  58. ;;  (autoload 'webster "webster" "look up a word in Webster's 7th edition" t)
  59. ;;
  60. ;; Then just hit M-x webster to look up a word.
  61. ;;
  62. ;; 3/21/89 Dave Sill <dsill@relay.nswc.navy.mil>
  63. ;; Removed webster-word and webster-define, adding default of current word to 
  64. ;; webster, webster-spell, and webster-endings instead.
  65. ;;
  66. ;; 1/21/91 Jamie Zawinski <jwz@lucid.com>
  67. ;; Added webster-reformat to produce better looking output.  Made it notice
  68. ;; references to other words in the definitions (all upper-case) and do
  69. ;; completion on them in the string read by meta-x webster.
  70. ;;
  71. ;; 9/14/91 Jamie Zawinski <jwz@lucid.com>
  72. ;; Improved the above.
  73.  
  74. (defvar webster-host "18.26.0.36"
  75.   "The host to use as a webster server.")
  76.  
  77. (defvar webster-port "103"
  78.   "The port to connect to. Either 103 or 2627")
  79.  
  80. (defvar webster-process nil
  81.   "The current webster process")
  82.  
  83. (defvar webster-process-name "webster"
  84.   "The current webster process")
  85.  
  86. (defvar webster-buffer nil
  87.   "The current webster process")
  88.  
  89. (defvar webster-running nil
  90.   "Used to determine when connection is established")
  91.  
  92. ;;;
  93. ;;; Initial filter for ignoring information until successfully connected
  94. ;;;
  95. (defun webster-initial-filter (proc string)
  96.   (let ((this-buffer (current-buffer)))
  97.     (set-buffer webster-buffer)
  98.     (goto-char (point-max))
  99.     (cond ((not (eq (process-status webster-process) 'run))
  100.        (setq webster-running t)
  101.        (message "Webster died"))
  102.       ((string-match "No such host" string)
  103.        (setq webster-running t)
  104.        (kill-buffer (process-buffer proc))
  105.        (error "No such host."))
  106.       ((string-match "]" string)
  107.        (setq webster-running t)
  108.        (set-process-filter proc 'webster-filter)))
  109.     (set-buffer this-buffer)))
  110.  
  111. (defvar webster-reformat t
  112.   "*Set this to t if you want the webster output to be prettied up, andfor the \\[webster] prompt to do completion across the set of words knownto be in the dictionary (words you've looked up, or which appeared in definitions as crossreferences.)")
  113.  
  114. (defun webster-filter (proc string)
  115.   (let ((this-buffer (current-buffer))
  116.     (endp nil))
  117.     (set-buffer webster-buffer)
  118.     (cond ((not (eq (process-status webster-process) 'run))
  119.        (message "Webster died"))
  120.       ((string-match "Connection closed" string)
  121.        (message "Closing webster connection...")
  122.        (kill-process proc)
  123.        (replace-regexp "Process webster killed" "" nil)
  124.        (goto-char 1)
  125.        (message "Closing webster connection...Done."))
  126.       ((string-match "SPELLING 0" string)
  127.        (insert-string "...Word not found in webster\n"))
  128.       ((string-match "SPELLING 1" string)
  129.        (insert-string "...Spelled correctly\n"))
  130.       ((let ((end-def-message (or (string-match "\200" string)
  131.                       (string-match "\0" string))))
  132.          (if end-def-message
  133.          (progn
  134.            (webster-filter
  135.             proc
  136.             (concat (substring string 0 (- end-def-message 1)) "\n\n"))
  137.            (setq endp t)
  138.            (goto-char (point-max))
  139.            t))))
  140.       (t
  141.        (goto-char (point-max))
  142.        (let ((now (point)))
  143.          (insert string)
  144.          (delete-char-in-region now (point) "\^M" " "))
  145.        (if (process-mark proc)
  146.            (set-marker (process-mark proc) (point)))))
  147.     (if endp
  148.     ;; if the webster window is visible, move the last line to the
  149.     ;; bottom of that window
  150.     (let ((webster-window (get-buffer-window webster-buffer))
  151.           (window (selected-window)))
  152.       (if webster-reformat (webster-reformat (process-mark proc)))
  153.       (if webster-window
  154.           (progn
  155.         (select-window webster-window)
  156.         (goto-char (point-max))
  157.         (recenter (1- (window-height webster-window)))
  158.         (select-window window)))))))
  159.  
  160. (defconst webster-completion-table (make-vector 511 0))
  161.  
  162. (defun webster-intern (string)
  163.   (while (string-match "\\." string)
  164.     (setq string (concat (substring string 0 (match-beginning 0))
  165.              (substring string (match-end 0)))))
  166.   (intern (downcase string) webster-completion-table))
  167.  
  168. (defun webster-reformat (end)
  169.   "Clean up the output of the webster server, and gather words for the completion table."
  170.   (if (not webster-reformat) nil
  171.     (goto-char end)
  172.     (let ((case-fold-search nil))
  173.       (re-search-backward "^[A-Z]+" nil t)
  174.       (if (not (looking-at "^DEFINITION [0-9]"))
  175.       nil
  176.     (forward-line 1)
  177.     (let ((p (point))
  178.           (indent 2))
  179.       (search-forward "\n\n" nil 0)
  180.       (narrow-to-region p (point))
  181.       (goto-char p)
  182.       (while (search-forward "\n" nil t)
  183.         (delete-char -1)
  184.         (just-one-space))
  185.       (goto-char p)
  186.       (while (not (eobp))
  187.         (cond ((looking-at " *[0-9]+\\. ")
  188.            (setq indent 5)
  189.            (delete-horizontal-space)
  190.            (insert "\n  ")
  191.            (skip-chars-forward "0-9. ")
  192.            (if (looking-at "[a-z]+")
  193.                (webster-intern
  194.             (buffer-substring (point) (match-end 0)))))
  195.           ((looking-at " *\\([0-9]+\\): *")
  196.            (let ((n (buffer-substring (match-beginning 1)
  197.                           (match-end 1))))
  198.              (delete-region (match-beginning 0) (match-end 0))
  199.              (insert "\n")
  200.              (indent-to (- 6 (length n)))
  201.              (insert n " : ")
  202.              (setq indent 9)))
  203.           ((looking-at " *\\([0-9]+\\)\\([a-z]+\\): *")
  204.            (let ((n (buffer-substring (match-beginning 1)
  205.                           (match-end 1)))
  206.              (m (buffer-substring (match-beginning 2)
  207.                           (match-end 2))))
  208.              (if (not (equal m "a")) (setq n " "))
  209.              (delete-region (match-beginning 0) (match-end 0))
  210.              (insert "\n")
  211.              (indent-to (- 6 (length n)))
  212.              (insert n "  ")
  213.              (insert m " : ")
  214.              (setq indent 12)))
  215.           ((looking-at " *\\([0-9]+\\)\\([a-z]+\\)\\([0-9]+\\): *")
  216.            (let ((n (buffer-substring (match-beginning 1)
  217.                           (match-end 1)))
  218.              (m (buffer-substring (match-beginning 2)
  219.                           (match-end 2)))
  220.              (o (buffer-substring (match-beginning 3)
  221.                           (match-end 3))))
  222.              (if (not (equal o "1")) (setq m " "))
  223.              (if (not (equal m "a")) (setq n " "))
  224.              (delete-region (match-beginning 0) (match-end 0))
  225.              (insert "\n")
  226.              (indent-to (- 6 (length n)))
  227.              (insert n "  ")
  228.              (insert m "  ")
  229.              (insert "(" o ") : ")
  230.              (setq indent 17)))
  231.           ((looking-at " *\\\\")
  232.            (setq indent 5)
  233.            (setq p (point))
  234.            (goto-char (match-end 0))
  235.            (search-forward "\\")
  236.            (if (> (current-column) fill-column)
  237.                (progn
  238.              (goto-char p)
  239.              (insert "\n")
  240.              (indent-to 18)
  241.              (search-forward "\\"))))
  242.           ((looking-at " *\\[")
  243.            (setq indent 6)
  244.            (delete-horizontal-space)
  245.            (insert "\n")
  246.            (indent-to 5)
  247.            (forward-char 1))
  248.           ((and (= (preceding-char) ?\])
  249.             (looking-at " *:"))
  250.            (delete-horizontal-space)
  251.            (setq indent 5)
  252.            (insert "\n "))
  253.           ((looking-at " *SYN *")
  254.            (delete-region (point) (match-end 0))
  255.            (insert "\n")
  256.            (delete-horizontal-space)
  257.            (insert "  ")
  258.            (setq indent 6)
  259.            (if (looking-at "syn ")
  260.                (progn (goto-char (match-end 0))
  261.                   (insert "see "))))
  262.           (t
  263.            (setq p (point))
  264.            (skip-chars-forward " ,:;-")
  265.            (if (looking-at "\\([A-Z][A-Z][A-Z]+\\)\\( [A-Z][A-Z]+\\)*")
  266.                (webster-intern
  267.             (buffer-substring (point) (match-end 0))))
  268.            (skip-chars-forward "^ \\")
  269.            (if (> (current-column) fill-column)
  270.                (progn
  271.              (goto-char p)
  272.              (insert "\n")
  273.              (delete-horizontal-space)
  274.              (indent-to indent)
  275.              (skip-chars-forward " ")
  276.              (skip-chars-forward "^ \\")
  277.              )))
  278.           )))
  279.     (goto-char (point-min))
  280.     (while (looking-at "\n") (delete-char 1))
  281.     (goto-char (point-max))
  282.     (insert "\n\n")
  283.     (widen)))))
  284.  
  285. ;; " \\(\\(slang\\|cap\\|pl\\|aj\\|av\\|n\\|v\\|vt\\|vi\\)\\(,[ \n]+\\)?\\)+\n"
  286.  
  287. ;;;
  288. ;;; delete char1 and char2 if it precedes char1
  289. ;;; used to get rid of <space><return>
  290. (defun delete-char-in-region (start end char1 char2)
  291.   (goto-char start)
  292.   (setq char2 (aref char2 0))
  293.   (while (search-forward char1 end t)
  294.     (delete-char -1)
  295.     (if (= (char-after (- (point) 1)) char2)
  296.     (delete-char -1))))
  297.  
  298. (defun webster (arg)
  299. "Look up a word in the Webster's dictionary.
  300. Open a network login connection to a webster host if necessary.
  301. Communication with host is recorded in a buffer *webster*."
  302.   (interactive (list
  303.         (let ((prompt (concat "Look up word in webster ("
  304.                       (current-word) "): "))
  305.               (completion-ignore-case t))
  306.           (downcase
  307.            (if webster-reformat
  308.                (completing-read prompt webster-completion-table
  309.                     nil nil)
  310.              (read-string prompt))))))
  311.   (if (equal "" arg) (setq arg (current-word)))
  312.   (webster-send-request "DEFINE" arg))
  313.  
  314. (defun webster-endings (arg)
  315. "Look up endings for a word in the Webster's dictionary.
  316. Open a network login connection to a webster host if necessary.
  317. Communication with host is recorded in a buffer *webster*."
  318.   (interactive (list
  319.         (read-string
  320.          (concat
  321.           "Find endings for word in webster (" (current-word) "): "))))
  322.   (if (equal "" arg) (setq arg (current-word)))
  323.   (webster-send-request "ENDINGS" arg))
  324.  
  325. (defun webster-spell (arg)
  326. "Look spelling for a word in the Webster's dictionary.
  327. Open a network login connection to a webster host if necessary.
  328. Communication with host is recorded in a buffer *webster*."
  329.   (interactive (list
  330.         (read-string
  331.          (concat
  332.           "Try to spell word in webster (" (current-word) "): "))))
  333.   (if (equal "" arg) (setq arg (current-word)))
  334.   (webster-send-request "SPELL" arg))
  335.  
  336. (defun webster-send-request (kind word)
  337.   (require 'shell)
  338.   (let
  339.       ((webster-command (concat "open " webster-host " " webster-port "\n")))
  340.     
  341.     (if (or 
  342.      (not webster-buffer)
  343.      (not webster-process)
  344.      (not (eq (process-status webster-process) 'run)))
  345.     (progn
  346.       (message
  347.        (concat "Attempting to connect to server " webster-host "..."))
  348.       (setq webster-buffer
  349.         (if (not (fboundp 'make-shell)) ;emacs19
  350.             (make-comint webster-process-name "telnet")
  351.           (make-shell webster-process-name "telnet")))
  352.       (let
  353.           ((this-buffer (current-buffer)))
  354.         (set-buffer webster-buffer)
  355.         (webster-mode)
  356.         (set-buffer this-buffer))
  357.  
  358.       (setq webster-process (get-process webster-process-name))
  359.       (set-process-filter webster-process 'webster-initial-filter)
  360.       (process-send-string  webster-process webster-command)
  361.       (setq webster-running nil);
  362.       (while (not webster-running)    ; wait for feedback
  363.         (accept-process-output))))    ;
  364.     (display-buffer webster-buffer nil)
  365.     (process-send-string webster-process (concat kind " " word "\n"))))
  366.  
  367. (defun webster-quit ()
  368.    "Close connection and quit webster-mode.  Buffer is not deleted."
  369.    (interactive)
  370.    (message "Closing connection to %s..." webster-host)
  371.    (kill-process webster-process)
  372.    (message "Closing connection to %s...done" webster-host)
  373.    (bury-buffer))
  374.  
  375. (defun webster-mode ()
  376.   "Major mode for interacting with on-line Webster's dictionary.
  377. \\{webster-mode-map}
  378. Use webster-mode-hook for customization."
  379.   (interactive)
  380.   (kill-all-local-variables)
  381.   (setq major-mode 'webster-mode)
  382.   (setq mode-name "Webster")
  383.   (use-local-map webster-mode-map)
  384.   (run-hooks 'webster-mode-hook))
  385.  
  386. (defvar webster-mode-map nil)
  387. (if webster-mode-map
  388.     nil
  389.   (setq webster-mode-map (make-sparse-keymap))
  390.   (define-key webster-mode-map "?" 'describe-mode)
  391.   (define-key webster-mode-map "d" 'webster)
  392.   (define-key webster-mode-map "e" 'webster-endings)
  393.   (define-key webster-mode-map "q" 'webster-quit)
  394.   (define-key webster-mode-map "s" 'webster-spell))
  395.  
  396. ;; Snatched from unix-apropos by Henry Kautz
  397. (defun current-word ()
  398.    "Word cursor is over, as a string."
  399.    (save-excursion
  400.       (let (beg end)
  401.      (re-search-backward "\\w" nil 2)
  402.      (re-search-backward "\\b" nil 2)
  403.      (setq beg (point))
  404.      (re-search-forward "\\w*\\b" nil 2)
  405.      (setq end (point))
  406.      (buffer-substring beg end))))
  407.  
  408.