home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / lisp / comint / inf-lisp.el < prev    next >
Encoding:
Text File  |  1992-06-29  |  10.2 KB  |  240 lines

  1. ;; -*-Emacs-Lisp-*- run an external lisp interpreter in an Emacs window
  2. ;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
  3.  
  4. ;; This file is part of GNU Emacs.
  5.  
  6. ;; GNU Emacs is free software; you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation; either version 2, or (at your option)
  9. ;; any later version.
  10.  
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;; GNU General Public License for more details.
  15.  
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  18. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. ;;; Hacked from tea.el and shell.el by Olin Shivers (shivers@cs.cmu.edu). 8/88
  21. ;;; Since these modes are built on top of the general command-interpreter-in-
  22. ;;; a-buffer mode (comint mode), they share a common base functionality, 
  23. ;;; and a common set of bindings, with all modes derived from comint mode.
  24.  
  25. ;;; Needs fixin:
  26. ;;; The load-file/compile-file default mechanism could be smarter -- it
  27. ;;; doesn't know about the relationship between filename extensions and
  28. ;;; whether the file is source or executable. If you compile foo.lisp
  29. ;;; with compile-file, then the next load-file should use foo.bin for
  30. ;;; the default, not foo.lisp. This is tricky to do right, particularly
  31. ;;; because the extension for executable files varies so much (.o, .bin,
  32. ;;; .lbin, .mo, .vo, .ao, ...).
  33. ;;;
  34. ;;; It would be nice if lisp (and inferior scheme, T, ...) modes
  35. ;;; had a verbose minor mode wherein sending or compiling defuns, etc.
  36. ;;; would be reflected in the transcript with suitable comments, e.g.
  37. ;;; ";;; redefining fact". Several ways to do this. Which is right?
  38. ;;;
  39. ;;; When sending text from a source file to a subprocess, the process-mark can 
  40. ;;; move off the window, so you can lose sight of the process interactions.
  41. ;;; Maybe I should ensure the process mark is in the window when I send
  42. ;;; text to the process? Switch selectable?
  43.  
  44. (require 'comint)
  45. (provide 'inf-lisp)
  46.  
  47. (defvar lisp-filter-regexp "\\`\\s *\\(:\\(\\w\\|\\s_\\)\\)?\\s *\\'"
  48.   "*What not to save on inferior Lisp's input history
  49. Input matching this regexp is not saved on the input history in lisp
  50. mode. Default is whitespace followed by 0 or 1 single-letter :keyword 
  51. (as in :a, :c, etc.)")
  52.  
  53. ;;; These commands augment lisp mode, so you can process lisp code in
  54. ;;; the source files.
  55. (define-key lisp-mode-map "\C-c\C-f" 'lisp-load-file)
  56. (define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file)
  57. (define-key lisp-mode-map "\M-\C-x"  'lisp-eval-defun) ; Gnu convention
  58. (define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-region)
  59. (define-key lisp-mode-map "\C-c\C-x" 'lisp-compile-defun)
  60. (define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-region)
  61.  
  62. (defvar inferior-lisp-mode-map nil)
  63. (if inferior-lisp-mode-map ()
  64.   (setq inferior-lisp-mode-map (copy-keymap shared-lisp-mode-map))
  65.   (set-keymap-parent inferior-lisp-mode-map comint-mode-map)
  66.   (define-key inferior-lisp-mode-map "\e\C-x" 'lisp-send-defun))
  67.  
  68. (defvar inferior-lisp-program "lisp"
  69.   "*Program name for invoking an inferior Lisp with `lisp'.
  70. Optionally, a list of strings the car of which is the programme to run
  71. and the cdr of which is command line arguments desired.")
  72.  
  73. (defvar inferior-lisp-load-command "(load \"%s\")\n"
  74.   "*Format-string for building a Lisp expression to load a file.
  75. This format string should use %s to substitute a file name
  76. and should result in a Lisp expression that will command the inferior Lisp
  77. to load that file.  The default works acceptably on most Lisps.
  78. The string \"(progn (load \\\"%s\\\" :verbose nil :print t) (values))\\\n\"
  79. produces cosmetically superior output for this application,
  80. but it works only in Common Lisp.")
  81.  
  82. (defvar inferior-lisp-prompt "^[^> ]*>+:? *"
  83.   "Regexp to recognise prompts in the inferior Lisp.
  84. Defaults to \"^[^> ]*>+:? *\", which works pretty good for Lucid, kcl,
  85. and franz. This variable is used to initialise comint-prompt-regexp in the 
  86. lisp buffer.
  87.  
  88. More precise choices:
  89. Lucid Common Lisp: \"^\\(>\\|\\(->\\)+\\) *\"
  90. franz: \"^\\(->\\|<[0-9]*>:\\) *\"
  91. kcl: \"^>+ *\"")
  92.  
  93. (defvar inferior-lisp-mode-hook '() "*Hook for customising lisp mode")
  94.  
  95. (defun inferior-lisp-mode () 
  96.   "Major mode for interacting with an inferior Lisp process.  
  97. Runs a Lisp interpreter as a subprocess of Emacs, with Lisp I/O through an
  98. Emacs buffer.  Variable inferior-lisp-program controls which Lisp interpreter
  99. is run.  Variables inferior-lisp-prompt, lisp-filter-regexp and
  100. inferior-lisp-load-command can customize this mode for different Lisp
  101. interpreters.
  102.  
  103. \\{inferior-lisp-mode-map}
  104.  
  105. Customization: Entry to this mode runs comint-mode-hook and lisp-mode-hook,
  106. in that order.
  107.  
  108. You can send text to the inferior Lisp process from other buffers containing
  109. Lisp source.  
  110.     lisp-eval-defun sends the current defun to the Lisp process.
  111.     lisp-compile-defun compiles the current defun.
  112.     lisp-eval-region sends the current region to the Lisp process.
  113.     lisp-compile-region compiles the current region.
  114.  
  115. Commands:
  116. Return after the end of the process' output sends the text from the 
  117.     end of process to point.
  118. Return before the end of the process' output copies the sexp ending at point
  119.     to the end of the process' output, and sends it.
  120. Delete converts tabs to spaces as it moves back.
  121. Tab indents for Lisp; with argument, shifts rest
  122.     of expression rigidly with the current line.
  123. C-M-q does Tab on each line starting within following expression.
  124. Paragraphs are separated only by blank lines.  Semicolons start comments.
  125. If you accidentally suspend your process, use \\[comint-continue-subjob]
  126. to continue it."
  127.   (interactive)
  128.   (comint-mode)
  129.   (use-local-map inferior-lisp-mode-map)
  130.   (setq major-mode 'inferior-lisp-mode
  131.     mode-name "Inferior Lisp"
  132.     comint-prompt-regexp inferior-lisp-prompt
  133.     comint-get-old-input (function inferior-lisp-get-old-input)
  134.     comint-input-filter (function inferior-lisp-input-filter)
  135.     comint-input-sentinel 'ignore)
  136.   (lisp-mode-variables t)
  137.   (run-hooks 'inferior-lisp-mode-hook))
  138.  
  139. (defun inferior-lisp-get-old-input ()
  140.   "Snarf the sexp ending at point"
  141.   (save-excursion
  142.     (let ((end (point)))
  143.       (backward-sexp)
  144.       (buffer-substring (point) end))))
  145.  
  146. (defun inferior-lisp-input-filter (str)
  147.   "Don't save anything matching lisp-filter-regexp"
  148.   (not (string-match lisp-filter-regexp str)))
  149.  
  150. (defun run-lisp ()
  151.   "Run an inferior Lisp process, input and output via buffer *lisp*.
  152. If there is a process already running in *lisp*, just switch to that buffer.
  153. Takes the program name from the variable inferior-lisp-program.
  154. \(Type \\[describe-mode] in the process buffer for a list of commands.)"
  155.   (interactive)
  156.   (let ((prog inferior-lisp-program) switches
  157.     (proc (get-buffer-process "*lisp*")))
  158.     (if (listp prog) (setq switches (cdr prog) prog (car prog)))
  159.     (cond ((not (and proc (memq (process-status proc) '(run stop))))
  160.        (set-buffer (apply 'make-comint "lisp" prog nil switches))
  161.        (inferior-lisp-mode))))
  162.   (switch-to-buffer "*lisp*"))
  163.  
  164. (defun lisp-eval-region (start end)
  165.   "Send the current region to the inferior Lisp process."
  166.   (interactive "r")
  167.   ;; i don't like the way all this code depends on the buffer name
  168.   (let* ((proc (get-buffer-process "*lisp*"))
  169.      (filename (format "/tmp/eme%d.lisp" (process-id proc))))
  170.     (if (not (and proc (memq (process-status proc) '(run stop))))
  171.     (error "No current lisp process")
  172.       (write-region start end filename nil 'nomessage)
  173.       (send-string proc (format inferior-lisp-load-command filename))
  174.       (send-string proc (format "(delete-file %s)\n" filename)))))
  175.  
  176. (defun lisp-eval-defun ()
  177.   "Send the current defun to the inferior Lisp process."
  178.   (interactive)
  179.   (save-excursion
  180.    (end-of-defun)
  181.    (let ((end (point)))
  182.      (beginning-of-defun)
  183.      (lisp-eval-region (point) end))))
  184.  
  185. ;;; CommonLisp COMPILE sux. 
  186. (defun lisp-compile-region (start end)
  187.   "Compile the current region in the inferior Lisp process."
  188.   ;; deja vu.  code look familiar?
  189.   (interactive "r")
  190.   (let* ((proc (get-buffer-process "*lisp*"))
  191.      (filename (format "/tmp/emc%d.lisp" (process-id proc))))
  192.     (if (not (and proc (memq (process-status proc) '(run stop))))
  193.     (error "No current lisp process")
  194.       (write-region
  195.        (concat "(funcall (compile nil `(lambda () (progn 'compile "
  196.            (buffer-substring start end)
  197.            "))))\n")
  198.        nil filename nil 'nomessage)
  199.       (send-string proc (format inferior-lisp-load-command filename))
  200.       (send-string proc (format "(delete-file %s)\n" filename)))))
  201.              
  202. (defun lisp-compile-defun ()
  203.   "Compile the current defun in the inferior Lisp process."
  204.   (interactive)
  205.   (save-excursion
  206.     (end-of-defun)
  207.     (let ((e (point)))
  208.       (beginning-of-defun)
  209.       (lisp-compile-region (point) e))))
  210.  
  211. (defvar lisp-prev-l/c-dir/file nil
  212.   "Saves the (directory . file) pair used in the last lisp-load-file or
  213. lisp-compile-file command. Used for determining the default in the 
  214. next one.")
  215.  
  216. (defvar lisp-source-modes '(lisp-mode)
  217.   "*Used to determine if a buffer contains Lisp source code.
  218. If it's loaded into a buffer that is in one of these major modes, it's
  219. considered a lisp source file by lisp-load-file and lisp-compile-file.
  220. Used by these commands to determine defaults.")
  221.  
  222. (defun lisp-load-file (file-name)
  223.   "Load a lisp file into the inferior Lisp process."
  224.   (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file
  225.                   lisp-source-modes nil))
  226.   (comint-check-source file-name) ; Check to see if buffer needs saved.
  227.   (setq lisp-prev-l/c-dir/file (cons (file-name-directory    file-name)
  228.                      (file-name-nondirectory file-name)))
  229.   (send-string "lisp" (format inferior-lisp-load-command file-name)))
  230.  
  231. (defun lisp-compile-file (file-name)
  232.   "Compile a Lisp file in the inferior Lisp process."
  233.   (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file
  234.                   lisp-source-modes nil)) ; NIL = don't need
  235.                                                           ; suffix .lisp
  236.   (comint-check-source file-name) ; Check to see if buffer needs saved.
  237.   (setq lisp-prev-l/c-dir/file (cons (file-name-directory    file-name)
  238.                      (file-name-nondirectory file-name)))
  239.   (send-string "lisp" (concat "(compile-file \"" file-name "\"\)\n")))
  240.