use super::{Context, Input, Result};
use crate::Env;
use crate::option::Option::Verbose;
use crate::option::State::On;
use crate::system::{Fcntl, Write};
use std::cell::RefCell;
#[derive(Debug)]
#[doc(alias = "Verbose")]
#[must_use = "Echo does nothing unless used by a parser"]
pub struct Echo<'a, 'b, S, T> {
inner: T,
env: &'a RefCell<&'b mut Env<S>>,
}
impl<'a, 'b, S, T> Echo<'a, 'b, S, T> {
pub fn new(inner: T, env: &'a RefCell<&'b mut Env<S>>) -> Self {
Self { inner, env }
}
}
impl<S, T: Clone> Clone for Echo<'_, '_, S, T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
env: self.env,
}
}
}
impl<S: Fcntl + Write, T: Input> Input for Echo<'_, '_, S, T> {
#[allow(clippy::await_holding_refcell_ref)]
async fn next_line(&mut self, context: &Context) -> Result {
let line = self.inner.next_line(context).await?;
let env = &mut **self.env.borrow_mut();
if env.options.get(Verbose) == On {
env.system.print_error(&line).await;
}
Ok(line)
}
}
#[cfg(test)]
mod tests {
use super::super::Memory;
use super::*;
use crate::system::r#virtual::VirtualSystem;
use crate::test_helper::assert_stderr;
use futures_util::FutureExt;
use std::rc::Rc;
#[test]
fn verbose_off() {
let system = VirtualSystem::new();
let state = Rc::clone(&system.state);
let mut env = Env::with_system(system);
let ref_env = RefCell::new(&mut env);
let memory = Memory::new("echo test\n");
let mut echo = Echo::new(memory, &ref_env);
let line = echo
.next_line(&Context::default())
.now_or_never()
.unwrap()
.unwrap();
assert_eq!(line, "echo test\n");
assert_stderr(&state, |stderr| assert_eq!(stderr, ""));
}
#[test]
fn verbose_on() {
let system = VirtualSystem::new();
let state = Rc::clone(&system.state);
let mut env = Env::with_system(system);
env.options.set(Verbose, On);
let ref_env = RefCell::new(&mut env);
let memory = Memory::new("echo test\nfoo");
let mut echo = Echo::new(memory, &ref_env);
let line = echo
.next_line(&Context::default())
.now_or_never()
.unwrap()
.unwrap();
assert_eq!(line, "echo test\n");
assert_stderr(&state, |stderr| assert_eq!(stderr, "echo test\n"));
let line = echo
.next_line(&Context::default())
.now_or_never()
.unwrap()
.unwrap();
assert_eq!(line, "foo");
assert_stderr(&state, |stderr| assert_eq!(stderr, "echo test\nfoo"));
}
}