inf-lisp.el 26.3 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
;;; inf-lisp.el --- an inferior-lisp mode
Erik Naggum's avatar
Erik Naggum committed
2

3
;; Copyright (C) 1988, 1993-1994, 2001-2011  Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
4

Eric S. Raymond's avatar
Eric S. Raymond committed
5
;; Author: Olin Shivers <shivers@cs.cmu.edu>
Eric S. Raymond's avatar
Eric S. Raymond committed
6
;; Keywords: processes, lisp
Eric S. Raymond's avatar
Eric S. Raymond committed
7

Erik Naggum's avatar
Erik Naggum committed
8
;; This file is part of GNU Emacs.
Jim Blandy's avatar
Jim Blandy committed
9

10
;; GNU Emacs is free software: you can redistribute it and/or modify
Erik Naggum's avatar
Erik Naggum committed
11
;; it under the terms of the GNU General Public License as published by
12 13
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Jim Blandy's avatar
Jim Blandy committed
14

Erik Naggum's avatar
Erik Naggum committed
15 16 17 18
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
Jim Blandy's avatar
Jim Blandy committed
19

Erik Naggum's avatar
Erik Naggum committed
20
;; You should have received a copy of the GNU General Public License
21
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Jim Blandy's avatar
Jim Blandy committed
22

Eric S. Raymond's avatar
Eric S. Raymond committed
23 24
;;; Commentary:

Erik Naggum's avatar
Erik Naggum committed
25 26
;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu). 8/88

Juanma Barranquero's avatar
Juanma Barranquero committed
27
;; This file defines a lisp-in-a-buffer package (inferior-lisp mode)
28 29
;; built on top of comint mode.  This version is more featureful,
;; robust, and uniform than the Emacs 18 version.  The key bindings are
Juanma Barranquero's avatar
Juanma Barranquero committed
30 31
;; also more compatible with the bindings of Hemlock and Zwei (the
;; Lisp Machine emacs).
Erik Naggum's avatar
Erik Naggum committed
32 33

;; Since this mode is built on top of the general command-interpreter-in-
34
;; a-buffer mode (comint mode), it shares a common base functionality,
Erik Naggum's avatar
Erik Naggum committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
;; and a common set of bindings, with all modes derived from comint mode.
;; This makes these modes easier to use.

;; For documentation on the functionality provided by comint mode, and
;; the hooks available for customising it, see the file comint.el.
;; For further information on inferior-lisp mode, see the comments below.

;; Needs fixin:
;; The load-file/compile-file default mechanism could be smarter -- it
;; doesn't know about the relationship between filename extensions and
;; whether the file is source or executable. If you compile foo.lisp
;; with compile-file, then the next load-file should use foo.bin for
;; the default, not foo.lisp. This is tricky to do right, particularly
;; because the extension for executable files varies so much (.o, .bin,
;; .lbin, .mo, .vo, .ao, ...).
;;
;; It would be nice if inferior-lisp (and inferior scheme, T, ...) modes
;; had a verbose minor mode wherein sending or compiling defuns, etc.
;; would be reflected in the transcript with suitable comments, e.g.
;; ";;; redefining fact". Several ways to do this. Which is right?
;;
56
;; When sending text from a source file to a subprocess, the process-mark can
Erik Naggum's avatar
Erik Naggum committed
57 58 59
;; move off the window, so you can lose sight of the process interactions.
;; Maybe I should ensure the process mark is in the window when I send
;; text to the process? Switch selectable?
Jim Blandy's avatar
Jim Blandy committed
60

Eric S. Raymond's avatar
Eric S. Raymond committed
61 62 63
;;; Code:

