mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-23 00:44:55 +03:00
Create Term structure to manage immediate and buffered stdout/stderr.
This commit is contained in:
parent
831dce6c8c
commit
3c4646dfdd
@ -196,10 +196,11 @@ impl Client {
|
||||
// Logs method, version and request headers now.
|
||||
if verbose {
|
||||
logger.debug_method_version_out(&lines[0]);
|
||||
for header in &request_headers {
|
||||
logger.debug_header_out(&header.name, &header.value);
|
||||
}
|
||||
logger.info(">");
|
||||
let headers = request_headers
|
||||
.iter()
|
||||
.map(|h| (h.name.as_str(), h.value.as_str()))
|
||||
.collect::<Vec<_>>();
|
||||
logger.debug_headers_out(&headers);
|
||||
}
|
||||
|
||||
// If we don't send any data, we log an empty body here instead of relying on
|
||||
@ -309,10 +310,13 @@ impl Client {
|
||||
.filter(|s| s.starts_with("HTTP/"))
|
||||
.for_each(|s| logger.debug_status_version_in(s.trim()));
|
||||
|
||||
for header in &response.headers {
|
||||
logger.debug_header_in(&header.name, &header.value);
|
||||
}
|
||||
logger.info("<");
|
||||
let headers = response
|
||||
.headers
|
||||
.iter()
|
||||
.map(|h| (h.name.as_str(), h.value.as_str()))
|
||||
.collect::<Vec<_>>();
|
||||
logger.debug_headers_in(&headers);
|
||||
|
||||
if very_verbose {
|
||||
logger.debug_important("Response body:");
|
||||
response.log_body(true, logger);
|
||||
|
@ -39,7 +39,7 @@ impl Response {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log_all(&self, logger: &Logger) {
|
||||
pub fn log_info_all(&self, logger: &Logger) {
|
||||
let status_line = self.get_status_line_headers(logger.color);
|
||||
logger.info(&status_line);
|
||||
self.log_body(false, logger);
|
||||
|
@ -68,8 +68,6 @@ pub fn write_body(
|
||||
Some(Output::File(file)) => Output::File(file.to_string()).write(&output, None)?,
|
||||
_ => runner::Output::StdOut.write(&output, None)?,
|
||||
}
|
||||
} else {
|
||||
logger.info("No response has been received");
|
||||
}
|
||||
} else {
|
||||
let source = if filename_in == "-" {
|
||||
|
@ -90,6 +90,7 @@ pub fn run(
|
||||
}
|
||||
};
|
||||
|
||||
// Now, we have a syntactically correct HurlFile instance, we can run it.
|
||||
log_run_info(&hurl_file, runner_options, variables, &logger);
|
||||
|
||||
let result = run_entries(
|
||||
@ -113,7 +114,6 @@ fn run_entries(
|
||||
variables: &HashMap<String, Value>,
|
||||
logger: &mut Logger,
|
||||
) -> HurlResult {
|
||||
// Now, we have a syntactically correct HurlFile instance, we can run it.
|
||||
let mut http_client = Client::new();
|
||||
let mut entries_result = vec![];
|
||||
let mut variables = variables.clone();
|
||||
@ -477,10 +477,7 @@ fn log_errors(entry_result: &EntryResult, content: &str, retry: bool, logger: &L
|
||||
|
||||
if logger.error_format == ErrorFormat::Long {
|
||||
if let Some(Call { response, .. }) = entry_result.calls.last() {
|
||||
response.log_all(logger);
|
||||
} else {
|
||||
logger.info("<No HTTP response>");
|
||||
logger.info("");
|
||||
response.log_info_all(logger);
|
||||
}
|
||||
}
|
||||
entry_result
|
||||
|
@ -22,6 +22,7 @@ use hurl_core::ast::SourceInfo;
|
||||
use hurl_core::error::Error;
|
||||
|
||||
use crate::runner::{HurlResult, Value};
|
||||
use crate::util::term::{Term, WriteMode};
|
||||
|
||||
/// A simple logger to log app related event (start, high levels error, etc...).
|
||||
/// When we run an [`hurl_core::ast::HurlFile`], user has to provide a dedicated Hurl logger (see [`Logger`]).
|
||||
@ -36,7 +37,7 @@ impl BaseLogger {
|
||||
}
|
||||
|
||||
pub fn info(&self, message: &str) {
|
||||
log_info(message);
|
||||
eprintln!("{message}");
|
||||
}
|
||||
|
||||
pub fn debug(&self, message: &str) {
|
||||
@ -44,25 +45,25 @@ impl BaseLogger {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug(message);
|
||||
eprintln!("{} {message}", "*".blue().bold());
|
||||
} else {
|
||||
log_debug_no_color(message);
|
||||
eprintln!("* {message}");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warning(&self, message: &str) {
|
||||
if self.color {
|
||||
log_warning(message);
|
||||
eprintln!("{}: {}", "warning".yellow().bold(), message.bold());
|
||||
} else {
|
||||
log_warning_no_color(message);
|
||||
eprintln!("warning: {message}");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(&self, message: &str) {
|
||||
if self.color {
|
||||
log_error(message);
|
||||
eprintln!("{}: {}", "error".red().bold(), message.bold());
|
||||
} else {
|
||||
log_error_no_color(message);
|
||||
eprintln!("error: {message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,6 +100,7 @@ pub struct Logger {
|
||||
pub(crate) progress_bar: bool,
|
||||
pub(crate) test: bool,
|
||||
pub(crate) verbosity: Option<Verbosity>,
|
||||
term: Term,
|
||||
}
|
||||
|
||||
impl From<&LoggerOptions> for Logger {
|
||||
@ -110,6 +112,7 @@ impl From<&LoggerOptions> for Logger {
|
||||
progress_bar: options.progress_bar,
|
||||
test: options.test,
|
||||
verbosity: options.verbosity,
|
||||
term: Term::new(WriteMode::Immediate),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -204,7 +207,7 @@ impl Default for LoggerOptionsBuilder {
|
||||
|
||||
impl Logger {
|
||||
pub fn info(&self, message: &str) {
|
||||
log_info(message);
|
||||
self.term.eprintln(message);
|
||||
}
|
||||
|
||||
pub fn debug(&self, message: &str) {
|
||||
@ -212,53 +215,9 @@ impl Logger {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug(message);
|
||||
self.term.eprintln_prefix(&"*".blue().bold(), message);
|
||||
} else {
|
||||
log_debug_no_color(message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_curl(&self, message: &str) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_curl(message);
|
||||
} else {
|
||||
log_debug_curl_no_color(message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_error<E: Error>(&self, content: &str, error: &E, entry_src_info: SourceInfo) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_error(&self.filename, content, error, entry_src_info);
|
||||
} else {
|
||||
log_debug_error_no_color(&self.filename, content, error, entry_src_info);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_header_in(&self, name: &str, value: &str) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_header_in(name, value);
|
||||
} else {
|
||||
log_debug_header_in_no_color(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_header_out(&self, name: &str, value: &str) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_header_out(name, value);
|
||||
} else {
|
||||
log_debug_header_out_no_color(name, value);
|
||||
self.term.eprintln_prefix("*", message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,45 +226,103 @@ impl Logger {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_important(message);
|
||||
self.term
|
||||
.eprintln_prefix(&"*".blue().bold(), &message.bold());
|
||||
} else {
|
||||
log_debug_no_color(message);
|
||||
self.term.eprintln_prefix("*", message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_curl(&self, message: &str) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
self.term.eprintln_prefix(&"**".blue().bold(), message);
|
||||
} else {
|
||||
self.term.eprintln_prefix("**", message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_error<E: Error>(&self, content: &str, error: &E, entry_src_info: SourceInfo) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
let message = error_string(
|
||||
&self.filename,
|
||||
content,
|
||||
error,
|
||||
Some(entry_src_info),
|
||||
self.color,
|
||||
);
|
||||
split_lines(&message).iter().for_each(|l| self.debug(l));
|
||||
}
|
||||
|
||||
pub fn debug_headers_in(&self, headers: &[(&str, &str)]) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
for (name, value) in headers {
|
||||
if self.color {
|
||||
self.term
|
||||
.eprintln(&format!("< {}: {}", name.cyan().bold(), value));
|
||||
} else {
|
||||
self.term.eprintln(&format!("< {}: {}", name, value));
|
||||
}
|
||||
}
|
||||
self.term.eprintln("<");
|
||||
}
|
||||
|
||||
pub fn debug_headers_out(&self, headers: &[(&str, &str)]) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
for (name, value) in headers {
|
||||
if self.color {
|
||||
self.term
|
||||
.eprintln(&format!("> {}: {}", name.cyan().bold(), value));
|
||||
} else {
|
||||
self.term.eprintln(&format!("> {}: {}", name, value));
|
||||
}
|
||||
}
|
||||
self.term.eprintln(">");
|
||||
}
|
||||
|
||||
pub fn debug_status_version_in(&self, line: &str) {
|
||||
if self.verbosity.is_none() {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_status_version_in(line);
|
||||
self.term.eprintln(&format!("< {}", line.green().bold()));
|
||||
} else {
|
||||
log_debug_status_version_in_no_color(line);
|
||||
self.term.eprintln(&format!("< {line}"));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warning(&self, message: &str) {
|
||||
if self.color {
|
||||
log_warning(message);
|
||||
self.term.eprintln(&format!(
|
||||
"{}: {}",
|
||||
"warning".yellow().bold(),
|
||||
message.bold()
|
||||
));
|
||||
} else {
|
||||
log_warning_no_color(message);
|
||||
self.term.eprintln(&format!("warning: {message}"));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(&self, message: &str) {
|
||||
if self.color {
|
||||
log_error(message);
|
||||
self.term
|
||||
.eprintln(&format!("{}: {}", "error".red().bold(), message.bold()));
|
||||
} else {
|
||||
log_error_no_color(message);
|
||||
self.term.eprintln(&format!("error: {message}"));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_parsing_rich<E: Error>(&self, content: &str, error: &E) {
|
||||
if self.color {
|
||||
log_error_rich(&self.filename, content, error, None);
|
||||
} else {
|
||||
log_error_rich_no_color(&self.filename, content, error, None);
|
||||
}
|
||||
let message = error_string(&self.filename, content, error, None, self.color);
|
||||
self.error_rich(&message);
|
||||
}
|
||||
|
||||
pub fn error_runtime_rich<E: Error>(
|
||||
@ -314,10 +331,22 @@ impl Logger {
|
||||
error: &E,
|
||||
entry_src_info: SourceInfo,
|
||||
) {
|
||||
let message = error_string(
|
||||
&self.filename,
|
||||
content,
|
||||
error,
|
||||
Some(entry_src_info),
|
||||
self.color,
|
||||
);
|
||||
self.error_rich(&message);
|
||||
}
|
||||
|
||||
fn error_rich(&self, message: &str) {
|
||||
if self.color {
|
||||
log_error_rich(&self.filename, content, error, Some(entry_src_info));
|
||||
self.term
|
||||
.eprintln(&format!("{}: {message}\n", "error".red().bold()));
|
||||
} else {
|
||||
log_error_rich_no_color(&self.filename, content, error, Some(entry_src_info));
|
||||
self.term.eprintln(&format!("error: {message}\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,9 +355,9 @@ impl Logger {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_debug_method_version_out(line);
|
||||
self.term.eprintln(&format!("> {}", line.purple().bold()));
|
||||
} else {
|
||||
log_debug_method_version_out_no_color(line);
|
||||
self.term.eprintln(&format!("> {line}"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,20 +366,42 @@ impl Logger {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_capture(name, value);
|
||||
self.term.eprintln(&format!(
|
||||
"{} {}: {value}",
|
||||
"*".blue().bold(),
|
||||
name.yellow().bold()
|
||||
));
|
||||
} else {
|
||||
log_capture_no_color(name, value);
|
||||
self.term.eprintln(&format!("* {name}: {value}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Term {
|
||||
fn eprintln_prefix(&self, prefix: &str, message: &str) {
|
||||
if message.is_empty() {
|
||||
self.eprintln(prefix);
|
||||
} else {
|
||||
self.eprintln(&format!("{prefix} {message}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// WIP: These methods must be removed from `Logger`. Semantically, they're using for reporting
|
||||
/// test progress and we need to extract them from `Logger`.
|
||||
impl Logger {
|
||||
pub fn test_running(&self, current: usize, total: usize) {
|
||||
if !self.test {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_test_running(&self.filename, current, total);
|
||||
eprintln!(
|
||||
"{}: {} [{current}/{total}]",
|
||||
self.filename.bold(),
|
||||
"Running".cyan().bold()
|
||||
);
|
||||
} else {
|
||||
log_test_running_no_color(&self.filename, current, total);
|
||||
eprintln!("{}: Running [{current}/{total}]", self.filename);
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,7 +409,8 @@ impl Logger {
|
||||
if !self.progress_bar {
|
||||
return;
|
||||
}
|
||||
log_test_progress(entry_index, count);
|
||||
let progress = progress_string(entry_index, count);
|
||||
eprint!(" {progress}\r");
|
||||
}
|
||||
|
||||
pub fn test_completed(&self, result: &HurlResult) {
|
||||
@ -366,9 +418,26 @@ impl Logger {
|
||||
return;
|
||||
}
|
||||
if self.color {
|
||||
log_test_completed(result, &self.filename);
|
||||
let state = if result.success {
|
||||
"Success".green().bold()
|
||||
} else {
|
||||
"Failure".red().bold()
|
||||
};
|
||||
let count = result.entries.iter().flat_map(|r| &r.calls).count();
|
||||
eprintln!(
|
||||
"{}: {} ({} request(s) in {} ms)",
|
||||
self.filename.bold(),
|
||||
state,
|
||||
count,
|
||||
result.time_in_ms
|
||||
);
|
||||
} else {
|
||||
log_test_completed_no_color(result, &self.filename);
|
||||
let state = if result.success { "Success" } else { "Failure" };
|
||||
let count = result.entries.iter().flat_map(|r| &r.calls).count();
|
||||
eprintln!(
|
||||
"{}: {} ({} request(s) in {} ms)",
|
||||
self.filename, state, count, result.time_in_ms
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,162 +452,6 @@ impl Logger {
|
||||
}
|
||||
}
|
||||
|
||||
fn log_info(message: &str) {
|
||||
eprintln!("{message}");
|
||||
}
|
||||
|
||||
fn log_debug(message: &str) {
|
||||
if message.is_empty() {
|
||||
eprintln!("{}", "*".blue().bold());
|
||||
} else {
|
||||
eprintln!("{} {}", "*".blue().bold(), message);
|
||||
}
|
||||
}
|
||||
|
||||
fn log_debug_no_color(message: &str) {
|
||||
if message.is_empty() {
|
||||
eprintln!("*");
|
||||
} else {
|
||||
eprintln!("* {message}");
|
||||
}
|
||||
}
|
||||
|
||||
fn log_debug_curl(message: &str) {
|
||||
if message.is_empty() {
|
||||
eprintln!("{}", "**".blue().bold());
|
||||
} else {
|
||||
eprintln!("{} {}", "**".blue().bold(), message.green());
|
||||
}
|
||||
}
|
||||
|
||||
fn log_debug_curl_no_color(message: &str) {
|
||||
if message.is_empty() {
|
||||
eprintln!("**");
|
||||
} else {
|
||||
eprintln!("** {message}");
|
||||
}
|
||||
}
|
||||
|
||||
fn log_debug_important(message: &str) {
|
||||
if message.is_empty() {
|
||||
eprintln!("{}", "*".blue().bold());
|
||||
} else {
|
||||
eprintln!("{} {}", "*".blue().bold(), message.bold());
|
||||
}
|
||||
}
|
||||
|
||||
fn log_debug_error<E: Error>(filename: &str, content: &str, error: &E, entry_src_info: SourceInfo) {
|
||||
let message = error_string(filename, content, error, Some(entry_src_info), true);
|
||||
split_lines(&message).iter().for_each(|l| log_debug(l));
|
||||
}
|
||||
|
||||
fn log_debug_error_no_color<E: Error>(
|
||||
filename: &str,
|
||||
content: &str,
|
||||
error: &E,
|
||||
entry_src_info: SourceInfo,
|
||||
) {
|
||||
let message = error_string(filename, content, error, Some(entry_src_info), false);
|
||||
split_lines(&message)
|
||||
.iter()
|
||||
.for_each(|l| log_debug_no_color(l));
|
||||
}
|
||||
|
||||
fn log_debug_header_in(name: &str, value: &str) {
|
||||
eprintln!("< {}: {}", name.cyan().bold(), value);
|
||||
}
|
||||
|
||||
fn log_debug_header_in_no_color(name: &str, value: &str) {
|
||||
eprintln!("< {name}: {value}");
|
||||
}
|
||||
|
||||
fn log_debug_header_out(name: &str, value: &str) {
|
||||
eprintln!("> {}: {}", name.cyan().bold(), value);
|
||||
}
|
||||
|
||||
fn log_debug_header_out_no_color(name: &str, value: &str) {
|
||||
eprintln!("> {name}: {value}");
|
||||
}
|
||||
|
||||
fn log_debug_method_version_out(line: &str) {
|
||||
eprintln!("> {}", line.purple().bold());
|
||||
}
|
||||
|
||||
fn log_debug_method_version_out_no_color(line: &str) {
|
||||
eprintln!("> {line}");
|
||||
}
|
||||
|
||||
fn log_debug_status_version_in(line: &str) {
|
||||
eprintln!("< {}", line.green().bold());
|
||||
}
|
||||
|
||||
fn log_debug_status_version_in_no_color(line: &str) {
|
||||
eprintln!("< {line}");
|
||||
}
|
||||
|
||||
fn log_warning(message: &str) {
|
||||
eprintln!("{}: {}", "warning".yellow().bold(), message.bold());
|
||||
}
|
||||
|
||||
fn log_warning_no_color(message: &str) {
|
||||
eprintln!("warning: {message}");
|
||||
}
|
||||
|
||||
fn log_error(message: &str) {
|
||||
eprintln!("{}: {}", "error".red().bold(), message.bold());
|
||||
}
|
||||
|
||||
fn log_error_no_color(message: &str) {
|
||||
eprintln!("error: {message}");
|
||||
}
|
||||
|
||||
fn log_error_rich<E: Error>(
|
||||
filename: &str,
|
||||
content: &str,
|
||||
error: &E,
|
||||
entry_src_info: Option<SourceInfo>,
|
||||
) {
|
||||
let message = error_string(filename, content, error, entry_src_info, true);
|
||||
eprintln!("{}: {}\n", "error".red().bold(), &message);
|
||||
}
|
||||
|
||||
fn log_error_rich_no_color<E: Error>(
|
||||
filename: &str,
|
||||
content: &str,
|
||||
error: &E,
|
||||
entry_src_info: Option<SourceInfo>,
|
||||
) {
|
||||
let message = error_string(filename, content, error, entry_src_info, false);
|
||||
eprintln!("error: {}\n", &message);
|
||||
}
|
||||
|
||||
fn log_capture(name: &str, value: &Value) {
|
||||
eprintln!("{} {}: {}", "*".blue().bold(), name.yellow().bold(), value);
|
||||
}
|
||||
|
||||
fn log_capture_no_color(name: &str, value: &Value) {
|
||||
eprintln!("* {name}: {value}");
|
||||
}
|
||||
|
||||
fn log_test_running(filename: &str, current: usize, total: usize) {
|
||||
eprintln!(
|
||||
"{}: {} [{}/{}]",
|
||||
filename.bold(),
|
||||
"Running".cyan().bold(),
|
||||
current,
|
||||
total
|
||||
);
|
||||
}
|
||||
|
||||
fn log_test_running_no_color(filename: &str, current: usize, total: usize) {
|
||||
eprintln!("{filename}: Running [{current}/{total}]");
|
||||
}
|
||||
|
||||
fn log_test_progress(entry_index: usize, count: usize) {
|
||||
let progress = progress_string(entry_index, count);
|
||||
eprint!(" {progress}\r");
|
||||
}
|
||||
|
||||
/// Returns the progress string with the current entry at `entry_index`.
|
||||
fn progress_string(entry_index: usize, count: usize) -> String {
|
||||
const WIDTH: usize = 24;
|
||||
@ -554,31 +467,6 @@ fn progress_string(entry_index: usize, count: usize) -> String {
|
||||
format!("[{completed}>{void}] {entry_index}/{count}")
|
||||
}
|
||||
|
||||
fn log_test_completed(result: &HurlResult, filename: &str) {
|
||||
let state = if result.success {
|
||||
"Success".green().bold()
|
||||
} else {
|
||||
"Failure".red().bold()
|
||||
};
|
||||
let count = result.entries.iter().flat_map(|r| &r.calls).count();
|
||||
eprintln!(
|
||||
"{}: {} ({} request(s) in {} ms)",
|
||||
filename.bold(),
|
||||
state,
|
||||
count,
|
||||
result.time_in_ms
|
||||
);
|
||||
}
|
||||
|
||||
fn log_test_completed_no_color(result: &HurlResult, filename: &str) {
|
||||
let state = if result.success { "Success" } else { "Failure" };
|
||||
let count = result.entries.iter().flat_map(|r| &r.calls).count();
|
||||
eprintln!(
|
||||
"{}: {} ({} request(s) in {} ms)",
|
||||
filename, state, count, result.time_in_ms
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the string representation of an `error`, given `lines` of content and a `filename`.
|
||||
///
|
||||
/// The source information where the error occurred can be retrieved in `error`; optionally,
|
||||
|
@ -17,3 +17,4 @@
|
||||
*/
|
||||
pub mod logger;
|
||||
pub mod path;
|
||||
mod term;
|
||||
|
42
packages/hurl/src/util/term.rs
Normal file
42
packages/hurl/src/util/term.rs
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Hurl (https://hurl.dev)
|
||||
* Copyright (C) 2024 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Term {
|
||||
mode: WriteMode,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum WriteMode {
|
||||
Immediate,
|
||||
Buffered,
|
||||
}
|
||||
|
||||
impl Term {
|
||||
pub fn new(mode: WriteMode) -> Self {
|
||||
Term { mode }
|
||||
}
|
||||
|
||||
pub fn eprintln(&self, message: &str) {
|
||||
match self.mode {
|
||||
WriteMode::Immediate => eprintln!("{message}"),
|
||||
WriteMode::Buffered => {}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user