Add configurable color options

This commit is contained in:
Lucien Greathouse
2020-03-18 12:03:07 -07:00
parent 0b0fe01a7c
commit 9f0a6101b8
3 changed files with 77 additions and 14 deletions

View File

@@ -3,12 +3,12 @@ use std::{env, error::Error, panic, process};
use backtrace::Backtrace; use backtrace::Backtrace;
use structopt::StructOpt; use structopt::StructOpt;
use librojo::cli::{self, Options, Subcommand}; use librojo::cli::{self, GlobalOptions, Options, Subcommand};
fn run(subcommand: Subcommand) -> Result<(), Box<dyn Error>> { fn run(global: GlobalOptions, subcommand: Subcommand) -> Result<(), Box<dyn Error>> {
match subcommand { match subcommand {
Subcommand::Init(init_options) => cli::init(init_options)?, Subcommand::Init(init_options) => cli::init(init_options)?,
Subcommand::Serve(serve_options) => cli::serve(serve_options)?, Subcommand::Serve(serve_options) => cli::serve(global, serve_options)?,
Subcommand::Build(build_options) => cli::build(build_options)?, Subcommand::Build(build_options) => cli::build(build_options)?,
Subcommand::Upload(upload_options) => cli::upload(upload_options)?, Subcommand::Upload(upload_options) => cli::upload(upload_options)?,
Subcommand::Doc => cli::doc()?, Subcommand::Doc => cli::doc()?,
@@ -63,7 +63,7 @@ fn main() {
let options = Options::from_args(); let options = Options::from_args();
let log_filter = match options.verbosity { let log_filter = match options.global.verbosity {
0 => "info", 0 => "info",
1 => "info,librojo=debug", 1 => "info,librojo=debug",
2 => "info,librojo=trace", 2 => "info,librojo=trace",
@@ -77,9 +77,10 @@ fn main() {
.format_timestamp(None) .format_timestamp(None)
// Indent following lines equal to the log level label, like `[ERROR] ` // Indent following lines equal to the log level label, like `[ERROR] `
.format_indent(Some(8)) .format_indent(Some(8))
.write_style(options.global.color.into())
.init(); .init();
if let Err(err) = run(options.subcommand) { if let Err(err) = run(options.global, options.subcommand) {
log::error!("{}", err); log::error!("{}", err);
let mut current_err: &dyn Error = &*err; let mut current_err: &dyn Error = &*err;

View File

@@ -16,6 +16,7 @@ use std::{
}; };
use structopt::StructOpt; use structopt::StructOpt;
use thiserror::Error;
pub use self::build::*; pub use self::build::*;
pub use self::doc::*; pub use self::doc::*;
@@ -27,16 +28,73 @@ pub use self::upload::*;
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
#[structopt(name = "Rojo", about, author)] #[structopt(name = "Rojo", about, author)]
pub struct Options { pub struct Options {
/// Sets verbosity level. Can be specified multiple times. #[structopt(flatten)]
#[structopt(long = "verbose", short, global(true), parse(from_occurrences))] pub global: GlobalOptions,
pub verbosity: u8,
/// Subcommand to run in this invocation. /// Subcommand to run in this invocation.
#[structopt(subcommand)] #[structopt(subcommand)]
pub subcommand: Subcommand, pub subcommand: Subcommand,
} }
/// All of Rojo's subcommands. #[derive(Debug, StructOpt)]
pub struct GlobalOptions {
/// Sets verbosity level. Can be specified multiple times.
#[structopt(long("verbose"), short, global(true), parse(from_occurrences))]
pub verbosity: u8,
/// Set color behavior. Valid values are auto, always, and never.
#[structopt(long("color"), global(true), default_value("auto"))]
pub color: ColorChoice,
}
#[derive(Debug, Clone, Copy)]
pub enum ColorChoice {
Auto,
Always,
Never,
}
impl FromStr for ColorChoice {
type Err = ColorChoiceParseError;
fn from_str(source: &str) -> Result<Self, Self::Err> {
match source {
"auto" => Ok(ColorChoice::Auto),
"always" => Ok(ColorChoice::Always),
"never" => Ok(ColorChoice::Never),
_ => Err(ColorChoiceParseError {
attempted: source.to_owned(),
}),
}
}
}
impl From<ColorChoice> for termcolor::ColorChoice {
fn from(value: ColorChoice) -> Self {
match value {
ColorChoice::Auto => termcolor::ColorChoice::Auto,
ColorChoice::Always => termcolor::ColorChoice::Always,
ColorChoice::Never => termcolor::ColorChoice::Never,
}
}
}
impl From<ColorChoice> for env_logger::WriteStyle {
fn from(value: ColorChoice) -> Self {
match value {
ColorChoice::Auto => env_logger::WriteStyle::Auto,
ColorChoice::Always => env_logger::WriteStyle::Always,
ColorChoice::Never => env_logger::WriteStyle::Never,
}
}
}
#[derive(Debug, Error)]
#[error("Invalid color choice '{attempted}'. Valid values are: auto, always, never")]
pub struct ColorChoiceParseError {
attempted: String,
}
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
pub enum Subcommand { pub enum Subcommand {
/// Creates a new Rojo project. /// Creates a new Rojo project.

View File

@@ -7,11 +7,15 @@ use anyhow::Result;
use memofs::Vfs; use memofs::Vfs;
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};
use crate::{cli::ServeCommand, serve_session::ServeSession, web::LiveServer}; use crate::{
cli::{GlobalOptions, ServeCommand},
serve_session::ServeSession,
web::LiveServer,
};
const DEFAULT_PORT: u16 = 34872; const DEFAULT_PORT: u16 = 34872;
pub fn serve(options: ServeCommand) -> Result<()> { pub fn serve(global: GlobalOptions, options: ServeCommand) -> Result<()> {
let vfs = Vfs::new_default(); let vfs = Vfs::new_default();
let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())); let session = Arc::new(ServeSession::new(vfs, &options.absolute_project()));
@@ -23,14 +27,14 @@ pub fn serve(options: ServeCommand) -> Result<()> {
let server = LiveServer::new(session); let server = LiveServer::new(session);
let _ = show_start_message(port); let _ = show_start_message(port, global.color.into());
server.start(port); server.start(port);
Ok(()) Ok(())
} }
fn show_start_message(port: u16) -> io::Result<()> { fn show_start_message(port: u16, color: ColorChoice) -> io::Result<()> {
let writer = BufferWriter::stdout(ColorChoice::Auto); let writer = BufferWriter::stdout(color);
let mut buffer = writer.buffer(); let mut buffer = writer.buffer();
writeln!(&mut buffer, "Rojo server listening:")?; writeln!(&mut buffer, "Rojo server listening:")?;