(require 'comint)
Jim Blandy's avatar
Jim Blandy committed
64 65
(require 'lisp-mode)

Jim Blandy's avatar
Jim Blandy committed
66

Luc Teirlinck's avatar
Luc Teirlinck committed
67 68 69 70 71
(defgroup inferior-lisp nil
  "Run an outside Lisp in an Emacs buffer."
  :group 'lisp
  :version "22.1")

Jim Blandy's avatar
Jim Blandy committed
72
;;;###autoload
Luc Teirlinck's avatar
Luc Teirlinck committed
73
(defcustom inferior-lisp-filter-regexp
74
  (purecopy "\\`\\s *\\(:\\(\\w\\|\\s_\\)\\)?\\s *\\'")
Richard M. Stallman's avatar
Richard M. Stallman committed
75 76
  "*What not to save on inferior Lisp's input history.
Input matching this regexp is not saved on the input history in Inferior Lisp
77
mode.  Default is whitespace followed by 0 or 1 single-letter colon-keyword
Luc Teirlinck's avatar
Luc Teirlinck committed
78 79 80
\(as in :a, :c, etc.)"
  :type 'regexp
  :group 'inferior-lisp)
Jim Blandy's avatar
Jim Blandy committed
81

82 83 84 85 86 87 88 89 90 91 92
(defvar inferior-lisp-mode-map
  (let ((map (copy-keymap comint-mode-map)))
    (set-keymap-parent map lisp-mode-shared-map)
    (define-key map "\C-x\C-e" 'lisp-eval-last-sexp)
    (define-key map "\C-c\C-l" 'lisp-load-file)
    (define-key map "\C-c\C-k" 'lisp-compile-file)
    (define-key map "\C-c\C-a" 'lisp-show-arglist)
    (define-key map "\C-c\C-d" 'lisp-describe-sym)
    (define-key map "\C-c\C-f" 'lisp-show-function-documentation)
    (define-key map "\C-c\C-v" 'lisp-show-variable-documentation)
    map))
Jim Blandy's avatar
Jim Blandy committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

;;; These commands augment Lisp mode, so you can process Lisp code in
;;; the source files.
(define-key lisp-mode-map "\M-\C-x"  'lisp-eval-defun)     ; Gnu convention
(define-key lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) ; Gnu convention
(define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-defun)
(define-key lisp-mode-map "\C-c\C-r" 'lisp-eval-region)
(define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-defun)
(define-key lisp-mode-map "\C-c\C-z" 'switch-to-lisp)
(define-key lisp-mode-map "\C-c\C-l" 'lisp-load-file)
(define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file)  ; "kompile" file
(define-key lisp-mode-map "\C-c\C-a" 'lisp-show-arglist)
(define-key lisp-mode-map "\C-c\C-d" 'lisp-describe-sym)
(define-key lisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation)
(define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation)


Jim Blandy's avatar
Jim Blandy committed
110 111 112 113
;;; This function exists for backwards compatibility.
;;; Previous versions of this package bound commands to C-c <letter>
;;; bindings, which is not allowed by the gnumacs standard.

Richard M. Stallman's avatar
Richard M. Stallman committed
114 115 116 117
;;;  "This function binds many inferior-lisp commands to C-c <letter> bindings,
;;;where they are more accessible. C-c <letter> bindings are reserved for the
;;;user, so these bindings are non-standard. If you want them, you should
;;;have this function called by the inferior-lisp-load-hook:
Luc Teirlinck's avatar
Luc Teirlinck committed
118
;;;  (add-hook 'inferior-lisp-load-hook 'inferior-lisp-install-letter-bindings)
Richard M. Stallman's avatar
Richard M. Stallman committed
119
;;;You can modify this function to install just the bindings you want."
Jim Blandy's avatar
Jim Blandy committed
120
(defun inferior-lisp-install-letter-bindings ()
Jim Blandy's avatar
Jim Blandy committed
121 122 123 124 125 126 127 128 129 130
  (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go)
  (define-key lisp-mode-map "\C-cr" 'lisp-eval-region-and-go)
  (define-key lisp-mode-map "\C-cc" 'lisp-compile-defun-and-go)
  (define-key lisp-mode-map "\C-cz" 'switch-to-lisp)
  (define-key lisp-mode-map "\C-cl" 'lisp-load-file)
  (define-key lisp-mode-map "\C-ck" 'lisp-compile-file)
  (define-key lisp-mode-map "\C-ca" 'lisp-show-arglist)
  (define-key lisp-mode-map "\C-cd" 'lisp-describe-sym)
  (define-key lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
  (define-key lisp-mode-map "\C-cv" 'lisp-show-variable-documentation)
131

Jim Blandy's avatar
Jim Blandy committed
132 133 134 135 136 137 138
  (define-key inferior-lisp-mode-map "\C-cl" 'lisp-load-file)
  (define-key inferior-lisp-mode-map "\C-ck" 'lisp-compile-file)
  (define-key inferior-lisp-mode-map "\C-ca" 'lisp-show-arglist)
  (define-key inferior-lisp-mode-map "\C-cd" 'lisp-describe-sym)
  (define-key inferior-lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
  (define-key inferior-lisp-mode-map "\C-cv"
    'lisp-show-variable-documentation))
Jim Blandy's avatar
Jim Blandy committed
139

Jim Blandy's avatar
Jim Blandy committed
140
;;;###autoload
141
(defcustom inferior-lisp-program (purecopy "lisp")
Luc Teirlinck's avatar
Luc Teirlinck committed
142 143 144
  "*Program name for invoking an inferior Lisp in Inferior Lisp mode."
  :type 'string
  :group 'inferior-lisp)
Jim Blandy's avatar
Jim Blandy committed
145

Jim Blandy's avatar
Jim Blandy committed
146
;;;###autoload
147
(defcustom inferior-lisp-load-command (purecopy "(load \"%s\")\n")
Jim Blandy's avatar
Jim Blandy committed
148
  "*Format-string for building a Lisp expression to load a file.
Richard M. Stallman's avatar
Richard M. Stallman committed
149
This format string should use `%s' to substitute a file name
Jim Blandy's avatar
Jim Blandy committed
150 151
and should result in a Lisp expression that will command the inferior Lisp
to load that file.  The default works acceptably on most Lisps.
152
The string \"(progn (load \\\"%s\\\" :verbose nil :print t) (values))\\n\"
Jim Blandy's avatar
Jim Blandy committed
153
produces cosmetically superior output for this application,
Luc Teirlinck's avatar
Luc Teirlinck committed
154 155 156
but it works only in Common Lisp."
  :type 'string
  :group 'inferior-lisp)
Jim Blandy's avatar
Jim Blandy committed
157

Jim Blandy's avatar
Jim Blandy committed
158
;;;###autoload
159
(defcustom inferior-lisp-prompt (purecopy "^[^> \n]*>+:? *")
160
  "Regexp to recognize prompts in the Inferior Lisp mode.
161
Defaults to \"^[^> \\n]*>+:? *\", which works pretty good for Lucid, kcl,
162
and franz.  This variable is used to initialize `comint-prompt-regexp' in the
Richard M. Stallman's avatar
Richard M. Stallman committed
163
Inferior Lisp buffer.
Jim Blandy's avatar
Jim Blandy committed
164

165
This variable is only used if the variable
166
`comint-use-prompt-regexp' is non-nil.
167

Jim Blandy's avatar
Jim Blandy committed
168
More precise choices:
169 170
Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
Jim Blandy's avatar
Jim Blandy committed
171 172
kcl: \"^>+ *\"

Luc Teirlinck's avatar
Luc Teirlinck committed
173 174 175
This is a fine thing to set in your .emacs file or through Custom."
  :type 'regexp
  :group 'inferior-lisp)
Jim Blandy's avatar
Jim Blandy committed
176

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
(defvar inferior-lisp-buffer nil "*The current inferior-lisp process buffer.

MULTIPLE PROCESS SUPPORT
===========================================================================
To run multiple Lisp processes, you start the first up
with \\[inferior-lisp].  It will be in a buffer named `*inferior-lisp*'.
Rename this buffer with \\[rename-buffer].  You may now start up a new
process with another \\[inferior-lisp].  It will be in a new buffer,
named `*inferior-lisp*'.  You can switch between the different process
buffers with \\[switch-to-buffer].

Commands that send text from source buffers to Lisp processes --
like `lisp-eval-defun' or `lisp-show-arglist' -- have to choose a process
to send to, when you have more than one Lisp process around.  This
is determined by the global variable `inferior-lisp-buffer'.  Suppose you
have three inferior Lisps running:
    Buffer              Process
    foo                 inferior-lisp
    bar                 inferior-lisp<2>
    *inferior-lisp*     inferior-lisp<3>
197
If you do a \\[lisp-eval-defun] command on some Lisp source code,
198 199
what process do you send it to?

200
- If you're in a process buffer (foo, bar, or *inferior-lisp*),
201 202 203 204 205 206 207 208 209 210 211
  you send it to that process.
- If you're in some other buffer (e.g., a source file), you
  send it to the process attached to buffer `inferior-lisp-buffer'.
This process selection is performed by function `inferior-lisp-proc'.

Whenever \\[inferior-lisp] fires up a new process, it resets
`inferior-lisp-buffer' to be the new process's buffer.  If you only run
one process, this does the right thing.  If you run multiple
processes, you can change `inferior-lisp-buffer' to another process
buffer with \\[set-variable].")

Jim Blandy's avatar
Jim Blandy committed
212
;;;###autoload
213
(defvar inferior-lisp-mode-hook '()
Juanma Barranquero's avatar
Juanma Barranquero committed
214
  "*Hook for customizing Inferior Lisp mode.")
Jim Blandy's avatar
Jim Blandy committed
215

216 217
(put 'inferior-lisp-mode 'mode-class 'special)

218
(define-derived-mode inferior-lisp-mode comint-mode "Inferior Lisp"
219
  "Major mode for interacting with an inferior Lisp process.
Jim Blandy's avatar
Jim Blandy committed
220
Runs a Lisp interpreter as a subprocess of Emacs, with Lisp I/O through an
Richard M. Stallman's avatar
Richard M. Stallman committed
221 222 223
Emacs buffer.  Variable `inferior-lisp-program' controls which Lisp interpreter
is run.  Variables `inferior-lisp-prompt', `inferior-lisp-filter-regexp' and
`inferior-lisp-load-command' can customize this mode for different Lisp
Jim Blandy's avatar
Jim Blandy committed
224 225 226
interpreters.

For information on running multiple processes in multiple buffers, see
Richard M. Stallman's avatar
Richard M. Stallman committed
227
documentation for variable `inferior-lisp-buffer'.
Jim Blandy's avatar
Jim Blandy committed
228

Jim Blandy's avatar
Jim Blandy committed
229
\\{inferior-lisp-mode-map}
Jim Blandy's avatar
Jim Blandy committed
230

231
Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
Richard M. Stallman's avatar
Richard M. Stallman committed
232
`inferior-lisp-mode-hook' (in that order).
Jim Blandy's avatar
Jim Blandy committed
233 234

You can send text to the inferior Lisp process from other buffers containing
235
Lisp source.
236 237 238 239 240
    `switch-to-lisp' switches the current buffer to the Lisp process buffer.
    `lisp-eval-defun' sends the current defun to the Lisp process.
    `lisp-compile-defun' compiles the current defun.
    `lisp-eval-region' sends the current region to the Lisp process.
    `lisp-compile-region' compiles the current region.
Jim Blandy's avatar
Jim Blandy committed
241

Jim Blandy's avatar
Jim Blandy committed
242 243 244
    Prefixing the lisp-eval/compile-defun/region commands with
    a \\[universal-argument] causes a switch to the Lisp process buffer after sending
    the text.
Jim Blandy's avatar
Jim Blandy committed
245

246 247
Commands:\\<inferior-lisp-mode-map>
\\[comint-send-input] after the end of the process' output sends the text from the
Jim Blandy's avatar
Jim Blandy committed
248
    end of process to point.
249
\\[comint-send-input] before the end of the process' output copies the sexp ending at point
Jim Blandy's avatar
Jim Blandy committed
250
    to the end of the process' output, and sends it.
251 252 253 254 255 256 257 258 259
\\[comint-copy-old-input] copies the sexp ending at point to the end of the process' output,
    allowing you to edit it before sending it.
If `comint-use-prompt-regexp' is nil (the default), \\[comint-insert-input] on old input
   copies the entire old input to the end of the process' output, allowing
   you to edit it before sending it.  When not used on old input, or if
   `comint-use-prompt-regexp' is non-nil, \\[comint-insert-input] behaves according to
   its global binding.
\\[backward-delete-char-untabify] converts tabs to spaces as it moves back.
\\[lisp-indent-line] indents for Lisp; with argument, shifts rest
Jim Blandy's avatar
Jim Blandy committed
260
    of expression rigidly with the current line.
261
\\[indent-sexp] does \\[lisp-indent-line] on each line starting within following expression.
Jim Blandy's avatar
Jim Blandy committed
262 263 264 265
Paragraphs are separated only by blank lines.  Semicolons start comments.
If you accidentally suspend your process, use \\[comint-continue-subjob]
to continue it."
  (setq comint-prompt-regexp inferior-lisp-prompt)
266
  (setq mode-line-process '(":%s"))
Jim Blandy's avatar
Jim Blandy committed
267
  (lisp-mode-variables t)
Jim Blandy's avatar
Jim Blandy committed
268
  (setq comint-get-old-input (function lisp-get-old-input))
269
  (setq comint-input-filter (function lisp-input-filter)))
Jim Blandy's avatar
Jim Blandy committed
270 271

(defun lisp-get-old-input ()
Richard M. Stallman's avatar
Richard M. Stallman committed
272
  "Return a string containing the sexp ending at point."
Jim Blandy's avatar
Jim Blandy committed
273 274 275 276 277 278
  (save-excursion
    (let ((end (point)))
      (backward-sexp)
      (buffer-substring (point) end))))

(defun lisp-input-filter (str)
Richard M. Stallman's avatar
Richard M. Stallman committed
279
  "t if STR does not match `inferior-lisp-filter-regexp'."
Jim Blandy's avatar
Jim Blandy committed
280
  (not (string-match inferior-lisp-filter-regexp str)))
Jim Blandy's avatar
Jim Blandy committed
281

Jim Blandy's avatar
Jim Blandy committed
282
;;;###autoload
Jim Blandy's avatar
Jim Blandy committed
283
(defun inferior-lisp (cmd)
Richard M. Stallman's avatar
Richard M. Stallman committed
284 285
  "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'.
If there is a process already running in `*inferior-lisp*', just switch
Jim Blandy's avatar
Jim Blandy committed
286
to that buffer.
Jim Blandy's avatar
Jim Blandy committed
287
With argument, allows you to edit the command line (default is value
Richard M. Stallman's avatar
Richard M. Stallman committed
288 289
of `inferior-lisp-program').  Runs the hooks from
`inferior-lisp-mode-hook' (after the `comint-mode-hook' is run).
Jim Blandy's avatar
Jim Blandy committed
290
\(Type \\[describe-mode] in the process buffer for a list of commands.)"
Jim Blandy's avatar
Jim Blandy committed
291 292
  (interactive (list (if current-prefix-arg
			 (read-string "Run lisp: " inferior-lisp-program)
Jim Blandy's avatar
Jim Blandy committed
293 294
		       inferior-lisp-program)))
  (if (not (comint-check-proc "*inferior-lisp*"))
295
      (let ((cmdlist (split-string cmd)))
Jim Blandy's avatar
Jim Blandy committed
296 297 298 299
	(set-buffer (apply (function make-comint)
			   "inferior-lisp" (car cmdlist) nil (cdr cmdlist)))
	(inferior-lisp-mode)))
  (setq inferior-lisp-buffer "*inferior-lisp*")
300
  (pop-to-buffer-same-window "*inferior-lisp*"))
Jim Blandy's avatar
Jim Blandy committed
301

Richard M. Stallman's avatar
Richard M. Stallman committed
302 303
;;;###autoload
(defalias 'run-lisp 'inferior-lisp)
Jim Blandy's avatar
Jim Blandy committed
304

Jim Blandy's avatar
Jim Blandy committed
305 306
(defun lisp-eval-region (start end &optional and-go)
  "Send the current region to the inferior Lisp process.
Richard M. Stallman's avatar
Richard M. Stallman committed
307
Prefix argument means switch to the Lisp buffer afterwards."
Jim Blandy's avatar
Jim Blandy committed
308
  (interactive "r\nP")
Jim Blandy's avatar
Jim Blandy committed
309 310
  (comint-send-region (inferior-lisp-proc) start end)
  (comint-send-string (inferior-lisp-proc) "\n")
Jim Blandy's avatar
Jim Blandy committed
311
  (if and-go (switch-to-lisp t)))
Jim Blandy's avatar
Jim Blandy committed
312

313 314 315 316 317 318 319 320 321 322 323
(defun lisp-compile-string (string)
  "Send the string to the inferior Lisp process to be compiled and executed."
  (comint-send-string
   (inferior-lisp-proc)
   (format "(funcall (compile nil (lambda () %s)))\n" string)))

(defun lisp-eval-string (string)
  "Send the string to the inferior Lisp process to be executed."
  (comint-send-string (inferior-lisp-proc) (concat string "\n")))

(defun lisp-do-defun (do-string do-region)
Jim Blandy's avatar
Jim Blandy committed
324
  "Send the current defun to the inferior Lisp process.
325 326 327
The actually processing is done by `do-string' and `do-region'
 which determine whether the code is compiled before evaluation.
DEFVAR forms reset the variables to the init values."
Jim Blandy's avatar
Jim Blandy committed
328
  (save-excursion
Jim Blandy's avatar
Jim Blandy committed
329 330
    (end-of-defun)
    (skip-chars-backward " \t\n\r\f") ;  Makes allegro happy
331
    (let ((end (point)) (case-fold-search t))
Jim Blandy's avatar
Jim Blandy committed
332
      (beginning-of-defun)
333 334 335 336 337 338 339 340 341 342 343 344 345 346
      (if (looking-at "(defvar")
          (funcall do-string
                   ;; replace `defvar' with `defparameter'
                   (concat "(defparameter "
                           (buffer-substring-no-properties (+ (point) 7) end)
                           "\n"))
        (funcall do-region (point) end)))))

(defun lisp-eval-defun (&optional and-go)
  "Send the current defun to the inferior Lisp process.
DEFVAR forms reset the variables to the init values.
Prefix argument means switch to the Lisp buffer afterwards."
  (interactive "P")
  (lisp-do-defun 'lisp-eval-string 'lisp-eval-region)
Jim Blandy's avatar
Jim Blandy committed
347
  (if and-go (switch-to-lisp t)))
Jim Blandy's avatar
Jim Blandy committed
348

Jim Blandy's avatar
Jim Blandy committed
349 350
(defun lisp-eval-last-sexp (&optional and-go)
  "Send the previous sexp to the inferior Lisp process.
Richard M. Stallman's avatar
Richard M. Stallman committed
351
Prefix argument means switch to the Lisp buffer afterwards."
Jim Blandy's avatar
Jim Blandy committed
352 353
  (interactive "P")
  (lisp-eval-region (save-excursion (backward-sexp) (point)) (point) and-go))
Jim Blandy's avatar
Jim Blandy committed
354

Jim Blandy's avatar
Jim Blandy committed
355 356
(defun lisp-compile-region (start end &optional and-go)
  "Compile the current region in the inferior Lisp process.
Richard M. Stallman's avatar
Richard M. Stallman committed
357
Prefix argument means switch to the Lisp buffer afterwards."
Jim Blandy's avatar
Jim Blandy committed
358
  (interactive "r\nP")
359
  (lisp-compile-string (buffer-substring-no-properties start end))
Jim Blandy's avatar
Jim Blandy committed
360
  (if and-go (switch-to-lisp t)))
Jim Blandy's avatar
Jim Blandy committed
361

Jim Blandy's avatar
Jim Blandy committed
362 363
(defun lisp-compile-defun (&optional and-go)
  "Compile the current defun in the inferior Lisp process.
364
DEFVAR forms reset the variables to the init values.
Richard M. Stallman's avatar
Richard M. Stallman committed
365
Prefix argument means switch to the Lisp buffer afterwards."
Jim Blandy's avatar
Jim Blandy committed
366
  (interactive "P")
367
  (lisp-do-defun 'lisp-compile-string 'lisp-compile-region)
Jim Blandy's avatar
Jim Blandy committed
368
  (if and-go (switch-to-lisp t)))
Jim Blandy's avatar
Jim Blandy committed
369 370 371 372 373

(defun switch-to-lisp (eob-p)
  "Switch to the inferior Lisp process buffer.
With argument, positions cursor at end of buffer."
  (interactive "P")
374
  (if (get-buffer-process inferior-lisp-buffer)
375 376 377 378 379 380
      (let ((pop-up-frames
	     ;; Be willing to use another frame
	     ;; that already has the window in it.
	     (or pop-up-frames
		 (get-buffer-window inferior-lisp-buffer t))))
	(pop-to-buffer inferior-lisp-buffer))
381 382
      (run-lisp inferior-lisp-program))
  (when eob-p
Jim Blandy's avatar
Jim Blandy committed
383
	 (push-mark)
384
    (goto-char (point-max))))
Jim Blandy's avatar
Jim Blandy committed
385

Jim Blandy's avatar
Jim Blandy committed
386 387 388 389 390 391

;;; Now that lisp-compile/eval-defun/region takes an optional prefix arg,
;;; these commands are redundant. But they are kept around for the user
;;; to bind if he wishes, for backwards functionality, and because it's
;;; easier to type C-c e than C-u C-c C-e.

Jim Blandy's avatar
Jim Blandy committed
392
(defun lisp-eval-region-and-go (start end)
Richard M. Stallman's avatar
Richard M. Stallman committed
393
  "Send the current region to the inferior Lisp, and switch to its buffer."
Jim Blandy's avatar
Jim Blandy committed
394
  (interactive "r")
Jim Blandy's avatar
Jim Blandy committed
395
  (lisp-eval-region start end t))
Jim Blandy's avatar
Jim Blandy committed
396 397

(defun lisp-eval-defun-and-go ()
Richard M. Stallman's avatar
Richard M. Stallman committed
398
  "Send the current defun to the inferior Lisp, and switch to its buffer."
Jim Blandy's avatar
Jim Blandy committed
399
  (interactive)
Jim Blandy's avatar
Jim Blandy committed
400
  (lisp-eval-defun t))
Jim Blandy's avatar
Jim Blandy committed
401 402

(defun lisp-compile-region-and-go (start end)
Richard M. Stallman's avatar
Richard M. Stallman committed
403
  "Compile the current region in the inferior Lisp, and switch to its buffer."
Jim Blandy's avatar
Jim Blandy committed
404
  (interactive "r")
Jim Blandy's avatar
Jim Blandy committed
405
  (lisp-compile-region start end t))
Jim Blandy's avatar
Jim Blandy committed
406 407

(defun lisp-compile-defun-and-go ()
Richard M. Stallman's avatar
Richard M. Stallman committed
408
  "Compile the current defun in the inferior Lisp, and switch to its buffer."
Jim Blandy's avatar
Jim Blandy committed
409
  (interactive)
Jim Blandy's avatar
Jim Blandy committed
410
  (lisp-compile-defun t))
Jim Blandy's avatar
Jim Blandy committed
411 412

;;; A version of the form in H. Shevis' soar-mode.el package. Less robust.
Jim Blandy's avatar
Jim Blandy committed
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
;;; (defun lisp-compile-sexp (start end)
;;;   "Compile the s-expression bounded by START and END in the inferior lisp.
;;; If the sexp isn't a DEFUN form, it is evaluated instead."
;;;   (cond ((looking-at "(defun\\s +")
;;; 	 (goto-char (match-end 0))
;;; 	 (let ((name-start (point)))
;;; 	   (forward-sexp 1)
;;; 	   (process-send-string "inferior-lisp"
;;; 				(format "(compile '%s #'(lambda "
;;; 					(buffer-substring name-start
;;; 							  (point)))))
;;; 	 (let ((body-start (point)))
;;; 	   (goto-char start) (forward-sexp 1) ; Can't use end-of-defun.
;;; 	   (process-send-region "inferior-lisp"
;;; 				(buffer-substring body-start (point))))
;;; 	 (process-send-string "inferior-lisp" ")\n"))
;;; 	(t (lisp-eval-region start end)))))
430
;;;
Jim Blandy's avatar
Jim Blandy committed
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
;;; (defun lisp-compile-region (start end)
;;;   "Each s-expression in the current region is compiled (if a DEFUN)
;;; or evaluated (if not) in the inferior lisp."
;;;   (interactive "r")
;;;   (save-excursion
;;;     (goto-char start) (end-of-defun) (beginning-of-defun) ; error check
;;;     (if (< (point) start) (error "region begins in middle of defun"))
;;;     (goto-char start)
;;;     (let ((s start))
;;;       (end-of-defun)
;;;       (while (<= (point) end) ; Zip through
;;; 	(lisp-compile-sexp s (point)) ; compiling up defun-sized chunks.
;;; 	(setq s (point))
;;; 	(end-of-defun))
;;;       (if (< s end) (lisp-compile-sexp s end)))))
446
;;;
Jim Blandy's avatar
Jim Blandy committed
447 448 449 450
;;; End of HS-style code


(defvar lisp-prev-l/c-dir/file nil
Richard M. Stallman's avatar
Richard M. Stallman committed
451 452 453
  "Record last directory and file used in loading or compiling.
This holds a cons cell of the form `(DIRECTORY . FILE)'
describing the last `lisp-load-file' or `lisp-compile-file' command.")
Jim Blandy's avatar
Jim Blandy committed
454

Luc Teirlinck's avatar
Luc Teirlinck committed
455
(defcustom lisp-source-modes '(lisp-mode)
Jim Blandy's avatar
Jim Blandy committed
456 457
  "*Used to determine if a buffer contains Lisp source code.
If it's loaded into a buffer that is in one of these major modes, it's
Richard M. Stallman's avatar
Richard M. Stallman committed
458
considered a Lisp source file by `lisp-load-file' and `lisp-compile-file'.
Luc Teirlinck's avatar
Luc Teirlinck committed
459 460 461
Used by these commands to determine defaults."
  :type '(repeat symbol)
  :group 'inferior-lisp)
Jim Blandy's avatar
Jim Blandy committed
462 463 464 465

(defun lisp-load-file (file-name)
  "Load a Lisp file into the inferior Lisp process."
  (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file
Pavel Janík's avatar
Pavel Janík committed
466
				  lisp-source-modes nil)) ; nil because LOAD
Jim Blandy's avatar
Jim Blandy committed
467
					; doesn't need an exact name
Jim Blandy's avatar
Jim Blandy committed
468 469 470
  (comint-check-source file-name) ; Check to see if buffer needs saved.
  (setq lisp-prev-l/c-dir/file (cons (file-name-directory    file-name)
				     (file-name-nondirectory file-name)))
Jim Blandy's avatar
Jim Blandy committed
471
  (comint-send-string (inferior-lisp-proc)
Jim Blandy's avatar
Jim Blandy committed
472 473
		      (format inferior-lisp-load-command file-name))
  (switch-to-lisp t))
Jim Blandy's avatar
Jim Blandy committed
474 475 476 477 478


(defun lisp-compile-file (file-name)
  "Compile a Lisp file in the inferior Lisp process."
  (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file
Pavel Janík's avatar
Pavel Janík committed
479
				  lisp-source-modes nil)) ; nil = don't need
Jim Blandy's avatar
Jim Blandy committed
480
					; suffix .lisp
Jim Blandy's avatar
Jim Blandy committed
481 482 483
  (comint-check-source file-name) ; Check to see if buffer needs saved.
  (setq lisp-prev-l/c-dir/file (cons (file-name-directory    file-name)
				     (file-name-nondirectory file-name)))
Jim Blandy's avatar
Jim Blandy committed
484 485 486
  (comint-send-string (inferior-lisp-proc) (concat "(compile-file \""
						   file-name
						   "\"\)\n"))
Jim Blandy's avatar
Jim Blandy committed
487
  (switch-to-lisp t))
Jim Blandy's avatar
Jim Blandy committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529



;;; Documentation functions: function doc, var doc, arglist, and
;;; describe symbol.
;;; ===========================================================================

;;; Command strings
;;; ===============

(defvar lisp-function-doc-command
  "(let ((fn '%s))
     (format t \"Documentation for ~a:~&~a\"
	     fn (documentation fn 'function))
     (values))\n"
  "Command to query inferior Lisp for a function's documentation.")

(defvar lisp-var-doc-command
  "(let ((v '%s))
     (format t \"Documentation for ~a:~&~a\"
	     v (documentation v 'variable))
     (values))\n"
  "Command to query inferior Lisp for a variable's documentation.")

(defvar lisp-arglist-command
  "(let ((fn '%s))
     (format t \"Arglist for ~a: ~a\" fn (arglist fn))
     (values))\n"
  "Command to query inferior Lisp for a function's arglist.")

(defvar lisp-describe-sym-command
  "(describe '%s)\n"
  "Command to query inferior Lisp for a variable's documentation.")


;;; Ancillary functions
;;; ===================

;;; Reads a string from the user.
(defun lisp-symprompt (prompt default)
  (list (let* ((prompt (if default
			   (format "%s (default %s): " prompt default)
Jim Blandy's avatar
Jim Blandy committed
530
			 (concat prompt ": ")))
Jim Blandy's avatar
Jim Blandy committed
531 532 533 534 535 536 537
	       (ans (read-string prompt)))
	  (if (zerop (length ans)) default ans))))


;;; Adapted from function-called-at-point in help.el.
(defun lisp-fn-called-at-pt ()
  "Returns the name of the function called in the current call.
Richard M. Stallman's avatar
Richard M. Stallman committed
538
The value is nil if it can't find one."
Jim Blandy's avatar
Jim Blandy committed
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
  (condition-case nil
      (save-excursion
	(save-restriction
	  (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
	  (backward-up-list 1)
	  (forward-char 1)
	  (let ((obj (read (current-buffer))))
	    (and (symbolp obj) obj))))
    (error nil)))


;;; Adapted from variable-at-point in help.el.
(defun lisp-var-at-pt ()
  (condition-case ()
      (save-excursion
	(forward-sexp -1)
	(skip-chars-forward "'")
	(let ((obj (read (current-buffer))))
	  (and (symbolp obj) obj)))
    (error nil)))


;;; Documentation functions: fn and var doc, arglist, and symbol describe.
;;; ======================================================================

(defun lisp-show-function-documentation (fn)
  "Send a command to the inferior Lisp to give documentation for function FN.
Richard M. Stallman's avatar
Richard M. Stallman committed
566
See variable `lisp-function-doc-command'."
Jim Blandy's avatar
Jim Blandy committed
567
  (interactive (lisp-symprompt "Function doc" (lisp-fn-called-at-pt)))
Jim Blandy's avatar
Jim Blandy committed
568 569
  (comint-proc-query (inferior-lisp-proc)
		     (format lisp-function-doc-command fn)))
Jim Blandy's avatar
Jim Blandy committed
570 571 572

(defun lisp-show-variable-documentation (var)
  "Send a command to the inferior Lisp to give documentation for function FN.
Richard M. Stallman's avatar
Richard M. Stallman committed
573
See variable `lisp-var-doc-command'."
Jim Blandy's avatar
Jim Blandy committed
574
  (interactive (lisp-symprompt "Variable doc" (lisp-var-at-pt)))
Jim Blandy's avatar
Jim Blandy committed
575
  (comint-proc-query (inferior-lisp-proc) (format lisp-var-doc-command var)))
Jim Blandy's avatar
Jim Blandy committed
576 577

(defun lisp-show-arglist (fn)
Richard M. Stallman's avatar
Richard M. Stallman committed
578 579
  "Send a query to the inferior Lisp for the arglist for function FN.
See variable `lisp-arglist-command'."
Jim Blandy's avatar
Jim Blandy committed
580
  (interactive (lisp-symprompt "Arglist" (lisp-fn-called-at-pt)))
Jim Blandy's avatar
Jim Blandy committed
581
  (comint-proc-query (inferior-lisp-proc) (format lisp-arglist-command fn)))
Jim Blandy's avatar
Jim Blandy committed
582 583 584

(defun lisp-describe-sym (sym)
  "Send a command to the inferior Lisp to describe symbol SYM.
Richard M. Stallman's avatar
Richard M. Stallman committed
585
See variable `lisp-describe-sym-command'."
Jim Blandy's avatar
Jim Blandy committed
586
  (interactive (lisp-symprompt "Describe" (lisp-var-at-pt)))
Jim Blandy's avatar
Jim Blandy committed
587 588
  (comint-proc-query (inferior-lisp-proc)
		     (format lisp-describe-sym-command sym)))
Jim Blandy's avatar
Jim Blandy committed
589 590


Richard M. Stallman's avatar
Richard M. Stallman committed
591 592
;;  "Returns the current inferior Lisp process.
;; See variable `inferior-lisp-buffer'."
Jim Blandy's avatar
Jim Blandy committed
593
(defun inferior-lisp-proc ()
594
  (let ((proc (get-buffer-process (if (derived-mode-p 'inferior-lisp-mode)
Jim Blandy's avatar
Jim Blandy committed
595
				      (current-buffer)
Jim Blandy's avatar
Jim Blandy committed
596
				    inferior-lisp-buffer))))
Jim Blandy's avatar
Jim Blandy committed
597
    (or proc
598
	(error "No Lisp subprocess; see variable `inferior-lisp-buffer'"))))
Jim Blandy's avatar
Jim Blandy committed
599 600 601 602


;;; Do the user's customisation...
;;;===============================
603 604
(defvar inferior-lisp-load-hook nil
  "This hook is run when the library `inf-lisp' is loaded.")
Jim Blandy's avatar
Jim Blandy committed
605 606

(run-hooks 'inferior-lisp-load-hook)
Jim Blandy's avatar
Jim Blandy committed
607 608 609

;;; CHANGE LOG
;;; ===========================================================================
Jim Blandy's avatar
Jim Blandy committed
610 611 612 613
;;; 7/21/92 Jim Blandy
;;; - Changed all uses of the cmulisp name or prefix to inferior-lisp;
;;;   this is now the official inferior lisp package.  Use the global
;;;   ChangeLog from now on.
Jim Blandy's avatar
Jim Blandy committed
614
;;; 5/24/90 Olin
615
;;; - Split cmulisp and cmushell modes into separate files.
Jim Blandy's avatar
Jim Blandy committed
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
;;;   Not only is this a good idea, it's apparently the way it'll be rel 19.
;;; - Upgraded process sends to use comint-send-string instead of
;;;   process-send-string.
;;; - Explicit references to process "cmulisp" have been replaced with
;;;   (cmulisp-proc). This allows better handling of multiple process bufs.
;;; - Added process query and var/function/symbol documentation
;;;   commands. Based on code written by Douglas Roberts.
;;; - Added lisp-eval-last-sexp, bound to C-x C-e.
;;;
;;; 9/20/90 Olin
;;; Added a save-restriction to lisp-fn-called-at-pt. This bug and fix
;;; reported by Lennart Staflin.
;;;
;;; 3/12/90 Olin
;;; - lisp-load-file and lisp-compile-file no longer switch-to-lisp.
;;;   Tale suggested this.
Jim Blandy's avatar
Jim Blandy committed
632 633 634 635 636 637 638
;;; - Reversed this decision 7/15/91. You need the visual feedback.
;;;
;;; 7/25/91 Olin
;;; Changed all keybindings of the form C-c <letter>. These are
;;; supposed to be reserved for the user to bind. This affected
;;; mainly the compile/eval-defun/region[-and-go] commands.
;;; This was painful, but necessary to adhere to the gnumacs standard.
639
;;; For some backwards compatibility, see the
Jim Blandy's avatar
Jim Blandy committed
640 641 642 643 644 645 646 647 648 649 650
;;;     cmulisp-install-letter-bindings
;;; function.
;;;
;;; 8/2/91 Olin
;;; - The lisp-compile/eval-defun/region commands now take a prefix arg,
;;;   which means switch-to-lisp after sending the text to the Lisp process.
;;;   This obsoletes all the -and-go commands. The -and-go commands are
;;;   kept around for historical reasons, and because the user can bind
;;;   them to key sequences shorter than C-u C-c C-<letter>.
;;; - If M-x cmulisp is invoked with a prefix arg, it allows you to
;;;   edit the command line.
Jim Blandy's avatar
Jim Blandy committed
651

Jim Blandy's avatar
Jim Blandy committed
652
(provide 'inf-lisp)
Jim Blandy's avatar
Jim Blandy committed
653

Jim Blandy's avatar
Jim Blandy committed
654
;;; inf-lisp.el ends here