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