diff --git a/src/lib.rs b/src/lib.rs index 73c396f..339f1e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,41 +1,29 @@ use std::fmt; use std::process::Command; -/// A command to run. -pub struct CommandLine { - program: String, - args: Vec, -} - -impl CommandLine { - /// Creates a new command line. - pub fn new(program: &str, args: &[&str]) -> CommandLine { - CommandLine { - program: program.to_string(), - args: args.iter().map(|x| String::from(*x)).collect::>(), - } - } - - /// Creates the command from the command line. - pub fn command(self) -> Command { - let mut command = Command::new(self.program); - command.args(&self.args); - command - } +/// Helper to create commands in one line. +pub fn command(program: &str, args: &[&str]) -> Command { + let mut command = Command::new(program); + command.args(args); + command } /// The supported package manager. #[derive(Copy, Clone)] pub enum PackageManager { + /// The apt manager, availble on Debian, Ubuntu and others. Apt, + + /// The pacman manager, available on ArchLinux, Manjaro and others. Pacman, } impl PackageManager { - pub fn install<'a>(&self, package: &'a str) -> CommandLine { + /// Returns the command to install a page using the right package manager. + pub fn install<'a>(&self, package: &'a str) -> Command { match self { - PackageManager::Apt => CommandLine::new("sudo", &["apt", "install", package]), - PackageManager::Pacman => CommandLine::new("sudo", &["pacman", "-S", package]), + PackageManager::Apt => command("sudo", &["apt", "install", package]), + PackageManager::Pacman => command("sudo", &["pacman", "-S", package]), } } } @@ -43,21 +31,23 @@ impl PackageManager { /// All the installable components. #[derive(Copy, Clone)] pub enum Component { + /// Whether the user is allowed to run sudo commands. Sudo, + + /// Git enables to clone repository, which is necessary for many components. Git, + + /// The configuration uses the zsh shell. Zsh, + + /// The configuration files. Dotfiles, } impl Component { /// List all components. pub fn all() -> Vec { - vec![ - Component::Sudo, - Component::Git, - Component::Zsh, - Component::Dotfiles, - ] + vec![Component::Git, Component::Zsh, Component::Dotfiles] } /// Installs a component. @@ -70,6 +60,16 @@ impl Component { } } + /// Returns a command that tests if a component is installed. + pub fn is_installed(self) -> bool { + match self { + Component::Sudo => panic!("can't use is_installed() on Component::Sudo"), + Component::Git => todo!(), + Component::Zsh => todo!(), + Component::Dotfiles => todo!(), + } + } + /// Returns the dependencies of each component. pub fn dependencies(self) -> &'static [Component] { match self { @@ -84,7 +84,7 @@ impl Component { impl fmt::Display for Component { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { - Component::Sudo => write!(fmt, "root"), + Component::Sudo => write!(fmt, "sudo"), Component::Git => write!(fmt, "git"), Component::Zsh => write!(fmt, "zsh"), Component::Dotfiles => write!(fmt, "dotfiles"), @@ -93,12 +93,47 @@ impl fmt::Display for Component { } /// The struct that holds the information about the install. -pub struct Installer; +pub struct Installer { + /// All the components to install, and whether the users want to install them. + components: Vec<(Component, bool)>, + + /// Where the users cursor is. + cursor: usize, +} impl Installer { /// Creates a new installer. pub fn new() -> Installer { - Installer + Installer { + components: Component::all().into_iter().map(|x| (x, true)).collect(), + cursor: 0, + } + } + + /// Prints the installer. + pub fn print(&self) { + print!("{}", self); + } +} + +impl fmt::Display for Installer { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + for (index, (component, to_install)) in self.components.iter().enumerate() { + writeln!( + fmt, + "{} [{}] {} (requires {})", + if self.cursor == index { ">" } else { " " }, + if *to_install { "x" } else { " " }, + component, + component + .dependencies() + .into_iter() + .map(|x| format!("{}", x)) + .collect::>() + .join(", ") + )?; + } + Ok(()) } } @@ -111,9 +146,12 @@ impl fmt::Display for Error { } } +/// The result type of this library. pub type Result = std::result::Result; /// Runs the installer pub fn main() -> Result<()> { + let installer = Installer::new(); + installer.print(); Ok(()) }