terminal-input.sl 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % Terminal-Input.SL - NMODE Terminal Input Routines
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 27 August 1982
  8. % Revised: 16 February 1983
  9. %
  10. % 16-Feb-83 Alan Snyder
  11. % Declare -> Declare-Flavor.
  12. % 26-Jan-83 Alan Snyder
  13. % Add ability to read from string.
  14. % 21-Dec-82 Alan Snyder
  15. % Efficiency improvement: Added declarations for text buffers.
  16. %
  17. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  18. (CompileTime (load objects fast-int fast-strings))
  19. (load wait)
  20. % External variables used:
  21. (fluid '(nmode-terminal
  22. nmode-allow-refresh-breakout
  23. ))
  24. % Internal static variables (don't use elsewhere!):
  25. (fluid
  26. '(nmode-prompt-string % current prompt for character input
  27. nmode-prompt-immediately % true => show prompt immediately
  28. nmode-terminal-script-buffer % if non-NIL, is a buffer to script to
  29. nmode-terminal-input-buffer % if non-NIL, is a buffer to read from
  30. nmode-terminal-input-string % if non-NIL, is a string to read from
  31. nmode-terminal-input-string-pos % index of next character in string
  32. ))
  33. (setf nmode-prompt-string "")
  34. (setf nmode-prompt-immediately NIL)
  35. (setf nmode-terminal-script-buffer NIL)
  36. (setf nmode-terminal-input-buffer NIL)
  37. (setf nmode-terminal-input-string NIL)
  38. (declare-flavor text-buffer
  39. nmode-terminal-input-buffer
  40. nmode-terminal-script-buffer)
  41. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42. % Functions:
  43. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  44. % A primary goal of this module is to support delayed prompting. Prompting can
  45. % mean both echoing (some kind of confirmation) of the previous input and
  46. % information relating to expected input. The basic idea behind delayed
  47. % prompting is that as long as the user is rapidly typing input characters,
  48. % there is no need for the system to display any prompts, since the user
  49. % probably knows what he is doing. However, should the user ever pause for a
  50. % "sufficiently long" time, then the current prompt should be displayed to
  51. % inform the user of the current state.
  52. % An important notion is that some command interactions form a logical sequence.
  53. % In the case of a logical sequence of prompted inputs, each additional prompt
  54. % string should be appended to the existing prompt string, without first erasing
  55. % the prompt line. Furthermore, once the prompt line for this sequence is
  56. % displayed, any further prompts within the same sequence should be output
  57. % immediately. A command sequence is started using the function
  58. % NMODE-SET-DELAYED-PROMPT. Additional prompting within the same sequence is
  59. % specified using either NMODE-APPEND-DELAYED-PROMPT or
  60. % NMODE-APPEND-SEPARATED-PROMPT.
  61. (de nmode-set-immediate-prompt (prompt-string)
  62. % This function is used to specify the beginning of a command sequence. It
  63. % causes the existing prompt string to be discarded and replaced by the
  64. % specified string. The specified string may be empty to indicate that the
  65. % new command sequence has no initial prompt. The prompt string will be
  66. % output immediately upon the next request for terminal input.
  67. (setf nmode-prompt-string prompt-string)
  68. (setf nmode-prompt-immediately T)
  69. )
  70. (de nmode-set-delayed-prompt (prompt-string)
  71. % This function is used to specify the beginning of a command sequence. It
  72. % causes the existing prompt string to be discarded and replaced by the
  73. % specified string. The specified string may be empty to indicate that the
  74. % new command sequence has no initial prompt. The prompt string will be
  75. % output when terminal input is next requested, provided that the user has
  76. % paused.
  77. (setf nmode-prompt-string prompt-string)
  78. (setf nmode-prompt-immediately NIL)
  79. )
  80. (de nmode-append-delayed-prompt (prompt-string)
  81. % This function is used to specify an additional prompt for the current
  82. % command sequence. The prompt string will be appended to the existing prompt
  83. % string. The prompt string will be output when terminal input is next
  84. % requested, provided that the user has paused within the current command
  85. % sequence. If the prompt string is currently empty, then the user must pause
  86. % at some future input request to cause the prompt to be displayed.
  87. (setf nmode-prompt-string (string-concat nmode-prompt-string prompt-string))
  88. )
  89. (de nmode-append-separated-prompt (prompt-string)
  90. % This function is the same as NMODE-APPEND-DELAYED-PROMPT, except that if the
  91. % existing prompt string is non-null, an extra space is appended before the
  92. % new prompt-string is appended.
  93. (nmode-append-delayed-prompt
  94. (if (not (string-empty? nmode-prompt-string))
  95. (string-concat " " prompt-string)
  96. prompt-string
  97. )))
  98. (de nmode-complete-prompt (prompt-string)
  99. % This function is used to specify an additional prompt for the current
  100. % command sequence. The prompt string will be appended to the existing prompt
  101. % string. The prompt string will be output immediately, if the current prompt
  102. % has already been output. This function is to be used for "completion" or
  103. % "echoing" of previously read input.
  104. (setf nmode-prompt-string (string-concat nmode-prompt-string prompt-string))
  105. (if nmode-prompt-immediately (write-prompt nmode-prompt-string))
  106. )
  107. (de input-available? ()
  108. % Return Non-NIL if and only if new terminal input is available. Note: this
  109. % function might be somewhat expensive.
  110. (or (and nmode-terminal-input-buffer
  111. (not (=> nmode-terminal-input-buffer at-buffer-end?)))
  112. nmode-terminal-input-string
  113. (~= (CharsInInputBuffer) 0)))
  114. (de input-direct-terminal-character ()
  115. % Prompt for (but do not echo) a single character from the terminal. The
  116. % above functions are used to specify the prompt string. Avoid displaying the
  117. % prompt string if the user has already typed a character or types a character
  118. % right away. Within a sequence of related prompts, once a non-empty prompt
  119. % is output, further prompting is done immediately.
  120. (cond
  121. (nmode-terminal-input-buffer (&input-character-from-buffer))
  122. (nmode-terminal-input-string (&input-character-from-string))
  123. (t (&input-character-from-terminal))
  124. ))
  125. (de &input-character-from-buffer ()
  126. % Internal function for reading from a buffer.
  127. (cond ((=> nmode-terminal-input-buffer at-buffer-end?)
  128. (setf nmode-terminal-input-buffer NIL)
  129. (setf nmode-allow-refresh-breakout T)
  130. (input-direct-terminal-character)
  131. )
  132. ((=> nmode-terminal-input-buffer at-line-end?)
  133. (=> nmode-terminal-input-buffer move-to-next-line)
  134. (input-direct-terminal-character)
  135. )
  136. (t
  137. (prog1
  138. (=> nmode-terminal-input-buffer next-character)
  139. (=> nmode-terminal-input-buffer move-forward)
  140. ))
  141. ))
  142. (de &input-character-from-string ()
  143. % Internal function for reading from a string.
  144. (let ((upper-bound (string-upper-bound nmode-terminal-input-string))
  145. (pos nmode-terminal-input-string-pos)
  146. )
  147. (cond ((= pos upper-bound)
  148. (let ((ch (string-fetch nmode-terminal-input-string pos)))
  149. (setf nmode-terminal-input-string NIL)
  150. (setf nmode-allow-refresh-breakout T)
  151. ch
  152. ))
  153. (t
  154. (let ((ch (string-fetch nmode-terminal-input-string pos)))
  155. (setf nmode-terminal-input-string-pos (+ pos 1))
  156. ch
  157. ))
  158. )))
  159. (de &input-character-from-terminal ()
  160. % Internal function for reading from the terminal.
  161. (let ((prompt-is-empty (string-empty? nmode-prompt-string)))
  162. (if (not nmode-prompt-immediately)
  163. (sleep-until-timeout-or-input
  164. (if prompt-is-empty 120 30) % don't rush to erase the prompt line
  165. ))
  166. (if (or nmode-prompt-immediately (not (input-available?)))
  167. (progn
  168. (write-prompt nmode-prompt-string)
  169. (setf nmode-prompt-immediately (not prompt-is-empty))
  170. ))
  171. (let ((ch (=> nmode-terminal get-character)))
  172. (if nmode-terminal-script-buffer (nmode-script-character ch))
  173. ch
  174. )))
  175. (de pause-until-terminal-input ()
  176. % Return when the user has typed a character. The character is eaten.
  177. % No refresh is performed.
  178. (=> nmode-terminal get-character)
  179. )
  180. (de sleep-until-timeout-or-input (n-60ths)
  181. (wait-timeout 'input-available? n-60ths)
  182. )
  183. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  184. (de nmode-script-terminal-input (b)
  185. % Make a script of all terminal (command) input by appending characters to the
  186. % specified buffer. Supercedes any previous such request. If B is NIL, then
  187. % no scripting is performed. Note: to keep the lines of reasonable length,
  188. % free Newlines will be inserted from time to time. Because of this, and
  189. % because many file systems cannot represent stray Newlines, the Newline
  190. % character is itself scripted as a CR followed by a TAB, since this is its
  191. % normal definition. Someday, perhaps, this hack will be replaced by a better
  192. % one.
  193. (setf nmode-terminal-script-buffer b)
  194. )
  195. (de nmode-execute-buffer (b)
  196. % Take input from the specified buffer. Supercedes any previous such request.
  197. % If B is NIL, then input is taken from the terminal. Newline characters are
  198. % ignored when reading from a buffer!
  199. (setf nmode-terminal-input-buffer b)
  200. (if b (=> b move-to-buffer-start))
  201. )
  202. (de nmode-execute-string (s)
  203. % Take input from the specified string. Supercedes any previous such request.
  204. % If S is NIL or empty, then input is taken from the terminal.
  205. (if (string-empty? s) (setf s NIL))
  206. (setf nmode-terminal-input-string s)
  207. (setf nmode-terminal-input-string-pos 0)
  208. )
  209. (de nmode-script-character (ch)
  210. % Write CH to the script buffer.
  211. (let* ((b nmode-terminal-script-buffer)
  212. (old-pos (=> b position))
  213. )
  214. (=> b move-to-buffer-end)
  215. (cond ((= ch #\LF)
  216. (=> b insert-character #\CR)
  217. (=> b insert-character #\TAB)
  218. )
  219. (t (=> b insert-character ch))
  220. )
  221. (if (>= (=> b current-line-length) 60)
  222. (=> b insert-eol)
  223. )
  224. (=> b set-position old-pos)
  225. ))
  226. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  227. (undeclare-flavor nmode-terminal-input-buffer nmode-terminal-script-buffer)