Mercurial > hg > xemacs-beta
diff lisp/ilisp/ilisp-hi.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-hi.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,603 @@ +;;; -*- Mode: Emacs-Lisp -*- + +;;; ilisp-hi.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 high level interface functions Lisp <-> Emacs +;;; + +;;;%Eval/compile +(defun lisp-send-region (start end switch message status format + &optional handler) + "Given START, END, SWITCH, MESSAGE, STATUS, FORMAT and optional +HANDLER send the region between START and END to the lisp buffer and +execute the command defined by FORMAT on the region, its package and +filename. If called with a positive prefix, the results will be +inserted at the end of the region. If SWITCH is T, the command will +be sent and the buffer switched to the inferior LISP buffer. if +SWITCH is 'call, a call will be inserted. If SWITCH is 'result the +result will be returned without being displayed. Otherwise the +results will be displayed in a popup window if lisp-wait-p is T and +the current-prefix-arg is not '- or if lisp-wait-p is nil and the +current-prefix-arg is '-. If not displayed in a pop-up window then +comint-handler will display the results in a pop-up window if they are +more than one line long, or they are from an error. STATUS will be +the process status when the command is actually executing. MESSAGE is +a message to let the user know what is going on." + (if (= start end) (error "Region is empty")) + (let ((sexp (lisp-count-pairs start end ?\( ?\))) + (string (buffer-substring start end))) + (setq string + (format (ilisp-value format) + (lisp-slashify + (if (= sexp 1) + string + (format (ilisp-value 'ilisp-block-command) string))) + (lisp-buffer-package) (buffer-file-name))) + (let ((result + (ilisp-send + string message status + (cond ((memq switch '(t call)) switch) + ((or (not (eq lisp-wait-p (lisp-minus-prefix))) + current-prefix-arg + (eq switch 'result)) nil) + (t 'dispatch)) + handler))) + + (if result + (if current-prefix-arg + (save-excursion + (goto-char end) + (insert ?\n) + (insert result)) + ;; Display the output in the usual way. + (lisp-display-output result))) + result))) + +;;;%%Eval +(defun eval-region-lisp (start end &optional switch message status handler) + "Evaluate the current region." + (interactive "r") + (setq message (or message + (concat "Evaluate " (lisp-region-name start end)))) + (let ((defvar (ilisp-value 'ilisp-defvar-regexp t))) + (if (and defvar + (save-excursion + (goto-char start) + (skip-chars-forward " \t\n") + (and (let ((case-fold-search t)) (looking-at defvar)) + (progn (forward-sexp) (skip-chars-forward " \t\n" end) + (= (point) end))))) + (lisp-send-region start end switch message (or status 'defvar) + 'ilisp-defvar-command handler) + (lisp-send-region start end switch message (or status 'eval) + 'ilisp-eval-command handler)))) + +;;; +(defun eval-next-sexp-lisp (&optional switch) + "Evaluate the next sexp." + (interactive) + (let (start end) + (save-excursion + (setq start (point)) + (forward-sexp) + (setq end (point))) + (eval-region-lisp start end switch + (format "Evaluate %s" (buffer-substring start end))))) + +;;; +(defun eval-defun-lisp (&optional switch) + "Evaluate the current form." + (interactive) + (let* ((form (lisp-defun-region-and-name)) + (result + (eval-region-lisp (car form) (car (cdr form)) (or switch 'result) + (format "Evaluating %s" (car (cdr (cdr form))))))) + ;; Display the returned value. -fmw + (lisp-display-output result))) + + +;;;%%%And go +(defun eval-region-and-go-lisp (start end) + "Evaluate the current region and switch to the current ILISP buffer." + (interactive "r") + (eval-region-lisp start end t)) + +(defun eval-next-sexp-and-go-lisp (&optional switch) + "Evaluate the next sexp and switch to the current ILISP buffer." + (interactive) + (eval-next-sexp-lisp t)) + +(defun eval-defun-and-go-lisp () + "Evaluate the current defun and switch to the current ILISP buffer. +With prefix, insert a call as well." + (interactive) + (eval-defun-lisp (if current-prefix-arg + (progn + (setq current-prefix-arg nil) + 'call) + t))) + +;;;%%Compile +(defun compile-region-lisp (start end &optional switch message status handler) + "Compile the current region." + (interactive "r") + (lisp-send-region + start end + (or switch 'result) ; Default to return the result. + (or message (concat "Compile " (lisp-region-name start end))) + (or status 'compile) + 'ilisp-compile-command + handler)) + + +;;; +(defun compile-defun-lisp (&optional switch) + "Compile the current defun or the last command in the input-ring of +an ILISP buffer if no current defun." + (interactive) + (let* ((form (lisp-defun-region-and-name)) + (start (car form)) + (end (car (cdr form)))) + (if (and (= start end) (memq major-mode ilisp-modes)) + (save-excursion + (let ((form (ring-ref (ilisp-get-input-ring) + (ilisp-input-ring-index)))) + (set-buffer "*ilisp-send*") + (delete-region (point-min) (point-max)) + (insert form) + (compile-defun-lisp))) + ;; Display the value returned by the compilation. -fmw + (let* ((thing (car (cdr (cdr form)))) + (result (compile-region-lisp start end (or switch 'result) + (format "Compiling %s" thing)))) + (lisp-display-output result))))) + +;;;%%%And-go +(defun compile-region-and-go-lisp (start end) + "Compile the current region and switch to the current ILISP buffer." + (interactive "r") + (compile-region-lisp start end t)) + +(defun compile-defun-and-go-lisp () + "Compile the current defun and switch to the current ILISP buffer." + (interactive) + (compile-defun-lisp + (if current-prefix-arg + (progn + (setq current-prefix-arg nil) + 'call) + t))) + +;;; +(defun compile-file-lisp (file-name &optional extension) + "Compile a Lisp file in the current inferior LISP and go there." + (interactive (comint-get-source + "Compile Lisp file: " lisp-prev-l/c-dir/file + lisp-source-modes nil)) + (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))) + (ilisp-init t) + ;; Ivan's hack for ange-ftp pathnames... + (let ((file-name + (if (string-match "/.*?@.*:" file-name) + (substring file-name (match-end 0)) + file-name))) + (ilisp-send + (format (ilisp-value 'ilisp-compile-file-command) file-name + (or extension (ilisp-value 'ilisp-binary-extension))) + (concat "Compile " file-name) 'compile + t))) + + +;;; +(defun ilisp-compile-inits () + "Compile the initialization files for the current inferior LISP dialect." + (interactive) + (ilisp-init t) + (let ((files (ilisp-value 'ilisp-load-inits t))) + (while files + (compile-file-lisp + (expand-file-name (cdr (car files)) ilisp-directory) + (ilisp-value 'ilisp-init-binary-extension t)) + (setq files (cdr files))))) + + +;;; +(defun close-and-send-lisp () + "Close and indent the current sexp then send it to the inferior +LISP." + (interactive) + (reindent-lisp) + (if (memq major-mode ilisp-modes) + (return-ilisp) + (eval-defun-lisp))) + +;;;%Special commands +(defun describe-lisp (sexp) + "Describe the current sexp using ilisp-describe-command. With a +negative prefix, prompt for the expression. If in an ILISP buffer, +and there is no current sexp, describe ilisp-last-command." + (interactive + (list + (if (lisp-minus-prefix) + (ilisp-read "Describe: " (lisp-previous-sexp t)) + (if (memq major-mode ilisp-modes) + (if (= (point) + (process-mark (get-buffer-process (current-buffer)))) + (or (ilisp-value 'ilisp-last-command t) + (error "No sexp to describe.")) + (lisp-previous-sexp t)) + (lisp-previous-sexp t))))) + (let ((result + (ilisp-send + (format (ilisp-value 'ilisp-describe-command) + (lisp-slashify sexp) (lisp-buffer-package)) + (concat "Describe " sexp) + 'describe))) + (lisp-display-output result))) + +;;; +(defun inspect-lisp (sexp) + "Inspect the current sexp using ilisp-inspect-command. With a +prefix, prompt for the expression. If in an ILISP buffer, and there +is no current sexp, inspect ilisp-last-command." + (interactive + (list + (if current-prefix-arg + (ilisp-read "Inspect: " (lisp-previous-sexp t)) + (if (memq major-mode ilisp-modes) + (if (= (point) + (process-mark (get-buffer-process (current-buffer)))) + (or (ilisp-value 'ilisp-last-command t) + (error "No sexp to inspect.")) + (lisp-previous-sexp t)) + (lisp-previous-sexp t))))) + (ilisp-send + (format (ilisp-value 'ilisp-inspect-command) + (lisp-slashify sexp) (lisp-buffer-package)) + (concat "Inspect " sexp) + 'inspect t)) + +;;; +(defun arglist-lisp (symbol) + "Return the arglist of the currently looked at function. With a +numeric prefix, the arglist will be inserted. With a negative one, +the symbol will be prompted for." + (interactive + (let* ((function (lisp-function-name))) + (list (if (lisp-minus-prefix) + (ilisp-read-symbol + (format "Arglist [%s]: " (lisp-buffer-symbol function)) + function t) + function)))) + (if (null symbol) + (error "No symbol") + (let* ((arglist + (ilisp-send + (format (ilisp-value 'ilisp-arglist-command) + (lisp-symbol-name symbol) + (lisp-symbol-package symbol)) + nil + 'args)) + (position (string-match "(" arglist))) + ;; Insert just the stuff after the open paren, + ;; but display everything the inferior lisp prints. + (cond ((and (not (ilisp-value 'comint-errorp t)) + current-prefix-arg position) + (let ((temp (point))) + (insert (substring arglist (1+ position))) + (goto-char temp))) + + (t + (lisp-display-output arglist)))))) + + +;;; +(defun documentation-lisp (symbol type) + "Return the documentation of the previous symbol using +ilisp-documentation-command. If the symbol is at the start of a list, +it is assumed to be a function, otherwise variable documentation is +searched for. With a minus prefix, prompt for the symbol and type. +With a numeric prefix always return the current function call +documentation." + (interactive + (if (lisp-minus-prefix) + (let* ((symbol-info (lisp-previous-symbol)) + (symbol (car symbol-info)) + (doc (ilisp-read-symbol + (format "Documentation [%s]: " + (lisp-buffer-symbol symbol)) + symbol)) + (default (if (car (cdr symbol-info)) + 'function + 'variable)) + (types (ilisp-value 'ilisp-documentation-types t)) + (type + (if types + (ilisp-completing-read + (if default + (format "Type [%s]: " default) + "Type: ") + types + default)))) + (list doc (if (stringp type) (read type) type))) + (if current-prefix-arg + (list (lisp-function-name) 'function) + (let* ((symbol-info (lisp-previous-symbol))) + (list (car symbol-info) + (if (car (cdr symbol-info)) + 'function + 'variable)))))) + (lisp-display-output + (ilisp-send + (format (ilisp-value 'ilisp-documentation-command) + (lisp-symbol-name symbol) (lisp-symbol-package symbol) type) + (format "Documentation %s %s" type (lisp-buffer-symbol symbol)) + 'doc))) + +;;;%%Macroexpand +(defun lisp-macroexpand-form () + "Return the next form for macroexpanding." + (save-excursion + (skip-chars-forward " \t\n") + (let* ((begin (point)) + (end (progn (forward-sexp) (point))) + (form (buffer-substring begin end))) + (list + (if (lisp-minus-prefix) + (ilisp-read "Macroexpand: " form) + form))))) + +;;; +(defun macroexpand-lisp (form &optional top) + "Macroexpand the next sexp until it is no longer a macro. With a +prefix, insert into buffer." + (interactive (lisp-macroexpand-form)) + (if (string-match "(\\([^ \t\n)]*\\)" form) + (let ((message (concat "Macroexpand" + (if top "-1 " " ") + (substring form + (match-beginning 1) + (match-end 1)))) + result) + (setq result + (ilisp-send + (format + (ilisp-value + (if top + 'ilisp-macroexpand-1-command + 'ilisp-macroexpand-command)) + (lisp-slashify form) + (lisp-buffer-package) + (buffer-file-name)) + message 'expand)) + (if current-prefix-arg + (save-excursion (forward-sexp) (insert ?\n) (insert result)) + (lisp-display-output result))) + (error "Not a form: %s" form))) + +(defun macroexpand-1-lisp (form) + "Macroexpand the next sexp once. With a prefix, insert into buffer." + (interactive (lisp-macroexpand-form)) + (macroexpand-lisp form t)) + + + +;;;%%Trace +(defun trace-defun-lisp-break (function) + "Trace FUNCTION without arg, untrace with. Prompt for function with +negative prefix. Default function is the current defun. +Trace with :break set." + (interactive + (let ((function (lisp-defun-name))) + (if (lisp-minus-prefix) + (list (ilisp-read-symbol + (format (if current-prefix-arg + "Untrace [%s]: " + "Trace [%s]: ") + (lisp-buffer-symbol function)) + function + t)) + (list function)))) + (trace-defun-lisp-internal function (not current-prefix-arg))) + +(defun trace-defun-lisp (function) + "Trace FUNCTION without arg, untrace with. Prompt for function with +negative prefix. Default function is the current defun." + (interactive + (let ((function (lisp-defun-name))) + (if (lisp-minus-prefix) + (list (ilisp-read-symbol + (format (if current-prefix-arg + "Untrace [%s]: " + "Trace [%s]: ") + (lisp-buffer-symbol function)) + function + t)) + (list function)))) + (trace-defun-lisp-internal function nil)) + +(defun trace-defun-lisp-internal (function breakp) + (cond (function + (let ((result + (ilisp-send + (if current-prefix-arg + (format (ilisp-value 'ilisp-untrace-command) + (lisp-symbol-name function) + (lisp-symbol-package function)) + (format (ilisp-value 'ilisp-trace-command) + (lisp-symbol-name function) + (lisp-symbol-package function) + breakp)) + (format "%srace %s" (if current-prefix-arg "Unt" "T") + (lisp-buffer-symbol function)) + (if current-prefix-arg 'untrace 'trace) + ;; Change to always wait, so we can see the result. -fmw, 10/13/93 + ;; (if lisp-wait-p nil 'dispatch) + nil))) + ;; Display the value returned -fmw + (lisp-display-output result))) + (t + (error "No function to %strace" (if current-prefix-arg "un" ""))))) + + + +;;;%%Default-directory +(defun default-directory-lisp (&optional buffer) + "Set the inferior LISP default directory to the default directory of +optional BUFFER. If you are in an inferior LISP buffer, set the +default directory to the current directory of the LISP." + (interactive) + (if (and (not buffer) (memq major-mode ilisp-modes)) + (let ((dir + (ilisp-send + (ilisp-value 'ilisp-directory-command) + (format "Getting LISP directory") + 'dir))) + (if (ilisp-value 'comint-errorp t) + (progn + (lisp-display-output dir) + (error "Error getting directory")) + (setq default-directory (read dir) + lisp-prev-l/c-dir/file (cons default-directory nil)) + (message "Default directory is %s" default-directory))) + (let ((directory (save-excursion + (set-buffer (or buffer (current-buffer))) + default-directory))) + (ilisp-send + (format (ilisp-value 'ilisp-set-directory-command) directory) + (format "Set %s's directory to %s" + (buffer-name (ilisp-buffer)) directory) + 'dir + ;; (if lisp-wait-p nil 'dispatch) + ;; The above line might cause problems with Lispworks. + ;; I just set the default to 'nil'. It shouldn't harm. + ;; Marco Antoniotti: Jan 2 1995. + )))) + + +;;; +(defun load-file-lisp (file-name) + "Load a lisp file into the current inferior LISP and go there." + (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file + lisp-source-modes nil)) + (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))) + (ilisp-init t) + (let* ((extension (ilisp-value 'ilisp-binary-extension t)) + (binary (lisp-file-extension file-name extension))) + (save-excursion + (set-buffer (ilisp-buffer)) + (if (not (eq comint-send-queue comint-end-queue)) + (if (y-or-n-p "Abort commands before loading? ") + (abort-commands-lisp) + (message "Waiting for commands to finish") + (while (not (eq comint-send-queue comint-end-queue)) + (accept-process-output) + (sit-for 0)))) + (if (and (car (comint-send-variables (car comint-send-queue))) + (y-or-n-p "Interrupt top level? ")) + (let ((result (comint-send-results (car comint-send-queue)))) + (interrupt-subjob-ilisp) + (while (not (cdr result)) + (accept-process-output) + (sit-for 0))))) + (if (file-newer-than-file-p file-name binary) + (if (and (not ilisp-load-no-compile-query) + extension (y-or-n-p "Compile first? ")) + ;; Load binary if just compiled + (progn + (message "") + (compile-file-lisp file-name) + (setq file-name binary))) + ;; Load binary if it is current + (if (file-readable-p binary) (setq file-name binary))) + (switch-to-lisp t t) + + ;; Ivan's hack for ange-ftp pathnames... + (let ((file-name + (if (string-match "/.*?@.*:" file-name) + (substring file-name (match-end 0)) + file-name))) + (comint-sender + (ilisp-process) + (format (ilisp-value 'ilisp-load-command) file-name)) + (message "Loading %s" file-name)))) + + + +;;;%Source +;;;%File operations +;;; +(defun lisp-find-file (file &optional pop no-name) + "Find FILE, optionally POPping. +If optional NO-NAME is nil, and there is a buffer with a name that is +the same as the final pathname component, select that instead of +reading the file associated with the full path name. If the expanded +name of FILE and buffer match, select that buffer." + + (let* ((buffers (buffer-list)) + (position 0) + (expand-symlinks t) + (expanded (expand-file-name file)) + filename) + (if (not no-name) + (progn (while (string-match "/" file position) + (setq position (match-end 0))) + (setq filename (substring file position)))) + (while buffers + (save-excursion + (set-buffer (car buffers)) + (let* ((name (and (not no-name) (buffer-name))) + (buffer-file (buffer-file-name)) + (buffer-expanded + (cdr + (if (string-equal buffer-file (car lisp-buffer-file)) + lisp-buffer-file + (setq lisp-buffer-file + (cons buffer-file + (expand-file-name buffer-file))))))) + (if (or (and name (string-equal filename name)) + (string-equal expanded buffer-expanded)) + (setq file buffer-file + buffers nil) + (setq buffers (cdr buffers))))))) + (if pop + (lisp-pop-to-buffer (find-file-noselect file)) + (find-file file))) + +;;; +(defun find-file-lisp (file-name) + "Find a file. +If point is on a string that points to an existing +file, that will be the default. If the buffer is one of +lisp-source-modes, the buffer file will be the default. Otherwise, +the last file used in a lisp-source-mode will be used." + (interactive + (comint-get-source "Find file: " + lisp-prev-l/c-dir/file + lisp-source-modes nil)) + (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name) + (file-name-nondirectory file-name))) + (lisp-find-file file-name nil t))