lisp-interface.sl 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % LISP-Interface.SL - NMODE Lisp Text Execution Interface
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 23 August 1982
  8. % Revised: 14 February 1983
  9. %
  10. % Adapted from Will Galway's EMODE
  11. %
  12. % 14-Feb-83 Alan Snyder
  13. % Added statement to flush output buffer cache.
  14. % 2-Feb-83 Alan Snyder
  15. % Added Execute-Defun-Command. Change to supply the free EOL at the end of
  16. % the input buffer whenever the buffer-modified flag is set, instead of only
  17. % when currently at the end of the buffer.
  18. % 25-Jan-83 Alan Snyder
  19. % Check terminal type after resuming.
  20. %
  21. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  22. (CompileTime (load objects))
  23. (fluid '(nmode-current-buffer
  24. nmode-output-buffer
  25. nmode-terminal
  26. nmode-initialized
  27. *NMODE-RUNNING
  28. *GC
  29. LispBanner*
  30. *RAWIO
  31. *nmode-init-running
  32. *nmode-init-has-run
  33. nmode-terminal-input-buffer
  34. nmode-default-init-file-name
  35. nmode-auto-start
  36. nmode-first-start
  37. ))
  38. (setf *NMODE-RUNNING NIL)
  39. (setf *nmode-init-running NIL)
  40. (setf *nmode-init-has-run NIL)
  41. (setf nmode-default-init-file-name "PSL:NMODE.INIT")
  42. (setf nmode-auto-start NIL)
  43. (setf nmode-first-start T)
  44. (fluid '(
  45. nmode-buffer-channel % Channel used for NMODE I/O.
  46. nmode-output-start-position % Where most recent "output" started in buffer.
  47. nmode-output-end-position % Where most recent "output" ended in buffer.
  48. OldStdIn
  49. OldStdOut
  50. OldErrOut
  51. ))
  52. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  53. (de yank-last-output-command ()
  54. % Insert "last output" typed in the OUTPUT buffer. Output is demarked by
  55. % NMODE-OUTPUT-START-POSITION and NMODE-OUTPUT-END-POSITION.
  56. (if (not nmode-output-start-position)
  57. (Ding)
  58. % Otherwise
  59. (let ((text (=> nmode-output-buffer
  60. extract-region
  61. NIL
  62. nmode-output-start-position
  63. (or nmode-output-end-position
  64. (buffer-position-create (=> nmode-output-buffer size) 0)
  65. )
  66. )))
  67. (=> nmode-current-buffer insert-text (cdr text))
  68. )))
  69. (de execute-form-command ()
  70. % Execute starting at the beginning of the current line.
  71. (set-mark-from-point) % in case the user wants to come back
  72. (move-to-start-of-line)
  73. (execute-from-buffer)
  74. )
  75. (de execute-defun-command ()
  76. % Execute starting at the beginning of the current defun (if the current
  77. % position is within a defun) or from the current position (otherwise).
  78. (set-mark-from-point) % in case the user wants to come back
  79. (move-to-start-of-current-defun)
  80. (execute-from-buffer)
  81. )
  82. (de make-buffer-terminated ()
  83. % If the current buffer ends with an "unterminated" line, add an EOL to
  84. % terminate it.
  85. (let ((old-pos (buffer-get-position)))
  86. (move-to-buffer-end)
  87. (when (not (current-line-empty?)) (insert-eol))
  88. (buffer-set-position old-pos)
  89. ))
  90. (de execute-from-buffer ()
  91. % Causes NMODE to return to the procedure that called it (via
  92. % nmode-channel-editor) with input redirected to come from the (now) current
  93. % buffer. We arrange for output to go to the end of the output buffer.
  94. (if (=> nmode-current-buffer modified?) (make-buffer-terminated))
  95. (buffer-channel-set-input-buffer nmode-buffer-channel nmode-current-buffer)
  96. % Output will go to end of the output buffer. Supply a free EOL if the last
  97. % line is unterminated. Record the current end-of-buffer for later use by
  98. % Lisp-Y.
  99. (let ((old-pos (=> nmode-output-buffer position)))
  100. (=> nmode-output-buffer move-to-buffer-end)
  101. (if (not (=> nmode-output-buffer current-line-empty?))
  102. (=> nmode-output-buffer insert-eol))
  103. (setf nmode-output-start-position (=> nmode-output-buffer position))
  104. (=> nmode-output-buffer set-position old-pos)
  105. )
  106. % Set things up to read from and write to NMODE buffers.
  107. (nmode-select-buffer-channel)
  108. (exit-nmode-reader)
  109. )
  110. (de nmode-exit-to-superior ()
  111. (if (not *NMODE-RUNNING)
  112. (original-quit)
  113. % else
  114. (leave-raw-mode) % Turn echoing back on. Next refresh is FULL.
  115. (original-quit)
  116. (enter-raw-mode) % Turn echoing off.
  117. (nmode-set-terminal) % Ensure proper terminal driver is loaded.
  118. ))
  119. % Redefine QUIT so that it restores the terminal to echoing before exiting.
  120. (when (FUnboundP 'original!-quit)
  121. (CopyD 'original!-quit 'quit)
  122. (CopyD 'quit 'nmode-exit-to-superior)
  123. )
  124. (de emode () (nmode)) % for user convenience
  125. (de nmode ()
  126. % Rebind the PSL input channel to the NMODE buffer channel and return. This
  127. % will cause the next READ to invoke Nmode-Channel-Editor and start running
  128. % NMODE. Use the function "exit-nmode" to switch back to original channels.
  129. (nmode-initialize) % does nothing if already initialized
  130. (when (neq STDIN* nmode-buffer-channel)
  131. (setf OldStdIn STDIN*)
  132. (setf OldStdOut STDOUT*)
  133. (setf OldErrOut ErrOut*)
  134. )
  135. (nmode-select-buffer-input-channel)
  136. )
  137. (de nmode-run-init-file ()
  138. (setf *nmode-init-has-run T)
  139. (let ((fn (namestring (init-file-pathname "NMODE"))))
  140. (cond ((FileP fn)
  141. (nmode-execute-init-file fn))
  142. ((FileP (setf fn nmode-default-init-file-name))
  143. (nmode-execute-init-file fn))
  144. )))
  145. (de nmode-execute-init-file (fn)
  146. (let ((*nmode-init-running T))
  147. (nmode-read-and-evaluate-file fn)
  148. ))
  149. (de nmode-read-and-evaluate-file (fn)
  150. (let ((chn (open fn 'INPUT))
  151. exp
  152. )
  153. (while (not (eq (setf exp (ChannelRead chn)) $Eof$))
  154. (eval exp)
  155. )
  156. (close chn)
  157. )
  158. )
  159. (de exit-nmode ()
  160. % Leave NMODE, return to normal listen loop.
  161. (nmode-select-old-channels)
  162. (=> nmode-terminal move-cursor (=> nmode-terminal maxrow) 0)
  163. (leave-raw-mode)
  164. (setf *NMODE-RUNNING NIL)
  165. (setf *GC T)
  166. (exit-nmode-reader) % Set flag to cause NMODE to exit.
  167. )
  168. % The following function is not currently used.
  169. (de nmode-invoke-lisp-listener ()
  170. % Invoke a normal listen loop.
  171. (let* ((*NMODE-RUNNING NIL)
  172. (OldIN* IN*)
  173. (OldOUT* OUT*)
  174. (ERROUT* 1)
  175. (StdIn* 0)
  176. (StdOut* 1)
  177. (old-raw-mode (=> nmode-terminal raw-mode))
  178. )
  179. (leave-raw-mode)
  180. (RDS 0)
  181. (WRS 1)
  182. (unwind-protect
  183. (TopLoop 'Read 'Print 'Eval "Lisp" "Return to NMODE with ^Z")
  184. (RDS OldIN*)
  185. (WRS OldOUT*)
  186. (if old-raw-mode (enter-raw-mode))
  187. )))
  188. % (de emode () (throw '$read$ $eof$)) % use with above function
  189. % (de nmode () (throw '$read$ $eof$)) % use with above function
  190. (de nmode-select-old-channels ()
  191. % Select channels that were in effect when "Lisp Interface" was started up.
  192. % (But don't turn echoing on.) NOTE that the "old channels" are normally
  193. % selected while NMODE is actually running (this is somewhat counter
  194. % intuitive). This is so that any error messages created by bugs in NMODE
  195. % will not be printed into NMODE buffers. (If they were, it might break
  196. % things recursively!)
  197. (setf STDIN* OldStdIn)
  198. (setf STDOUT* OldStdOut)
  199. (setf ErrOut* OldErrOut)
  200. (RDS STDIN*) % Select the channels.
  201. (WRS STDOUT*)
  202. )
  203. (de nmode-select-buffer-channel ()
  204. % Select channels that read from and write to NMODE buffers.
  205. (nmode-select-buffer-input-channel)
  206. (setf STDOUT* nmode-buffer-channel)
  207. (setf ErrOut* nmode-buffer-channel)
  208. (WRS STDOUT*)
  209. )
  210. (de nmode-select-buffer-input-channel ()
  211. % Select channel that reads from NMODE buffer. "NMODE-Channel-Editor" is
  212. % called when read routines invoke the "editor routine" for the newly selected
  213. % channel.
  214. (if (null nmode-buffer-channel)
  215. (setf nmode-buffer-channel
  216. (OpenBufferChannel NIL nmode-output-buffer 'nmode-channel-editor)))
  217. (setf STDIN* nmode-buffer-channel)
  218. (RDS STDIN*)
  219. )
  220. (de nmode-channel-editor (chn)
  221. % This procedure is called every time that input is requested from an NMODE
  222. % buffer. It starts up NMODE (if not already running) and resumes NMODE
  223. % execution. When the user has decided on what input to give to the channel
  224. % (by performing Lisp-E), the NMODE-reader will return with I/O bound to the
  225. % "buffer channel". The reader will also return if the user performs Lisp-L,
  226. % in which case I/O will remain bound to the "standard" channels.
  227. % Select "old" channels, so if an error occurs we don't get a bad recursive
  228. % situation where printing into a buffer causes more trouble!
  229. (nmode-select-old-channels)
  230. (cond ((not *NMODE-RUNNING)
  231. (setf *NMODE-RUNNING T)
  232. (setf *GC NIL)
  233. (if (not *nmode-init-has-run)
  234. (nmode-run-init-file)
  235. )
  236. )
  237. (t
  238. (buffer-channel-flush nmode-buffer-channel)
  239. (setf nmode-output-end-position (=> nmode-output-buffer position))
  240. % compensate for moving to line start on next Lisp-E:
  241. (if (not (at-line-start?))
  242. (move-to-next-line))
  243. )
  244. )
  245. (enter-raw-mode)
  246. (nmode-select-major-window) % just in case
  247. (NMODE-reader NIL) % NIL => don't exit when a command aborts
  248. )
  249. (de nmode-main ()
  250. (setf CurrentReadMacroIndicator* 'LispReadMacro) % Crock!
  251. (setf CurrentScanTable* LispScanTable*)
  252. (when (not toploopread*)
  253. (setf toploopread* 'read)
  254. (setf toploopprint* 'print)
  255. (setf toploopeval* 'eval)
  256. (setf toploopname* "NMODE Lisp")
  257. )
  258. (nmode-initialize) % does nothing if already initialized
  259. (nmode-set-terminal) % ensure proper terminal driver is loaded
  260. % Note: RESET may cause echoing to be turned on without clearing *RawIO.
  261. (when *RawIO
  262. (setf *RawIO NIL)
  263. (EchoOff)
  264. )
  265. (when nmode-first-start
  266. (setf nmode-first-start NIL) % never again
  267. (cond (nmode-auto-start
  268. (setf *NMODE-RUNNING T) % see below
  269. (let ((was-modified? (=> nmode-output-buffer modified?)))
  270. (=> nmode-output-buffer insert-line LispBanner*)
  271. (if (not was-modified?)
  272. (=> nmode-output-buffer set-modified? NIL)
  273. )))
  274. (t
  275. (printf "%w%n" LispBanner*)
  276. ))
  277. )
  278. (while T
  279. (setf nmode-terminal-input-buffer NIL) % flush execution from buffers
  280. (cond (*NMODE-RUNNING
  281. (setf *NMODE-RUNNING NIL) % force full start-up
  282. (nmode) % cause next READ to start up NMODE
  283. )
  284. (t
  285. (RDS 0)
  286. (WRS 1)
  287. ))
  288. (nmode-top-loop)
  289. ))
  290. (copyd 'main 'nmode-main)
  291. (de nmode-top-loop ()
  292. (TopLoop toploopread* toploopprint* toploopeval* toploopname* "")
  293. (Printf "End of File read!")
  294. )