* print a newline before reading if not at column 0

* flush the output before reading in `read-cmdline-syntax'
* rep.ss starts readline only when the input is a terminal

svn: r6128
This commit is contained in:
Eli Barzilay 2007-05-03 09:17:24 +00:00
parent bd9e1ca291
commit bab0a88ada
4 changed files with 38 additions and 22 deletions

View File

@ -18,13 +18,14 @@ You can start MzScheme with
or you can put the following in your ~/.mzschemerc so that MzScheme
starts with readline support when appropriate:
(when (and (regexp-match? #rx"xterm" (getenv "TERM"))
(terminal-port? (current-input-port)))
(when (regexp-match? #rx"xterm" (getenv "TERM"))
(dynamic-require '(lib "rep.ss" "readline") #f))
(The first condition rules out running in dumb terminals, eg, inside
Emacs, and the second condition avoids using it when input is
redirected.)
The "rep.ss" module is actually a wrapper around "rep-start.ss", it
will *not* invoke it if the input port is not a terminal port (eg,
when the input is redirected from a file). Still the TERM condition
above is useful for starting MzScheme in dumb terminals, eg, inside
Emacs.
The readline history is stored across invocations in MzScheme's
preferences file, assuming MzScheme exits normally.
@ -64,7 +65,6 @@ customized with these parameters:
> keep-blanks
If #f (the default), blank input lines are not kept in history.
The new input port that you get when you require "rep.ss" is a custom
port that uses readline for all inputs. The problem is when you want
to display a prompt and then read some input: readline will get
@ -75,14 +75,17 @@ line, which is why it has a `prompt' argument. To use this prompt:
...code-that-reads...)
This will make the first call to readline use the prompt, and
subsequent calls will use an all-spaces prompt of the same length
(this can happen if you're reading an s-expression). The normal value
of `readline-prompt' is #f for an empty prompt (and 'spaces after the
subsequent calls will use an all-spaces prompt of the same length (for
example, when you're reading an s-expression). The normal value of
`readline-prompt' is #f for an empty prompt (and 'spaces after the
prompt is used, which is why you should use `parameterize' to restore
it to #f).
(A proper solution would be to install a custom output port too which
will keep track of text that is displayed without a trailing newline.)
A proper solution would be to install a custom output port too which
keeps track of text that is displayed without a trailing newline. As
a cheaper solution, if line-counting is enabled for the terminal's
output-port, then a newline is printed before reading if the column is
not 0. ("rep.ss" enables line-counting for the output port.)
Warning

View File

@ -20,7 +20,13 @@
(define (save-history)
(put-preferences '(readline-input-history) (list (reverse local-history))))
;; captured now so we don't flush some other output port
(define readline-output-port (current-output-port))
(define (readline-bytes/hist p)
(when (eq? readline-output-port (current-output-port))
(let-values ([(line col pos) (port-next-location readline-output-port)])
(when (and col (< 0 col)) (newline))))
(let ([s (readline-bytes p)])
(when (and (bytes? s)
(or (keep-blanks) (not (zero? (bytes-length s))))
@ -137,6 +143,7 @@
(provide read-cmdline-syntax)
(define (read-cmdline-syntax)
(define prompt (current-prompt))
(flush-output)
;; needs to set `readline-prompt' to get a prompt when reading
(parameterize ([read-accept-reader #t]
[readline-prompt prompt])

View File

@ -0,0 +1,9 @@
;; This module initializes readline unconditionally, "rep.ss" uses it if we're
;; using a `terminal-port?' for input.
(module rep-start mzscheme
(require "pread.ss")
;; Change the input port and readline-prompt hook
(current-input-port readline-input)
(current-prompt-read read-cmdline-syntax))

View File

@ -1,13 +1,10 @@
;; This is a wrapper around "rep-start.ss" -- use it if we're using a terminal
(module rep mzscheme
(require "pread.ss")
(require (lib "runtime-path.ss"))
(define-runtime-path rep-start "rep-start.ss")
;; Change the input port and readline-prompt hook
(if (eq? 'stdin (object-name (current-input-port)))
(current-input-port readline-input)
;; don't replace some random port
(error 'readline-input
"invoke this library when the current-input-port is stdin"))
(current-prompt-read read-cmdline-syntax))
(let ([inp (current-input-port)] [outp (current-output-port)])
(when (and (eq? 'stdin (object-name inp)) (terminal-port? inp))
(dynamic-require rep-start #f)
(when (terminal-port? outp)
(port-count-lines! outp)))))