(calcDigit-key): Use minibuffer-prompt-end instead of point-min.
[bpt/emacs.git] / lisp / ielm.el
index 3b625f6..8194a65 100644 (file)
@@ -1,7 +1,9 @@
 ;;; ielm.el --- interaction mode for Emacs Lisp
+
 ;; Copyright (C) 1994 Free Software Foundation, Inc.
 
 ;; Author: David Smith <maa036@lancaster.ac.uk>
+;; Maintainer: FSF
 ;; Created: 25 Feb 1994
 ;; Keywords: lisp
 
@@ -18,8 +20,9 @@
 ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; 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:
 
 ;;
 ;;   (autoload 'ielm "ielm" "Start an inferior Emacs Lisp session" t)
 ;;
-;; For completion to work, the comint.el from FSF Emacs 19.23 is
+;; For completion to work, the comint.el from Emacs 19.23 is
 ;; required.  If you do not have it, or if you are running Lemacs,
 ;; also add the following code to your .emacs:
 ;;
 ;;    (setq ielm-mode-hook
 ;;         '(lambda nil
 ;;              (define-key ielm-map "\t"
-;;                 '(lambda nil (interactive) (or (ielm-tab) 
+;;                 '(lambda nil (interactive) (or (ielm-tab)
 ;;                                                 (lisp-complete-symbol))))))
 
 ;; To start: M-x ielm.  Type C-h m in the *ielm* buffer for more info.
 
-;; The latest version is available by WWW from 
+;; The latest version is available by WWW from
 ;;      http://mathssun5.lancs.ac.uk:2080/~maa036/elisp/dir.html
 ;; or by anonymous FTP from
 ;;      /anonymous@wingra.stat.wisc.edu:pub/src/emacs-lisp/ielm.el.gz
 
 ;;; User variables
 
