@@ -6,6 +6,7 @@ extern crate env_logger;
66extern crate log;
77extern crate rustpython_parser;
88extern crate rustpython_vm;
9+ extern crate rustyline;
910
1011use clap:: { App , Arg } ;
1112use rustpython_parser:: parser;
@@ -14,8 +15,8 @@ use rustpython_vm::print_exception;
1415use rustpython_vm:: pyobject:: { PyObjectRef , PyResult } ;
1516use rustpython_vm:: VirtualMachine ;
1617use rustpython_vm:: { compile, import} ;
17- use std :: io ;
18- use std :: io :: prelude :: * ;
18+ use rustyline :: error :: ReadlineError ;
19+ use rustyline :: Editor ;
1920use std:: path:: Path ;
2021
2122fn main ( ) {
@@ -146,23 +147,30 @@ fn run_shell(vm: &mut VirtualMachine) -> PyResult {
146147
147148 // Read a single line:
148149 let mut input = String :: new ( ) ;
150+ let mut rl = Editor :: < ( ) > :: new ( ) ;
151+
152+ // TODO: Store the history in a proper XDG directory
153+ let repl_history_path = ".repl_history.txt" ;
154+ if rl. load_history ( repl_history_path) . is_err ( ) {
155+ println ! ( "No previous history." ) ;
156+ }
157+
149158 loop {
150159 // TODO: modules dont support getattr / setattr yet
151160 //let prompt = match vm.get_attribute(vm.sys_module.clone(), "ps1") {
152161 // Ok(value) => objstr::get_value(&value),
153162 // Err(_) => ">>>>> ".to_string(),
154163 //};
155- print ! ( ">>>>> " ) ;
156164
157- io:: stdout ( ) . flush ( ) . expect ( "Could not flush stdout" ) ;
158- match io:: stdin ( ) . read_line ( & mut input) {
159- Ok ( 0 ) => {
160- break ;
161- }
162- Ok ( _) => {
165+ match rl. readline ( ">>> " ) {
166+ Ok ( line) => {
167+ input. push_str ( & line) ;
168+ input. push_str ( "\n " ) ;
169+
163170 debug ! ( "You entered {:?}" , input) ;
164171 if shell_exec ( vm, & input, vars. clone ( ) ) {
165172 // Line was complete.
173+ rl. add_history_entry ( input. as_ref ( ) ) ;
166174 input = String :: new ( ) ;
167175 } else {
168176 loop {
@@ -171,16 +179,11 @@ fn run_shell(vm: &mut VirtualMachine) -> PyResult {
171179 // Ok(value) => objstr::get_value(&value),
172180 // Err(_) => "..... ".to_string(),
173181 //};
174- print ! ( "..... " ) ;
175- io:: stdout ( ) . flush ( ) . expect ( "Could not flush stdout" ) ;
176- let mut line = String :: new ( ) ;
177- match io:: stdin ( ) . read_line ( & mut line) {
178- Ok ( _) => {
179- line = line
180- . trim_right_matches ( |c| c == '\r' || c == '\n' )
181- . to_string ( ) ;
182+ match rl. readline ( "... " ) {
183+ Ok ( line) => {
182184 if line. len ( ) == 0 {
183185 if shell_exec ( vm, & input, vars. clone ( ) ) {
186+ rl. add_history_entry ( input. as_ref ( ) ) ;
184187 input = String :: new ( ) ;
185188 break ;
186189 }
@@ -194,9 +197,21 @@ fn run_shell(vm: &mut VirtualMachine) -> PyResult {
194197 }
195198 }
196199 }
197- Err ( msg) => panic ! ( "Error: {:?}" , msg) ,
200+ Err ( ReadlineError :: Interrupted ) => {
201+ // TODO: Raise a real KeyboardInterrupt exception
202+ println ! ( "^C" ) ;
203+ break ;
204+ }
205+ Err ( ReadlineError :: Eof ) => {
206+ break ;
207+ }
208+ Err ( err) => {
209+ println ! ( "Error: {:?}" , err) ;
210+ break ;
211+ }
198212 } ;
199213 }
214+ rl. save_history ( repl_history_path) . unwrap ( ) ;
200215
201216 Ok ( vm. get_none ( ) )
202217}
0 commit comments