diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fancyfmt.rs | 55 | ||||
| -rw-r--r-- | src/install.rs | 13 | ||||
| -rw-r--r-- | src/main.rs | 9 | ||||
| -rw-r--r-- | src/uiutil.rs | 20 | 
4 files changed, 74 insertions, 23 deletions
diff --git a/src/fancyfmt.rs b/src/fancyfmt.rs new file mode 100644 index 0000000..6c631b3 --- /dev/null +++ b/src/fancyfmt.rs @@ -0,0 +1,55 @@ +//! This module provides some methods for "fancily" formatting data. +//! +//! This mainly exists so that we can have a version of [`std::fmt::Display`] that can use the +//! colors provided by [`termcolor`]. +use std::io::Write; + +use anyhow::Result; +use modderbaas::{contentdb::ContentMeta, World}; +use termcolor::{Color, ColorSpec, StandardStream, WriteColor}; + +/// A trait for objects to output them to a (possibly) colored stream. +pub trait ColoredDisplay { +    /// Output the object to the colored stream. +    fn fmt(&self, output: &mut StandardStream) -> Result<()>; +} + +impl<T: ColoredDisplay> ColoredDisplay for &T { +    fn fmt(&self, output: &mut StandardStream) -> Result<()> { +        (*self).fmt(output) +    } +} + +impl ColoredDisplay for &str { +    fn fmt(&self, output: &mut StandardStream) -> Result<()> { +        write!(output, "{}", *self)?; +        Ok(()) +    } +} + +impl ColoredDisplay for String { +    fn fmt(&self, output: &mut StandardStream) -> Result<()> { +        (self as &str).fmt(output) +    } +} + +impl ColoredDisplay for World { +    fn fmt(&self, output: &mut StandardStream) -> Result<()> { +        write!(output, "{}", self)?; +        Ok(()) +    } +} + +impl ColoredDisplay for ContentMeta { +    fn fmt(&self, output: &mut StandardStream) -> Result<()> { +        output.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?; +        write!(output, "{}", self.title)?; +        output.reset()?; +        write!(output, " by ")?; +        output.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)))?; +        write!(output, "{}", self.author)?; +        output.reset()?; +        write!(output, " - {}", self.short_description)?; +        Ok(()) +    } +} diff --git a/src/install.rs b/src/install.rs index 56754d3..e34ffc3 100644 --- a/src/install.rs +++ b/src/install.rs @@ -69,21 +69,12 @@ impl<'o, 'p> Installer for InteractiveInstaller<'o, 'p> {          } else if candidates.len() == 1 {              Ok(Source::Http(candidates.into_iter().next().unwrap().url))          } else { -            let items = candidates -                .into_iter() -                .map(|c| { -                    ( -                        format!("{} by {} - {}", c.title, c.author, c.short_description), -                        c, -                    ) -                }) -                .collect::<Vec<_>>();              writeln!(                  &mut self.output,                  "{} candidates found, please select one:", -                items.len() +                candidates.len()              )?; -            let candidate = user_choice(&items, self.output)?; +            let candidate = user_choice(&candidates, self.output)?;              Ok(Source::Http(candidate.url.clone()))          }      } diff --git a/src/main.rs b/src/main.rs index 5390479..20e8653 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,8 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};  use modderbaas::{baas::Baas, MineMod, Snapshot, World}; +mod fancyfmt; +  mod uiutil;  use uiutil::{ask_continue, user_choice}; @@ -137,8 +139,11 @@ fn select_world(      }      // Here, we cannot do an automatic selection, so ask the user: -    let mut worlds = worlds.iter().collect::<Vec<_>>(); -    worlds.sort_by_key(|i| i.0); +    let worlds = worlds +        .iter() +        .sorted_by_key(|i| i.0) +        .map(|i| i.1) +        .collect::<Vec<_>>();      writeln!(          output,          "The following worlds were found, please select one:" diff --git a/src/uiutil.rs b/src/uiutil.rs index 188e20c..0cc88a9 100644 --- a/src/uiutil.rs +++ b/src/uiutil.rs @@ -1,22 +1,22 @@  //! Utility functions for user interaction. -use std::{ -    fmt::Display, -    io::{self, Write}, -}; +use std::io::{self, Write};  use anyhow::{bail, Result};  use termcolor::{Color, ColorSpec, StandardStream, WriteColor}; +use super::fancyfmt::ColoredDisplay; +  /// Presents the user with a choice of items and awaits a selection. -pub fn user_choice<'i, L: Display, I>( -    items: &'i [(L, I)], +pub fn user_choice<'i, I: ColoredDisplay>( +    items: &'i [I],      output: &mut StandardStream,  ) -> Result<&'i I> { -    for (i, (label, _)) in items.iter().enumerate() { +    for (i, item) in items.iter().enumerate() {          output.set_color(ColorSpec::new().set_fg(Some(Color::Blue)))?; -        write!(output, "[{}]", i)?; +        write!(output, "[{}] ", i)?;          output.reset()?; -        writeln!(output, " {}", label)?; +        item.fmt(output)?; +        writeln!(output)?;      }      let stdin = io::stdin(); @@ -27,7 +27,7 @@ pub fn user_choice<'i, L: Display, I>(          stdin.read_line(&mut buffer)?;          if let Ok(number) = buffer.trim().parse::<usize>() {              if number < items.len() { -                return Ok(&items[number].1); +                return Ok(&items[number]);              }          }      }  | 