-(defvar ielm-noisy t
-  "*If non-nil, IELM will beep on error.")
+(defgroup ielm nil
+  "Interaction mode for Emacs Lisp."
+  :group 'lisp)
+
+
+(defcustom ielm-noisy t
+  "*If non-nil, IELM will beep on error."
+  :type 'boolean
+  :group 'ielm)
 
 (defvar ielm-prompt "ELISP> "
   "Prompt used in IELM.")
 
-(defvar ielm-dynamic-return t
+(defcustom ielm-dynamic-return t
   "*Controls whether \\<ielm-map>\\[ielm-return] has intelligent behaviour in IELM.
 If non-nil, \\[ielm-return] evaluates input for complete sexps, or inserts a newline
-and indents for incomplete sexps.  If nil, always inserts newlines.")
+and indents for incomplete sexps.  If nil, always inserts newlines."
+  :type 'boolean
+  :group 'ielm)
 
-(defvar ielm-dynamic-multiline-inputs t
+(defcustom ielm-dynamic-multiline-inputs t
   "*Force multiline inputs to start from column zero?
 If non-nil, after entering the first line of an incomplete sexp, a newline
 will be inserted after the prompt, moving the input to the next line.
 This gives more frame width for large indented sexps, and allows functions
-such as `edebug-defun' to work with such inputs.")
+such as `edebug-defun' to work with such inputs."
+  :type 'boolean
+  :group 'ielm)
+
+(defcustom ielm-mode-hook nil
+  "*Hooks to be run when IELM (`inferior-emacs-lisp-mode') is started."
+  :type 'hook
+  :group 'ielm)
 
-(defvar ielm-mode-hook nil
-  "*Hooks to be run when IELM (`inferior-emacs-lisp-mode') is started.")
+(defvar * nil
+  "Most recent value evaluated in IELM.")
+
+(defvar ** nil
+  "Second-most-recent value evaluated in IELM.")
+
+(defvar *** nil
+  "Third-most-recent value evaluated in IELM.")
 
 ;;; System variables
 
@@ -84,12 +109,8 @@ such as `edebug-defun' to work with such inputs.")
   "Buffer in which IELM sexps will be evaluated.
 This variable is buffer-local.")
 
-(defvar ielm-header 
-  (concat
-   "*** Welcome to IELM version "
-   (substring "$Revision: 1.2 $" 11 -2)
-   " ***  Type (describe-mode) for help.\n"
-   "IELM has ABSOLUTELY NO WARRANTY; type (describe-no-warranty) for details.\n")
+(defvar ielm-header
+  "*** Welcome to IELM ***  Type (describe-mode) for help.\n"
   "Message to display when IELM is started.")
 
 (defvar ielm-map nil)
@@ -106,16 +127,23 @@ This variable is buffer-local.")
   (define-key ielm-map "\C-j" 'ielm-send-input)
   (define-key ielm-map "\e\C-x" 'eval-defun)         ; for consistency with
   (define-key ielm-map "\e\t" 'lisp-complete-symbol) ; lisp-interaction-mode
-  ;; These bindings are from shared-lisp-mode-map -- can you inherit
+  ;; These bindings are from `lisp-mode-shared-map' -- can you inherit
   ;; from more than one keymap??
-  (define-key ielm-map "\e\C-q" 'indent-sexp)      
-  (define-key ielm-map "\eq" 'lisp-fill-paragraph) 
+  (define-key ielm-map "\e\C-q" 'indent-sexp)
   (define-key ielm-map "\177" 'backward-delete-char-untabify)
   ;; Some convenience bindings for setting the working buffer
   (define-key ielm-map "\C-c\C-b" 'ielm-change-working-buffer)
   (define-key ielm-map "\C-c\C-f" 'ielm-display-working-buffer)
   (define-key ielm-map "\C-c\C-v" 'ielm-print-working-buffer))
 
+(defvar ielm-font-lock-keywords
+  (list
+   (cons (concat "^" (regexp-quote ielm-prompt)) 'font-lock-keyword-face)
+   '("\\(^\\*\\*\\*[^*]+\\*\\*\\*\\)\\(.*$\\)"
+     (1 font-lock-comment-face)
+     (2 font-lock-constant-face)))
+  "Additional expressions to highlight in ielm buffers.")
+
 ;;; Completion stuff
 
 (defun ielm-tab nil
@@ -126,7 +154,7 @@ This variable is buffer-local.")
       (progn
        (ielm-indent-line)
        t)))
-  
+
 (defun ielm-complete-symbol nil
   "Complete the lisp symbol before point."
   ;; A wrapper for lisp-complete symbol that returns non-nil if
@@ -136,10 +164,10 @@ This variable is buffer-local.")
         (ctick (and cbuffer (buffer-modified-tick cbuffer))))
     (lisp-complete-symbol)
      ;; completion has occurred if:
-    (or 
+    (or
      ;; the buffer has been modified
-     (not (= btick (buffer-modified-tick))) 
-     ;; a completions buffer has been modifed or created
+     (not (= btick (buffer-modified-tick)))
+     ;; a completions buffer has been modified or created
      (if cbuffer
         (not (= ctick (buffer-modified-tick cbuffer)))
        (get-buffer "*Completions*")))))
@@ -148,12 +176,10 @@ This variable is buffer-local.")
   "Dynamically complete filename before point, if in a string."
   (if (nth 3 (parse-partial-sexp comint-last-input-start (point)))
       (comint-dynamic-complete-filename)))
-     
+
 (defun ielm-indent-line nil
   "Indent the current line as Lisp code if it is not a prompt line."
-  (if (save-excursion
-       (beginning-of-line)
-       (looking-at comint-prompt-regexp)) nil
+  (when (save-excursion (comint-bol) (bolp))
     (lisp-indent-line)))
 
 ;;; Working buffer manipulation
@@ -188,8 +214,8 @@ Complete sexps are evaluated; for incomplete sexps inserts a newline
 and indents.  If however `ielm-dynamic-return' is nil, this always
 simply inserts a newline."
   (interactive)
-  (if ielm-dynamic-return 
-      (let ((state       
+  (if ielm-dynamic-return
+      (let ((state
             (save-excursion
               (end-of-line)
               (parse-partial-sexp (ielm-pm)
@@ -206,8 +232,10 @@ simply inserts a newline."
          (newline-and-indent)))
     (newline)))
 
+(defvar ielm-input)
+
 (defun ielm-input-sender (proc input)
-  ;; Just sets the variable ielm-input, which is in the scope of 
+  ;; Just sets the variable ielm-input, which is in the scope of
   ;; `ielm-send-input's call.
   (setq ielm-input input))
 
@@ -282,15 +310,15 @@ simply inserts a newline."
              (if (ielm-is-whitespace (substring ielm-string ielm-pos))
                  ;; need this awful let convolution to work around
                  ;; an Emacs bug involving local vbls and let binding
-                 (let ((:save :)
-                       (::save ::)
-                       (:::save :::))
+                 (let ((*save *)
+                       (**save **)
+                       (***save ***))
                    (save-excursion
                      (set-buffer ielm-working-buffer)
                      (condition-case err
-                         (let ((: :save)
-                               (:: ::save)
-                               (::: :::save)
+                         (let ((* *save)
+                               (** **save)
+                               (*** ***save)
                                (ielm-obuf (current-buffer)))
                            (setq ielm-result (eval ielm-form))
                            (setq ielm-wbuf (current-buffer))
@@ -326,10 +354,10 @@ simply inserts a newline."
                (if ielm-noisy (ding))
                (setq ielm-output (concat ielm-output "*** " ielm-error-type " ***  "))
                (setq ielm-output (concat ielm-output ielm-result)))
-           ;; There was no error, so shift the ::: values
-           (setq ::: ::)
-           (setq :: :)
-           (setq : ielm-result))
+           ;; There was no error, so shift the *** values
+           (setq *** **)
+           (setq ** *)
+           (setq * ielm-result))
          (setq ielm-output (concat ielm-output "\n"))))
     (setq ielm-output (concat ielm-output ielm-prompt))
     (comint-output-filter (ielm-process) ielm-output)))
@@ -350,6 +378,8 @@ simply inserts a newline."
 
 ;;; Major mode
 
+(put 'inferior-emacs-lisp-mode 'mode-class 'special)
+
 (defun inferior-emacs-lisp-mode nil
   "Major mode for interactively evaluating Emacs Lisp expressions.
 Uses the interface provided by `comint-mode' (which see).
@@ -362,10 +392,10 @@ Uses the interface provided by `comint-mode' (which see).
   Inputs longer than one line are moved to the line following the
   prompt (but see variable `ielm-dynamic-multiline-inputs').
 
-* \\[comint-dynamic-complete] completes Lisp symbols (or filenames, within strings), 
+* \\[comint-dynamic-complete] completes Lisp symbols (or filenames, within strings),
   or indents the line if there is nothing to complete.
 
-During evaluations, the values of the variables `:', `::', and `:::'
+During evaluations, the values of the variables `*', `**', and `***'
 are the results of the previous, second previous and third previous
 evaluations respectively.
 
@@ -395,9 +425,12 @@ Customised bindings may be defined in `ielm-map', which currently contains:
   (setq paragraph-start comint-prompt-regexp)
   (setq comint-input-sender 'ielm-input-sender)
   (setq comint-process-echoes nil)
-  (setq comint-dynamic-complete-functions 
+  (setq comint-dynamic-complete-functions
        '(ielm-tab comint-replace-by-expanded-history ielm-complete-filename ielm-complete-symbol))
   (setq comint-get-old-input 'ielm-get-old-input)
+  (make-local-variable 'comint-completion-addsuffix)
+  (setq comint-completion-addsuffix
+       (cons (char-to-string directory-sep-char) ""))
 
   (setq major-mode 'inferior-emacs-lisp-mode)
   (setq mode-name "IELM")
@@ -408,14 +441,21 @@ Customised bindings may be defined in `ielm-map', which currently contains:
   (make-local-variable 'ielm-working-buffer)
   (setq ielm-working-buffer (current-buffer))
   (setq indent-line-function 'ielm-indent-line)
+  (make-local-variable 'fill-paragraph-function)
+  (setq fill-paragraph-function 'lisp-fill-paragraph)
 
   ;; Value holders
-  (setq : nil)
-  (make-local-variable ':)
-  (setq :: nil)
-  (make-local-variable '::)
-  (setq ::: nil)
-  (make-local-variable ':::)
+  (setq * nil)
+  (make-local-variable '*)
+  (setq ** nil)
+  (make-local-variable '**)
+  (setq *** nil)
+  (make-local-variable '***)
+
+  ;; font-lock support
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults
+       '(ielm-font-lock-keywords nil nil ((?: . "w") (?- . "w") (?* . "w"))))
 
   ;; A dummy process to keep comint happy. It will never get any input
   (if (comint-check-proc (current-buffer)) nil
@@ -441,15 +481,20 @@ Customised bindings may be defined in `ielm-map', which currently contains:
 
 ;;; User command
 
+;;;###autoload (add-hook 'same-window-buffer-names "*ielm*")
+
 ;;;###autoload
 (defun ielm nil
   "Interactively evaluate Emacs Lisp expressions.
-Switches to the buffer *ielm*, or creates it if it does not exist."
+Switches to the buffer `*ielm*', or creates it if it does not exist."
   (interactive)
-  (if (comint-check-proc "*ielm*") nil
-    (progn
+  (if (comint-check-proc "*ielm*")
+      nil
+    (save-excursion
       (set-buffer (get-buffer-create "*ielm*"))
       (inferior-emacs-lisp-mode)))
-  (switch-to-buffer "*ielm*"))
+  (pop-to-buffer "*ielm*"))
+
+(provide 'ielm)
 
 ;;; ielm.el ends here