dsill@RELAY.NSWC.NAVY.MIL (03/22/89)
Yesterday I posted a version of webster that provided the current word as the default word to be spelled, defined, or ended. Also yesterday, Dirk Grunwald posted a version of webster that provided webster-word and webster-define to spell or define, respectively, the word to the left of point. There is an inconsistency in the way Emacs functions on words work. Some, like ispell-word or webster-word, operate on a word in the current buffer. Others, like apropos or webster, read their argument from the minibuffer, after prompting. Some of the latter, like unix-apropos and webster as I modified it, provide a default response of the current word. Personally, I think it's better to have one function that can operate on either the current word or one read from the minibuffer than to have two separate functions. The former has the advantage of showing the operator exactly what word will be operated on if the default is taken. The only thing that could be considered a drawback of this approach is that it requires the operator to confirm his choice by pressing return. What's the consensus: two separate functions, one operating on the current word and one reading from the minibuffer; or one function reading from the minibuffer providing the current word as a default? A related problem is that these functions determine the current word differently. Most, like ispell-word, use the regular expression \\w to find the complete word to the left of point. Others, like webster-word, use the partial word from point to the beginning of the word to the left of point. Perhaps the function ``interactive'' could be modified to include a code, say "w", meaning "the complete word to the left of point". But that would only solve half the problem. There would still need to be some way to handle defaults. How about a general default mechanism added to ``interactive''? Something like: (interactive "wISpell word (%s): ") (interactive "aDescribe function (default %s): ") which would result in: ISpell word (prefrobnicate): Describe function (default interactive): Comments? Flames? Implementations? ================ Above opinions are mine. "The ultimate metric that I would like to propose for user friendliness is quite simple: if this system were a person, how long would it take before you punched it in the nose?" -- Tom Carey
news@bbn.COM (News system owner ID) (03/22/89)
> From: dsill@RELAY.NSWC.NAVY.MIL > Newsgroups: comp.emacs > Date: 21 Mar 89 16:37:34 GMT > > Perhaps the function ``interactive'' could be modified to include a > code, say "w", meaning "the complete word to the left of point". But > that would only solve half the problem. There would still need to be > some way to handle defaults. How about a general default mechanism > added to ``interactive''? Something like: > (interactive "wISpell word (%s): ") > (interactive "aDescribe function (default %s): ") > which would result in: > ISpell word (prefrobnicate): > Describe function (default interactive): > Well, something like this is already there: look for example at the way find-tag and find-tag-tag are implemented, and you'll see a more complex interaction between finding some string from the buffer and constructing a call to interactive with it (i changed my definition of find-tag-tag because i didn't like the way it lost if point is just inside a left paren). The crucial documentation from C-h d interactive is this prose: The argument of interactive is usually a string containing a code letter followed by a prompt... If the argument is not a string, it is evaluated to get a list of arguments to pass to the function. And so you can call arbitrary bits of code to supply defaults by looking at the buffer in smart ways. I also wish there were a more standard way to do this, but maybe that's hoping for too much (sometimes you want completion, sometimes you want to obey syntactic conventions of the language in the buffer, etc.). ........................................ Sean Boisen -- sboisen@bbn.com BBN Systems and Technologies Corporation, Cambridge MA Disclaimer: these opinions void where prohibited by lawyers. Sean
grunwald@flute.cs.uiuc.edu (03/22/89)
personally, I agree with you -- functions should provide default arguments instead of having two ways of doing things. My brain went to lunch, leaving my fingers behind, ergo ``webster-word'' (actually, I had been using spell-word and said `gee, I'd like to use webster for spellings too'...) Here's a combined version: ;; 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. ;; ;; 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. ;; (defvar webster-host "128.197.2.40" "Host that is a webster server (Boston U). Try also 26.0.0.73, which is sri-nic") (defvar webster-port "103" "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)) (progn (setq webster-running t) (message "Webster died"))) ((string-match "No such host" string) (progn (setq webster-running t) (kill-buffer (process-buffer proc)) (error "No such host."))) ((string-match "]" string) (progn (setq webster-running t) (set-process-filter proc 'webster-filter)))) (set-buffer this-buffer))) (defun webster-filter (proc string) (let ((closed-message (string-match "Connection closed" string)) (end-def-message (or (string-match "\200" string) (string-match "\0" string))) ( this-buffer (current-buffer))) (set-buffer webster-buffer) (cond ((not (eq (process-status webster-process) 'run)) (message "Webster died")) (closed-message (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-string "...Word not found in webster\n")) ((string-match "SPELLING 1" string) (insert-string "...Spelled correctly\n")) (end-def-message (webster-filter proc (concat (substring string 0 (- end-def-message 1)) "\n\n")) (goto-char (point-max))) (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 webster is visible, move the last line to the bottom of that window ;; (let ((here (selected-window))) (let ((webster-window (get-buffer-window webster-buffer))) (if (windowp webster-window) (progn (select-window webster-window) (recenter -1) (select-window here))))) (set-buffer this-buffer))) ;;; ;;; 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) (while (search-forward (char-to-string char1) end t) (backward-delete-char 1) (if (equal (char-after (- (point) 1)) char2) (backward-delete-char 1)))) ;; Snatched from unix-apropos by Henry Kautz (defun webster-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 (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 (read-string (concat "Look up word in webster (" (webster-current-word) "): ")))) (if (equal "" arg) (setq arg (webster-current-word))) (webster-send-request "DEFINE" arg)) (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 (" (webster-current-word) "): ")))) (webster-send-request "ENDINGS" arg)) (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 "Spell word in webster (" (webster-current-word) "): ")))) (if (equal "" arg) (setq arg (webster-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 (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)) (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)) (defvar webster-mode-map nil) (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)) -- Dirk Grunwald Univ. of Illinois grunwald@flute.cs.uiuc.edu