1use super::{Context, Input, Result};
20use crate::Env;
21use crate::option::Option::Verbose;
22use crate::option::State::On;
23use crate::system::{Fcntl, Write};
24use std::cell::RefCell;
25
26#[derive(Debug)]
33#[doc(alias = "Verbose")]
34#[must_use = "Echo does nothing unless used by a parser"]
35pub struct Echo<'a, 'b, S, T> {
36 inner: T,
37 env: &'a RefCell<&'b mut Env<S>>,
38}
39
40impl<'a, 'b, S, T> Echo<'a, 'b, S, T> {
41 pub fn new(inner: T, env: &'a RefCell<&'b mut Env<S>>) -> Self {
49 Self { inner, env }
50 }
51}
52
53impl<S, T: Clone> Clone for Echo<'_, '_, S, T> {
55 fn clone(&self) -> Self {
56 Self {
57 inner: self.inner.clone(),
58 env: self.env,
59 }
60 }
61}
62
63impl<S: Fcntl + Write, T: Input> Input for Echo<'_, '_, S, T> {
64 #[allow(clippy::await_holding_refcell_ref)]
67 async fn next_line(&mut self, context: &Context) -> Result {
68 let line = self.inner.next_line(context).await?;
69
70 let env = &mut **self.env.borrow_mut();
71 if env.options.get(Verbose) == On {
72 env.system.print_error(&line).await;
73 }
74
75 Ok(line)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::super::Memory;
82 use super::*;
83 use crate::system::r#virtual::VirtualSystem;
84 use crate::tests::assert_stderr;
85 use futures_util::FutureExt;
86 use std::rc::Rc;
87
88 #[test]
89 fn verbose_off() {
90 let system = VirtualSystem::new();
91 let state = Rc::clone(&system.state);
92 let mut env = Env::with_system(system);
93 let ref_env = RefCell::new(&mut env);
94 let memory = Memory::new("echo test\n");
95 let mut echo = Echo::new(memory, &ref_env);
96
97 let line = echo
98 .next_line(&Context::default())
99 .now_or_never()
100 .unwrap()
101 .unwrap();
102 assert_eq!(line, "echo test\n");
103 assert_stderr(&state, |stderr| assert_eq!(stderr, ""));
104 }
105
106 #[test]
107 fn verbose_on() {
108 let system = VirtualSystem::new();
109 let state = Rc::clone(&system.state);
110 let mut env = Env::with_system(system);
111 env.options.set(Verbose, On);
112 let ref_env = RefCell::new(&mut env);
113 let memory = Memory::new("echo test\nfoo");
114 let mut echo = Echo::new(memory, &ref_env);
115
116 let line = echo
117 .next_line(&Context::default())
118 .now_or_never()
119 .unwrap()
120 .unwrap();
121 assert_eq!(line, "echo test\n");
122 assert_stderr(&state, |stderr| assert_eq!(stderr, "echo test\n"));
123
124 let line = echo
125 .next_line(&Context::default())
126 .now_or_never()
127 .unwrap()
128 .unwrap();
129 assert_eq!(line, "foo");
130 assert_stderr(&state, |stderr| assert_eq!(stderr, "echo test\nfoo"));
131 }
132}