Mercurial > hg > xemacs-beta
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/ilisp/ilisp-snd.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,512 @@ +;;; -*- Mode: Emacs-Lisp -*- + +;;; ilisp-snd.el -- + +;;; This file is part of ILISP. +;;; Version: 5.7 +;;; +;;; Copyright (C) 1990, 1991, 1992, 1993 Chris McConnell +;;; 1993, 1994 Ivan Vasquez +;;; 1994, 1995 Marco Antoniotti and Rick Busdiecker +;;; +;;; Other authors' names for which this Copyright notice also holds +;;; may appear later in this file. +;;; +;;; Send mail to 'ilisp-request@lehman.com' to be included in the +;;; ILISP mailing list. 'ilisp@lehman.com' is the general ILISP +;;; mailing list were bugs and improvements are discussed. +;;; +;;; ILISP is freely redistributable under the terms found in the file +;;; COPYING. + + + +;;; +;;; ILISP send and support. +;;; + + +;;;%% Package / Symbol support +;;; +(defun lisp-buffer-package () + "Return the package for this buffer. The package name is a string. +If there is none, return NIL. This caches the package unless +ilisp-dont-cache-package is non-nil, so calling this more than once +is cheap." + (cond ((and (not (eq buffer-package 'not-yet-computed)) + (null lisp-dont-cache-package)) + buffer-package) + (ilisp-completion-package ilisp-completion-package) + (lisp-dont-cache-package + ;; Refind the package each time. + (let ((package (lisp-buffer-package-internal nil))) + (message "") + (setq buffer-package 'not-yet-computed) + (if package + (setq mode-name + (concat + (or buffer-mode-name + (setq buffer-mode-name mode-name)) + ":" package))) + package)) + ((or lisp-buffer-package + (memq major-mode ilisp-modes) + (not (memq major-mode lisp-source-modes))) + nil) + (t + (make-local-variable 'buffer-package) + (make-local-variable 'buffer-mode-name) + (let ((package (lisp-buffer-package-internal t))) + (message "") + (setq buffer-package package) + ;; Display package in mode line + (if package + (setq mode-name + (concat (or buffer-mode-name + (setq buffer-mode-name mode-name)) + ":" buffer-package))) + buffer-package)))) + +(defun lisp-buffer-package-internal (search-from-start) + "Returns the package of the buffer. If SEARCH-FROM-START is T then +will search from the beginning of the buffer, otherwise will search +backwards from current point." + (setq mode-line-process 'ilisp-status) + (let* ((lisp-buffer-package t) + (case-fold-search t) + (regexp (ilisp-value 'ilisp-package-regexp t)) + (spec + (if regexp + (save-excursion + (if (or (and search-from-start + (goto-char (point-min)) + (re-search-forward regexp nil t)) + (re-search-backward regexp nil t)) + (buffer-substring (match-beginning 0) + (progn + (goto-char (match-beginning 0)) + (forward-sexp) + (point))))))) + (str (format (ilisp-value 'ilisp-package-command) spec)) + (package + (if spec + (ilisp-send + str + "Finding buffer package" + 'pkg)))) + (if (ilisp-value 'comint-errorp t) + (progn + (lisp-display-output package) + (error "No package")) + (if (and package + ;; There was a bug here, used to have the second * + ;; outside of the parens. + (string-match "[ \n\t:\"]*\\([^ \n\t\"]*\\)" package)) + (setq package + (substring package + (match-beginning 1) (match-end 1))))) + package)) + +;;; +(defun package-lisp () + "Show current inferior LISP package." + (interactive) + (message "Inferior LISP package is %s" + (ilisp-send (ilisp-value 'ilisp-package-name-command) + "Finding inferior LISP package" 'pkg))) + +;;; +(defun set-package-lisp (package) + "Set inferior LISP to package of buffer or a named package with prefix." + (interactive + (let ((default (lisp-buffer-package))) + (if (or current-prefix-arg (null default)) + (let ((name + (read-string + (format "Package [%s]: " (lisp-buffer-package)) ""))) + (list (if (equal name "") default name))) + (list default)))) + (if package + (ilisp-send (format (ilisp-value 'ilisp-in-package-command) package) + (format "Set %s's package to %s" + (buffer-name (ilisp-buffer)) + package) + 'pkg 'dispatch) + (error "No package"))) + +;;; +(defun set-buffer-package-lisp (package) + "Reset the current package of the current buffer. With prefix +specify manually." + (interactive (if current-prefix-arg + (list (read-from-minibuffer "Package: " )) + (list nil))) + (if package + (setq buffer-package package + mode-name (concat (or buffer-mode-name mode-name) ":" package)) + (setq buffer-package 'not-yet-computed) + (lisp-buffer-package))) + + + +;;;%Interface functions +;;;%%Symbols +(defun lisp-string-to-symbol (string) + "Convert STRING to a symbol, (package delimiter symbol) where the +package is either package:symbol or from the current buffer." + (let* ((start (string-match ":+" string)) + (end (if start (match-end 0)))) + (if start + (lisp-symbol + (if (= start 0) + "" + (substring string 0 start)) + (substring string start end) + (substring string end)) + (let ((package (lisp-buffer-package))) + (lisp-symbol package (if package "::") string))))) + +;;; +(defun lisp-symbol-to-string (symbol) + "Convert SYMBOL to a string." + (apply 'concat symbol)) + +;;; +(defun lisp-buffer-symbol (symbol) + "Return SYMBOL as a string qualified for the current buffer." + (let ((symbol-name (lisp-symbol-name symbol)) + (pkg (lisp-symbol-package symbol)) + (delimiter (lisp-symbol-delimiter symbol))) + (cond ((string= pkg (lisp-buffer-package)) symbol-name) + ((string= pkg "") (concat ":" symbol-name)) + (pkg (concat pkg delimiter symbol-name)) + (t symbol-name)))) + +;;; +(defun lisp-previous-symbol (&optional stay) + "Return the immediately preceding symbol as ((package delimiter symbol) +function-p start end). If STAY is T, the end of the symbol will be point." + (save-excursion + (if (or (and (memq major-mode ilisp-modes) + (= (point) (process-mark (get-buffer-process + (current-buffer))))) + (progn + (skip-chars-backward " \t\n") + (or (bobp) (memq (char-after (1- (point))) '(?\) ?\"))))) + nil + (let* ((delimiters (ilisp-value 'ilisp-symbol-delimiters)) + (end (progn + (if (not stay) (skip-chars-forward delimiters)) + (point))) + (start (progn + (skip-chars-backward delimiters) + (point))) + (prefix (if (not (bobp)) (1- start))) + (function-p + (and prefix + (or (eq (char-after prefix) ?\() + (and (eq (char-after prefix) ?') + (not (bobp)) + (eq (char-after (1- prefix)) ?#))) + (not (looking-at "[^: \t\n]*:*\\*[^ \t\n]"))))) + (cons (lisp-string-to-symbol (buffer-substring start end)) + (list function-p start end)))))) + + +;;; +(defun lisp-function-name () + "Return the previous function symbol. This is either after a #' or +at the start of the current sexp. If there is no current sexp, return +nil." + (save-excursion + (let ((symbol (lisp-previous-symbol))) + (if (car (cdr symbol)) + (car symbol) + (condition-case () + (if (and (memq major-mode ilisp-modes) + (= (point) + (process-mark + (get-buffer-process (current-buffer))))) + nil + (backward-up-list 1) + (down-list 1) + (lisp-string-to-symbol + (buffer-substring (point) + (progn (forward-sexp 1) (point))))) + (error nil)))))) + + +;;; +(defun lisp-defun-name () + "Return the name of the current defun." + (save-excursion + (lisp-defun-begin) + (lisp-string-to-symbol (lisp-def-name t)))) + + +;;;%% ILISP initializations +;;; +(defun ilisp-initialized () + "Return T if the current inferior LISP has been initialized." + (memq (buffer-name (ilisp-buffer)) ilisp-initialized)) + +;;; +(defun ilisp-load-init (dialect file) + "Add FILE to the files to be loaded into the inferior LISP when +dialect is initialized. If FILE is NIL, the entry will be removed." + (let ((old (assoc dialect ilisp-load-inits))) + (if file + (if old + (rplacd old file) + (setq ilisp-load-inits (nconc ilisp-load-inits + (list (cons dialect file))))) + (if old (setq ilisp-load-inits (delq old ilisp-load-inits)))))) + +;;; +(defun ilisp-binary (init var) + "Initialize VAR to the result of INIT if VAR is NIL." + (if (not (ilisp-value var t)) + (let ((binary (ilisp-value init t))) + (if binary + (comint-send + (ilisp-process) binary + t nil 'binary nil + (` (lambda (error wait message output last) + (if (or error + (not (string-match "\"[^\"]*\"" output))) + (progn + (lisp-display-output output) + (abort-commands-lisp "No binary")) + (setq (, var) + (substring output + (1+ (match-beginning 0)) + (1- (match-end 0)))))))))))) + +;;; +(defun ilisp-done-init () + "Make sure that initialization is done and if not dispatch another check." + (if ilisp-load-files + (comint-send-code (get-buffer-process (current-buffer)) + 'ilisp-done-init) + (if ilisp-initializing + (progn + (message "Finished initializing %s" (car ilisp-dialect)) + (setq ilisp-initializing nil + ilisp-initialized + (cons (buffer-name (current-buffer)) ilisp-initialized)))))) + +;;; +(defun ilisp-init-internal (&optional sync) + "Send all of the stuff necessary to initialize." + (unwind-protect + (progn + (if sync + (comint-sync + (ilisp-process) + "\"Start sync\"" "[ \t\n]*\"Start sync\"" + "\"End sync\"" "\"End sync\"")) + (ilisp-binary 'ilisp-binary-command 'ilisp-binary-extension) + (ilisp-binary 'ilisp-init-binary-command + 'ilisp-init-binary-extension) + ;; This gets executed in the process buffer + (comint-send-code + (ilisp-process) + (function (lambda () + (let ((files ilisp-load-inits) + (done nil)) + (unwind-protect + (progn + (if (not ilisp-init-binary-extension) + (setq ilisp-init-binary-extension + ilisp-binary-extension)) + (while files + (ilisp-load-or-send + (expand-file-name + (cdr (car files)) ilisp-directory)) + (setq files (cdr files))) + (comint-send-code (ilisp-process) + 'ilisp-done-init) + (setq done t)) + (if (not done) + (progn + (setq ilisp-initializing nil) + (abort-commands-lisp)))))))) + + (set-ilisp-value 'ilisp-initializing t)) ; progn + + (if (not (ilisp-value 'ilisp-initializing t)) + (abort-commands-lisp)))) + +;;; +(defun ilisp-init (&optional waitp forcep sync) + "Initialize the current inferior LISP if necessary by loading the +files in ilisp-load-inits. Optional WAITP waits for initialization to +finish. When called interactively, force reinitialization. With a +prefix, get the binary extensions again." + (interactive + (list (if current-prefix-arg + (progn + (set-ilisp-value 'ilisp-init-binary-extension nil) + (set-ilisp-value 'ilisp-binary-extension nil) + nil)) + t)) + (if (or forcep (not (ilisp-initialized))) + (progn + (message "Started initializing ILISP") + (if (not ilisp-directory) + (setq ilisp-directory (or (ilisp-directory "ilisp.elc" load-path) + (ilisp-directory "ilisp.el" load-path)))) + (if (not (ilisp-value 'ilisp-initializing t)) + (ilisp-init-internal sync)) + (if waitp + (while (ilisp-value 'ilisp-initializing t) + (accept-process-output) + (sit-for 0)))))) + +;;; +(defun ilisp-init-and-sync () + "Synchronize with the inferior LISP and then initialize." + (ilisp-init nil nil t)) + + + +;;; +(defun call-defun-lisp (arg) + "Put a call of the current defun in the inferior LISP and go there. +If it is a \(def* name form, look up reasonable forms of name in the +input history unless called with prefix ARG. If not found, use \(name +or *name* as the call. If is not a def* form, put the whole form in +the buffer." + (interactive "P") + (if (save-excursion (lisp-defun-begin) (looking-at "(def")) + (let* ((symbol (lisp-defun-name)) + (name (lisp-symbol-name symbol)) + (package (if (lisp-symbol-package symbol) + (concat "\\(" + (lisp-symbol-package symbol) ":+\\)?"))) + (variablep (string-match "^\\*" name)) + (setfp (string-match "(setf \\([^\)]+\\)" name))) + (switch-to-lisp t t) + (cond (setfp + (setq name + (substring name (match-beginning 1) (match-end 1))) + (lisp-match-ring (if (not arg) + (concat "(setf[ \t\n]*(" + package name "[ \t\n]")) + (concat "(setf (" name))) + (variablep (lisp-match-ring (if (not arg) + (concat package name)) + name)) + (t + (let ((fun (concat "(" name))) + (setq name (regexp-quote name)) + (or (lisp-match-ring + (if (not arg) (concat "(" package name "[ \t\n\)]")) + fun + (not arg)) + (lisp-match-ring (concat "(" package + "[^ \t\n]*-*" name) + fun)))))) + (let ((form + (save-excursion + (buffer-substring (lisp-defun-begin) + (lisp-end-defun-text t))))) + (switch-to-lisp t t) + (comint-kill-input) + (insert form)))) + + + +;;; +(defun ilisp-send (string &optional message status and-go handler) + "Send STRING to the ILISP buffer, print MESSAGE set STATUS and +return the result if AND-GO is NIL, otherwise switch to ilisp if +and-go is T and show message and results. If AND-GO is 'dispatch, +then the command will be executed without waiting for results. If +AND-GO is 'call, then a call will be generated. If this is the first +time an ilisp command has been executed, the lisp will also be +initialized from the files in ilisp-load-inits. If there is an error, +comint-errorp will be T and it will be handled by HANDLER." + (ilisp-init t) + (let ((process (ilisp-process)) + (dispatch (eq and-go 'dispatch))) + (if message + (message "%s" (if dispatch + (concat "Started " message) + message))) + ;; No completion table + (setq ilisp-original nil) + (if (memq and-go '(t call)) + (progn (comint-send process string nil nil status message handler) + (if (eq and-go 'call) + (call-defun-lisp nil) + (switch-to-lisp t t)) + nil) + (let* ((save (ilisp-value 'ilisp-save-command t)) + (result + (comint-send + process + (if save (format save string) string) + ;; Interrupt without waiting + t (if (not dispatch) 'wait) status message handler))) + (if save + (comint-send + process + (ilisp-value 'ilisp-restore-command t) + t nil 'restore "Restore" t t)) + (if (not dispatch) + (progn + (while (not (cdr result)) + (sit-for 0) + (accept-process-output)) + (comint-remove-whitespace (car result)))))))) + + + +;;; +(defun ilisp-load-or-send (file) + "Try to load FILE into the inferior LISP. If the file is not +accessible in the inferior LISP as determined by +ilisp-load-or-send-command, then visit the file and send the file over +the process interface." + (let* ((command + (format (ilisp-value 'ilisp-load-or-send-command) + (lisp-file-extension + file + (ilisp-value 'ilisp-init-binary-extension t)) + file))) + (set-ilisp-value 'ilisp-load-files + (nconc (ilisp-value 'ilisp-load-files t) (list file))) + (comint-send + (ilisp-process) command t nil 'load + (format "Loading %s" file) + (function (lambda (error wait message output last) + (let* ((file (lisp-last ilisp-load-files)) + (process (get-buffer-process (current-buffer))) + (case-fold-search t)) + (if (and output + (string-match "nil" (car (lisp-last-line output)))) + (let* ((old-buffer (get-file-buffer file)) + (buffer (find-file-noselect file)) + (string (save-excursion + (set-buffer buffer) + (buffer-string)))) + (if (not old-buffer) (kill-buffer buffer)) + (if (string= "" string) + (abort-commands-lisp (format "Can't find file %s" file)) + (comint-send + process + (format ilisp-block-command string) + t nil 'send (format "Sending %s" file) + (function (lambda (error wait message output last) + (if error + (progn + (comint-display-error output) + (abort-commands-lisp + (format "Error sending %s" + (lisp-last ilisp-load-files)))) + (setq ilisp-load-files + (delq (lisp-last ilisp-load-files) + ilisp-load-files)))))))) + (if error (ilisp-handler error wait message output last)) + (setq ilisp-load-files (delq file ilisp-load-files)))))))))