1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! The read-eval-print loop.
//!
//! One loop covers both of the reference interpreter's stdin modes, because
//! they differ only in what they print. With a terminal `tclsh` writes a `% `
//! prompt and echoes the value of each command; reading a piped script it
//! writes neither. Everything else is the same in both, and is not what a
//! script file gets:
//!
//! * commands are evaluated one at a time as they complete, not as one script;
//! * a command that fails is reported and the loop goes on to the next;
//! * end of input exits successfully — which is why `tclsh < script` exits 0
//! where `tclsh script` exits 1 — and text left half-typed is discarded.
//!
//! Reading one line at a time is not enough: a command can span lines. The loop
//! keeps reading while the text so far leaves a brace, quote or bracket open,
//! which is what a `{` at the end of a line does.
use ;
use ExitCode;
use Interp;
/// What `tclsh` writes when it wants a command. Its continuation prompt is
/// empty, so a command being typed across lines is not prefixed at all.
const PROMPT: &str = "% ";
/// Read commands from stdin until end of input, evaluating each against
/// `interp`. Prompts and echoes results only when `interactive`.
/// Whether `src` needs more input before it is a script.
///
/// The answer lives in [`tclrs::parser::incomplete`], because `info complete`
/// asks the same question of the same parser and the two must not be able to
/// disagree — a REPL that kept reading where `info complete` said 1 would be
/// answering from a second reading of the same text.
/// True when stdin is a terminal, and the loop should prompt and echo.