rush-shell 0.1.1

Rush CLI shell
//! Shell I/O functionality for process/sub-processes input and output.
//!
//! This make equivalent object streams to standard raw streams.
//! This try to follow similar API as Rust's `std::io` module.
//!
//! # File descriptors equivalents
//!
//! |        | STDIO | OBJIO |
//! | ------ |:-----:|:-----:|
//! | Input  |   0   |   3   |
//! | Output |   1   |   4   |
//! | Error  |   2   |   5   |
//! 

use std::io::{stdin, stdout, Write, BufReader, BufRead};
use std::fs::{File};
use std::path::{Path};

const OBJECT_IN_FILE_NUMBER: i32 = 3;
const OBJECT_OUT_FILE_NUMBER: i32 = 4;
const OBJECT_ERR_FILE_NUMBER: i32 = 5;

pub trait ObjectRead<T> {
    fn read(&mut self) -> std::io::Result<T>;
}

pub trait ObjectWrite<T> {
    fn write(&mut self, object: T) -> std::io::Result<()>;
    fn flush(&mut self) -> std::io::Result<()>;
}

pub enum Input {
    Stdin {
        prompt: String,
    },
    Script {
        file: BufReader<File>,
    }
}

impl Input {
    pub fn from_stdin() -> Self { Self::Stdin { prompt: ">".to_string() } }
    pub fn from_script_file(path: &Path) -> std::io::Result<Self> {
        let file = BufReader::new(File::open(path)?);
        return Ok(Self::Script { file });
    }
    pub fn is_stdin(&self) -> bool {
        match self {
            Self::Stdin {..} => true,
            _ => false,
        }
    }
    pub fn is_script(&self) -> bool { !self.is_stdin() }
    pub fn read_line(&mut self, mut input_line: &mut String) -> std::io::Result<usize> {
        match self {
            Self::Stdin { prompt } => {
                // If stdin is not a tty it does not need
                // to show prompt as it is not a user.
                if atty::is(atty::Stream::Stdin) {
                    let stdout = stdout();
                    let mut stdout = stdout.lock();
                    write!(stdout, "{} ", prompt)?;
                    stdout.flush()?;
                }
                return stdin().read_line(&mut input_line);
            }
            Self::Script { file } => {
                return file.read_line(&mut input_line);
            }
        }
    }
}