From bab0a88ada485019ad214798feac99108c94bafe Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Thu, 3 May 2007 09:17:24 +0000 Subject: [PATCH] * 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 --- collects/readline/doc.txt | 25 ++++++++++++++----------- collects/readline/pread.ss | 7 +++++++ collects/readline/rep-start.ss | 9 +++++++++ collects/readline/rep.ss | 19 ++++++++----------- 4 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 collects/readline/rep-start.ss diff --git a/collects/readline/doc.txt b/collects/readline/doc.txt index 0e206fe46a..4fba66a436 100644 --- a/collects/readline/doc.txt +++ b/collects/readline/doc.txt @@ -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 diff --git a/collects/readline/pread.ss b/collects/readline/pread.ss index 04394d5ab1..3ae48e6162 100644 --- a/collects/readline/pread.ss +++ b/collects/readline/pread.ss @@ -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]) diff --git a/collects/readline/rep-start.ss b/collects/readline/rep-start.ss new file mode 100644 index 0000000000..bf7eb0cd59 --- /dev/null +++ b/collects/readline/rep-start.ss @@ -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)) diff --git a/collects/readline/rep.ss b/collects/readline/rep.ss index 2bb64f2026..9f8a44c22f 100644 --- a/collects/readline/rep.ss +++ b/collects/readline/rep.ss @@ -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)))))