@@ -15,12 +15,28 @@ enum ShellExecResult {
1515 Continue ,
1616}
1717
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 {
1926 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+ }
2440 Err ( CompileError {
2541 body :
2642 CompileErrorBody {
@@ -37,7 +53,31 @@ fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> ShellExecResul
3753 } ,
3854 ..
3955 } ) => 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+ }
4181 }
4282}
4383
@@ -60,6 +100,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
60100 }
61101
62102 let mut continuing = false ;
103+ let mut last_row: usize = 0 ;
63104
64105 loop {
65106 let prompt_name = if continuing { "ps2" } else { "ps1" } ;
@@ -78,7 +119,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
78119
79120 repl. add_history_entry ( line. trim_end ( ) ) . unwrap ( ) ;
80121
81- let stop_continuing = line. is_empty ( ) ;
122+ let empty_line_given = line. is_empty ( ) ;
82123
83124 if full_input. is_empty ( ) {
84125 full_input = line;
@@ -87,30 +128,47 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
87128 }
88129 full_input. push ( '\n' ) ;
89130
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+ ) {
99139 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+ }
102158 }
103159 ShellExecResult :: Continue => {
104160 continuing = true ;
105161 Ok ( ( ) )
106162 }
107163 ShellExecResult :: PyErr ( err) => {
164+ continuing = false ;
108165 full_input. clear ( ) ;
109166 Err ( err)
110167 }
111168 }
112169 }
113170 ReadlineResult :: Interrupt => {
171+ last_row = 0 ;
114172 continuing = false ;
115173 full_input. clear ( ) ;
116174 let keyboard_interrupt =
0 commit comments