1use super::{Context, Input, Result};
20use crate::Env;
21use crate::option::Option::Verbose;
22use crate::option::State::On;
23use crate::system::concurrency::WriteAll;
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: WriteAll, T: Input> Input for Echo<'_, '_, S, T> {
64 #[allow(
65 clippy::await_holding_refcell_ref,
66 reason = "other decorators, the parser, or the executor do not run concurrently with this method"
67 )]
68 async fn next_line(&mut self, context: &Context) -> Result {
69 let line = self.inner.next_line(context).await?;
70
71 let env = &mut **self.env.borrow_mut();
72 if env.options.get(Verbose) == On {
73 env.system.print_error(&line).await;
74 }
75
76 Ok(line)
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::super::Memory;
83 use super::*;
84 use crate::system::Concurrent;
85 use crate::system::r#virtual::VirtualSystem;
86 use crate::test_helper::assert_stderr;
87 use futures_util::FutureExt as _;
88 use std::rc::Rc;
89
90 #[test]
91 fn verbose_off() {
92 let system = VirtualSystem::new();
93 let state = Rc::clone(&system.state);
94 let mut env = Env::with_system(Rc::new(Concurrent::new(system)));
95 let ref_env = RefCell::new(&mut env);
96 let memory = Memory::new("echo test\n");
97 let mut echo = Echo::new(memory, &ref_env);
98
99 let line = echo
100 .next_line(&Context::default())
101 .now_or_never()
102 .unwrap()
103 .unwrap();
104 assert_eq!(line, "echo test\n");
105 assert_stderr(&state, |stderr| assert_eq!(stderr, ""));
106 }
107
108 #[test]
109 fn verbose_on() {
110 let system = VirtualSystem::new();
111 let state = Rc::clone(&system.state);
112 let mut env = Env::with_system(Rc::new(Concurrent::new(system)));
113 env.options.set(Verbose, On);
114 let ref_env = RefCell::new(&mut env);
115 let memory = Memory::new("echo test\nfoo");
116 let mut echo = Echo::new(memory, &ref_env);
117
118 let line = echo
119 .next_line(&Context::default())
120 .now_or_never()
121 .unwrap()
122 .unwrap();
123 assert_eq!(line, "echo test\n");
124 assert_stderr(&state, |stderr| assert_eq!(stderr, "echo test\n"));
125
126 let line = echo
127 .next_line(&Context::default())
128 .now_or_never()
129 .unwrap()
130 .unwrap();
131 assert_eq!(line, "foo");
132 assert_stderr(&state, |stderr| assert_eq!(stderr, "echo test\nfoo"));
133 }
134}