@@ -5,23 +5,24 @@ extern crate env_logger;
55extern crate log;
66
77use clap:: { App , AppSettings , Arg , ArgMatches } ;
8- use rustpython_compiler:: { compile, error:: CompileError , error:: CompileErrorType } ;
9- use rustpython_parser:: error:: ParseErrorType ;
8+ use rustpython_compiler:: compile;
109use rustpython_vm:: {
1110 import, match_class,
1211 obj:: { objint:: PyInt , objtuple:: PyTuple , objtype} ,
1312 print_exception,
14- pyobject:: { ItemProtocol , PyObjectRef , PyResult } ,
13+ pyobject:: { ItemProtocol , PyResult } ,
1514 scope:: Scope ,
1615 util, PySettings , VirtualMachine ,
1716} ;
18- use std:: convert:: TryInto ;
1917
18+ use std:: convert:: TryInto ;
2019use std:: env;
2120use std:: path:: PathBuf ;
2221use std:: process;
2322use std:: str:: FromStr ;
2423
24+ mod shell;
25+
2526fn main ( ) {
2627 #[ cfg( feature = "flame-it" ) ]
2728 let main_guard = flame:: start_guard ( "RustPython main" ) ;
@@ -365,7 +366,7 @@ fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> {
365366 } else if let Some ( filename) = matches. value_of ( "script" ) {
366367 run_script ( & vm, scope, filename) ?
367368 } else {
368- run_shell ( & vm, scope) ?;
369+ shell :: run_shell ( & vm, scope) ?;
369370 }
370371
371372 Ok ( ( ) )
@@ -457,220 +458,3 @@ fn test_run_script() {
457458 let r = run_script ( & vm, vm. new_scope_with_builtins ( ) , "tests/snippets/dir_main" ) ;
458459 assert ! ( r. is_ok( ) ) ;
459460}
460-
461- enum ShellExecResult {
462- Ok ,
463- PyErr ( PyObjectRef ) ,
464- Continue ,
465- }
466-
467- fn shell_exec ( vm : & VirtualMachine , source : & str , scope : Scope ) -> ShellExecResult {
468- match vm. compile ( source, compile:: Mode :: Single , "<stdin>" . to_string ( ) ) {
469- Ok ( code) => {
470- match vm. run_code_obj ( code, scope. clone ( ) ) {
471- Ok ( value) => {
472- // Save non-None values as "_"
473- if !vm. is_none ( & value) {
474- let key = "_" ;
475- scope. globals . set_item ( key, value, vm) . unwrap ( ) ;
476- }
477- ShellExecResult :: Ok
478- }
479- Err ( err) => ShellExecResult :: PyErr ( err) ,
480- }
481- }
482- Err ( CompileError {
483- error : CompileErrorType :: Parse ( ParseErrorType :: EOF ) ,
484- ..
485- } ) => ShellExecResult :: Continue ,
486- Err ( err) => ShellExecResult :: PyErr ( vm. new_syntax_error ( & err) ) ,
487- }
488- }
489-
490- #[ cfg( not( target_os = "wasi" ) ) ]
491- fn run_shell ( vm : & VirtualMachine , scope : Scope ) -> PyResult < ( ) > {
492- use rustyline:: { error:: ReadlineError , Editor } ;
493-
494- println ! (
495- "Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596} " ,
496- crate_version!( )
497- ) ;
498-
499- // Read a single line:
500- let mut input = String :: new ( ) ;
501- let mut repl = Editor :: < ( ) > :: new ( ) ;
502-
503- // Retrieve a `history_path_str` dependent on the OS
504- let repl_history_path = match dirs:: config_dir ( ) {
505- Some ( mut path) => {
506- path. push ( "rustpython" ) ;
507- path. push ( "repl_history.txt" ) ;
508- path
509- }
510- None => ".repl_history.txt" . into ( ) ,
511- } ;
512-
513- if !repl_history_path. exists ( ) {
514- if let Some ( parent) = repl_history_path. parent ( ) {
515- std:: fs:: create_dir_all ( parent) . unwrap ( ) ;
516- }
517- }
518-
519- if repl. load_history ( & repl_history_path) . is_err ( ) {
520- println ! ( "No previous history." ) ;
521- }
522-
523- let mut continuing = false ;
524-
525- loop {
526- let prompt_name = if continuing { "ps2" } else { "ps1" } ;
527- let prompt = vm
528- . get_attribute ( vm. sys_module . clone ( ) , prompt_name)
529- . and_then ( |prompt| vm. to_str ( & prompt) ) ;
530- let prompt = match prompt {
531- Ok ( ref s) => s. as_str ( ) ,
532- Err ( _) => "" ,
533- } ;
534- let result = match repl. readline ( prompt) {
535- Ok ( line) => {
536- debug ! ( "You entered {:?}" , line) ;
537-
538- repl. add_history_entry ( line. trim_end ( ) ) ;
539-
540- let stop_continuing = line. is_empty ( ) ;
541-
542- if input. is_empty ( ) {
543- input = line;
544- } else {
545- input. push_str ( & line) ;
546- }
547- input. push_str ( "\n " ) ;
548-
549- if continuing {
550- if stop_continuing {
551- continuing = false ;
552- } else {
553- continue ;
554- }
555- }
556-
557- match shell_exec ( vm, & input, scope. clone ( ) ) {
558- ShellExecResult :: Ok => {
559- input. clear ( ) ;
560- Ok ( ( ) )
561- }
562- ShellExecResult :: Continue => {
563- continuing = true ;
564- Ok ( ( ) )
565- }
566- ShellExecResult :: PyErr ( err) => {
567- input. clear ( ) ;
568- Err ( err)
569- }
570- }
571- }
572- Err ( ReadlineError :: Interrupted ) => {
573- continuing = false ;
574- input. clear ( ) ;
575- let keyboard_interrupt = vm
576- . new_empty_exception ( vm. ctx . exceptions . keyboard_interrupt . clone ( ) )
577- . unwrap ( ) ;
578- Err ( keyboard_interrupt)
579- }
580- Err ( ReadlineError :: Eof ) => {
581- break ;
582- }
583- Err ( err) => {
584- eprintln ! ( "Readline error: {:?}" , err) ;
585- break ;
586- }
587- } ;
588-
589- if let Err ( exc) = result {
590- if objtype:: isinstance ( & exc, & vm. ctx . exceptions . system_exit ) {
591- repl. save_history ( & repl_history_path) . unwrap ( ) ;
592- return Err ( exc) ;
593- }
594- print_exception ( vm, & exc) ;
595- }
596- }
597- repl. save_history ( & repl_history_path) . unwrap ( ) ;
598-
599- Ok ( ( ) )
600- }
601-
602- #[ cfg( target_os = "wasi" ) ]
603- fn run_shell ( vm : & VirtualMachine , scope : Scope ) -> PyResult < ( ) > {
604- use std:: io:: prelude:: * ;
605- use std:: io:: { self , BufRead } ;
606-
607- println ! (
608- "Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596} " ,
609- crate_version!( )
610- ) ;
611-
612- // Read a single line:
613- let mut input = String :: new ( ) ;
614- let mut continuing = false ;
615-
616- loop {
617- let prompt_name = if continuing { "ps2" } else { "ps1" } ;
618- let prompt = vm
619- . get_attribute ( vm. sys_module . clone ( ) , prompt_name)
620- . and_then ( |prompt| vm. to_str ( & prompt) ) ;
621- let prompt = match prompt {
622- Ok ( ref s) => s. as_str ( ) ,
623- Err ( _) => "" ,
624- } ;
625- print ! ( "{}" , prompt) ;
626- io:: stdout ( ) . flush ( ) . ok ( ) . expect ( "Could not flush stdout" ) ;
627-
628- let stdin = io:: stdin ( ) ;
629-
630- let result = match stdin. lock ( ) . lines ( ) . next ( ) . unwrap ( ) {
631- Ok ( line) => {
632- debug ! ( "You entered {:?}" , line) ;
633- let stop_continuing = line. is_empty ( ) ;
634-
635- if input. is_empty ( ) {
636- input = line;
637- } else {
638- input. push_str ( & line) ;
639- }
640- input. push_str ( "\n " ) ;
641-
642- if continuing {
643- if stop_continuing {
644- continuing = false ;
645- } else {
646- continue ;
647- }
648- }
649-
650- match shell_exec ( vm, & input, scope. clone ( ) ) {
651- ShellExecResult :: Ok => {
652- input. clear ( ) ;
653- Ok ( ( ) )
654- }
655- ShellExecResult :: Continue => {
656- continuing = true ;
657- Ok ( ( ) )
658- }
659- ShellExecResult :: PyErr ( err) => {
660- input. clear ( ) ;
661- Err ( err)
662- }
663- }
664- }
665- Err ( err) => {
666- eprintln ! ( "Readline error: {:?}" , err) ;
667- break ;
668- }
669- } ;
670-
671- if let Err ( exc) = result {
672- print_exception ( vm, & exc) ;
673- }
674- }
675- Ok ( ( ) )
676- }
0 commit comments