From c9a4c83fceb19edc742ab29f52d5494a9b854ce7 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Thu, 7 Oct 2021 01:19:35 -0700 Subject: [PATCH] Run cargo fmt on schala-repl code --- schala-repl/src/language.rs | 88 +++-- schala-repl/src/lib.rs | 120 ++++--- schala-repl/src/repl/command_tree.rs | 187 +++++----- schala-repl/src/repl/directive_actions.rs | 223 ++++++------ schala-repl/src/repl/directives.rs | 141 +++++--- schala-repl/src/repl/help.rs | 108 +++--- schala-repl/src/repl/mod.rs | 413 ++++++++++++---------- schala-repl/src/repl/repl_options.rs | 63 ++-- schala-repl/src/repl/response.rs | 111 +++--- 9 files changed, 799 insertions(+), 655 deletions(-) diff --git a/schala-repl/src/language.rs b/schala-repl/src/language.rs index 92b03ec..fa391e9 100644 --- a/schala-repl/src/language.rs +++ b/schala-repl/src/language.rs @@ -1,80 +1,76 @@ -use std::time; use std::collections::HashSet; +use std::time; pub trait ProgrammingLanguageInterface { - fn get_language_name(&self) -> String; - fn get_source_file_suffix(&self) -> String; + fn get_language_name(&self) -> String; + fn get_source_file_suffix(&self) -> String; - fn run_computation(&mut self, _request: ComputationRequest) -> ComputationResponse { - ComputationResponse { - main_output: Err(format!("Computation pipeline not implemented")), - global_output_stats: GlobalOutputStats::default(), - debug_responses: vec![], + fn run_computation(&mut self, _request: ComputationRequest) -> ComputationResponse { + ComputationResponse { + main_output: Err(format!("Computation pipeline not implemented")), + global_output_stats: GlobalOutputStats::default(), + debug_responses: vec![], + } } - } - fn request_meta(&mut self, _request: LangMetaRequest) -> LangMetaResponse { - LangMetaResponse::Custom { kind: format!("not-implemented"), value: format!("") } - } + fn request_meta(&mut self, _request: LangMetaRequest) -> LangMetaResponse { + LangMetaResponse::Custom { + kind: format!("not-implemented"), + value: format!(""), + } + } } pub struct ComputationRequest<'a> { - pub source: &'a str, - pub debug_requests: HashSet, + pub source: &'a str, + pub debug_requests: HashSet, } pub struct ComputationResponse { - pub main_output: Result, - pub global_output_stats: GlobalOutputStats, - pub debug_responses: Vec, + pub main_output: Result, + pub global_output_stats: GlobalOutputStats, + pub debug_responses: Vec, } #[derive(Default, Debug)] pub struct GlobalOutputStats { - pub total_duration: time::Duration, - pub stage_durations: Vec<(String, time::Duration)> + pub total_duration: time::Duration, + pub stage_durations: Vec<(String, time::Duration)>, } #[derive(Debug, Clone, Hash, Eq, PartialEq, Deserialize, Serialize)] pub enum DebugAsk { - Timing, - ByStage { stage_name: String, token: Option }, + Timing, + ByStage { + stage_name: String, + token: Option, + }, } impl DebugAsk { - pub fn is_for_stage(&self, name: &str) -> bool { - match self { - DebugAsk::ByStage { stage_name, .. } if stage_name == name => true, - _ => false + pub fn is_for_stage(&self, name: &str) -> bool { + match self { + DebugAsk::ByStage { stage_name, .. } if stage_name == name => true, + _ => false, + } } - } } pub struct DebugResponse { - pub ask: DebugAsk, - pub value: String + pub ask: DebugAsk, + pub value: String, } pub enum LangMetaRequest { - StageNames, - Docs { - source: String, - }, - Custom { - kind: String, - value: String - }, - ImmediateDebug(DebugAsk), + StageNames, + Docs { source: String }, + Custom { kind: String, value: String }, + ImmediateDebug(DebugAsk), } pub enum LangMetaResponse { - StageNames(Vec), - Docs { - doc_string: String, - }, - Custom { - kind: String, - value: String - }, - ImmediateDebug(DebugResponse), + StageNames(Vec), + Docs { doc_string: String }, + Custom { kind: String, value: String }, + ImmediateDebug(DebugResponse), } diff --git a/schala-repl/src/lib.rs b/schala-repl/src/lib.rs index 528740e..ffcfa62 100644 --- a/schala-repl/src/lib.rs +++ b/schala-repl/src/lib.rs @@ -1,91 +1,95 @@ #![feature(box_patterns, box_syntax, proc_macro_hygiene, decl_macro)] #![feature(plugin)] -extern crate getopts; -extern crate linefeed; -extern crate itertools; extern crate colored; +extern crate getopts; +extern crate itertools; +extern crate linefeed; #[macro_use] extern crate serde_derive; -extern crate serde_json; extern crate includedir; extern crate phf; +extern crate serde_json; use std::collections::HashSet; -use std::path::Path; use std::fs::File; use std::io::Read; +use std::path::Path; use std::process::exit; -mod repl; mod language; +mod repl; -pub use language::{ProgrammingLanguageInterface, -ComputationRequest, ComputationResponse, -LangMetaRequest, LangMetaResponse, -DebugResponse, DebugAsk, GlobalOutputStats}; +pub use language::{ + ComputationRequest, ComputationResponse, DebugAsk, DebugResponse, GlobalOutputStats, + LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface, +}; include!(concat!(env!("OUT_DIR"), "/static.rs")); const VERSION_STRING: &'static str = "0.1.0"; pub fn start_repl(langs: Vec>) { - let options = command_line_options().parse(std::env::args()).unwrap_or_else(|e| { - println!("{:?}", e); - exit(1); - }); + let options = command_line_options() + .parse(std::env::args()) + .unwrap_or_else(|e| { + println!("{:?}", e); + exit(1); + }); - if options.opt_present("help") { - println!("{}", command_line_options().usage("Schala metainterpreter")); - exit(0); - } + if options.opt_present("help") { + println!("{}", command_line_options().usage("Schala metainterpreter")); + exit(0); + } - match options.free[..] { - [] | [_] => { - let mut repl = repl::Repl::new(langs); - repl.run_repl(); - } - [_, ref filename, ..] => { - run_noninteractive(filename, langs); - } - }; + match options.free[..] { + [] | [_] => { + let mut repl = repl::Repl::new(langs); + repl.run_repl(); + } + [_, ref filename, ..] => { + run_noninteractive(filename, langs); + } + }; } fn run_noninteractive(filename: &str, languages: Vec>) { - let path = Path::new(filename); - let ext = path.extension().and_then(|e| e.to_str()).unwrap_or_else(|| { - println!("Source file lacks extension"); - exit(1); - }); - let mut language = Box::new(languages.into_iter().find(|lang| lang.get_source_file_suffix() == ext) - .unwrap_or_else(|| { - println!("Extension .{} not recognized", ext); - exit(1); - })); + let path = Path::new(filename); + let ext = path + .extension() + .and_then(|e| e.to_str()) + .unwrap_or_else(|| { + println!("Source file lacks extension"); + exit(1); + }); + let mut language = Box::new( + languages + .into_iter() + .find(|lang| lang.get_source_file_suffix() == ext) + .unwrap_or_else(|| { + println!("Extension .{} not recognized", ext); + exit(1); + }), + ); - let mut source_file = File::open(path).unwrap(); - let mut buffer = String::new(); - source_file.read_to_string(&mut buffer).unwrap(); + let mut source_file = File::open(path).unwrap(); + let mut buffer = String::new(); + source_file.read_to_string(&mut buffer).unwrap(); - let request = ComputationRequest { - source: &buffer, - debug_requests: HashSet::new(), - }; + let request = ComputationRequest { + source: &buffer, + debug_requests: HashSet::new(), + }; - let response = language.run_computation(request); - match response.main_output { - Ok(s) => println!("{}", s), - Err(s) => println!("{}", s) - }; + let response = language.run_computation(request); + match response.main_output { + Ok(s) => println!("{}", s), + Err(s) => println!("{}", s), + }; } - fn command_line_options() -> getopts::Options { - let mut options = getopts::Options::new(); - options.optflag("h", - "help", - "Show help text"); - options.optflag("w", - "webapp", - "Start up web interpreter"); - options + let mut options = getopts::Options::new(); + options.optflag("h", "help", "Show help text"); + options.optflag("w", "webapp", "Start up web interpreter"); + options } diff --git a/schala-repl/src/repl/command_tree.rs b/schala-repl/src/repl/command_tree.rs index 9c4ee89..09e2120 100644 --- a/schala-repl/src/repl/command_tree.rs +++ b/schala-repl/src/repl/command_tree.rs @@ -1,4 +1,4 @@ -use super::{Repl, InterpreterDirectiveOutput}; +use super::{InterpreterDirectiveOutput, Repl}; use crate::repl::directive_actions::DirectiveAction; use colored::*; @@ -7,93 +7,116 @@ use colored::*; /// and then execute it with any remaining arguments #[derive(Clone)] pub enum CommandTree { - Terminal { - name: String, - children: Vec, - help_msg: Option, - action: DirectiveAction, - }, - NonTerminal { - name: String, - children: Vec, - help_msg: Option, - action: DirectiveAction, - }, - Top(Vec), + Terminal { + name: String, + children: Vec, + help_msg: Option, + action: DirectiveAction, + }, + NonTerminal { + name: String, + children: Vec, + help_msg: Option, + action: DirectiveAction, + }, + Top(Vec), } impl CommandTree { - pub fn nonterm_no_further_tab_completions(s: &str, help: Option<&str>) -> CommandTree { - CommandTree::NonTerminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), children: vec![], action: DirectiveAction::Null } - } - - pub fn terminal(s: &str, help: Option<&str>, children: Vec, action: DirectiveAction) -> CommandTree { - CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), children, action} - } - - pub fn nonterm(s: &str, help: Option<&str>, children: Vec) -> CommandTree { - CommandTree::NonTerminal { - name: s.to_string(), - help_msg: help.map(|x| x.to_string()), - children, - action: DirectiveAction::Null + pub fn nonterm_no_further_tab_completions(s: &str, help: Option<&str>) -> CommandTree { + CommandTree::NonTerminal { + name: s.to_string(), + help_msg: help.map(|x| x.to_string()), + children: vec![], + action: DirectiveAction::Null, + } } - } - pub fn get_cmd(&self) -> &str { - match self { - CommandTree::Terminal { name, .. } => name.as_str(), - CommandTree::NonTerminal {name, ..} => name.as_str(), - CommandTree::Top(_) => "", + pub fn terminal( + s: &str, + help: Option<&str>, + children: Vec, + action: DirectiveAction, + ) -> CommandTree { + CommandTree::Terminal { + name: s.to_string(), + help_msg: help.map(|x| x.to_string()), + children, + action, + } } - } - pub fn get_help(&self) -> &str { - match self { - CommandTree::Terminal { help_msg, ..} => help_msg.as_ref().map(|s| s.as_str()).unwrap_or(""), - CommandTree::NonTerminal { help_msg, .. } => help_msg.as_ref().map(|s| s.as_str()).unwrap_or(""), - CommandTree::Top(_) => "" - } - } - pub fn get_children(&self) -> &Vec { - use CommandTree::*; - match self { - Terminal { children, .. } | - NonTerminal { children, .. } | - Top(children) => children - } - } - pub fn get_subcommands(&self) -> Vec<&str> { - self.get_children().iter().map(|x| x.get_cmd()).collect() - } - pub fn perform(&self, repl: &mut Repl, arguments: &Vec<&str>) -> InterpreterDirectiveOutput { - let mut dir_pointer: &CommandTree = self; - let mut idx = 0; - - let res: Result<(DirectiveAction, usize), String> = loop { - match dir_pointer { - CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => { - let next_command = match arguments.get(idx) { - Some(cmd) => cmd, - None => break Err(format!("Command requires arguments")) - }; - idx += 1; - match subcommands.iter().find(|sc| sc.get_cmd() == *next_command) { - Some(command_tree) => { - dir_pointer = command_tree; - }, - None => break Err(format!("Command {} not found", next_command)) - }; - }, - CommandTree::Terminal { action, .. } => { - break Ok((action.clone(), idx)); - }, - } - }; - - match res { - Ok((action, idx)) => action.perform(repl, &arguments[idx..]), - Err(err) => Some(err.red().to_string()) + pub fn nonterm(s: &str, help: Option<&str>, children: Vec) -> CommandTree { + CommandTree::NonTerminal { + name: s.to_string(), + help_msg: help.map(|x| x.to_string()), + children, + action: DirectiveAction::Null, + } + } + + pub fn get_cmd(&self) -> &str { + match self { + CommandTree::Terminal { name, .. } => name.as_str(), + CommandTree::NonTerminal { name, .. } => name.as_str(), + CommandTree::Top(_) => "", + } + } + pub fn get_help(&self) -> &str { + match self { + CommandTree::Terminal { help_msg, .. } => help_msg + .as_ref() + .map(|s| s.as_str()) + .unwrap_or(""), + CommandTree::NonTerminal { help_msg, .. } => help_msg + .as_ref() + .map(|s| s.as_str()) + .unwrap_or(""), + CommandTree::Top(_) => "", + } + } + pub fn get_children(&self) -> &Vec { + use CommandTree::*; + match self { + Terminal { children, .. } | NonTerminal { children, .. } | Top(children) => children, + } + } + pub fn get_subcommands(&self) -> Vec<&str> { + self.get_children().iter().map(|x| x.get_cmd()).collect() + } + + pub fn perform(&self, repl: &mut Repl, arguments: &Vec<&str>) -> InterpreterDirectiveOutput { + let mut dir_pointer: &CommandTree = self; + let mut idx = 0; + + let res: Result<(DirectiveAction, usize), String> = loop { + match dir_pointer { + CommandTree::Top(subcommands) + | CommandTree::NonTerminal { + children: subcommands, + .. + } => { + let next_command = match arguments.get(idx) { + Some(cmd) => cmd, + None => break Err(format!("Command requires arguments")), + }; + idx += 1; + match subcommands.iter().find(|sc| sc.get_cmd() == *next_command) { + Some(command_tree) => { + dir_pointer = command_tree; + } + None => break Err(format!("Command {} not found", next_command)), + }; + } + CommandTree::Terminal { action, .. } => { + break Ok((action.clone(), idx)); + } + } + }; + + match res { + Ok((action, idx)) => action.perform(repl, &arguments[idx..]), + Err(err) => Some(err.red().to_string()), + } } - } } diff --git a/schala-repl/src/repl/directive_actions.rs b/schala-repl/src/repl/directive_actions.rs index 338e979..e53a591 100644 --- a/schala-repl/src/repl/directive_actions.rs +++ b/schala-repl/src/repl/directive_actions.rs @@ -1,132 +1,145 @@ -use super::{Repl, InterpreterDirectiveOutput}; +use super::{InterpreterDirectiveOutput, Repl}; +use crate::language::{DebugAsk, DebugResponse, LangMetaRequest, LangMetaResponse}; use crate::repl::help::help; -use crate::language::{LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse}; use std::fmt::Write as FmtWrite; #[derive(Debug, Clone)] pub enum DirectiveAction { - Null, - Help, - QuitProgram, - ListPasses, - ShowImmediate, - Show, - Hide, - TotalTimeOff, - TotalTimeOn, - StageTimeOff, - StageTimeOn, - Doc, + Null, + Help, + QuitProgram, + ListPasses, + ShowImmediate, + Show, + Hide, + TotalTimeOff, + TotalTimeOn, + StageTimeOff, + StageTimeOn, + Doc, } impl DirectiveAction { - pub fn perform(&self, repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput { - use DirectiveAction::*; - match self { - Null => None, - Help => help(repl, arguments), - QuitProgram => { - repl.save_before_exit(); - ::std::process::exit(0) - }, - ListPasses => { - let language_state = repl.get_cur_language_state(); - let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) { - LangMetaResponse::StageNames(names) => names, - _ => vec![], - }; + pub fn perform(&self, repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput { + use DirectiveAction::*; + match self { + Null => None, + Help => help(repl, arguments), + QuitProgram => { + repl.save_before_exit(); + ::std::process::exit(0) + } + ListPasses => { + let language_state = repl.get_cur_language_state(); + let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) { + LangMetaResponse::StageNames(names) => names, + _ => vec![], + }; - let mut buf = String::new(); - for pass in pass_names.iter().map(|name| Some(name)).intersperse(None) { - match pass { - Some(pass) => write!(buf, "{}", pass).unwrap(), - None => write!(buf, " -> ").unwrap(), - } + let mut buf = String::new(); + for pass in pass_names.iter().map(|name| Some(name)).intersperse(None) { + match pass { + Some(pass) => write!(buf, "{}", pass).unwrap(), + None => write!(buf, " -> ").unwrap(), + } + } + Some(buf) + } + ShowImmediate => { + let cur_state = repl.get_cur_language_state(); + let stage_name = match arguments.get(0) { + Some(s) => s.to_string(), + None => return Some(format!("Must specify a thing to debug")), + }; + let meta = LangMetaRequest::ImmediateDebug(DebugAsk::ByStage { + stage_name: stage_name.clone(), + token: None, + }); + let meta_response = cur_state.request_meta(meta); + + let response = match meta_response { + LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => match ask { + DebugAsk::ByStage { + stage_name: ref this_stage_name, + .. + } if *this_stage_name == stage_name => value, + _ => return Some(format!("Wrong debug stage")), + }, + _ => return Some(format!("Invalid language meta response")), + }; + Some(response) + } + Show => { + let this_stage_name = match arguments.get(0) { + Some(s) => s.to_string(), + None => return Some(format!("Must specify a stage to show")), + }; + let token = arguments.get(1).map(|s| s.to_string()); + repl.options.debug_asks.retain(|ask| match ask { + DebugAsk::ByStage { stage_name, .. } if *stage_name == this_stage_name => false, + _ => true, + }); + + let ask = DebugAsk::ByStage { + stage_name: this_stage_name, + token, + }; + repl.options.debug_asks.insert(ask); + None + } + Hide => { + let stage_name_to_remove = match arguments.get(0) { + Some(s) => s.to_string(), + None => return Some(format!("Must specify a stage to hide")), + }; + repl.options.debug_asks.retain(|ask| match ask { + DebugAsk::ByStage { stage_name, .. } if *stage_name == stage_name_to_remove => { + false + } + _ => true, + }); + None + } + TotalTimeOff => total_time_off(repl, arguments), + TotalTimeOn => total_time_on(repl, arguments), + StageTimeOff => stage_time_off(repl, arguments), + StageTimeOn => stage_time_on(repl, arguments), + Doc => doc(repl, arguments), } - Some(buf) - }, - ShowImmediate => { - let cur_state = repl.get_cur_language_state(); - let stage_name = match arguments.get(0) { - Some(s) => s.to_string(), - None => return Some(format!("Must specify a thing to debug")), - }; - let meta = LangMetaRequest::ImmediateDebug(DebugAsk::ByStage { stage_name: stage_name.clone(), token: None }); - let meta_response = cur_state.request_meta(meta); - - let response = match meta_response { - LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => match ask { - DebugAsk::ByStage { stage_name: ref this_stage_name, ..} if *this_stage_name == stage_name => value, - _ => return Some(format!("Wrong debug stage")) - }, - _ => return Some(format!("Invalid language meta response")), - }; - Some(response) - }, - Show => { - let this_stage_name = match arguments.get(0) { - Some(s) => s.to_string(), - None => return Some(format!("Must specify a stage to show")), - }; - let token = arguments.get(1).map(|s| s.to_string()); - repl.options.debug_asks.retain(|ask| match ask { - DebugAsk::ByStage { stage_name, .. } if *stage_name == this_stage_name => false, - _ => true - }); - - let ask = DebugAsk::ByStage { stage_name: this_stage_name, token }; - repl.options.debug_asks.insert(ask); - None - }, - Hide => { - let stage_name_to_remove = match arguments.get(0) { - Some(s) => s.to_string(), - None => return Some(format!("Must specify a stage to hide")), - }; - repl.options.debug_asks.retain(|ask| match ask { - DebugAsk::ByStage { stage_name, .. } if *stage_name == stage_name_to_remove => false, - _ => true - }); - None - }, - TotalTimeOff => total_time_off(repl, arguments), - TotalTimeOn => total_time_on(repl, arguments), - StageTimeOff => stage_time_off(repl, arguments), - StageTimeOn => stage_time_on(repl, arguments), - Doc => doc(repl, arguments), } - } } fn total_time_on(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { - repl.options.show_total_time = true; - None + repl.options.show_total_time = true; + None } fn total_time_off(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { - repl.options.show_total_time = false; - None + repl.options.show_total_time = false; + None } fn stage_time_on(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { - repl.options.show_stage_times = true; - None + repl.options.show_stage_times = true; + None } fn stage_time_off(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { - repl.options.show_stage_times = false; - None + repl.options.show_stage_times = false; + None } fn doc(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput { - arguments.get(0).map(|cmd| { - let source = cmd.to_string(); - let meta = LangMetaRequest::Docs { source }; - let cur_state = repl.get_cur_language_state(); - match cur_state.request_meta(meta) { - LangMetaResponse::Docs { doc_string } => Some(doc_string), - _ => Some(format!("Invalid doc response")) - } - }).unwrap_or(Some(format!(":docs needs an argument"))) + arguments + .get(0) + .map(|cmd| { + let source = cmd.to_string(); + let meta = LangMetaRequest::Docs { source }; + let cur_state = repl.get_cur_language_state(); + match cur_state.request_meta(meta) { + LangMetaResponse::Docs { doc_string } => Some(doc_string), + _ => Some(format!("Invalid doc response")), + } + }) + .unwrap_or(Some(format!(":docs needs an argument"))) } - diff --git a/schala-repl/src/repl/directives.rs b/schala-repl/src/repl/directives.rs index c1a91d3..59e78a1 100644 --- a/schala-repl/src/repl/directives.rs +++ b/schala-repl/src/repl/directives.rs @@ -2,54 +2,103 @@ use crate::repl::command_tree::CommandTree; use crate::repl::directive_actions::DirectiveAction; pub fn directives_from_pass_names(pass_names: &Vec) -> CommandTree { - let passes_directives: Vec = pass_names.iter() - .map(|pass_name| { - if pass_name == "parsing" { - CommandTree::nonterm(pass_name, None, vec![ - CommandTree::nonterm_no_further_tab_completions("compact", None), - CommandTree::nonterm_no_further_tab_completions("expanded", None), - CommandTree::nonterm_no_further_tab_completions("trace", None), - ]) - } else { - CommandTree::nonterm_no_further_tab_completions(pass_name, None) - } - }) - .collect(); - CommandTree::Top(get_list(&passes_directives, true)) + let passes_directives: Vec = pass_names + .iter() + .map(|pass_name| { + if pass_name == "parsing" { + CommandTree::nonterm( + pass_name, + None, + vec![ + CommandTree::nonterm_no_further_tab_completions("compact", None), + CommandTree::nonterm_no_further_tab_completions("expanded", None), + CommandTree::nonterm_no_further_tab_completions("trace", None), + ], + ) + } else { + CommandTree::nonterm_no_further_tab_completions(pass_name, None) + } + }) + .collect(); + CommandTree::Top(get_list(&passes_directives, true)) } fn get_list(passes_directives: &Vec, include_help: bool) -> Vec { - use DirectiveAction::*; + use DirectiveAction::*; - vec![ - CommandTree::terminal("exit", Some("exit the REPL"), vec![], QuitProgram), - CommandTree::terminal("quit", Some("exit the REPL"), vec![], QuitProgram), - CommandTree::terminal("help", Some("Print this help message"), if include_help { get_list(passes_directives, false) } else { vec![] }, Help), - CommandTree::nonterm("debug", - Some("Configure debug information"), - vec![ - CommandTree::terminal("list-passes", Some("List all registered compiler passes"), vec![], ListPasses), - CommandTree::terminal("show-immediate", None, passes_directives.clone(), ShowImmediate), - CommandTree::terminal("show", Some("Show debug output for a specific pass"), passes_directives.clone(), Show), - CommandTree::terminal("hide", Some("Hide debug output for a specific pass"), passes_directives.clone(), Hide), - CommandTree::nonterm("total-time", None, vec![ - CommandTree::terminal("on", None, vec![], TotalTimeOn), - CommandTree::terminal("off", None, vec![], TotalTimeOff), - ]), - CommandTree::nonterm("stage-times", Some("Computation time per-stage"), vec![ - CommandTree::terminal("on", None, vec![], StageTimeOn), - CommandTree::terminal("off", None, vec![], StageTimeOff), - ]) - ] - ), - CommandTree::nonterm("lang", - Some("switch between languages, or go directly to a langauge by name"), - vec![ - CommandTree::nonterm_no_further_tab_completions("next", None), - CommandTree::nonterm_no_further_tab_completions("prev", None), - CommandTree::nonterm("go", None, vec![]), - ] - ), - CommandTree::terminal("doc", Some("Get language-specific help for an item"), vec![], Doc), - ] + vec![ + CommandTree::terminal("exit", Some("exit the REPL"), vec![], QuitProgram), + CommandTree::terminal("quit", Some("exit the REPL"), vec![], QuitProgram), + CommandTree::terminal( + "help", + Some("Print this help message"), + if include_help { + get_list(passes_directives, false) + } else { + vec![] + }, + Help, + ), + CommandTree::nonterm( + "debug", + Some("Configure debug information"), + vec![ + CommandTree::terminal( + "list-passes", + Some("List all registered compiler passes"), + vec![], + ListPasses, + ), + CommandTree::terminal( + "show-immediate", + None, + passes_directives.clone(), + ShowImmediate, + ), + CommandTree::terminal( + "show", + Some("Show debug output for a specific pass"), + passes_directives.clone(), + Show, + ), + CommandTree::terminal( + "hide", + Some("Hide debug output for a specific pass"), + passes_directives.clone(), + Hide, + ), + CommandTree::nonterm( + "total-time", + None, + vec![ + CommandTree::terminal("on", None, vec![], TotalTimeOn), + CommandTree::terminal("off", None, vec![], TotalTimeOff), + ], + ), + CommandTree::nonterm( + "stage-times", + Some("Computation time per-stage"), + vec![ + CommandTree::terminal("on", None, vec![], StageTimeOn), + CommandTree::terminal("off", None, vec![], StageTimeOff), + ], + ), + ], + ), + CommandTree::nonterm( + "lang", + Some("switch between languages, or go directly to a langauge by name"), + vec![ + CommandTree::nonterm_no_further_tab_completions("next", None), + CommandTree::nonterm_no_further_tab_completions("prev", None), + CommandTree::nonterm("go", None, vec![]), + ], + ), + CommandTree::terminal( + "doc", + Some("Get language-specific help for an item"), + vec![], + Doc, + ), + ] } diff --git a/schala-repl/src/repl/help.rs b/schala-repl/src/repl/help.rs index 0ac07a2..b39a030 100644 --- a/schala-repl/src/repl/help.rs +++ b/schala-repl/src/repl/help.rs @@ -1,59 +1,83 @@ use std::fmt::Write as FmtWrite; -use colored::*; use super::command_tree::CommandTree; -use super::{Repl, InterpreterDirectiveOutput}; +use super::{InterpreterDirectiveOutput, Repl}; +use colored::*; pub fn help(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput { - match arguments { - [] => return global_help(repl), - commands => { - let dirs = repl.get_directives(); - Some(match get_directive_from_commands(commands, &dirs) { - None => format!("Directive `{}` not found", commands.last().unwrap()), - Some(dir) => { - let mut buf = String::new(); - let cmd = dir.get_cmd(); - let children = dir.get_children(); - writeln!(buf, "`{}` - {}", cmd, dir.get_help()).unwrap(); - for sub in children.iter() { - writeln!(buf, "\t`{} {}` - {}", cmd, sub.get_cmd(), sub.get_help()).unwrap(); - } - buf + match arguments { + [] => return global_help(repl), + commands => { + let dirs = repl.get_directives(); + Some(match get_directive_from_commands(commands, &dirs) { + None => format!("Directive `{}` not found", commands.last().unwrap()), + Some(dir) => { + let mut buf = String::new(); + let cmd = dir.get_cmd(); + let children = dir.get_children(); + writeln!(buf, "`{}` - {}", cmd, dir.get_help()).unwrap(); + for sub in children.iter() { + writeln!(buf, "\t`{} {}` - {}", cmd, sub.get_cmd(), sub.get_help()) + .unwrap(); + } + buf + } + }) } - }) } - } } -fn get_directive_from_commands<'a>(commands: &[&str], dirs: &'a CommandTree) -> Option<&'a CommandTree> { - let mut directive_list = dirs.get_children(); - let mut matched_directive = None; - for cmd in commands { - let found = directive_list.iter().find(|directive| directive.get_cmd() == *cmd); - if let Some(dir) = found { - directive_list = dir.get_children(); - } +fn get_directive_from_commands<'a>( + commands: &[&str], + dirs: &'a CommandTree, +) -> Option<&'a CommandTree> { + let mut directive_list = dirs.get_children(); + let mut matched_directive = None; + for cmd in commands { + let found = directive_list + .iter() + .find(|directive| directive.get_cmd() == *cmd); + if let Some(dir) = found { + directive_list = dir.get_children(); + } - matched_directive = found; - } - matched_directive + matched_directive = found; + } + matched_directive } fn global_help(repl: &mut Repl) -> InterpreterDirectiveOutput { - let mut buf = String::new(); - let sigil = repl.interpreter_directive_sigil; + let mut buf = String::new(); + let sigil = repl.interpreter_directive_sigil; - writeln!(buf, "{} version {}", "Schala REPL".bright_red().bold(), crate::VERSION_STRING).unwrap(); - writeln!(buf, "-----------------------").unwrap(); + writeln!( + buf, + "{} version {}", + "Schala REPL".bright_red().bold(), + crate::VERSION_STRING + ) + .unwrap(); + writeln!(buf, "-----------------------").unwrap(); - for directive in repl.get_directives().get_children() { - writeln!(buf, "{}{} - {}", sigil, directive.get_cmd(), directive.get_help()).unwrap(); - } + for directive in repl.get_directives().get_children() { + writeln!( + buf, + "{}{} - {}", + sigil, + directive.get_cmd(), + directive.get_help() + ) + .unwrap(); + } - let ref lang = repl.get_cur_language_state(); - writeln!(buf, "").unwrap(); - writeln!(buf, "Language-specific help for {}", lang.get_language_name()).unwrap(); - writeln!(buf, "-----------------------").unwrap(); - Some(buf) + let ref lang = repl.get_cur_language_state(); + writeln!(buf, "").unwrap(); + writeln!( + buf, + "Language-specific help for {}", + lang.get_language_name() + ) + .unwrap(); + writeln!(buf, "-----------------------").unwrap(); + Some(buf) } diff --git a/schala-repl/src/repl/mod.rs b/schala-repl/src/repl/mod.rs index 4ce3070..b10906f 100644 --- a/schala-repl/src/repl/mod.rs +++ b/schala-repl/src/repl/mod.rs @@ -1,8 +1,9 @@ -use std::sync::Arc; use std::collections::HashSet; +use std::sync::Arc; -use crate::language::{ProgrammingLanguageInterface, -ComputationRequest, LangMetaResponse, LangMetaRequest}; +use crate::language::{ + ComputationRequest, LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface, +}; mod command_tree; use self::command_tree::CommandTree; @@ -21,231 +22,253 @@ const OPTIONS_SAVE_FILE: &'static str = ".schala_repl"; type InterpreterDirectiveOutput = Option; pub struct Repl { - pub interpreter_directive_sigil: char, - line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>, - language_states: Vec>, - options: ReplOptions, + pub interpreter_directive_sigil: char, + line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>, + language_states: Vec>, + options: ReplOptions, } #[derive(Clone)] enum PromptStyle { - Normal, - Multiline + Normal, + Multiline, } impl Repl { - pub fn new(initial_states: Vec>) -> Repl { - use linefeed::Interface; - let line_reader = Interface::new("schala-repl").unwrap(); - let interpreter_directive_sigil = ':'; + pub fn new(initial_states: Vec>) -> Repl { + use linefeed::Interface; + let line_reader = Interface::new("schala-repl").unwrap(); + let interpreter_directive_sigil = ':'; - Repl { - interpreter_directive_sigil, - line_reader, - language_states: initial_states, - options: ReplOptions::new(), - } - } - - pub fn run_repl(&mut self) { - println!("Schala MetaInterpreter version {}", crate::VERSION_STRING); - println!("Type {}help for help with the REPL", self.interpreter_directive_sigil); - self.load_options(); - self.handle_repl_loop(); - self.save_before_exit(); - println!("Exiting..."); - } - - fn load_options(&mut self) { - self.line_reader.load_history(HISTORY_SAVE_FILE).unwrap_or(()); - match ReplOptions::load_from_file(OPTIONS_SAVE_FILE) { - Ok(options) => { - self.options = options; - }, - Err(()) => () - }; - } - - fn handle_repl_loop(&mut self) { - use linefeed::ReadResult::*; - let sigil = self.interpreter_directive_sigil; - - 'main: loop { - macro_rules! match_or_break { - ($line:expr) => { - match $line { - Err(e) => { - println!("readline IO Error: {}", e); - break 'main; - }, - Ok(Eof) | Ok(Signal(_)) => break 'main, - Ok(Input(ref input)) => input, - } + Repl { + interpreter_directive_sigil, + line_reader, + language_states: initial_states, + options: ReplOptions::new(), } - } - self.update_line_reader(); - let line = self.line_reader.read_line(); - let input: &str = match_or_break!(line); + } - self.line_reader.add_history_unique(input.to_string()); - let mut chars = input.chars().peekable(); - let repl_responses = match chars.nth(0) { - Some(ch) if ch == sigil => { - if chars.peek() == Some(&'{') { - let mut buf = String::new(); - buf.push_str(input.get(2..).unwrap()); - 'multiline: loop { - self.set_prompt(PromptStyle::Multiline); - let new_line = self.line_reader.read_line(); - let new_input = match_or_break!(new_line); - if new_input.starts_with(":}") { - break 'multiline; - } else { - buf.push_str(new_input); - buf.push_str("\n"); - } + pub fn run_repl(&mut self) { + println!("Schala MetaInterpreter version {}", crate::VERSION_STRING); + println!( + "Type {}help for help with the REPL", + self.interpreter_directive_sigil + ); + self.load_options(); + self.handle_repl_loop(); + self.save_before_exit(); + println!("Exiting..."); + } + + fn load_options(&mut self) { + self.line_reader + .load_history(HISTORY_SAVE_FILE) + .unwrap_or(()); + match ReplOptions::load_from_file(OPTIONS_SAVE_FILE) { + Ok(options) => { + self.options = options; } - self.handle_input(&buf) - } else { - match self.handle_interpreter_directive(input) { - Some(directive_output) => println!("<> {}", directive_output), - None => (), + Err(()) => (), + }; + } + + fn handle_repl_loop(&mut self) { + use linefeed::ReadResult::*; + let sigil = self.interpreter_directive_sigil; + + 'main: loop { + macro_rules! match_or_break { + ($line:expr) => { + match $line { + Err(e) => { + println!("readline IO Error: {}", e); + break 'main; + } + Ok(Eof) | Ok(Signal(_)) => break 'main, + Ok(Input(ref input)) => input, + } + }; } - continue - } - }, - _ => self.handle_input(input) - }; + self.update_line_reader(); + let line = self.line_reader.read_line(); + let input: &str = match_or_break!(line); - for repl_response in repl_responses.iter() { - println!("{}", repl_response); - } - } - } + self.line_reader.add_history_unique(input.to_string()); + let mut chars = input.chars().peekable(); + let repl_responses = match chars.nth(0) { + Some(ch) if ch == sigil => { + if chars.peek() == Some(&'{') { + let mut buf = String::new(); + buf.push_str(input.get(2..).unwrap()); + 'multiline: loop { + self.set_prompt(PromptStyle::Multiline); + let new_line = self.line_reader.read_line(); + let new_input = match_or_break!(new_line); + if new_input.starts_with(":}") { + break 'multiline; + } else { + buf.push_str(new_input); + buf.push_str("\n"); + } + } + self.handle_input(&buf) + } else { + match self.handle_interpreter_directive(input) { + Some(directive_output) => println!("<> {}", directive_output), + None => (), + } + continue; + } + } + _ => self.handle_input(input), + }; - fn update_line_reader(&mut self) { - let tab_complete_handler = TabCompleteHandler::new(self.interpreter_directive_sigil, self.get_directives()); - self.line_reader.set_completer(Arc::new(tab_complete_handler)); //TODO fix this here - self.set_prompt(PromptStyle::Normal); - } - - fn set_prompt(&mut self, prompt_style: PromptStyle) { - let prompt_str = match prompt_style { - PromptStyle::Normal => ">> ".to_string(), - PromptStyle::Multiline => ">| ".to_string(), - }; - - self.line_reader.set_prompt(&prompt_str).unwrap(); - } - - fn save_before_exit(&self) { - self.line_reader.save_history(HISTORY_SAVE_FILE).unwrap_or(()); - self.options.save_to_file(OPTIONS_SAVE_FILE); - } - - fn handle_interpreter_directive(&mut self, input: &str) -> InterpreterDirectiveOutput { - let mut iter = input.chars(); - iter.next(); - let arguments: Vec<&str> = iter - .as_str() - .split_whitespace() - .collect(); - - if arguments.len() < 1 { - return None; + for repl_response in repl_responses.iter() { + println!("{}", repl_response); + } + } } - let directives = self.get_directives(); - directives.perform(self, &arguments) - } - - fn get_cur_language_state(&mut self) -> &mut Box { - //TODO this is obviously not complete - &mut self.language_states[0] - } - - fn handle_input(&mut self, input: &str) -> Vec { - let mut debug_requests = HashSet::new(); - for ask in self.options.debug_asks.iter() { - debug_requests.insert(ask.clone()); + fn update_line_reader(&mut self) { + let tab_complete_handler = + TabCompleteHandler::new(self.interpreter_directive_sigil, self.get_directives()); + self.line_reader + .set_completer(Arc::new(tab_complete_handler)); //TODO fix this here + self.set_prompt(PromptStyle::Normal); } - let request = ComputationRequest { source: input, debug_requests }; - let ref mut language_state = self.get_cur_language_state(); - let response = language_state.run_computation(request); - response::handle_computation_response(response, &self.options) - } + fn set_prompt(&mut self, prompt_style: PromptStyle) { + let prompt_str = match prompt_style { + PromptStyle::Normal => ">> ".to_string(), + PromptStyle::Multiline => ">| ".to_string(), + }; - fn get_directives(&mut self) -> CommandTree { - let language_state = self.get_cur_language_state(); - let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) { - LangMetaResponse::StageNames(names) => names, - _ => vec![], - }; + self.line_reader.set_prompt(&prompt_str).unwrap(); + } - directives_from_pass_names(&pass_names) - } + fn save_before_exit(&self) { + self.line_reader + .save_history(HISTORY_SAVE_FILE) + .unwrap_or(()); + self.options.save_to_file(OPTIONS_SAVE_FILE); + } + + fn handle_interpreter_directive(&mut self, input: &str) -> InterpreterDirectiveOutput { + let mut iter = input.chars(); + iter.next(); + let arguments: Vec<&str> = iter.as_str().split_whitespace().collect(); + + if arguments.len() < 1 { + return None; + } + + let directives = self.get_directives(); + directives.perform(self, &arguments) + } + + fn get_cur_language_state(&mut self) -> &mut Box { + //TODO this is obviously not complete + &mut self.language_states[0] + } + + fn handle_input(&mut self, input: &str) -> Vec { + let mut debug_requests = HashSet::new(); + for ask in self.options.debug_asks.iter() { + debug_requests.insert(ask.clone()); + } + + let request = ComputationRequest { + source: input, + debug_requests, + }; + let ref mut language_state = self.get_cur_language_state(); + let response = language_state.run_computation(request); + response::handle_computation_response(response, &self.options) + } + + fn get_directives(&mut self) -> CommandTree { + let language_state = self.get_cur_language_state(); + let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) { + LangMetaResponse::StageNames(names) => names, + _ => vec![], + }; + + directives_from_pass_names(&pass_names) + } } - struct TabCompleteHandler { - sigil: char, - top_level_commands: CommandTree, + sigil: char, + top_level_commands: CommandTree, } -use linefeed::complete::{Completion, Completer}; +use linefeed::complete::{Completer, Completion}; use linefeed::terminal::Terminal; impl TabCompleteHandler { - fn new(sigil: char, top_level_commands: CommandTree) -> TabCompleteHandler { - TabCompleteHandler { - top_level_commands, - sigil, + fn new(sigil: char, top_level_commands: CommandTree) -> TabCompleteHandler { + TabCompleteHandler { + top_level_commands, + sigil, + } } - } } impl Completer for TabCompleteHandler { - fn complete(&self, word: &str, prompter: &::linefeed::prompter::Prompter, start: usize, _end: usize) -> Option> { - let line = prompter.buffer(); + fn complete( + &self, + word: &str, + prompter: &::linefeed::prompter::Prompter, + start: usize, + _end: usize, + ) -> Option> { + let line = prompter.buffer(); - if !line.starts_with(self.sigil) { - return None; - } - - let mut words = line[1..(if start == 0 { 1 } else { start })].split_whitespace(); - let mut completions = Vec::new(); - let mut command_tree: Option<&CommandTree> = Some(&self.top_level_commands); - - loop { - match words.next() { - None => { - let top = match command_tree { - Some(CommandTree::Top(_)) => true, - _ => false - }; - let word = if top { word.get(1..).unwrap() } else { word }; - for cmd in command_tree.map(|x| x.get_subcommands()).unwrap_or(vec![]).into_iter() { - if cmd.starts_with(word) { - completions.push(Completion { - completion: format!("{}{}", if top { ":" } else { "" }, cmd), - display: Some(cmd.to_string()), - suffix: ::linefeed::complete::Suffix::Some(' ') - }) - } - } - break; - }, - Some(s) => { - let new_ptr: Option<&CommandTree> = command_tree.and_then(|cm| match cm { - CommandTree::Top(children) => children.iter().find(|c| c.get_cmd() == s), - CommandTree::NonTerminal { children, .. } => children.iter().find(|c| c.get_cmd() == s), - CommandTree::Terminal { children, .. } => children.iter().find(|c| c.get_cmd() == s), - }); - command_tree = new_ptr; + if !line.starts_with(self.sigil) { + return None; } - } + + let mut words = line[1..(if start == 0 { 1 } else { start })].split_whitespace(); + let mut completions = Vec::new(); + let mut command_tree: Option<&CommandTree> = Some(&self.top_level_commands); + + loop { + match words.next() { + None => { + let top = match command_tree { + Some(CommandTree::Top(_)) => true, + _ => false, + }; + let word = if top { word.get(1..).unwrap() } else { word }; + for cmd in command_tree + .map(|x| x.get_subcommands()) + .unwrap_or(vec![]) + .into_iter() + { + if cmd.starts_with(word) { + completions.push(Completion { + completion: format!("{}{}", if top { ":" } else { "" }, cmd), + display: Some(cmd.to_string()), + suffix: ::linefeed::complete::Suffix::Some(' '), + }) + } + } + break; + } + Some(s) => { + let new_ptr: Option<&CommandTree> = command_tree.and_then(|cm| match cm { + CommandTree::Top(children) => children.iter().find(|c| c.get_cmd() == s), + CommandTree::NonTerminal { children, .. } => { + children.iter().find(|c| c.get_cmd() == s) + } + CommandTree::Terminal { children, .. } => { + children.iter().find(|c| c.get_cmd() == s) + } + }); + command_tree = new_ptr; + } + } + } + Some(completions) } - Some(completions) - } } diff --git a/schala-repl/src/repl/repl_options.rs b/schala-repl/src/repl/repl_options.rs index b14f624..2dc8626 100644 --- a/schala-repl/src/repl/repl_options.rs +++ b/schala-repl/src/repl/repl_options.rs @@ -1,47 +1,46 @@ use crate::language::DebugAsk; -use std::io::{Read, Write}; use std::collections::HashSet; use std::fs::File; +use std::io::{Read, Write}; #[derive(Serialize, Deserialize)] pub struct ReplOptions { - pub debug_asks: HashSet, - pub show_total_time: bool, - pub show_stage_times: bool, + pub debug_asks: HashSet, + pub show_total_time: bool, + pub show_stage_times: bool, } impl ReplOptions { - pub fn new() -> ReplOptions { - ReplOptions { - debug_asks: HashSet::new(), - show_total_time: true, - show_stage_times: false, + pub fn new() -> ReplOptions { + ReplOptions { + debug_asks: HashSet::new(), + show_total_time: true, + show_stage_times: false, + } } - } - pub fn save_to_file(&self, filename: &str) { - let res = File::create(filename) - .and_then(|mut file| { - let buf = crate::serde_json::to_string(self).unwrap(); - file.write_all(buf.as_bytes()) - }); - if let Err(err) = res { - println!("Error saving {} file {}", filename, err); + pub fn save_to_file(&self, filename: &str) { + let res = File::create(filename).and_then(|mut file| { + let buf = crate::serde_json::to_string(self).unwrap(); + file.write_all(buf.as_bytes()) + }); + if let Err(err) = res { + println!("Error saving {} file {}", filename, err); + } } - } - pub fn load_from_file(filename: &str) -> Result { - File::open(filename) - .and_then(|mut file| { - let mut contents = String::new(); - file.read_to_string(&mut contents)?; - Ok(contents) - }) - .and_then(|contents| { - let output: ReplOptions = crate::serde_json::from_str(&contents)?; - Ok(output) - }) - .map_err(|_| ()) - } + pub fn load_from_file(filename: &str) -> Result { + File::open(filename) + .and_then(|mut file| { + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + Ok(contents) + }) + .and_then(|contents| { + let output: ReplOptions = crate::serde_json::from_str(&contents)?; + Ok(output) + }) + .map_err(|_| ()) + } } diff --git a/schala-repl/src/repl/response.rs b/schala-repl/src/repl/response.rs index b5423fc..2414e58 100644 --- a/schala-repl/src/repl/response.rs +++ b/schala-repl/src/repl/response.rs @@ -3,65 +3,78 @@ use std::fmt; use std::fmt::Write; use super::ReplOptions; -use crate::language::{ DebugAsk, ComputationResponse}; +use crate::language::{ComputationResponse, DebugAsk}; pub struct ReplResponse { - label: Option, - text: String, - color: Option + label: Option, + text: String, + color: Option, } impl fmt::Display for ReplResponse { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut buf = String::new(); - if let Some(ref label) = self.label { - write!(buf, "({})", label).unwrap(); + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut buf = String::new(); + if let Some(ref label) = self.label { + write!(buf, "({})", label).unwrap(); + } + write!(buf, "=> {}", self.text).unwrap(); + write!( + f, + "{}", + match self.color { + Some(c) => buf.color(c), + None => buf.normal(), + } + ) } - write!(buf, "=> {}", self.text).unwrap(); - write!(f, "{}", match self.color { - Some(c) => buf.color(c), - None => buf.normal() - }) - } } +pub fn handle_computation_response( + response: ComputationResponse, + options: &ReplOptions, +) -> Vec { + let mut responses = vec![]; -pub fn handle_computation_response(response: ComputationResponse, options: &ReplOptions) -> Vec { - let mut responses = vec![]; + if options.show_total_time { + responses.push(ReplResponse { + label: Some("Total time".to_string()), + text: format!("{:?}", response.global_output_stats.total_duration), + color: None, + }); + } - if options.show_total_time { - responses.push(ReplResponse { - label: Some("Total time".to_string()), - text: format!("{:?}", response.global_output_stats.total_duration), - color: None, + if options.show_stage_times { + responses.push(ReplResponse { + label: Some("Stage times".to_string()), + text: format!("{:?}", response.global_output_stats.stage_durations), + color: None, + }); + } + + for debug_resp in response.debug_responses { + let stage_name = match debug_resp.ask { + DebugAsk::ByStage { stage_name, .. } => stage_name, + _ => continue, + }; + responses.push(ReplResponse { + label: Some(stage_name.to_string()), + text: debug_resp.value, + color: Some(Color::Red), + }); + } + + responses.push(match response.main_output { + Ok(s) => ReplResponse { + label: None, + text: s, + color: None, + }, + Err(e) => ReplResponse { + label: Some("Error".to_string()), + text: e, + color: Some(Color::Red), + }, }); - } - if options.show_stage_times { - responses.push(ReplResponse { - label: Some("Stage times".to_string()), - text: format!("{:?}", response.global_output_stats.stage_durations), - color: None, - }); - } - - for debug_resp in response.debug_responses { - let stage_name = match debug_resp.ask { - DebugAsk::ByStage { stage_name, .. } => stage_name, - _ => continue, - }; - responses.push(ReplResponse { - label: Some(stage_name.to_string()), - text: debug_resp.value, - color: Some(Color::Red), - }); - } - - responses.push(match response.main_output { - Ok(s) => ReplResponse { label: None, text: s, color: None }, - Err(e) => ReplResponse { label: Some("Error".to_string()), text: e, color: Some(Color::Red) }, - }); - - responses + responses } -