PageRenderTime 23ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/old-archive/modes/cmushell/tea.el

https://github.com/emacsmirror/ohio-archive
Emacs Lisp | 483 lines | 322 code | 61 blank | 100 comment | 23 complexity | c7ae5c8b5774741be853c8f824a7e97a MD5 | raw file
  1. ;;; tea.el -- Teach emacs about T.
  2. ;;; Copyright Olin Shivers (1988)
  3. ;;; Please imagine a long, tedious, legalistic 5-page gnu-style copyright
  4. ;;; notice appearing here to the effect that you may use this code any
  5. ;;; way you like, as long as you don't charge money for it, remove this
  6. ;;; notice, or hold me liable for its results.
  7. ;;;
  8. ;;; 1. Major mode for editing T source: t-mode
  9. ;;; This is just a variant of scheme-mode, tweaked for T.
  10. ;;; 2. Major mode for running T in a buffer: run-tea
  11. ;;; This is a customisation of comint-mode.
  12. ;;;
  13. ;;; Written by Olin Shivers (olin.shivers@cs.cmu.edu). With bits and pieces
  14. ;;; lifted from scheme.el, shell.el, clisp.el, newclisp.el, cobol.el, et al..
  15. ;;; 8/88
  16. ;;; Please send me bug reports, bug fixes, and extensions, so that I can
  17. ;;; merge them into the master source.
  18. ;;;
  19. ;;; Change log at end of file.
  20. ;; YOUR .EMACS FILE
  21. ;;=============================================================================
  22. ;; Some suggestions for your .emacs file.
  23. ;;
  24. ;; ; If tea.el lives in some non-standard directory, you must tell emacs
  25. ;; ; where to get it. This may or may not be necessary.
  26. ;; (setq load-path (cons (expand-file-name "~jones/lib/emacs") load-path))
  27. ;;
  28. ;; ; Autoload run-tea and t-mode from file tea.el
  29. ;; (autoload 'run-tea "tea"
  30. ;; "Run an inferior T process."
  31. ;; t)
  32. ;;
  33. ;; (autoload 't-mode "tea"
  34. ;; "Major mode for editing T source. Just Scheme mode, tuned a bit."
  35. ;; t)
  36. ;;
  37. ;; ; Files ending in ".t" are T source, so put their buffers in t-mode.
  38. ;; (setq auto-mode-alist
  39. ;; (cons '("\\.t$" . t-mode)
  40. ;; auto-mode-alist))
  41. ;;
  42. ;; ; Define C-c C-t to run my favorite command in inferior T mode:
  43. ;; (setq tea-load-hook
  44. ;; '((lambda () (define-key inferior-t-mode-map "\C-c\C-t"
  45. ;; 'favorite-cmd))))
  46. ;; ETAGS
  47. ;;=============================================================================
  48. ;; A suggestion for modifying the etags program so that it knows about T.
  49. ;; You should modify the few lines that allow etags to conclude that
  50. ;; files that end with ".t" are lisp or scheme source code.
  51. ;; Find a line that looks like
  52. ;; /* .scm or .sm or .scheme implies scheme source code */
  53. ;; and add a
  54. ;; !strcmp (cp + 1, "t") ||
  55. ;; suffix check to the following clauses that check filename suffixes.
  56. ;; This is already done for some versions of etags. Have a look, or try it
  57. ;; & see.
  58. (setq scheme-mit-dialect nil) ; Give me a break.
  59. (require 'scheme)
  60. (require 'cmushell)
  61. ;;; T mode stuff
  62. ;;;============================================================================
  63. ;;; Note: T mode alters the scheme-mode syntax table and indentation
  64. ;;; hooks slightly. If you were using scheme-mode and t-mode simultaneously
  65. ;;; this might be a problem, except that the alterations are fairly
  66. ;;; innocuous.
  67. ;; This adds [] and {} as matching delimiters. So emacs will treat #[Char 0]
  68. ;; or #{Procedure 1 ADD} as an s-exp with a quote sign in front.
  69. (modify-syntax-entry ?[ "(]" scheme-mode-syntax-table)
  70. (modify-syntax-entry ?] ")[" scheme-mode-syntax-table)
  71. (modify-syntax-entry ?{ "(}" scheme-mode-syntax-table)
  72. (modify-syntax-entry ?} "){" scheme-mode-syntax-table)
  73. ;; Modify scheme-indent-hook for T.
  74. (put 'labels 'scheme-indent-hook 1)
  75. (put 'block 'scheme-indent-hook 0)
  76. (put 'block0 'scheme-indent-hook 0)
  77. (put 'object 'scheme-indent-hook 1)
  78. (put 'lset 'scheme-indent-hook 1)
  79. (put 'xcase 'scheme-indent-hook 1)
  80. (put 'select 'scheme-indent-hook 1)
  81. (put 'xselect 'scheme-indent-hook 1)
  82. (put 'iterate 'scheme-indent-hook 2)
  83. (put 'cond 'scheme-indent-hook 0)
  84. (put 'xcond 'scheme-indent-hook 0)
  85. (put 'catch 'scheme-indent-hook 1)
  86. (put 'bind 'scheme-indent-hook 1)
  87. (put 'define-operation 'scheme-indent-hook 1)
  88. (put 'operation 'scheme-indent-hook 1)
  89. (put 'object 'scheme-indent-hook 1)
  90. (put 'join 'scheme-indent-hook 0)
  91. (put 'destructure 'scheme-indent-hook 1)
  92. (put 'destructure* 'scheme-indent-hook 1)
  93. (put 'define-integrable 'scheme-indent-hook 1)
  94. (put 'define-constant 'scheme-indent-hook 1)
  95. (put 'define-syntax 'scheme-indent-hook 1)
  96. (put 'let-syntax 'scheme-indent-hook 1)
  97. (put 'define-local-syntax 'scheme-indent-hook 1)
  98. (put 'macro-expander 'scheme-indent-hook 1)
  99. (put 'with-open-streams 'scheme-indent-hook 1)
  100. (put 'with-open-ports 'scheme-indent-hook 1)
  101. (put 'with-input-from-string 'scheme-indent-hook 1)
  102. (put 'with-output-to-string 'scheme-indent-hook 1)
  103. (put 'with-output-width-string 'scheme-indent-hook 1)
  104. (put 'receive 'scheme-indent-hook 2)
  105. (put 'receive-values 'scheme-indent-hook 1)
  106. (defvar t-mode-hook nil
  107. "*Hook for customising T mode")
  108. (defvar t-mode-map (full-copy-sparse-keymap scheme-mode-map))
  109. (defun t-mode ()
  110. "Major mode for editing T code.
  111. This is Scheme mode, slightly tuned for T. Editing commands are similar
  112. to those of Lisp mode.
  113. In addition, if an inferior T process is running, some additional
  114. commands will be defined, for evaluating expressions and controlling
  115. the interpreter, and the state of the process will be displayed in the
  116. modeline of all T buffers. The names of commands that interact
  117. with the T process start with \"tea-\". For more information
  118. see the documentation for inferior-t-mode.
  119. Commands:
  120. Delete converts tabs to spaces as it moves back.
  121. Blank lines separate paragraphs. Semicolons start comments.
  122. \\{t-mode-map}
  123. Customisation: Entry to this mode runs the hooks on t-mode-hook"
  124. (interactive)
  125. (kill-all-local-variables)
  126. (use-local-map t-mode-map)
  127. (scheme-mode-variables)
  128. (setq major-mode 't-mode)
  129. (setq mode-name "T")
  130. (run-hooks 't-mode-hook))
  131. ;;; INFERIOR T MODE STUFF
  132. ;;;============================================================================
  133. (defvar inferior-t-mode-map nil)
  134. (cond ((not inferior-t-mode-map)
  135. (setq inferior-t-mode-map (full-copy-sparse-keymap comint-mode-map))
  136. (scheme-mode-commands inferior-t-mode-map)
  137. (define-key inferior-t-mode-map "\M-\C-x" 'tea-send-definition)
  138. (define-key inferior-t-mode-map "\C-x\C-e" 'tea-send-last-sexp)
  139. (define-key inferior-t-mode-map "\C-cl" 'tea-load-file)
  140. (define-key inferior-t-mode-map "\C-ck" 'tea-compile-file) ;"kompile"
  141. ))
  142. ;; Install the process communication commands in the scheme-mode keymap.
  143. (define-key t-mode-map "\M-\C-x" 'tea-send-definition) ; gnu convention
  144. (define-key t-mode-map "\C-x\C-e" 'tea-send-last-sexp) ; gnu convention
  145. (define-key t-mode-map "\C-ce" 'tea-send-definition)
  146. (define-key t-mode-map "\C-c\C-e" 'tea-send-definition-and-go)
  147. (define-key t-mode-map "\C-cr" 'tea-send-region)
  148. (define-key t-mode-map "\C-c\C-r" 'tea-send-region-and-go)
  149. (define-key t-mode-map "\C-cc" 'tea-compile-definition)
  150. (define-key t-mode-map "\C-c\C-c" 'tea-compile-definition-and-go)
  151. (define-key t-mode-map "\C-cz" 'switch-to-tea)
  152. (define-key t-mode-map "\C-cl" 'tea-load-file)
  153. (define-key t-mode-map "\C-ck" 'tea-compile-file)
  154. (defvar inferior-t-mode-hook nil
  155. "*Hook for customising inferior-T mode")
  156. (defun inferior-t-mode ()
  157. "Major mode for interacting with an inferior T process.
  158. The following commands are available:
  159. \\{inferior-t-mode-map}
  160. A T process can be fired up with M-x run-tea.
  161. Customisation: Entry to this mode runs the hooks on comint-mode-hook and
  162. inferior-t-mode-hook (in that order).
  163. You can send text to the inferior T process from other buffers containing
  164. T source.
  165. switch-to-tea switches the current buffer to the T process buffer.
  166. tea-send-definition sends the current definition to the T process.
  167. tea-compile-definition compiles the current definition.
  168. tea-send-region sends the current region to the T process.
  169. tea-compile-region compiles the current region.
  170. tea-send-definition-and-go, tea-compile-definition-and-go,
  171. tea-send-region-and-go, and tea-compile-region-and-go
  172. switch to the T process buffer after sending their text.
  173. For information on running multiple processes in multiple buffers, see
  174. documentation for variable tea-buffer.
  175. Commands:
  176. Return after the end of the process' output sends the text from the
  177. end of process to point.
  178. Return before the end of the process' output copies the sexp ending at point
  179. to the end of the process' output, and sends it.
  180. Delete converts tabs to spaces as it moves back.
  181. Tab indents for T; with argument, shifts rest
  182. of expression rigidly with the current line.
  183. C-M-q does Tab on each line starting within following expression.
  184. Paragraphs are separated only by blank lines. Semicolons start comments.
  185. If you accidentally suspend your process, use \\[comint-continue-subjob]
  186. to continue it."
  187. (interactive)
  188. (comint-mode)
  189. (setq comint-prompt-regexp "^>+ *") ; Customise in inferior-t-mode-hook
  190. (scheme-mode-variables)
  191. (setq major-mode 'inferior-t-mode)
  192. (setq mode-name "Inferior T")
  193. (setq mode-line-process '(": %s"))
  194. (use-local-map inferior-t-mode-map)
  195. (setq comint-input-filter 'tea-input-filter)
  196. (setq comint-input-sentinel 'ignore)
  197. (setq comint-get-old-input 'tea-get-old-input)
  198. (run-hooks 'inferior-t-mode-hook))
  199. (defun tea-input-filter (str)
  200. "Don't save anything matching tea-filter-regexp"
  201. (not (string-match tea-filter-regexp str)))
  202. (defvar tea-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
  203. "*Input matching this regexp are not saved on the history list.
  204. Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
  205. (defun tea-get-old-input ()
  206. "Snarf the sexp ending at point"
  207. (save-excursion
  208. (let ((end (point)))
  209. (backward-sexp)
  210. (buffer-substring (point) end))))
  211. ;;; This will break if you have an argument with whitespace, as in
  212. ;;; string = "-ab +c -x 'you lose'".
  213. (defun tea-args-to-list (string)
  214. (let ((where (string-match "[ \t]" string)))
  215. (cond ((null where) (list string))
  216. ((not (= where 0))
  217. (cons (substring string 0 where)
  218. (tea-args-to-list (substring string (+ 1 where)
  219. (length string)))))
  220. (t (let ((pos (string-match "[^ \t]" string)))
  221. (if (null pos)
  222. nil
  223. (tea-args-to-list (substring string pos
  224. (length string)))))))))
  225. (defvar tea-program-name "t"
  226. "*Program invoked by the run-tea command")
  227. ;;; Obsolete
  228. (defun tea (&rest foo) (message "Use run-tea"))
  229. (defun run-tea (cmd)
  230. "Run an inferior T process, input and output via buffer *tea*.
  231. If there is a process already running in *tea*, just switch to that buffer.
  232. With argument, allows you to edit the command line (default is value
  233. of tea-program-name). Runs the hooks from inferior-t-mode-hook (after the
  234. comint-mode-hook is run).
  235. \(Type \\[describe-mode] in the process buffer for a list of commands.)"
  236. (interactive (list (if current-prefix-arg
  237. (read-string "Run T: " tea-program-name)
  238. tea-program-name)))
  239. (if (not (comint-check-proc "*tea*"))
  240. (let ((cmdlist (tea-args-to-list cmd)))
  241. (set-buffer (apply 'make-comint "tea" (car cmdlist)
  242. nil (cdr cmdlist)))
  243. (inferior-t-mode)))
  244. (setq tea-buffer "*tea*")
  245. (switch-to-buffer "*tea*"))
  246. (defun tea-send-region (start end)
  247. "Send the current region to the inferior T process"
  248. (interactive "r")
  249. (comint-send-region (tea-proc) start end)
  250. (comint-send-string (tea-proc) "\n"))
  251. (defun tea-send-definition ()
  252. "Send the current definition to the inferior T process."
  253. (interactive)
  254. (save-excursion
  255. (end-of-defun)
  256. (let ((end (point)))
  257. (beginning-of-defun)
  258. (tea-send-region (point) end))))
  259. (defun tea-send-last-sexp ()
  260. "Send the previous sexp to the inferior T process."
  261. (interactive)
  262. (tea-send-region (save-excursion (backward-sexp) (point)) (point)))
  263. (defun tea-compile-region (start end)
  264. "Compile the current region in the inferior T process.
  265. \(A BLOCK is wrapped around the region: (BLOCK <region>)"
  266. (interactive "r")
  267. (comint-send-string (tea-proc) "(orbit '(block ")
  268. (comint-send-region (tea-proc) start end)
  269. (comint-send-string (tea-proc) "))\n"))
  270. (defun tea-compile-definition ()
  271. "Compile the current definition in the inferior T process."
  272. (interactive)
  273. (save-excursion
  274. (end-of-defun)
  275. (let ((end (point)))
  276. (beginning-of-defun)
  277. (tea-compile-region (point) end))))
  278. (defun switch-to-tea (eob-p)
  279. "Switch to the T process buffer.
  280. With argument, positions cursor at end of buffer."
  281. (interactive "P")
  282. (if (get-buffer tea-buffer)
  283. (pop-to-buffer tea-buffer)
  284. (error "No current process buffer. See variable tea-buffer."))
  285. (cond (eob-p
  286. (push-mark)
  287. (goto-char (point-max)))))
  288. (defun tea-send-region-and-go (start end)
  289. "Send the current region to the inferior T process,
  290. and switch to the process buffer."
  291. (interactive "r")
  292. (tea-send-region start end)
  293. (switch-to-tea t))
  294. (defun tea-send-definition-and-go ()
  295. "Send the current definition to the inferior T process,
  296. and switch to the process buffer."
  297. (interactive)
  298. (tea-send-definition)
  299. (switch-to-tea t))
  300. (defun tea-compile-region-and-go (start end)
  301. "Compile the current region in the inferior T process,
  302. and switch to process buffer."
  303. (interactive "r")
  304. (tea-compile-region start end)
  305. (switch-to-tea t))
  306. (defun tea-compile-definition-and-go ()
  307. "Compile the current definition in the inferior T process,
  308. and switch to process buffer."
  309. (interactive)
  310. (tea-compile-definition)
  311. (switch-to-tea t))
  312. (defvar tea-source-modes '(t-mode)
  313. "*Used to determine if a buffer contains T source code.
  314. If it's loaded into a buffer that is in one of these major modes, it's
  315. considered a T source file by tea-load-file and tea-compile-file.
  316. Used by these commands to determine defaults.")
  317. (defvar tea-prev-l/c-dir/file nil
  318. "Caches the (directory . file) pair used in the last tea-load-file or
  319. tea-compile-file command. Used for determining the default in the next one.")
  320. (defun tea-load-file (file-name)
  321. "Load a T file into the inferior T process."
  322. (interactive (comint-get-source "Load T file: " tea-prev-l/c-dir/file
  323. tea-source-modes t)) ; T because LOAD needs
  324. ; an exact name.
  325. (comint-check-source file-name) ; Check to see if buffer needs saved.
  326. (setq tea-prev-l/c-dir/file (cons (file-name-directory file-name)
  327. (file-name-nondirectory file-name)))
  328. (comint-send-string (tea-proc) (concat "(load \""
  329. file-name
  330. "\"\)\n"))
  331. (switch-to-tea t))
  332. (defun tea-compile-file (file-name)
  333. "Compile a T file in the inferior T process."
  334. (interactive (comint-get-source "Compile T file: " tea-prev-l/c-dir/file
  335. tea-source-modes
  336. nil)) ; NIL because COMPILE doesn't
  337. ; need an exact name.
  338. (comint-check-source file-name) ; Check to see if buffer needs saved.
  339. (setq tea-prev-l/c-dir/file (cons (file-name-directory file-name)
  340. (file-name-nondirectory file-name)))
  341. (comint-send-string (tea-proc) (concat "(compile-file \""
  342. file-name
  343. "\"\)\n"))
  344. (switch-to-tea t))
  345. ;;; This helps when you run more than one T process at a time.
  346. ;;; If we're in some inferior T buffer, return its process,
  347. ;;; even if the buffer's been renamed. If we're elsewhere, assume
  348. ;;; the standard process named "tea".
  349. (defun tea-proc ()
  350. (let ((proc (get-buffer-process (current-buffer))))
  351. (if (and proc (eq major-mode 'inferior-t-mode)) proc
  352. (get-process "tea"))))
  353. (defvar tea-buffer nil "*The current T process buffer.
  354. MULTIPLE PROCESS SUPPORT
  355. ===========================================================================
  356. Tea.el supports, in a fairly simple fashion, running multiple T
  357. processes. To run multiple T processes, you start the first up with
  358. \\[run-tea]. It will be in a buffer named *tea*. Rename this buffer
  359. with \\[rename-buffer]. You may now start up a new process with another
  360. \\[run-tea]. It will be in a new buffer, named *tea*. You can
  361. switch between the different process buffers with \\[switch-to-buffer].
  362. Commands that send text from source buffers to T processes --
  363. like tea-send-definition or tea-compile-region -- have to choose a
  364. process to send to, when you have more than one T process around. This
  365. is determined by the global variable tea-buffer. Suppose you
  366. have three inferior T's running:
  367. Buffer Process
  368. foo tea
  369. bar tea<2>
  370. *tea* tea<3>
  371. If you do a \\[tea-send-definition-and-go] command on some T source code,
  372. what process do you send it to?
  373. - If you're in a process buffer (foo, bar, or *tea*),
  374. you send it to that process.
  375. - If you're in some other buffer (e.g., a source file), you
  376. send it to the process attached to buffer tea-buffer.
  377. This process selection is performed by function tea-proc.
  378. Whenever \\[run-tea] fires up a new process, it resets tea-buffer
  379. to be the new process's buffer. If you only run one process, this will
  380. do the right thing. If you run multiple processes, you can change
  381. tea-buffer to another process buffer with \\[set-variable].
  382. More sophisticated approaches are, of course, possible. If you find youself
  383. needing to switch back and forth between multiple processes frequently,
  384. you may wish to consider ilisp.el, a larger, more sophisticated package
  385. for running inferior Lisp and Scheme processes. The approach taken here is
  386. for a minimal, simple implementation. Feel free to extend it.")
  387. (defun tea-proc ()
  388. "Returns the current T process. See variable tea-buffer."
  389. (let ((proc (get-buffer-process (if (eq major-mode 'inferior-t-mode)
  390. (current-buffer)
  391. tea-buffer))))
  392. (or proc
  393. (error "No current process. See variable tea-buffer"))))
  394. ;;; Do the user's customisation...
  395. (defvar tea-load-hook nil
  396. "This hook is run when tea is loaded in.
  397. This is a good place to put keybindings.")
  398. (run-hooks 'tea-load-hook)
  399. ;;; CHANGE LOG
  400. ;;; ===========================================================================
  401. ;;; 8/88 Olin
  402. ;;; Created.
  403. ;;;
  404. ;;; 2/15/89 Olin
  405. ;;; Removed -emacs flag from process invocation. It's only useful for
  406. ;;; cscheme, and makes cscheme assume it's running under xscheme.el,
  407. ;;; which messes things up royally. A bug.
  408. ;;;
  409. ;;; 5/22/90 Olin
  410. ;;; Upgraded to use comint-send-string and comint-send-region.
  411. ;;; - run-tea now offers to let you edit the command line if
  412. ;;; you invoke it with a prefix-arg. M-x tea is redundant, and
  413. ;;; has been removed.
  414. ;;; - Explicit references to process "tea" have been replaced with
  415. ;;; (tea-proc). This allows better handling of multiple process bufs.
  416. ;;; - Added tea-send-last-sexp, bound to C-x C-e. A gnu convention.
  417. ;;; - Have not added process query facility a la cmulisp.el's lisp-show-arglist
  418. ;;; and friends, but interested hackers might find a useful application
  419. ;;; of this facility.