aopt-shell 0.3.2

A flexible and typed getopt tools
Documentation
use std::io::Write;
use std::marker::PhantomData;

use crate::acore::opt::Opt;
use crate::acore::Error;
use crate::shell::Shell;
use crate::SHELL_PSH;
use crate::SHELL_PSH7;

pub struct PowerShell<O, W> {
    name: &'static str,
    w: Option<W>,
    __marker: PhantomData<O>,
}

impl<O, W> Default for PowerShell<O, W> {
    fn default() -> Self {
        Self {
            name: SHELL_PSH,
            w: Default::default(),
            __marker: Default::default(),
        }
    }
}

impl<O, W> PowerShell<O, W> {
    pub fn new() -> Self {
        Self {
            name: SHELL_PSH,
            w: None,
            __marker: PhantomData,
        }
    }

    pub fn new7() -> Self {
        Self {
            name: SHELL_PSH7,
            w: None,
            __marker: PhantomData,
        }
    }

    pub fn buffer(&mut self) -> Result<&mut W, Error> {
        self.w
            .as_mut()
            .ok_or_else(|| crate::error!("must set buffer before write to"))
    }

    pub fn with_buffer(mut self, w: W) -> Self {
        self.w = Some(w);
        self
    }
}

macro_rules! wln2buf {
    ($w:expr, $fmt:literal, $($arg:tt)*) => {
        writeln!( $w, $fmt, $($arg)* )
            .map_err(|e| $crate::error!("can not write to buffer: {e:?}"))
    };
}

impl<O, W> Shell<O, W> for PowerShell<O, W>
where
    W: Write,
    O: Opt,
{
    type Err = Error;

    fn is_avail(&self, name: &str) -> bool {
        name == self.name
    }

    fn set_buff(&mut self, w: W) {
        self.w = Some(w);
    }

    fn write_cmd(&mut self, name: &str, opt: &O) -> Result<(), Self::Err> {
        if opt.help().is_empty() {
            wln2buf!(self.buffer()?, "{}", name)
        } else {
            wln2buf!(self.buffer()?, "{}\t{}", name, opt.help())
        }
    }

    fn write_opt(&mut self, name: &str, opt: &O) -> Result<(), Self::Err> {
        if opt.help().is_empty() {
            wln2buf!(self.buffer()?, "{}", name)
        } else {
            wln2buf!(self.buffer()?, "{}\t{}", name, opt.help())
        }
    }

    fn write_pos(&mut self, name: &str, opt: &O) -> Result<(), Self::Err> {
        if opt.help().is_empty() {
            wln2buf!(self.buffer()?, "{}", name)
        } else {
            wln2buf!(self.buffer()?, "{}\t{}", name, opt.help())
        }
    }

    fn write_val(&mut self, val: &std::ffi::OsStr, _: &O) -> Result<(), Self::Err> {
        wln2buf!(self.buffer()?, "{}", val.display())
    }

    fn write_eq(&mut self, name: &str, val: &std::ffi::OsStr, _: &O) -> Result<(), Self::Err> {
        wln2buf!(self.buffer()?, "{}={}", name, val.display())
    }

    fn finish(&mut self) -> Result<(), Self::Err> {
        Ok(())
    }

    fn take_buff(&mut self) -> Option<W> {
        self.w.take()
    }
}