Color output

This commit is contained in:
Patrick Lühne 2020-05-12 04:25:49 +02:00
parent 2de8a59b63
commit 7d06601c17
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
4 changed files with 251 additions and 58 deletions

View File

@ -5,11 +5,13 @@ authors = ["Patrick Lühne <patrick@luehne.de>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
atty = "0.2"
foliage = {git = "https://github.com/pluehne/foliage", branch = "parser-new"} foliage = {git = "https://github.com/pluehne/foliage", branch = "parser-new"}
log = "0.4" log = "0.4"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"
regex = "1" regex = "1"
structopt = "0.3" structopt = "0.3"
termcolor = "1.1"
[dependencies.clingo] [dependencies.clingo]
git = "https://github.com/potassco/clingo-rs" git = "https://github.com/potassco/clingo-rs"

View File

@ -1,5 +1,8 @@
pub(crate) mod shell;
pub(crate) mod tptp; pub(crate) mod tptp;
pub(crate) use shell::Shell;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Format pub enum Format
{ {

126
src/output/shell.rs Normal file
View File

@ -0,0 +1,126 @@
pub struct Shell
{
output: ShellOutput,
}
enum ShellOutput
{
Basic(Box<dyn std::io::Write>),
WithColorSupport
{
stream: termcolor::StandardStream,
color_choice: ColorChoice,
is_a_tty: bool,
},
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum ColorChoice
{
Always,
Never,
Auto,
}
impl Shell
{
pub fn from_stdout() -> Self
{
Self
{
output: ShellOutput::WithColorSupport
{
stream:
termcolor::StandardStream::stdout(ColorChoice::Auto.to_termcolor_color_choice()),
color_choice: ColorChoice::Auto,
is_a_tty: atty::is(atty::Stream::Stdout),
},
}
}
pub fn print(&mut self, text: &dyn std::fmt::Display, color: &termcolor::ColorSpec)
-> std::io::Result<()>
{
self.output.print(text, color)
}
pub fn println(&mut self, text: &dyn std::fmt::Display, color: &termcolor::ColorSpec)
-> std::io::Result<()>
{
self.output.println(text, color)
}
pub fn erase_line(&mut self)
{
self.output.erase_line();
}
}
impl ShellOutput
{
fn print(&mut self, text: &dyn std::fmt::Display, color: &termcolor::ColorSpec)
-> std::io::Result<()>
{
use std::io::Write as _;
use termcolor::WriteColor as _;
match *self
{
Self::Basic(ref mut write) => write!(write, "{}", text),
Self::WithColorSupport{ref mut stream, ..} =>
{
stream.reset()?;
stream.set_color(color)?;
write!(stream, "{}", text)?;
stream.reset()
},
}
}
fn println(&mut self, text: &dyn std::fmt::Display, color: &termcolor::ColorSpec)
-> std::io::Result<()>
{
self.print(text, color)?;
use std::io::Write as _;
match *self
{
Self::Basic(ref mut write) => writeln!(write, ""),
Self::WithColorSupport{ref mut stream, ..} => writeln!(stream, ""),
}
}
#[cfg(unix)]
pub fn erase_line(&mut self)
{
let erase_sequence = b"\x1b[2K";
use std::io::Write as _;
let _ = match *self
{
Self::Basic(ref mut write) => write.write_all(erase_sequence),
Self::WithColorSupport{ref mut stream, ..} => stream.write_all(erase_sequence),
};
}
}
impl ColorChoice
{
fn to_termcolor_color_choice(self) -> termcolor::ColorChoice
{
match self
{
Self::Always => termcolor::ColorChoice::Always,
Self::Never => termcolor::ColorChoice::Never,
Self::Auto => match atty::is(atty::Stream::Stdout)
{
true => termcolor::ColorChoice::Auto,
false => termcolor::ColorChoice::Never,
},
}
}
}

View File

@ -18,6 +18,9 @@ pub enum StatementKind
enum ProofStatus enum ProofStatus
{ {
AssumedProven, AssumedProven,
Proven,
NotProven,
Disproven,
ToProveNow, ToProveNow,
ToProveLater, ToProveLater,
Ignored, Ignored,
@ -96,6 +99,8 @@ pub struct Problem
pub input_predicate_declarations: std::cell::RefCell<foliage::PredicateDeclarations>, pub input_predicate_declarations: std::cell::RefCell<foliage::PredicateDeclarations>,
// TODO: clean up as variable declarations are dropped // TODO: clean up as variable declarations are dropped
variable_declaration_domains: std::cell::RefCell<VariableDeclarationDomains>, variable_declaration_domains: std::cell::RefCell<VariableDeclarationDomains>,
shell: std::cell::RefCell<crate::output::Shell>,
} }
impl Problem impl Problem
@ -117,6 +122,8 @@ impl Problem
std::cell::RefCell::new(foliage::PredicateDeclarations::new()), std::cell::RefCell::new(foliage::PredicateDeclarations::new()),
variable_declaration_domains: variable_declaration_domains:
std::cell::RefCell::new(VariableDeclarationDomains::new()), std::cell::RefCell::new(VariableDeclarationDomains::new()),
shell: std::cell::RefCell::new(crate::output::Shell::from_stdout()),
} }
} }
@ -128,12 +135,25 @@ impl Problem
section.push(statement); section.push(statement);
} }
fn print_step_title(&self, step_title: &str, color: &termcolor::ColorSpec)
{
let longest_possible_key = " Finished";
self.shell.borrow_mut().print(
&format!("{:>step_title_width$} ", step_title,
step_title_width = longest_possible_key.chars().count()),
color);
}
pub fn prove(&self, proof_direction: ProofDirection) -> Result<(), crate::Error> pub fn prove(&self, proof_direction: ProofDirection) -> Result<(), crate::Error>
{ {
if proof_direction == ProofDirection::Forward if proof_direction == ProofDirection::Forward
|| proof_direction == ProofDirection::Both || proof_direction == ProofDirection::Both
{ {
println!("Verifying assertions from completed definitions"); self.print_step_title("Started",
termcolor::ColorSpec::new().set_bold(true).set_fg(Some(termcolor::Color::Green)));
self.shell.borrow_mut().println(&"verification of assertions from completed definitions",
&termcolor::ColorSpec::new());
let mut statements = self.statements.borrow_mut(); let mut statements = self.statements.borrow_mut();
@ -157,10 +177,20 @@ impl Problem
drop(statements); drop(statements);
self.prove_unproven_statements()?; let proof_result = self.prove_unproven_statements()?;
print_step_title("Finished proof"); let mut step_title_color = termcolor::ColorSpec::new();
println!(""); step_title_color.set_bold(true);
match proof_result
{
ProofResult::Proven => step_title_color.set_fg(Some(termcolor::Color::Green)),
ProofResult::NotProven => step_title_color.set_fg(Some(termcolor::Color::Yellow)),
ProofResult::Disproven => step_title_color.set_fg(Some(termcolor::Color::Red)),
};
self.print_step_title("Finished", &step_title_color);
println!("verification of assertions from completed definitions");
} }
if proof_direction == ProofDirection::Both if proof_direction == ProofDirection::Both
@ -171,7 +201,10 @@ impl Problem
if proof_direction == ProofDirection::Backward if proof_direction == ProofDirection::Backward
|| proof_direction == ProofDirection::Both || proof_direction == ProofDirection::Both
{ {
println!("Verifying completed definitions from assertions"); self.print_step_title("Started",
termcolor::ColorSpec::new().set_bold(true).set_fg(Some(termcolor::Color::Green)));
self.shell.borrow_mut().println(&"verification of completed definitions from assertions",
&termcolor::ColorSpec::new());
let mut statements = self.statements.borrow_mut(); let mut statements = self.statements.borrow_mut();
@ -195,10 +228,20 @@ impl Problem
drop(statements); drop(statements);
self.prove_unproven_statements()?; let proof_result = self.prove_unproven_statements()?;
print_step_title("Finished proof"); let mut step_title_color = termcolor::ColorSpec::new();
println!(""); step_title_color.set_bold(true);
match proof_result
{
ProofResult::Proven => step_title_color.set_fg(Some(termcolor::Color::Green)),
ProofResult::NotProven => step_title_color.set_fg(Some(termcolor::Color::Yellow)),
ProofResult::Disproven => step_title_color.set_fg(Some(termcolor::Color::Red)),
};
self.print_step_title("Finished", &step_title_color);
println!("verification of completed definitions from assertions");
} }
Ok(()) Ok(())
@ -223,7 +266,7 @@ impl Problem
None None
} }
fn prove_unproven_statements(&self) -> Result<(), crate::Error> fn prove_unproven_statements(&self) -> Result<ProofResult, crate::Error>
{ {
let format_context = FormatContext let format_context = FormatContext
{ {
@ -239,21 +282,39 @@ impl Problem
{ {
let step_title = match statement.proof_status let step_title = match statement.proof_status
{ {
ProofStatus::AssumedProven => format!("{}", section_kind.display_capitalized()), ProofStatus::AssumedProven => format!("Established"),
ProofStatus::ToProveNow => format!("Verifying {}", section_kind), ProofStatus::Proven => format!("Verified"),
ProofStatus::ToProveLater => format!("Skipping {}", section_kind), ProofStatus::NotProven
ProofStatus::Ignored => format!("Ignoring {}", section_kind), | ProofStatus::Disproven
| ProofStatus::ToProveNow => format!("Verifying"),
ProofStatus::ToProveLater => format!("Skipped"),
ProofStatus::Ignored => format!("Ignored"),
}; };
print_step_title(&step_title); let mut step_title_color = termcolor::ColorSpec::new();
step_title_color.set_bold(true);
match statement.proof_status
{
ProofStatus::AssumedProven
| ProofStatus::Proven => step_title_color.set_fg(Some(termcolor::Color::Green)),
ProofStatus::NotProven => step_title_color.set_fg(Some(termcolor::Color::Yellow)),
ProofStatus::Disproven => step_title_color.set_fg(Some(termcolor::Color::Red)),
_ => step_title_color.set_fg(Some(termcolor::Color::Cyan)),
};
self.print_step_title(&step_title, &step_title_color);
self.shell.borrow_mut().print(&format!("{}: ", section_kind),
&termcolor::ColorSpec::new());
match statement.kind match statement.kind
{ {
StatementKind::Program => StatementKind::Program =>
println!("{}", print!("{}",
foliage::format::display_formula(&statement.formula, format_context)), foliage::format::display_formula(&statement.formula, format_context)),
_ => _ =>
println!("{}", statement.formula), print!("{}", statement.formula),
} }
}; };
@ -264,6 +325,7 @@ impl Problem
.filter(|statement| statement.proof_status == ProofStatus::AssumedProven) .filter(|statement| statement.proof_status == ProofStatus::AssumedProven)
{ {
display_statement(*section_kind, statement, &format_context); display_statement(*section_kind, statement, &format_context);
println!("");
} }
} }
@ -274,7 +336,12 @@ impl Problem
{ {
statement.proof_status = ProofStatus::ToProveNow; statement.proof_status = ProofStatus::ToProveNow;
print!("\x1b[s");
display_statement(section_kind, statement, &format_context); display_statement(section_kind, statement, &format_context);
print!("\x1b[u");
use std::io::Write as _;
std::io::stdout().flush();
}) })
{ {
Some(_) => (), Some(_) => (),
@ -293,50 +360,49 @@ impl Problem
// TODO: make configurable again // TODO: make configurable again
let (proof_result, proof_time_seconds) = let (proof_result, proof_time_seconds) =
run_vampire(&tptp_problem_to_prove_next_statement, run_vampire(&tptp_problem_to_prove_next_statement,
Some(&["--mode", "casc", "--cores", "8", "--time_limit", "300"]))?; Some(&["--mode", "casc", "--cores", "8", "--time_limit", "15"]))?;
match self.next_unproven_statement_do_mut(
|section_kind, statement|
{
statement.proof_status = match proof_result
{
ProofResult::Proven => ProofStatus::Proven,
ProofResult::NotProven => ProofStatus::NotProven,
ProofResult::Disproven => ProofStatus::Disproven,
};
self.shell.borrow_mut().erase_line();
display_statement(section_kind, statement, &format_context);
match proof_result match proof_result
{ {
ProofResult::NotProven => ProofResult::Proven => (),
{ ProofResult::NotProven => print!(" (not proven)"),
print_step_title(""); ProofResult::Disproven => print!(" (disproven)"),
println!("⌛ could not prove statement");
return Ok(());
},
ProofResult::Disproven =>
{
print_step_title("");
println!("× statement disproven");
return Ok(());
},
_ => (),
} }
match self.next_unproven_statement_do_mut( if let Some(proof_time_seconds) = proof_time_seconds
|_, statement| statement.proof_status = ProofStatus::AssumedProven) {
self.shell.borrow_mut().print(&format!(" in {} seconds", proof_time_seconds),
termcolor::ColorSpec::new().set_fg(Some(termcolor::Color::Black)).set_intense(true));
}
})
{ {
Some(_) => (), Some(_) => (),
None => unreachable!("could not set the statement to proven"), None => unreachable!(),
} }
match proof_time_seconds self.shell.borrow_mut().println(&"", &termcolor::ColorSpec::new());
if proof_result != ProofResult::Proven
{ {
None => return Ok(proof_result);
{
print_step_title("");
println!("✓ statement proven");
},
Some(proof_time_seconds) =>
{
print_step_title("");
println!("✓ statement proven in {} seconds", proof_time_seconds);
},
} }
} }
Ok(()) Ok(ProofResult::Proven)
} }
fn write_tptp_problem_to_prove_next_statement(&self, formatter: &mut String) -> std::fmt::Result fn write_tptp_problem_to_prove_next_statement(&self, formatter: &mut String) -> std::fmt::Result
@ -476,7 +542,10 @@ impl Problem
let statement_type = match statement.proof_status let statement_type = match statement.proof_status
{ {
ProofStatus::AssumedProven => "axiom", ProofStatus::AssumedProven
| ProofStatus::Proven => "axiom",
ProofStatus::NotProven
| ProofStatus::Disproven => unreachable!(),
ProofStatus::ToProveNow => "conjecture", ProofStatus::ToProveNow => "conjecture",
// Skip statements that will be proven later // Skip statements that will be proven later
ProofStatus::ToProveLater => continue, ProofStatus::ToProveLater => continue,
@ -673,13 +742,6 @@ impl<'a, 'b> foliage::format::Format for FormatContext<'a, 'b>
} }
} }
fn print_step_title(title: &str)
{
let longest_possible_key = "Verifying completed definition";
print!("{:>title_width$} ", title, title_width = longest_possible_key.chars().count())
}
fn run_vampire<I, S>(input: &str, arguments: Option<I>) fn run_vampire<I, S>(input: &str, arguments: Option<I>)
-> Result<(ProofResult, Option<f32>), crate::Error> -> Result<(ProofResult, Option<f32>), crate::Error>
where where