read-command.scm 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Marcus Crestani
  3. ; Read a command. No command name completion, yet.
  4. (define (read-command prompt form-preferred? i-port)
  5. (really-read-command prompt form-preferred? i-port))
  6. (define (really-read-command prompt form-preferred? i-port)
  7. (let ((o-port (command-output)))
  8. (let prompt-loop ()
  9. (if (and prompt (not (batch-mode?)))
  10. (display prompt o-port))
  11. (force-output o-port) ;foo
  12. (let loop ()
  13. (let ((c (peek-char i-port)))
  14. (cond ((eof-object? c)
  15. (read-char i-port))
  16. ((char-whitespace? c)
  17. (read-char i-port)
  18. (if (char=? c #\newline)
  19. (prompt-loop)
  20. (loop)))
  21. ((char=? c #\;) ;Comment
  22. (gobble-line i-port)
  23. (prompt-loop))
  24. ((char=? c #\)) ;Erroneous right paren
  25. (read-char i-port)
  26. (warning 'read-command "discarding extraneous right parenthesis")
  27. (loop))
  28. ((char=? c command-prefix)
  29. (read-char i-port)
  30. (read-named-command i-port form-preferred?))
  31. ((or form-preferred?
  32. (and (not (char-alphabetic? c))
  33. (not (char-numeric? c))
  34. (not (char=? c #\?))))
  35. (read-evaluation-command i-port))
  36. (else
  37. (read-named-command i-port form-preferred?))))))))
  38. (define (read-command-carefully prompt form-preferred? i-port)
  39. (call-with-current-continuation
  40. (lambda (k)
  41. (with-handler
  42. (lambda (c punt)
  43. (cond ((batch-mode?)
  44. (punt))
  45. ((and (i/o-port-error? c)
  46. (or (i/o-error? c) ; should really be i/o-read-error?
  47. (read-command-error? c)))
  48. (let ((port (i/o-error-port c)))
  49. (if (eq? port i-port)
  50. (eat-until-newline i-port))
  51. (display-condition c (command-output)
  52. (condition-writing-depth) (condition-writing-length))
  53. (k #f)))
  54. ((reset-command-input-condition? c)
  55. (k #f))
  56. (else
  57. (punt))))
  58. (lambda ()
  59. (really-read-command prompt form-preferred? i-port))))))
  60. (define (eat-until-newline port)
  61. (do ()
  62. ((or (not (char-ready? port))
  63. (let ((c (read-char port)))
  64. (or (eof-object? c)
  65. (char=? c #\newline)))))))
  66. (define (read-evaluation-command i-port)
  67. (let ((form (read-form i-port)))
  68. (if (eq? (skip-over horizontal-space? i-port) #\newline)
  69. (read-char i-port))
  70. (make-command 'run (list form))))
  71. ; Read a single form, allowing ## as a way to refer to last command
  72. ; output.
  73. (define (read-form port)
  74. (with-sharp-sharp (make-node (get-operator 'quote)
  75. (list 'quote (focus-object)))
  76. (lambda () (read-datum port))))
  77. ; Read a command line: <name> <arg> ... <newline>
  78. (define (read-named-command port form-preferred?)
  79. (let ((c-name (read-datum port)))
  80. (cond ((and (integer? c-name)
  81. (<= 0 c-name))
  82. (make-command 'select-menu-item
  83. (cons c-name
  84. (read-command-arguments '(&rest selection-command)
  85. #f
  86. port
  87. #f))))
  88. ((and (symbol? c-name)
  89. (get-command-syntax c-name))
  90. => (lambda (syntax)
  91. (make-command c-name
  92. (read-command-arguments syntax #f port
  93. form-preferred?))))
  94. (else
  95. (read-command-arguments '(&rest form) #f port #f) ; flush junk
  96. (write-line "Unrecognized command name." (command-output))
  97. #f))))
  98. (define (read-command-arguments ds opt? port form-preferred?)
  99. (let recur ((ds ds) (opt? opt?))
  100. (let ((c (skip-over horizontal-space? port)))
  101. (cond ((and (not (null? ds))
  102. (eq? (car ds) '&opt))
  103. (recur (cdr ds) #t))
  104. ((or (eof-object? c)
  105. (char=? c #\newline)
  106. (if (char=? c #\;) ;Comment
  107. (begin (gobble-line port)
  108. #t)
  109. #f))
  110. (cond ((or (null? ds)
  111. (eq? (car ds) '&rest)
  112. opt?)
  113. (read-char port)
  114. '())
  115. (else
  116. (read-command-error port
  117. "too few command arguments"))))
  118. ((null? ds)
  119. (read-command-error port "too many command arguments"))
  120. ((eq? (car ds) '&rest)
  121. (let ((arg (read-command-argument (cadr ds) port)))
  122. (cons arg (recur ds #f))))
  123. ((eq? (car ds) 'command) ; must be the last argument
  124. (if (not (null? (cdr ds)))
  125. (assertion-violation 'read-command-arguments
  126. "invalid argument descriptions" ds))
  127. (list (really-read-command #f form-preferred? port)))
  128. (else
  129. (let ((arg (read-command-argument (car ds) port)))
  130. (cons arg (recur (cdr ds) opt?))))))))
  131. (define (read-command-argument d port)
  132. (if (procedure? d)
  133. (d port)
  134. (case d
  135. ((filename)
  136. (read-filename port))
  137. ((expression form)
  138. (read-form port))
  139. ((name)
  140. (let ((thing (read-datum port)))
  141. (if (symbol? thing)
  142. thing
  143. (read-command-error port "invalid name" thing))))
  144. ((literal)
  145. (read-datum port))
  146. ((selection-command)
  147. (let ((x (read-datum port)))
  148. (if (selection-command? x)
  149. x
  150. (read-command-error port "invalid selection command" x))))
  151. (else
  152. (assertion-violation 'read-command-argument
  153. "invalid argument description" d)))))
  154. (define (read-filename port)
  155. (let ((c (peek-char port)))
  156. (if (and (char? c)
  157. (char=? (peek-char port) #\"))
  158. (read-datum port)
  159. (read-string port char-whitespace?))))
  160. (define-condition-type &read-command-error &error
  161. make-read-command-error read-command-error?)
  162. (define (read-command-error port message . rest)
  163. (signal-condition (condition (make-read-command-error)
  164. (make-irritants-condition (cons port rest))
  165. (make-i/o-port-error port)
  166. (make-message-condition message))))
  167. (define (read-datum port)
  168. ((package-reader (interaction-environment)) port))
  169. ; Utilities.
  170. (define (horizontal-space? c)
  171. (and (char-whitespace? c)
  172. (not (char=? c #\newline))))
  173. (define (read-string port delimiter?)
  174. (let loop ((l '()))
  175. (let ((c (peek-char port)))
  176. (cond ((or (eof-object? c)
  177. (delimiter? c))
  178. (list->string (reverse l)))
  179. (else
  180. (loop (cons (read-char port) l)))))))
  181. (define (skip-over pred port)
  182. (let ((c (peek-char port)))
  183. (cond ((eof-object? c) c)
  184. ((pred c) (read-char port) (skip-over pred port))
  185. (else c))))
  186. ; ## should evaluate to the last REP-loop result.
  187. (define-sharp-macro #\#
  188. (lambda (c port)
  189. (read-char port)
  190. ((current-sharp-sharp) port)))
  191. (define (current-sharp-sharp)
  192. (fluid $sharp-sharp))
  193. (define $sharp-sharp
  194. (make-fluid (lambda (port) (reading-error port "## in invalid context"))))
  195. (define (with-sharp-sharp form body)
  196. (let-fluid $sharp-sharp (lambda (port) form) body))
  197. (define make-command cons) ;(name . args)
  198. ; (put 'with-sharp-sharp 'scheme-indent-hook 1)