1use std::io::Write;
2use std::marker::PhantomData;
3
4use crate::acore::opt::Opt;
5use crate::acore::Error;
6use crate::shell::Shell;
7use crate::SHELL_ZSH;
8
9pub struct Zsh<O, W> {
10 w: Option<W>,
11 __marker: PhantomData<O>,
12}
13
14impl<O, W> Default for Zsh<O, W> {
15 fn default() -> Self {
16 Self {
17 w: Default::default(),
18 __marker: Default::default(),
19 }
20 }
21}
22
23impl<O, W> Zsh<O, W> {
24 pub fn new() -> Self {
25 Self {
26 w: None,
27 __marker: PhantomData,
28 }
29 }
30
31 pub fn buffer(&mut self) -> Result<&mut W, Error> {
32 self.w
33 .as_mut()
34 .ok_or_else(|| crate::error!("must set buffer before write to"))
35 }
36
37 pub fn with_buffer(mut self, w: W) -> Self {
38 self.w = Some(w);
39 self
40 }
41}
42
43macro_rules! wln2buf {
44 ($w:expr, $fmt:literal, $($arg:tt)*) => {
45 writeln!( $w, $fmt, $($arg)* )
46 .map_err(|e| $crate::error!("can not write to buffer: {e:?}"))
47 };
48}
49
50impl<O, W> Shell<O, W> for Zsh<O, W>
51where
52 W: Write,
53 O: Opt,
54{
55 type Err = Error;
56
57 fn is_avail(&self, name: &str) -> bool {
58 name == SHELL_ZSH
59 }
60
61 fn set_buff(&mut self, w: W) {
62 self.w = Some(w);
63 }
64
65 fn write_cmd(&mut self, name: &str, opt: &O) -> Result<(), Self::Err> {
66 if opt.help().is_empty() {
67 wln2buf!(self.buffer()?, "{}", name)
68 } else {
69 wln2buf!(self.buffer()?, "{}:{}", name, opt.help())
70 }
71 }
72
73 fn write_opt(&mut self, name: &str, opt: &O) -> Result<(), Self::Err> {
74 if opt.help().is_empty() {
75 wln2buf!(self.buffer()?, "{}", name)
76 } else {
77 wln2buf!(self.buffer()?, "{}:{}", name, opt.help())
78 }
79 }
80
81 fn write_pos(&mut self, name: &str, opt: &O) -> Result<(), Self::Err> {
82 if opt.help().is_empty() {
83 wln2buf!(self.buffer()?, "{}", name)
84 } else {
85 wln2buf!(self.buffer()?, "{}:{}", name, opt.help())
86 }
87 }
88
89 fn write_val(&mut self, val: &std::ffi::OsStr, _: &O) -> Result<(), Self::Err> {
90 wln2buf!(self.buffer()?, "{}", val.display())
91 }
92
93 fn write_eq(&mut self, name: &str, val: &std::ffi::OsStr, _: &O) -> Result<(), Self::Err> {
94 wln2buf!(self.buffer()?, "{}={}", name, val.display())
95 }
96
97 fn finish(&mut self) -> Result<(), Self::Err> {
98 Ok(())
99 }
100
101 fn take_buff(&mut self) -> Option<W> {
102 self.w.take()
103 }
104}