comparison lisp/ilisp/ilisp-snd.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children b82b59fe008d
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; -*- Mode: Emacs-Lisp -*-
2
3 ;;; ilisp-snd.el --
4
5 ;;; This file is part of ILISP.
6 ;;; Version: 5.7
7 ;;;
8 ;;; Copyright (C) 1990, 1991, 1992, 1993 Chris McConnell
9 ;;; 1993, 1994 Ivan Vasquez
10 ;;; 1994, 1995 Marco Antoniotti and Rick Busdiecker
11 ;;;
12 ;;; Other authors' names for which this Copyright notice also holds
13 ;;; may appear later in this file.
14 ;;;
15 ;;; Send mail to 'ilisp-request@lehman.com' to be included in the
16 ;;; ILISP mailing list. 'ilisp@lehman.com' is the general ILISP
17 ;;; mailing list were bugs and improvements are discussed.
18 ;;;
19 ;;; ILISP is freely redistributable under the terms found in the file
20 ;;; COPYING.
21
22
23
24 ;;;
25 ;;; ILISP send and support.
26 ;;;
27
28
29 ;;;%% Package / Symbol support
30 ;;;
31 (defun lisp-buffer-package ()
32 "Return the package for this buffer. The package name is a string.
33 If there is none, return NIL. This caches the package unless
34 ilisp-dont-cache-package is non-nil, so calling this more than once
35 is cheap."
36 (cond ((and (not (eq buffer-package 'not-yet-computed))
37 (null lisp-dont-cache-package))
38 buffer-package)
39 (ilisp-completion-package ilisp-completion-package)
40 (lisp-dont-cache-package
41 ;; Refind the package each time.
42 (let ((package (lisp-buffer-package-internal nil)))
43 (message "")
44 (setq buffer-package 'not-yet-computed)
45 (if package
46 (setq mode-name
47 (concat
48 (or buffer-mode-name
49 (setq buffer-mode-name mode-name))
50 ":" package)))
51 package))
52 ((or lisp-buffer-package
53 (memq major-mode ilisp-modes)
54 (not (memq major-mode lisp-source-modes)))
55 nil)
56 (t
57 (make-local-variable 'buffer-package)
58 (make-local-variable 'buffer-mode-name)
59 (let ((package (lisp-buffer-package-internal t)))
60 (message "")
61 (setq buffer-package package)
62 ;; Display package in mode line
63 (if package
64 (setq mode-name
65 (concat (or buffer-mode-name
66 (setq buffer-mode-name mode-name))
67 ":" buffer-package)))
68 buffer-package))))
69
70 (defun lisp-buffer-package-internal (search-from-start)
71 "Returns the package of the buffer. If SEARCH-FROM-START is T then
72 will search from the beginning of the buffer, otherwise will search
73 backwards from current point."
74 (setq mode-line-process 'ilisp-status)
75 (let* ((lisp-buffer-package t)
76 (case-fold-search t)
77 (regexp (ilisp-value 'ilisp-package-regexp t))
78 (spec
79 (if regexp
80 (save-excursion
81 (if (or (and search-from-start
82 (goto-char (point-min))
83 (re-search-forward regexp nil t))
84 (re-search-backward regexp nil t))
85 (buffer-substring (match-beginning 0)
86 (progn
87 (goto-char (match-beginning 0))
88 (forward-sexp)
89 (point)))))))
90 (str (format (ilisp-value 'ilisp-package-command) spec))
91 (package
92 (if spec
93 (ilisp-send
94 str
95 "Finding buffer package"
96 'pkg))))
97 (if (ilisp-value 'comint-errorp t)
98 (progn
99 (lisp-display-output package)
100 (error "No package"))
101 (if (and package
102 ;; There was a bug here, used to have the second *
103 ;; outside of the parens.
104 (string-match "[ \n\t:\"]*\\([^ \n\t\"]*\\)" package))
105 (setq package
106 (substring package
107 (match-beginning 1) (match-end 1)))))
108 package))
109
110 ;;;
111 (defun package-lisp ()
112 "Show current inferior LISP package."
113 (interactive)
114 (message "Inferior LISP package is %s"
115 (ilisp-send (ilisp-value 'ilisp-package-name-command)
116 "Finding inferior LISP package" 'pkg)))
117
118 ;;;
119 (defun set-package-lisp (package)
120 "Set inferior LISP to package of buffer or a named package with prefix."
121 (interactive
122 (let ((default (lisp-buffer-package)))
123 (if (or current-prefix-arg (null default))
124 (let ((name
125 (read-string
126 (format "Package [%s]: " (lisp-buffer-package)) "")))
127 (list (if (equal name "") default name)))
128 (list default))))
129 (if package
130 (ilisp-send (format (ilisp-value 'ilisp-in-package-command) package)
131 (format "Set %s's package to %s"
132 (buffer-name (ilisp-buffer))
133 package)
134 'pkg 'dispatch)
135 (error "No package")))
136
137 ;;;
138 (defun set-buffer-package-lisp (package)
139 "Reset the current package of the current buffer. With prefix
140 specify manually."
141 (interactive (if current-prefix-arg
142 (list (read-from-minibuffer "Package: " ))
143 (list nil)))
144 (if package
145 (setq buffer-package package
146 mode-name (concat (or buffer-mode-name mode-name) ":" package))
147 (setq buffer-package 'not-yet-computed)
148 (lisp-buffer-package)))
149
150
151
152 ;;;%Interface functions
153 ;;;%%Symbols
154 (defun lisp-string-to-symbol (string)
155 "Convert STRING to a symbol, (package delimiter symbol) where the
156 package is either package:symbol or from the current buffer."
157 (let* ((start (string-match ":+" string))
158 (end (if start (match-end 0))))
159 (if start
160 (lisp-symbol
161 (if (= start 0)
162 ""
163 (substring string 0 start))
164 (substring string start end)
165 (substring string end))
166 (let ((package (lisp-buffer-package)))
167 (lisp-symbol package (if package "::") string)))))
168
169 ;;;
170 (defun lisp-symbol-to-string (symbol)
171 "Convert SYMBOL to a string."
172 (apply 'concat symbol))
173
174 ;;;
175 (defun lisp-buffer-symbol (symbol)
176 "Return SYMBOL as a string qualified for the current buffer."
177 (let ((symbol-name (lisp-symbol-name symbol))
178 (pkg (lisp-symbol-package symbol))
179 (delimiter (lisp-symbol-delimiter symbol)))
180 (cond ((string= pkg (lisp-buffer-package)) symbol-name)
181 ((string= pkg "") (concat ":" symbol-name))
182 (pkg (concat pkg delimiter symbol-name))
183 (t symbol-name))))
184
185 ;;;
186 (defun lisp-previous-symbol (&optional stay)
187 "Return the immediately preceding symbol as ((package delimiter symbol)
188 function-p start end). If STAY is T, the end of the symbol will be point."
189 (save-excursion
190 (if (or (and (memq major-mode ilisp-modes)
191 (= (point) (process-mark (get-buffer-process
192 (current-buffer)))))
193 (progn
194 (skip-chars-backward " \t\n")
195 (or (bobp) (memq (char-after (1- (point))) '(?\) ?\")))))
196 nil
197 (let* ((delimiters (ilisp-value 'ilisp-symbol-delimiters))
198 (end (progn
199 (if (not stay) (skip-chars-forward delimiters))
200 (point)))
201 (start (progn
202 (skip-chars-backward delimiters)
203 (point)))
204 (prefix (if (not (bobp)) (1- start)))
205 (function-p
206 (and prefix
207 (or (eq (char-after prefix) ?\()
208 (and (eq (char-after prefix) ?')
209 (not (bobp))
210 (eq (char-after (1- prefix)) ?#)))
211 (not (looking-at "[^: \t\n]*:*\\*[^ \t\n]")))))
212 (cons (lisp-string-to-symbol (buffer-substring start end))
213 (list function-p start end))))))
214
215
216 ;;;
217 (defun lisp-function-name ()
218 "Return the previous function symbol. This is either after a #' or
219 at the start of the current sexp. If there is no current sexp, return
220 nil."
221 (save-excursion
222 (let ((symbol (lisp-previous-symbol)))
223 (if (car (cdr symbol))
224 (car symbol)
225 (condition-case ()
226 (if (and (memq major-mode ilisp-modes)
227 (= (point)
228 (process-mark
229 (get-buffer-process (current-buffer)))))
230 nil
231 (backward-up-list 1)
232 (down-list 1)
233 (lisp-string-to-symbol
234 (buffer-substring (point)
235 (progn (forward-sexp 1) (point)))))
236 (error nil))))))
237
238
239 ;;;
240 (defun lisp-defun-name ()
241 "Return the name of the current defun."
242 (save-excursion
243 (lisp-defun-begin)
244 (lisp-string-to-symbol (lisp-def-name t))))
245
246
247 ;;;%% ILISP initializations
248 ;;;
249 (defun ilisp-initialized ()
250 "Return T if the current inferior LISP has been initialized."
251 (memq (buffer-name (ilisp-buffer)) ilisp-initialized))
252
253 ;;;
254 (defun ilisp-load-init (dialect file)
255 "Add FILE to the files to be loaded into the inferior LISP when
256 dialect is initialized. If FILE is NIL, the entry will be removed."
257 (let ((old (assoc dialect ilisp-load-inits)))
258 (if file
259 (if old
260 (rplacd old file)
261 (setq ilisp-load-inits (nconc ilisp-load-inits
262 (list (cons dialect file)))))
263 (if old (setq ilisp-load-inits (delq old ilisp-load-inits))))))
264
265 ;;;
266 (defun ilisp-binary (init var)
267 "Initialize VAR to the result of INIT if VAR is NIL."
268 (if (not (ilisp-value var t))
269 (let ((binary (ilisp-value init t)))
270 (if binary
271 (comint-send
272 (ilisp-process) binary
273 t nil 'binary nil
274 (` (lambda (error wait message output last)
275 (if (or error
276 (not (string-match "\"[^\"]*\"" output)))
277 (progn
278 (lisp-display-output output)
279 (abort-commands-lisp "No binary"))
280 (setq (, var)
281 (substring output
282 (1+ (match-beginning 0))
283 (1- (match-end 0))))))))))))
284
285 ;;;
286 (defun ilisp-done-init ()
287 "Make sure that initialization is done and if not dispatch another check."
288 (if ilisp-load-files
289 (comint-send-code (get-buffer-process (current-buffer))
290 'ilisp-done-init)
291 (if ilisp-initializing
292 (progn
293 (message "Finished initializing %s" (car ilisp-dialect))
294 (setq ilisp-initializing nil
295 ilisp-initialized
296 (cons (buffer-name (current-buffer)) ilisp-initialized))))))
297
298 ;;;
299 (defun ilisp-init-internal (&optional sync)
300 "Send all of the stuff necessary to initialize."
301 (unwind-protect
302 (progn
303 (if sync
304 (comint-sync
305 (ilisp-process)
306 "\"Start sync\"" "[ \t\n]*\"Start sync\""
307 "\"End sync\"" "\"End sync\""))
308 (ilisp-binary 'ilisp-binary-command 'ilisp-binary-extension)
309 (ilisp-binary 'ilisp-init-binary-command
310 'ilisp-init-binary-extension)
311 ;; This gets executed in the process buffer
312 (comint-send-code
313 (ilisp-process)
314 (function (lambda ()
315 (let ((files ilisp-load-inits)
316 (done nil))
317 (unwind-protect
318 (progn
319 (if (not ilisp-init-binary-extension)
320 (setq ilisp-init-binary-extension
321 ilisp-binary-extension))
322 (while files
323 (ilisp-load-or-send
324 (expand-file-name
325 (cdr (car files)) ilisp-directory))
326 (setq files (cdr files)))
327 (comint-send-code (ilisp-process)
328 'ilisp-done-init)
329 (setq done t))
330 (if (not done)
331 (progn
332 (setq ilisp-initializing nil)
333 (abort-commands-lisp))))))))
334
335 (set-ilisp-value 'ilisp-initializing t)) ; progn
336
337 (if (not (ilisp-value 'ilisp-initializing t))
338 (abort-commands-lisp))))
339
340 ;;;
341 (defun ilisp-init (&optional waitp forcep sync)
342 "Initialize the current inferior LISP if necessary by loading the
343 files in ilisp-load-inits. Optional WAITP waits for initialization to
344 finish. When called interactively, force reinitialization. With a
345 prefix, get the binary extensions again."
346 (interactive
347 (list (if current-prefix-arg
348 (progn
349 (set-ilisp-value 'ilisp-init-binary-extension nil)
350 (set-ilisp-value 'ilisp-binary-extension nil)
351 nil))
352 t))
353 (if (or forcep (not (ilisp-initialized)))
354 (progn
355 (message "Started initializing ILISP")
356 (if (not ilisp-directory)
357 (setq ilisp-directory (or (ilisp-directory "ilisp.elc" load-path)
358 (ilisp-directory "ilisp.el" load-path))))
359 (if (not (ilisp-value 'ilisp-initializing t))
360 (ilisp-init-internal sync))
361 (if waitp
362 (while (ilisp-value 'ilisp-initializing t)
363 (accept-process-output)
364 (sit-for 0))))))
365
366 ;;;
367 (defun ilisp-init-and-sync ()
368 "Synchronize with the inferior LISP and then initialize."
369 (ilisp-init nil nil t))
370
371
372
373 ;;;
374 (defun call-defun-lisp (arg)
375 "Put a call of the current defun in the inferior LISP and go there.
376 If it is a \(def* name form, look up reasonable forms of name in the
377 input history unless called with prefix ARG. If not found, use \(name
378 or *name* as the call. If is not a def* form, put the whole form in
379 the buffer."
380 (interactive "P")
381 (if (save-excursion (lisp-defun-begin) (looking-at "(def"))
382 (let* ((symbol (lisp-defun-name))
383 (name (lisp-symbol-name symbol))
384 (package (if (lisp-symbol-package symbol)
385 (concat "\\("
386 (lisp-symbol-package symbol) ":+\\)?")))
387 (variablep (string-match "^\\*" name))
388 (setfp (string-match "(setf \\([^\)]+\\)" name)))
389 (switch-to-lisp t t)
390 (cond (setfp
391 (setq name
392 (substring name (match-beginning 1) (match-end 1)))
393 (lisp-match-ring (if (not arg)
394 (concat "(setf[ \t\n]*("
395 package name "[ \t\n]"))
396 (concat "(setf (" name)))
397 (variablep (lisp-match-ring (if (not arg)
398 (concat package name))
399 name))
400 (t
401 (let ((fun (concat "(" name)))
402 (setq name (regexp-quote name))
403 (or (lisp-match-ring
404 (if (not arg) (concat "(" package name "[ \t\n\)]"))
405 fun
406 (not arg))
407 (lisp-match-ring (concat "(" package
408 "[^ \t\n]*-*" name)
409 fun))))))
410 (let ((form
411 (save-excursion
412 (buffer-substring (lisp-defun-begin)
413 (lisp-end-defun-text t)))))
414 (switch-to-lisp t t)
415 (comint-kill-input)
416 (insert form))))
417
418
419
420 ;;;
421 (defun ilisp-send (string &optional message status and-go handler)
422 "Send STRING to the ILISP buffer, print MESSAGE set STATUS and
423 return the result if AND-GO is NIL, otherwise switch to ilisp if
424 and-go is T and show message and results. If AND-GO is 'dispatch,
425 then the command will be executed without waiting for results. If
426 AND-GO is 'call, then a call will be generated. If this is the first
427 time an ilisp command has been executed, the lisp will also be
428 initialized from the files in ilisp-load-inits. If there is an error,
429 comint-errorp will be T and it will be handled by HANDLER."
430 (ilisp-init t)
431 (let ((process (ilisp-process))
432 (dispatch (eq and-go 'dispatch)))
433 (if message
434 (message "%s" (if dispatch
435 (concat "Started " message)
436 message)))
437 ;; No completion table
438 (setq ilisp-original nil)
439 (if (memq and-go '(t call))
440 (progn (comint-send process string nil nil status message handler)
441 (if (eq and-go 'call)
442 (call-defun-lisp nil)
443 (switch-to-lisp t t))
444 nil)
445 (let* ((save (ilisp-value 'ilisp-save-command t))
446 (result
447 (comint-send
448 process
449 (if save (format save string) string)
450 ;; Interrupt without waiting
451 t (if (not dispatch) 'wait) status message handler)))
452 (if save
453 (comint-send
454 process
455 (ilisp-value 'ilisp-restore-command t)
456 t nil 'restore "Restore" t t))
457 (if (not dispatch)
458 (progn
459 (while (not (cdr result))
460 (sit-for 0)
461 (accept-process-output))
462 (comint-remove-whitespace (car result))))))))
463
464
465
466 ;;;
467 (defun ilisp-load-or-send (file)
468 "Try to load FILE into the inferior LISP. If the file is not
469 accessible in the inferior LISP as determined by
470 ilisp-load-or-send-command, then visit the file and send the file over
471 the process interface."
472 (let* ((command
473 (format (ilisp-value 'ilisp-load-or-send-command)
474 (lisp-file-extension
475 file
476 (ilisp-value 'ilisp-init-binary-extension t))
477 file)))
478 (set-ilisp-value 'ilisp-load-files
479 (nconc (ilisp-value 'ilisp-load-files t) (list file)))
480 (comint-send
481 (ilisp-process) command t nil 'load
482 (format "Loading %s" file)
483 (function (lambda (error wait message output last)
484 (let* ((file (lisp-last ilisp-load-files))
485 (process (get-buffer-process (current-buffer)))
486 (case-fold-search t))
487 (if (and output
488 (string-match "nil" (car (lisp-last-line output))))
489 (let* ((old-buffer (get-file-buffer file))
490 (buffer (find-file-noselect file))
491 (string (save-excursion
492 (set-buffer buffer)
493 (buffer-string))))
494 (if (not old-buffer) (kill-buffer buffer))
495 (if (string= "" string)
496 (abort-commands-lisp (format "Can't find file %s" file))
497 (comint-send
498 process
499 (format ilisp-block-command string)
500 t nil 'send (format "Sending %s" file)
501 (function (lambda (error wait message output last)
502 (if error
503 (progn
504 (comint-display-error output)
505 (abort-commands-lisp
506 (format "Error sending %s"
507 (lisp-last ilisp-load-files))))
508 (setq ilisp-load-files
509 (delq (lisp-last ilisp-load-files)
510 ilisp-load-files))))))))
511 (if error (ilisp-handler error wait message output last))
512 (setq ilisp-load-files (delq file ilisp-load-files)))))))))