diff lisp/packages/webster.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/packages/webster.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,511 @@
+;; Copyright (C) 1989 Free Software Foundation
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY.  No author or distributor
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing.  Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License.   A copy of this license is
+;; supposed to have been given to you along with GNU Emacs so you
+;; can know your rights and responsibilities.  It should be in a
+;; file named COPYING.  Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+;;
+;;; Synched up with: Not in FSF.
+
+;; Author Jason R. Glasgow (glasgow@cs.yale.edu)
+;; Modified from telnet.el by William F. Schelter
+;; But almost entirely different.
+;;
+;; Modified by Dirk Grunwald to maintain an open connection.
+;;
+;; 3/18/89 Ashwin Ram <Ram-Ashwin@yale.edu>
+;; Added webster-mode.
+;; Fixed documentation.
+;;
+;; 3/20/89 Dirk Grunwald <grunwald@flute.cs.uiuc.edu>
+;; Merged Rams changes with new additions: smarter window placement,
+;; correctly handles un-exposed webster windows, minor cleanups.
+;; Also, ``webster-word'', akin to ``spell-word''.
+;;
+;; To use this, you might want to add this line to your .emacs file:
+;;
+;;  (autoload 'webster "webster" "look up a word in Webster's 7th edition" t)
+;;
+;; Then just hit M-x webster to look up a word.
+;;
+;; 3/21/89 Dave Sill <dsill@relay.nswc.navy.mil>
+;; Removed webster-word and webster-define, adding default of current word to 
+;; webster, webster-spell, and webster-endings instead.
+;;
+;; 1/21/91 Jamie Zawinski <jwz@lucid.com>
+;; Added webster-reformat to produce better looking output.  Made it notice
+;; references to other words in the definitions (all upper-case) and do
+;; completion on them in the string read by meta-x webster.
+;;
+;; 9/14/91 Jamie Zawinski <jwz@lucid.com>
+;; Improved the above.
+;;
+;; 4/15/92 Jamie Zawinski <jwz@lucid.com>
+;; Improved formatting some more, and added Lucid GNU Emacs font and mouse
+;; support (mostly cannibalized from webster-ucb.el.)
+
+(defvar webster-host "agate.berkeley.edu" ;"129.79.254.192"
+  "The host to use as a webster server.")
+
+(defvar webster-port "2627"
+  "The port to connect to. Either 103 or 2627")
+
+(defvar webster-process nil
+  "The current webster process")
+
+(defvar webster-process-name "webster"
+  "The current webster process")
+
+(defvar webster-buffer nil
+  "The current webster process")
+
+(defvar webster-running nil
+  "Used to determine when connection is established")
+
+;;;
+;;; Initial filter for ignoring information until successfully connected
+;;;
+(defun webster-initial-filter (proc string)
+  (let ((this-buffer (current-buffer)))
+    (set-buffer webster-buffer)
+    (goto-char (point-max))
+    (cond ((not (eq (process-status webster-process) 'run))
+	   (setq webster-running t)
+	   (message "Webster died"))
+	  ((string-match "No such host" string)
+	   (setq webster-running t)
+	   (kill-buffer (process-buffer proc))
+	   (error "No such host."))
+	  ((string-match "]" string)
+	   (setq webster-running t)
+	   (set-process-filter proc 'webster-filter)))
+    (set-buffer this-buffer)))
+
+(defvar webster-reformat t
+  "*Set this to t if you want the webster output to be prettied up, and
+for the \\[webster] prompt to do completion across the set of words known
+to be in the dictionary (words you've looked up, or which appeared in 
+definitions as crossreferences.)")
+
+(defun webster-filter (proc string)
+  (let ((this-buffer (current-buffer))
+	(endp nil))
+    (set-buffer webster-buffer)
+    (cond ((not (eq (process-status webster-process) 'run))
+	   (message "Webster died"))
+	  ((string-match "Connection closed" string)
+	   (message "Closing webster connection...")
+	   (kill-process proc)
+	   (replace-regexp "Process webster killed" "" nil)
+	   (goto-char 1)
+	   (message "Closing webster connection...Done."))
+	  ((string-match "SPELLING 0" string)
+	   (insert "...Word not found in webster\n"))
+	  ((string-match "SPELLING 1" string)
+	   (insert "...Spelled correctly\n"))
+	  ((let ((end-def-message (or (string-match "\200" string)
+				      (string-match "\0" string))))
+	     (if end-def-message
+		 (progn
+		   (webster-filter
+		    proc
+		    (concat (substring string 0 (- end-def-message 1)) "\n\n"))
+		   (setq endp t)
+		   (goto-char (point-max))
+		   t))))
+	  (t
+	   (goto-char (point-max))
+	   (let ((now (point)))
+	     (insert string)
+	     (delete-char-in-region now (point) "\^M" " "))
+	   (if (process-mark proc)
+	       (set-marker (process-mark proc) (point)))))
+    (if endp
+	;; if the webster window is visible, move the last line to the
+	;; bottom of that window
+	(let ((webster-window (get-buffer-window webster-buffer))
+	      (window (selected-window)))
+	  (if webster-reformat (webster-reformat (process-mark proc)))
+	  (if webster-window
+	      (progn
+		(select-window webster-window)
+		(goto-char (point-max))
+		(recenter (1- (window-height webster-window)))
+		(select-window window)))))))
+
+(defconst webster-completion-table (make-vector 511 0))
+
+(defun webster-intern (string)
+  (while (string-match "\\." string)
+    (setq string (concat (substring string 0 (match-beginning 0))
+			 (substring string (match-end 0)))))
+  (intern (downcase string) webster-completion-table))
+
+(defvar webster-fontify (string-match "XEmacs" emacs-version)
+  "*Set to t to use the XEmacs/Lucid Emacs font-change mechanism.")
+
+(cond ((fboundp 'make-face)
+       (or (find-face 'webster)
+	   (face-differs-from-default-p (make-face 'webster))
+	   (copy-face 'default 'webster))
+       (or (find-face 'webster-bold)
+	   (face-differs-from-default-p (make-face 'webster-bold))
+	   (copy-face 'bold 'webster-bold))
+       (or (find-face 'webster-italic)
+	   (face-differs-from-default-p (make-face 'webster-italic))
+	   (copy-face 'italic 'webster-italic))
+       (or (find-face 'webster-bold-italic)
+	   (face-differs-from-default-p (make-face 'webster-bold-italic))
+	   (copy-face 'bold-italic 'webster-bold-italic))
+       (or (find-face 'webster-small)
+	   (face-differs-from-default-p (make-face 'webster-small))
+	   (copy-face 'webster-bold 'webster-small))
+       ))
+
+(defun webster-fontify (start end face &optional highlight)
+  (let ((e (make-extent start end (current-buffer))))
+    (set-extent-face e face)
+    (if highlight (set-extent-property e 'highlight t))))
+
+
+(defun webster-reformat (end)
+  "Clean up the output of the webster server, and gather words for the 
+completion table."
+  (if (not webster-reformat) nil
+    (goto-char end)
+    (let ((case-fold-search nil))
+      (re-search-backward "^[A-Z]+" nil t)
+      (if webster-fontify
+	  (save-excursion
+	    (previous-line 1)
+	    (if (looking-at "^DEFINE \\([^ \n]+\\)")
+		(webster-fontify (match-beginning 1) (match-end 1)
+				 'webster-bold t))))
+      (cond
+       ((or (looking-at "^DEFINITION [0-9]")
+	    (looking-at "^SPELLING"))
+	(forward-line 1)
+	(let ((p (point))
+	      (indent 2))
+	  (search-forward "\n\n" nil 0)
+	  (narrow-to-region p (point))
+	  (goto-char p)
+	  (while (search-forward "\n" nil t)
+	    (delete-char -1)
+	    (just-one-space))
+	  (goto-char p)
+	  (while (not (eobp))
+	    (if (looking-at " *\n")
+		(delete-region (match-beginning 0) (match-end 0)))
+	    (cond ((looking-at "^[0-9]+ ")
+		   (if webster-fontify
+		       (webster-fontify (point) (match-end 0)
+					'webster-bold-italic))
+		   (goto-char (match-end 0))
+		   (if (looking-at "[^\n0-9]+ [0-9]")
+		       (save-excursion
+			 (goto-char (1- (match-end 0)))
+			 (insert "\n")))
+		   (if (looking-at "[a-z]+\\( [a-z]+\\)*[ \n]")
+		       (webster-intern
+			(buffer-substring (point) (1- (match-end 0)))))
+		   (if webster-fontify
+		       (webster-fontify (point) (1- (match-end 0))
+					'webster-bold t))
+		   (goto-char (1- (match-end 0)))
+		   (if (looking-at " *\n") (forward-line 1)))
+		  ((looking-at " *[0-9]+\\. ")
+		   (setq indent 5)
+		   (delete-horizontal-space)
+		   (insert (if (= (preceding-char) ?\n) "  " "\n  "))
+		   (skip-chars-forward "0-9. ")
+		   (if webster-fontify
+		       (webster-fontify
+			(save-excursion (beginning-of-line) (point))
+			(point)
+			'webster-bold-italic)))
+		  ((looking-at " *\\([0-9]+\\): *")
+		   (let ((n (buffer-substring (match-beginning 1)
+					      (match-end 1))))
+		     (delete-region (match-beginning 0) (match-end 0))
+		     (insert "\n")
+		     (indent-to (- 6 (length n)))
+		     (insert n " : ")
+		     (setq indent 9)
+		     (if webster-fontify
+			 (webster-fontify
+			  (save-excursion (beginning-of-line) (point))
+			  (point)
+			  'webster-bold-italic))))
+		  ((looking-at " *\\([0-9]+\\)\\([a-z]+\\): *")
+		   (let ((n (buffer-substring (match-beginning 1)
+					      (match-end 1)))
+			 (m (buffer-substring (match-beginning 2)
+					      (match-end 2))))
+		     (if (not (equal m "a")) (setq n " "))
+		     (delete-region (match-beginning 0) (match-end 0))
+		     (insert "\n")
+		     (indent-to (- 6 (length n)))
+		     (insert n "  ")
+		     (insert m " : ")
+		     (setq indent 12)
+		     (if webster-fontify
+			 (webster-fontify
+			  (save-excursion (beginning-of-line) (point))
+			  (point)
+			  'webster-bold-italic))))
+		  ((looking-at " *\\([0-9]+\\)\\([a-z]+\\)\\([0-9]+\\): *")
+		   (let ((n (buffer-substring (match-beginning 1)
+					      (match-end 1)))
+			 (m (buffer-substring (match-beginning 2)
+					      (match-end 2)))
+			 (o (buffer-substring (match-beginning 3)
+					      (match-end 3))))
+		     (if (not (equal o "1")) (setq m " "))
+		     (if (not (equal m "a")) (setq n " "))
+		     (delete-region (match-beginning 0) (match-end 0))
+		     (insert "\n")
+		     (indent-to (- 6 (length n)))
+		     (insert n "  ")
+		     (insert m "  ")
+		     (insert "(" o ") : ")
+		     (setq indent 17)
+		     (if webster-fontify
+			 (webster-fontify
+			  (save-excursion (beginning-of-line) (point))
+			  (point)
+			  'webster-bold-italic))))
+		  ((looking-at " *\\\\")
+		   (setq indent 5)
+		   (setq p (point))
+		   (goto-char (match-end 0))
+		   (search-forward "\\")
+		   (if (> (current-column) fill-column)
+		       (progn
+			 (goto-char p)
+			 (insert "\n")
+			 (indent-to 18)
+			 (search-forward "\\")))
+		   (if webster-fontify
+		       (webster-fontify p (point) 'webster-italic)))
+		  ((looking-at " *\\[")
+		   (setq indent 6)
+		   (delete-horizontal-space)
+		   (insert "\n")
+		   (indent-to 5)
+		   (forward-char 1))
+		  ((and (= (preceding-char) ?\])
+			(looking-at " *:"))
+		   (delete-horizontal-space)
+		   (setq indent 5)
+		   (insert "\n "))
+		  ((looking-at " *SYN *")
+		   (delete-region (point) (match-end 0))
+		   (insert "\n")
+		   (delete-horizontal-space)
+		   (insert "  ")
+		   (setq indent 6)
+		   (if (looking-at "syn ")
+		       (progn
+			 (if webster-fontify
+			     (webster-fontify (point) (+ (point) 3)
+					      'webster-bold))
+			 (goto-char (match-end 0))
+			 (insert "see "))))
+		  (t
+		   (setq p (point))
+		   (skip-chars-forward " ,:;-")
+		   (if (or (looking-at
+			  "\\([A-Z][-A-Z]+[A-Z]\\)\\( [A-Z][-A-Z]*[A-Z]\\)*")
+			   (looking-at "[a-z][-a-z]*\\(\\.[a-z][-a-z]*\\)+"))
+		       (let ((s (buffer-substring (point) (match-end 0))))
+			 (if webster-fontify
+			     (webster-fontify (point) (match-end 0)
+					      'webster-bold t))
+			 (while (string-match "\\." s)
+			   (setq s (concat (substring s 0 (match-beginning 0))
+					   (substring s (match-end 0)))))
+			 (webster-intern s)))
+		   (skip-chars-forward "^ \\")
+		   (if (> (current-column) fill-column)
+		       (progn
+			 (goto-char p)
+			 (insert "\n")
+			 (delete-horizontal-space)
+			 (indent-to indent)
+			 (skip-chars-forward " ")
+			 (skip-chars-forward "^ \\")
+			 )))
+		  )))
+	(goto-char (point-min))
+	(while (looking-at "\n") (delete-char 1))
+	(goto-char (point-max))
+	(insert "\n\n")
+	(widen))))))
+
+;; " \\(\\(slang\\|cap\\|pl\\|aj\\|av\\|n\\|v\\|vt\\|vi\\)\\(,[ \n]+\\)?\\)+\n"
+
+;;;
+;;; delete char1 and char2 if it precedes char1
+;;; used to get rid of <space><return>
+(defun delete-char-in-region (start end char1 char2)
+  (goto-char start)
+  (setq char2 (aref char2 0))
+  (while (search-forward char1 end t)
+    (delete-char -1)
+    (if (= (char-after (- (point) 1)) char2)
+	(delete-char -1))))
+
+;;;###autoload
+(defun webster (arg)
+"Look up a word in the Webster's dictionary.
+Open a network login connection to a webster host if necessary.
+Communication with host is recorded in a buffer *webster*."
+  (interactive (list
+		(let ((prompt (concat "Look up word in webster ("
+				      (current-word) "): "))
+		      (completion-ignore-case t))
+		  (downcase
+		   (if webster-reformat
+		       (completing-read prompt webster-completion-table
+					nil nil)
+		     (read-string prompt))))))
+  (if (equal "" arg) (setq arg (current-word)))
+  (webster-send-request "DEFINE" arg))
+
+;;;###autoload
+(defun webster-endings (arg)
+"Look up endings for a word in the Webster's dictionary.
+Open a network login connection to a webster host if necessary.
+Communication with host is recorded in a buffer *webster*."
+  (interactive (list
+		(read-string
+		 (concat
+		  "Find endings for word in webster (" (current-word) "): "))))
+  (if (equal "" arg) (setq arg (current-word)))
+  (webster-send-request "ENDINGS" arg))
+
+;;;###autoload
+(defun webster-spell (arg)
+"Look spelling for a word in the Webster's dictionary.
+Open a network login connection to a webster host if necessary.
+Communication with host is recorded in a buffer *webster*."
+  (interactive (list
+		(read-string
+		 (concat
+		  "Try to spell word in webster (" (current-word) "): "))))
+  (if (equal "" arg) (setq arg (current-word)))
+  (webster-send-request "SPELL" arg))
+
+(defun webster-send-request (kind word)
+  (require 'shell)
+  (let
+      ((webster-command (concat "open " webster-host " " webster-port "\n")))
+    
+    (if (or 
+	 (not webster-buffer)
+	 (not webster-process)
+	 (not (eq (process-status webster-process) 'run)))
+	(progn
+	  (message
+	   (concat "Attempting to connect to server " webster-host "..."))
+	  (setq webster-buffer
+		(if (not (fboundp 'make-shell)) ;emacs19
+		    (make-comint webster-process-name "telnet")
+		  (make-shell webster-process-name "telnet")))
+	  (let
+	      ((this-buffer (current-buffer)))
+	    (set-buffer webster-buffer)
+	    (webster-mode)
+	    (set-buffer this-buffer))
+
+	  (setq webster-process (get-process webster-process-name))
+	  (set-process-filter webster-process 'webster-initial-filter)
+	  (process-send-string  webster-process webster-command)
+	  (setq webster-running nil);
+	  (while (not webster-running)	; wait for feedback
+	    (accept-process-output))))	;
+    (display-buffer webster-buffer nil)
+    (process-send-string webster-process (concat kind " " word "\n"))))
+
+(defun webster-quit ()
+   "Close connection and quit webster-mode.  Buffer is not deleted."
+   (interactive)
+   (message "Closing connection to %s..." webster-host)
+   (kill-process webster-process)
+   (message "Closing connection to %s...done" webster-host)
+   (bury-buffer))
+
+(defvar webster-mode-map nil)
+
+(defun webster-mode ()
+  "Major mode for interacting with on-line Webster's dictionary.
+\\{webster-mode-map}
+Use webster-mode-hook for customization."
+  (interactive)
+  (kill-all-local-variables)
+  (setq major-mode 'webster-mode)
+  (setq mode-name "Webster")
+  (use-local-map webster-mode-map)
+  (run-hooks 'webster-mode-hook))
+
+(if webster-mode-map
+    nil
+  (setq webster-mode-map (make-sparse-keymap))
+  (define-key webster-mode-map "?" 'describe-mode)
+  (define-key webster-mode-map "d" 'webster)
+  (define-key webster-mode-map "e" 'webster-endings)
+  (define-key webster-mode-map "q" 'webster-quit)
+  (define-key webster-mode-map "s" 'webster-spell)
+  (if (string-match "XEmacs" emacs-version)
+      (define-key webster-mode-map 'button2 'webster-xref-word)))
+
+;; now in simple.el
+;(defun current-word ()
+;   "Word cursor is over, as a string."
+;   (save-excursion
+;      (let (beg end)
+;	 (re-search-backward "\\w" nil 2)
+;	 (re-search-backward "\\b" nil 2)
+;	 (setq beg (point))
+;	 (re-search-forward "\\w*\\b" nil 2)
+;	 (setq end (point))
+;	 (buffer-substring beg end))))
+
+(defun webster-xref-word (event)
+  "Define the highlighted word under the mouse.
+Words which are known to have definitions are highlighted when the mouse
+moves over them.  You may define any word by selecting it with the left
+mouse button and then clicking middle."
+  (interactive "e")
+  (let* ((buffer (event-buffer event))
+	 (extent (extent-at (event-point event) buffer 'highlight))
+	 text)
+    (cond (extent
+	   (setq text (save-excursion
+			(set-buffer buffer)
+			(buffer-substring
+			 (extent-start-position extent)
+			 (extent-end-position extent)))))
+	  ((x-selection-owner-p) ; the selection is in this emacs process.
+	   (setq text (x-get-selection)))
+	  (t
+	   (error "click on a highlighted word to define")))
+    (while (string-match "\\." text)
+      (setq text (concat (substring text 0 (match-beginning 0))
+			 (substring text (match-end 0)))))
+    (message "looking up %s..." (upcase text))
+    (goto-char (point-max))
+    (webster text)))