|
|
1.1 root 1: ;;
2: ;; copyright (C) 1987, 1988 Franz Inc, Berkeley, Ca.
3: ;;
4: ;; The software, data and information contained herein are the property
5: ;; of Franz, Inc.
6: ;;
7: ;; This file (or any derivation of it) may be distributed without
8: ;; further permission from Franz Inc. as long as:
9: ;;
10: ;; * it is not part of a product for sale,
11: ;; * no charge is made for the distribution, other than a tape
12: ;; fee, and
13: ;; * all copyright notices and this notice are preserved.
14: ;;
15: ;; If you have any comments or questions on this interface, please feel
16: ;; free to contact Franz Inc. at
17: ;; Franz Inc.
18: ;; Attn: Kevin Layer
19: ;; 1995 University Ave
20: ;; Suite 275
21: ;; Berkeley, CA 94704
22: ;; (415) 548-3600
23: ;; or
24: ;; emacs-info%[email protected]
25: ;; ucbvax!franz!emacs-info
26:
27: ;; This file has its (distant) roots in lisp/shell.el, so:
28: ;;
29: ;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
30: ;;
31: ;; This file is derived from part of GNU Emacs.
32: ;;
33: ;; GNU Emacs is distributed in the hope that it will be useful,
34: ;; but WITHOUT ANY WARRANTY. No author or distributor
35: ;; accepts responsibility to anyone for the consequences of using it
36: ;; or for whether it serves any particular purpose or works at all,
37: ;; unless he says so in writing. Refer to the GNU Emacs General Public
38: ;; License for full details.
39: ;;
40: ;; Everyone is granted permission to copy, modify and redistribute
41: ;; GNU Emacs, but only under the conditions described in the
42: ;; GNU Emacs General Public License. A copy of this license is
43: ;; supposed to have been given to you along with GNU Emacs so you
44: ;; can know your rights and responsibilities. It should be in a
45: ;; file named COPYING. Among other things, the copyright notice
46: ;; and this notice must be preserved on all copies.
47:
48: ;; $Header: sublisp.el,v 1.35 89/02/17 19:36:18 layer Exp $
49:
50: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
51: ;;;
52: ;;; User Visibles
53: ;;;
54: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55:
56: (defvar fi:emacs-to-lisp-transaction-directory "/tmp"
57: "*The directory in which files for Emacs/Lisp communication are stored.
58: When using Lisp and Emacs on different machines, this directory should be
59: accessible on both machine with the same pathname (via the wonders of NFS).")
60:
61: (defvar fi:pop-to-sublisp-buffer-after-lisp-eval t
62: "*If non-nil, then after sending expressions to a Lisp process do pop to
63: the buffer which contains the Lisp.")
64:
65: (defvar fi:package nil
66: "A buffer-local variable whose value should either be nil or a string
67: which names a package in the Lisp world (ie, in a Lisp subprocess running
68: as an inferior of Emacs in some buffer). It is used when expressions are
69: sent from an Emacs buffer to a Lisp process so that the symbols are read
70: into the correct Lisp package.")
71:
72: (defvar fi:echo-evals-from-buffer-in-listener-p nil
73: "*If non-NIL, forms evalutated directly from a lisp buffer by the
74: fi:lisp-eval-* functions will be echoed by the lisp listener.")
75:
76: (defun fi:set-associated-sublisp (buffer-name)
77: "When evaluated in a Lisp source buffer causes further `eval'
78: commands (those which send expressions from Emacs to Lisp) to use
79: BUFFER-NAME as the buffer which contains a Lisp subprocess. If evaluated
80: when not in a Lisp source buffer, then the process type is read from the
81: minibuffer (\"common-lisp\" or \"franz-lisp\"). The buffer name is
82: interactively read and must be the name of an existing buffer. New buffers
83: with the same mode as the current buffer will also use BUFFER-NAME for
84: future `eval' commands."
85: (interactive "bBuffer name containing a Lisp process: ")
86: (let* ((process (get-buffer-process (get-buffer buffer-name)))
87: (mode (or (and (memq major-mode '(fi:common-lisp-mode
88: fi:franz-lisp-mode))
89: major-mode)
90: (let* ((alist '(("common-lisp" . fi:common-lisp-mode)
91: ("franz-lisp" . fi:franz-lisp-mode)))
92: (type (completing-read "Lisp type: "
93: alist nil t "common-lisp")))
94: (cdr (assoc type alist))))))
95: (if process
96: (let ((buffers (buffer-list))
97: (proc-name (process-name process)))
98: (cond ((eq mode 'fi:common-lisp-mode)
99: (setq fi::freshest-common-sublisp-name proc-name))
100: ((eq mode 'fi:franz-lisp-mode)
101: (setq fi::freshest-franz-sublisp-name proc-name)))
102: (while buffers
103: (if (eq mode (fi::symbol-value-in-buffer 'major-mode
104: (car buffers)))
105: (fi::set-in-buffer 'fi::sublisp-name proc-name
106: (car buffers)))
107: (setq buffers (cdr buffers))))
108: (error "There is no process associated with buffer %s!"
109: buffer-name))))
110:
111: ;;;;
112: ;;; Internals
113: ;;;;
114:
115: (defun fi:inferior-lisp-send-input (arg type)
116: "Send ARG, which is an s-expression, to the Lisp subprocess. TYPE
117: must be either 'sexps or 'lists, specifying whether lists or
118: s-expressions should be parsed (internally, either `(scan-sexps)' or
119: `(scan-lists)' is used). If at the end of buffer, everything typed since
120: the last output from the Lisp subprocess is collected and sent to the Lisp
121: subprocess. With an argument, only the specified number of s-expressions
122: or lists from the end of the buffer are sent. If in the middle of the
123: buffer, the current s-expression(s) or list(s) is(are) copied to the end of
124: the buffer and then sent. An argument specifies the number of s-expressions
125: or lists to be sent. If s-expressions are being parsed,the cursor
126: follows a closing parenthesis, the preceding s-expression(s) is(are)
127: processed. If the cursor is at an opening parenthesis, the following
128: s-expression(s) is(are) processed. If the cursor is at a closing
129: parenthesis, the preceding s-expression(s) is(are) processed. Otherwise,
130: the enclosing s-expression(s) is(are) processed. If lists are being
131: parsed, the enclosing list is processed."
132: (if (and (eobp) (null arg))
133: (progn
134: (move-marker fi::last-input-start
135: (process-mark (get-buffer-process (current-buffer))))
136: (insert "\n")
137: (funcall indent-line-function)
138: (move-marker fi::last-input-end (point)))
139:
140: ;; we are in the middle of the buffer somewhere and need to collect
141: ;; and s-exp to re-send
142: ;; we grab everything from the end of the current line back to the end
143: ;; of the last prompt
144: ;;
145: (let ((exp-to-resend "")
146: (start-resend (point))
147: (end-resend (point)))
148: (if (null arg) (setq arg 1))
149: (if (equal type 'sexp)
150: (setq exp-to-resend
151: (buffer-substring
152: (setq start-resend
153: (save-excursion
154: (cond
155: ((= (preceding-char) ?\)) (scan-sexps (point) (- arg)))
156: ((= (following-char) ?\() (point))
157: ((= (following-char) ?\))
158: (forward-char 1) (scan-sexps (point) (- arg)))
159: ((not (memq (char-syntax (preceding-char)) '(?w ?_)))
160: (point))
161: (t (scan-sexps (point) (- arg))))))
162: (setq end-resend
163: (save-excursion
164: (cond
165: ((= (preceding-char) ?\)) (point))
166: ((= (following-char) ?\() (scan-sexps (point) arg))
167: ((= (following-char) ?\)) (forward-char 1) (point))
168: ((not (memq (char-syntax (following-char)) '(?w ?_)))
169: (point))
170: (t (scan-sexps (point) arg)))))))
171: (setq exp-to-resend
172: (buffer-substring
173: (setq start-resend (scan-lists (point) (- arg) 1))
174: (setq end-resend (scan-lists (point) arg 1)))))
175: (if (eobp)
176: (progn
177: (insert "\n")
178: (funcall indent-line-function)
179: (move-marker fi::last-input-start start-resend)
180: (move-marker fi::last-input-end (point-max)))
181: (progn
182: (goto-char (point-max))
183: (move-marker fi::last-input-start (point))
184: (insert exp-to-resend)
185: (if (not (bolp)) (insert "\n"))
186: (move-marker fi::last-input-end (point))))))
187: (let ((process (get-buffer-process (current-buffer))))
188: (fi::send-region-split process fi::last-input-start fi::last-input-end
189: fi:subprocess-map-nl-to-cr)
190: (fi::input-ring-save fi::last-input-start (1- fi::last-input-end))
191: (set-marker (process-mark process) (point))))
192:
193: (defun fi::eval-send (start end compile-file-p)
194: "Send the text from START to END over to the sublisp, in the
195: correct fi:package, of course."
196: (fi::sublisp-select)
197: (let* ((stuff (buffer-substring start end))
198: (sublisp-process (get-process fi::sublisp-name)))
199: (fi::send-string-load
200: sublisp-process stuff fi:subprocess-map-nl-to-cr compile-file-p)
201: (fi::send-string-split sublisp-process "\n" fi:subprocess-map-nl-to-cr)
202: (if fi:pop-to-sublisp-buffer-after-lisp-eval
203: (progn
204: (switch-to-buffer-other-window (process-buffer sublisp-process))
205: (goto-char (point-max))))))
206:
207: (defun fi::eval-string-send (string compile-file-p &optional always-pop-to-p)
208: "Send STRING to the sublisp, in the correct package, of course."
209: (fi::sublisp-select)
210: (let ((sublisp-process (get-process fi::sublisp-name)))
211: (fi::send-string-load
212: sublisp-process string fi:subprocess-map-nl-to-cr compile-file-p)
213: (fi::send-string-split sublisp-process "\n" fi:subprocess-map-nl-to-cr)
214: (if (or always-pop-to-p fi:pop-to-sublisp-buffer-after-lisp-eval)
215: (progn
216: (switch-to-buffer-other-window (process-buffer sublisp-process))
217: (goto-char (point-max))))))
218:
219: (defun fi::sublisp-select ()
220: "Find a sublisp for eval commands to send code to. Result stored in
221: the variable fi::sublisp-name. If fi::sublisp-name is set, and there is an
222: associated process buffer, thats that. If fi::sublisp-name is nil, or if
223: there is no process buffer with that name, then try for
224: freshest-<franz,common>-sublisp-name, which should contain the name of the
225: most recently started sublisp. If neither of these exist, runs the command
226: franz-lisp or common-lisp, depending on the major mode of the buffer."
227: ;; see if sublisp is named yet. if its not, name it intelligently.
228: (cond (fi::sublisp-name t)
229: ((eq major-mode 'fi:inferior-common-lisp-mode)
230: (setq fi::sublisp-name fi::freshest-common-sublisp-name))
231: ((eq major-mode 'fi:inferior-franz-lisp-mode)
232: (setq fi::sublisp-name fi::freshest-franz-sublisp-name))
233: ((eq major-mode 'fi:franz-lisp-mode)
234: (if fi::freshest-franz-sublisp-name
235: (setq fi::sublisp-name fi::freshest-franz-sublisp-name)
236: (setq fi::sublisp-name "franz-lisp")))
237: ((eq major-mode 'fi:common-lisp-mode)
238: (if fi::freshest-common-sublisp-name
239: (setq fi::sublisp-name fi::freshest-common-sublisp-name)
240: (setq fi::sublisp-name "common-lisp")))
241: (t (error "Cant start a subprocess for Major mode %s." major-mode)))
242: ;; start-up the sublisp process if necessary and possible
243: (cond ((get-process fi::sublisp-name) t)
244: ((eql major-mode 'fi:franz-lisp-mode)
245: (if (and fi::freshest-franz-sublisp-name
246: (get-process fi::freshest-franz-sublisp-name))
247: (setq fi::sublisp-name fi::freshest-franz-sublisp-name)
248: (setq fi::sublisp-name (prog1
249: (fi:franz-lisp)
250: (switch-to-buffer nil)
251: (sleep-for 5)))))
252: ((eql major-mode 'fi:common-lisp-mode)
253: (if (and fi::freshest-common-sublisp-name
254: (get-process fi::freshest-common-sublisp-name))
255: (setq fi::sublisp-name fi::freshest-common-sublisp-name)
256: (setq fi::sublisp-name (prog1
257: (fi:common-lisp)
258: (switch-to-buffer nil)
259: (sleep-for 1)))))
260: (t (error "Can't start a subprocess for sublisp-name %s."
261: fi::sublisp-name))))
262:
263: (defun fi::send-string-load (process text nl-to-cr compile-file-p)
264: (let (pkg)
265: (if (null fi::emacs-to-lisp-transaction-file)
266: (let ()
267: (setq fi::emacs-to-lisp-transaction-file
268: (let* ((filename (buffer-file-name (current-buffer))))
269: (format "%s/%s,%s" fi:emacs-to-lisp-transaction-directory
270: (user-login-name)
271: (if filename (file-name-nondirectory filename)
272: "noname"))))
273: (setq fi::emacs-to-lisp-package
274: (if fi:package
275: (format "(in-package :%s)\n" fi:package)
276: nil))
277: (setq fi::emacs-to-lisp-transaction-buf
278: (let ((name (file-name-nondirectory
279: fi::emacs-to-lisp-transaction-file)))
280: (or (get-buffer name)
281: (create-file-buffer name))))
282: (let ((file fi::emacs-to-lisp-transaction-file))
283: (save-window-excursion
284: (pop-to-buffer fi::emacs-to-lisp-transaction-buf)
285: (set 'fi::remove-file-on-kill-emacs file)
286: (set 'fi::remove-file-on-kill-emacs file)))))
287: (setq pkg fi::emacs-to-lisp-package)
288: (save-window-excursion
289: (let ((file fi::emacs-to-lisp-transaction-file))
290: (pop-to-buffer fi::emacs-to-lisp-transaction-buf)
291: (erase-buffer)
292: (if (and pkg (not fi:echo-evals-from-buffer-in-listener-p))
293: (insert pkg))
294: (insert text)
295: ;; (newline) Unneeded? -smh
296: (write-region (point-min) (point-max) file)
297: (bury-buffer)))
298: (let ((load-string
299: (if compile-file-p
300: (format
301: "(let ((*record-source-files* nil))
302: (excl::compile-file-if-needed \"%s\")
303: (load \"%s.fasl\"))"
304: fi::emacs-to-lisp-transaction-file
305: (fi::file-name-sans-type fi::emacs-to-lisp-transaction-file))
306: (if fi:echo-evals-from-buffer-in-listener-p
307: (format "(with-open-file (istm \"%s\")
308: (let ((*record-source-files* nil)
309: (*package* *package*)
310: (stm (make-echo-stream istm *terminal-io*)))
311: %s
312: (princ \" ;; eval from emacs: \") (fresh-line)
313: (load stm :verbose nil)))"
314: fi::emacs-to-lisp-transaction-file
315: (if pkg pkg ""))
316: (format "(let ((*record-source-files* nil)) (load \"%s\"))"
317: fi::emacs-to-lisp-transaction-file)))))
318: (fi::send-string-split process load-string nl-to-cr))))
319:
320: (defun fi:remove-all-temporary-lisp-transaction-files ()
321: "This function will clean up all the files created for Lisp/Emacs
322: communication. See the variable fi:emacs-to-lisp-transaction-directory for
323: the location of the files."
324: (let ((buffers (buffer-list))
325: file)
326: (while buffers
327: (setq file (fi::symbol-value-in-buffer
328: 'fi::remove-file-on-kill-emacs (car buffers)))
329: (if (and file (file-exists-p file)) (delete-file file))
330: (setq buffers (cdr buffers)))))
331:
332: (make-variable-buffer-local 'fi::remove-file-on-kill-emacs)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.