@@ -15,12 +15,28 @@ enum ShellExecResult {
15
15
Continue ,
16
16
}
17
17
18
- fn shell_exec ( vm : & VirtualMachine , source : & str , scope : Scope ) -> ShellExecResult {
18
+ fn shell_exec (
19
+ vm : & VirtualMachine ,
20
+ source : & str ,
21
+ scope : Scope ,
22
+ last_row : & mut usize ,
23
+ empty_line_given : bool ,
24
+ continuing : bool ,
25
+ ) -> ShellExecResult {
19
26
match vm. compile ( source, compiler:: Mode :: Single , "<stdin>" . to_owned ( ) ) {
20
- Ok ( code) => match vm. run_code_obj ( code, scope) {
21
- Ok ( _val) => ShellExecResult :: Ok ,
22
- Err ( err) => ShellExecResult :: PyErr ( err) ,
23
- } ,
27
+ Ok ( code) => {
28
+ if empty_line_given || !continuing {
29
+ // We want to execute the full code
30
+ * last_row = 0 ;
31
+ match vm. run_code_obj ( code, scope) {
32
+ Ok ( _val) => ShellExecResult :: Ok ,
33
+ Err ( err) => ShellExecResult :: PyErr ( err) ,
34
+ }
35
+ } else {
36
+ // We can just return an ok result
37
+ ShellExecResult :: Ok
38
+ }
39
+ }
24
40
Err ( CompileError {
25
41
body :
26
42
CompileErrorBody {
@@ -37,7 +53,31 @@ fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> ShellExecResul
37
53
} ,
38
54
..
39
55
} ) => ShellExecResult :: Continue ,
40
- Err ( err) => ShellExecResult :: PyErr ( vm. new_syntax_error ( & err) ) ,
56
+ Err ( err) => {
57
+ // Indent error or something else?
58
+ let indent_error = match err. body . error {
59
+ CompileErrorType :: Parse ( ref p) => p. is_indentation_error ( ) ,
60
+ _ => false ,
61
+ } ;
62
+
63
+ if indent_error && !empty_line_given {
64
+ // The input line is not empty and it threw an indentation error
65
+ let l = err. body . location ;
66
+
67
+ // This is how we can mask unnecesary errors
68
+ if l. row ( ) > * last_row {
69
+ * last_row = l. row ( ) ;
70
+ ShellExecResult :: Continue
71
+ } else {
72
+ * last_row = 0 ;
73
+ ShellExecResult :: PyErr ( vm. new_syntax_error ( & err) )
74
+ }
75
+ } else {
76
+ // Throw the error for all other cases
77
+ * last_row = 0 ;
78
+ ShellExecResult :: PyErr ( vm. new_syntax_error ( & err) )
79
+ }
80
+ }
41
81
}
42
82
}
43
83
@@ -60,6 +100,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
60
100
}
61
101
62
102
let mut continuing = false ;
103
+ let mut last_row: usize = 0 ;
63
104
64
105
loop {
65
106
let prompt_name = if continuing { "ps2" } else { "ps1" } ;
@@ -78,7 +119,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
78
119
79
120
repl. add_history_entry ( line. trim_end ( ) ) . unwrap ( ) ;
80
121
81
- let stop_continuing = line. is_empty ( ) ;
122
+ let empty_line_given = line. is_empty ( ) ;
82
123
83
124
if full_input. is_empty ( ) {
84
125
full_input = line;
@@ -87,30 +128,47 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
87
128
}
88
129
full_input. push ( '\n' ) ;
89
130
90
- if continuing {
91
- if stop_continuing {
92
- continuing = false ;
93
- } else {
94
- continue ;
95
- }
96
- }
97
-
98
- match shell_exec ( vm, & full_input, scope. clone ( ) ) {
131
+ match shell_exec (
132
+ vm,
133
+ & full_input,
134
+ scope. clone ( ) ,
135
+ & mut last_row,
136
+ empty_line_given,
137
+ continuing,
138
+ ) {
99
139
ShellExecResult :: Ok => {
100
- full_input. clear ( ) ;
101
- Ok ( ( ) )
140
+ if continuing {
141
+ if empty_line_given {
142
+ // We should be exiting continue mode
143
+ continuing = false ;
144
+ full_input. clear ( ) ;
145
+ Ok ( ( ) )
146
+ } else {
147
+ // We should stay in continue mode
148
+ continuing = true ;
149
+ Ok ( ( ) )
150
+ }
151
+ } else {
152
+ // We aren't in continue mode so proceed normally
153
+ last_row = 0 ;
154
+ continuing = false ;
155
+ full_input. clear ( ) ;
156
+ Ok ( ( ) )
157
+ }
102
158
}
103
159
ShellExecResult :: Continue => {
104
160
continuing = true ;
105
161
Ok ( ( ) )
106
162
}
107
163
ShellExecResult :: PyErr ( err) => {
164
+ continuing = false ;
108
165
full_input. clear ( ) ;
109
166
Err ( err)
110
167
}
111
168
}
112
169
}
113
170
ReadlineResult :: Interrupt => {
171
+ last_row = 0 ;
114
172
continuing = false ;
115
173
full_input. clear ( ) ;
116
174
let keyboard_interrupt =
0 commit comments