From 44faf981957e153483a535c9968f2b7b0e5654b0 Mon Sep 17 00:00:00 2001 From: Noah Friedman Date: Sat, 19 Sep 1998 02:15:26 +0000 Subject: [PATCH] (eldoc-message): Check for 1-arg case, and store string in eldoc-last-message without consing a new string. Rearrange logic from nested if's into cond's. (eldoc-print-fnsym-args): Renamed to eldoc-get-fnsym-args-string. Do not print message; just return string. (eldoc-get-var-docstring): Renamed from eldoc-print-var-docstring. Do not print message; just return string. Cache that string in eldoc-last-data. (eldoc-last-data): Make into a vector. (eldoc-get-fnsym-args-string): Use new data form of structure. (eldoc-get-var-docstring): Here also. (eldoc-last-data-store): New function. (eldoc-get-fnsym-args-string): Use it. (eldoc-get-var-docstring): Here also. (eldoc-docstring-first-line): Minimize interim string consing. Call substitute-command-keys on the result. (eldoc-print-var-docstrings, eldoc-print-docstring, eldoc-docstring-message): Functions removed. (eldoc-docstring-format-sym-doc): New function, functionality ripped out of eldoc-docstring-message. (eldoc-get-fnsym-args-string, eldoc-get-var-docstring): Use it. --- lisp/emacs-lisp/eldoc.el | 230 +++++++++++++++++++++------------------ 1 file changed, 126 insertions(+), 104 deletions(-) diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 1a2d3c7ee37..f294ddbfe8d 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -1,13 +1,13 @@ ;;; eldoc.el --- show function arglist or variable docstring in echo area -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. -;; Author: Noah Friedman -;; Maintainer: friedman@prep.ai.mit.edu +;; Author: Noah Friedman +;; Maintainer: friedman@splode.com ;; Keywords: extensions ;; Created: 1995-10-06 -;; $Id: eldoc.el,v 1.13 1997/05/22 06:47:41 friedman Exp $ +;; $Id: eldoc.el,v 1.14 1997/07/09 12:44:15 friedman Exp $ ;; This file is part of GNU Emacs. @@ -123,10 +123,12 @@ returns another string is acceptable." ;; Remember to keep it a prime number to improve hash performance. (defvar eldoc-message-commands-table-size 31) -;; Bookkeeping; the car contains the last symbol read from the buffer. -;; The cdr contains the string last displayed in the echo area, so it can -;; be printed again if necessary without reconsing. -(defvar eldoc-last-data (cons nil nil)) +;; Bookkeeping; elements are as follows: +;; 0 - contains the last symbol read from the buffer. +;; 1 - contains the string last displayed in the echo area for that +;; symbol, so it can be printed again if necessary without reconsing. +;; 2 - 'function if function args, 'variable if variable documentation. +(defvar eldoc-last-data (make-vector 3 nil)) (defvar eldoc-last-message nil) ;; Idle timers are supported in Emacs 19.31 and later. @@ -182,6 +184,7 @@ the mode, respectively." (interactive) (eldoc-mode 1)) + ;; Idle timers are part of Emacs 19.31 and later. (defun eldoc-schedule-timer () (or (and eldoc-timer @@ -195,54 +198,48 @@ the mode, respectively." (setq eldoc-current-idle-delay eldoc-idle-delay) (timer-set-idle-time eldoc-timer eldoc-idle-delay t)))) -;; This function goes on pre-command-hook for XEmacs or when using idle -;; timers in Emacs. Motion commands clear the echo area for some reason, -;; which make eldoc messages flicker or disappear just before motion -;; begins. This function reprints the last eldoc message immediately -;; before the next command executes, which does away with the flicker. -;; This doesn't seem to be required for Emacs 19.28 and earlier. -(defun eldoc-pre-command-refresh-echo-area () - (and eldoc-last-message - (if (eldoc-display-message-no-interference-p) - (eldoc-message eldoc-last-message) - (setq eldoc-last-message nil)))) - (defun eldoc-message (&rest args) (let ((omessage eldoc-last-message)) (cond ((eq (car args) eldoc-last-message)) ((or (null args) (null (car args))) (setq eldoc-last-message nil)) + ;; If only one arg, no formatting to do so put it in + ;; eldoc-last-message so eq test above might succeed on + ;; subsequent calls. + ((null (cdr args)) + (setq eldoc-last-message (car args))) (t (setq eldoc-last-message (apply 'format args)))) ;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages ;; are recorded in a log. Do not put eldoc messages in that log since ;; they are Legion. - (if (fboundp 'display-message) - ;; XEmacs 19.13 way of preventing log messages. - (if eldoc-last-message - (display-message 'no-log eldoc-last-message) - (and omessage - (clear-message 'no-log))) - (let ((message-log-max nil)) - (if eldoc-last-message - (message "%s" eldoc-last-message) - (and omessage - (message nil)))))) + (cond ((fboundp 'display-message) + ;; XEmacs 19.13 way of preventing log messages. + (cond (eldoc-last-message + (display-message 'no-log eldoc-last-message)) + (omessage + (clear-message 'no-log)))) + (t + ;; Emacs way of preventing log messages. + (let ((message-log-max nil)) + (cond (eldoc-last-message + (message "%s" eldoc-last-message)) + (omessage + (message nil))))))) eldoc-last-message) - -(defun eldoc-print-current-symbol-info () - (and (eldoc-display-message-p) - (let ((current-symbol (eldoc-current-symbol)) - (current-fnsym (eldoc-fnsym-in-current-sexp))) - (or (cond ((eq current-symbol current-fnsym) - (or (eldoc-print-fnsym-args current-fnsym) - (eldoc-print-var-docstring current-symbol))) - (t - (or (eldoc-print-var-docstring current-symbol) - (eldoc-print-fnsym-args current-fnsym)))) - (eldoc-message nil))))) +;; This function goes on pre-command-hook for XEmacs or when using idle +;; timers in Emacs. Motion commands clear the echo area for some reason, +;; which make eldoc messages flicker or disappear just before motion +;; begins. This function reprints the last eldoc message immediately +;; before the next command executes, which does away with the flicker. +;; This doesn't seem to be required for Emacs 19.28 and earlier. +(defun eldoc-pre-command-refresh-echo-area () + (and eldoc-last-message + (if (eldoc-display-message-no-interference-p) + (eldoc-message eldoc-last-message) + (setq eldoc-last-message nil)))) ;; Decide whether now is a good time to display a message. (defun eldoc-display-message-p () @@ -274,26 +271,98 @@ the mode, respectively." (not cursor-in-echo-area) (not (eq (selected-window) (minibuffer-window))))) -(defun eldoc-print-fnsym-args (sym) - (interactive) - (let ((args nil)) + +(defun eldoc-print-current-symbol-info () + (and (eldoc-display-message-p) + (let* ((current-symbol (eldoc-current-symbol)) + (current-fnsym (eldoc-fnsym-in-current-sexp)) + (doc (cond ((eq current-symbol current-fnsym) + (or (eldoc-get-fnsym-args-string current-fnsym) + (eldoc-get-var-docstring current-symbol))) + (t + (or (eldoc-get-var-docstring current-symbol) + (eldoc-get-fnsym-args-string current-fnsym)))))) + (eldoc-message doc)))) + +;; Return a string containing the function parameter list, or 1-line +;; docstring if function is a subr and no arglist is obtainable from the +;; docstring or elsewhere. +(defun eldoc-get-fnsym-args-string (sym) + (let ((args nil) + (doc nil)) (cond ((not (and sym (symbolp sym) (fboundp sym)))) - ((eq sym (car eldoc-last-data)) - (setq args (cdr eldoc-last-data))) + ((and (eq sym (aref eldoc-last-data 0)) + (eq 'function (aref eldoc-last-data 2))) + (setq doc (aref eldoc-last-data 1))) ((subrp (eldoc-symbol-function sym)) (setq args (or (eldoc-function-argstring-from-docstring sym) - (eldoc-docstring-first-line (documentation sym t)))) - (setcar eldoc-last-data sym) - (setcdr eldoc-last-data args)) + (eldoc-docstring-first-line (documentation sym t))))) (t - (setq args (eldoc-function-argstring sym)) - (setcar eldoc-last-data sym) - (setcdr eldoc-last-data args))) - (and args - (eldoc-message "%s: %s" sym args)))) + (setq args (eldoc-function-argstring sym)))) + (cond (args + (setq doc (eldoc-docstring-format-sym-doc sym args)) + (eldoc-last-data-store sym doc 'function))) + doc)) + +;; Return a string containing a brief (one-line) documentation string for +;; the variable. +(defun eldoc-get-var-docstring (sym) + (cond ((and (eq sym (aref eldoc-last-data 0)) + (eq 'variable (aref eldoc-last-data 2))) + (aref eldoc-last-data 1)) + (t + (let ((doc (documentation-property sym 'variable-documentation t))) + (cond (doc + (setq doc (eldoc-docstring-format-sym-doc + sym (eldoc-docstring-first-line doc))) + (eldoc-last-data-store sym doc 'variable))) + doc)))) + +(defun eldoc-last-data-store (symbol doc type) + (aset eldoc-last-data 0 symbol) + (aset eldoc-last-data 1 doc) + (aset eldoc-last-data 2 type)) + +;; Note that any leading `*' in the docstring (which indicates the variable +;; is a user option) is removed. +(defun eldoc-docstring-first-line (doc) + (and (stringp doc) + (substitute-command-keys + (save-match-data + (let ((start (if (string-match "^\\*" doc) (match-end 0) 0))) + (cond ((string-match "\n" doc) + (substring doc start (match-beginning 0))) + ((zerop start) doc) + (t (substring doc start)))))))) + +;; If the entire line cannot fit in the echo area, the symbol name may be +;; truncated or eliminated entirely from the output to make room for the +;; description. +(defun eldoc-docstring-format-sym-doc (sym doc) + (save-match-data + (let* ((name (symbol-name sym)) + (doclen (+ (length name) (length ": ") (length doc))) + ;; Subtract 1 from window width since emacs seems not to write + ;; any chars to the last column, at least for some terminal types. + (strip (- doclen (1- (window-width (minibuffer-window)))))) + (cond ((> strip 0) + (let* ((len (length name))) + (cond ((>= strip len) + (format "%s" doc)) + (t + ;;(setq name (substring name 0 (- len strip))) + ;; + ;; Show the end of the partial symbol name, rather + ;; than the beginning, since the former is more likely + ;; to be unique given package namespace conventions. + (setq name (substring name strip)) + (format "%s: %s" name doc))))) + (t + (format "%s: %s" sym doc)))))) + (defun eldoc-fnsym-in-current-sexp () (let ((p (point))) (eldoc-beginning-of-sexp) @@ -365,54 +434,6 @@ the mode, respectively." arglist)))) (concat "(" (mapconcat 'identity arglist " ") ")")) - -(defun eldoc-print-var-docstring (sym) - (eldoc-print-docstring sym (documentation-property - sym 'variable-documentation t))) - -;; Print the brief (one-line) documentation string for the symbol. -(defun eldoc-print-docstring (symbol doc) - (and doc - (eldoc-message "%s" (eldoc-docstring-message symbol doc)))) - -;; If the entire line cannot fit in the echo area, the variable name may be -;; truncated or eliminated entirely from the output to make room. -;; Any leading `*' in the docstring (which indicates the variable is a user -;; option) is not printed." -(defun eldoc-docstring-message (symbol doc) - (and doc - (let ((name (symbol-name symbol))) - (setq doc (eldoc-docstring-first-line doc)) - (save-match-data - (let* ((doclen (+ (length name) (length ": ") (length doc))) - ;; Subtract 1 from window width since emacs seems not to - ;; write any chars to the last column, at least for some - ;; terminal types. - (strip (- doclen (1- (window-width (minibuffer-window)))))) - (cond ((> strip 0) - (let* ((len (length name))) - (cond ((>= strip len) - (format "%s" doc)) - (t - ;;(setq name (substring name 0 (- len strip))) - ;; - ;; Show the end of the partial variable name, - ;; rather than the beginning, since the former - ;; is more likely to be unique given package - ;; namespace conventions. - (setq name (substring name strip)) - (format "%s: %s" name doc))))) - (t - (format "%s: %s" symbol doc)))))))) - -(defun eldoc-docstring-first-line (doc) - (save-match-data - (and (string-match "\n" doc) - (setq doc (substring doc 0 (match-beginning 0)))) - (and (string-match "^\\*" doc) - (setq doc (substring doc 1)))) - doc) - ;; Alist of predicate/action pairs. ;; Each member of the list is a sublist consisting of a predicate function @@ -598,6 +619,7 @@ the mode, respectively." (all-completions (car names) eldoc-message-commands)) (setq names (cdr names)))) + ;; Prime the command list. (eldoc-add-command-completions "backward-" "beginning-of-" "delete-other-windows" "delete-window" -- 2.39.2