read-command.scm 6.1 KB

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