Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: replace lazy_static with once_cell #167

Merged
merged 1 commit into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ chrono = { version = "0.4", optional = true, features = ["serde"] }
color-backtrace = { version = "0.3", optional = true, default-features = false }
generational-arena = { version = "0.2", optional = true }
gumdrop = { version = "0.7", optional = true }
lazy_static = "1"
once_cell = "1.2"
regex = { version = "1", optional = true }
secrecy = { version = "0.5", optional = true, features = ["serde"] }
semver = { version = "0.9", optional = true }
Expand Down
3 changes: 2 additions & 1 deletion core/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub use abscissa_derive::Command;
use crate::{runnable::Runnable, terminal};
use gumdrop::Options;
use std::fmt::Debug;
use termcolor::ColorChoice;

/// Subcommand of an application: derives or otherwise implements the `Options`
/// trait, but also has a `call()` method which can be used to invoke the given
Expand All @@ -33,7 +34,7 @@ pub trait Command: Debug + Options + Runnable {
let args: Vec<_> = into_args.into_iter().collect();

Self::parse_args_default(args.as_slice()).unwrap_or_else(|err| {
terminal::init();
terminal::init(ColorChoice::Auto);
Usage::for_command::<Self>().print_error_and_exit(err, args.as_slice());
})
}
Expand Down
130 changes: 65 additions & 65 deletions core/src/command/usage.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Usage information presenter

use super::Command;
use crate::{terminal::stream::STDOUT, Version};
use crate::{terminal::stdout, Version};
use std::{
io::{self, Write},
process,
Expand Down Expand Up @@ -76,8 +76,8 @@ impl Usage {

/// Print usage for a particular subcommand
pub fn print_subcommand(&self, args: &[String]) -> Result<(), io::Error> {
let mut stdout = STDOUT.lock();
stdout.reset()?;
let mut s = stdout().lock();
s.reset()?;

let mut recognized = vec![];
let mut command = self;
Expand All @@ -104,29 +104,29 @@ impl Usage {
let mut bold = ColorSpec::new();
bold.set_bold(true);

stdout.set_color(&bold)?;
writeln!(stdout, "USAGE:")?;
stdout.reset()?;
s.set_color(&bold)?;
writeln!(s, "USAGE:")?;
s.reset()?;

let mut usage_items = vec![self.package_name.clone()];
usage_items.extend(recognized.iter().map(|s| s.to_string()));
let usage_string = usage_items.join(" ");

if command.subcommands.is_empty() {
writeln!(stdout, " {} <OPTIONS>", &usage_string)?;
writeln!(s, " {} <OPTIONS>", &usage_string)?;
} else {
writeln!(stdout, " {} <SUBCOMMAND>", &usage_string)?;
writeln!(s, " {} <SUBCOMMAND>", &usage_string)?;
}

writeln!(stdout)?;
writeln!(s)?;

if let Some(desc) = description {
stdout.set_color(&bold)?;
writeln!(stdout, "DESCRIPTION:")?;
stdout.reset()?;
s.set_color(&bold)?;
writeln!(s, "DESCRIPTION:")?;
s.reset()?;

writeln!(stdout, " {}", desc)?;
writeln!(stdout)?;
writeln!(s, " {}", desc)?;
writeln!(s)?;
}

command.print_usage()
Expand Down Expand Up @@ -163,32 +163,32 @@ impl Usage {
}
}

let mut stdout = STDOUT.lock();
stdout.reset().unwrap();
let mut s = stdout().lock();
s.reset().unwrap();

let mut red = ColorSpec::new();
red.set_fg(Some(Color::Red));
red.set_bold(true);

stdout.set_color(&red).unwrap();
write!(stdout, "error: ").unwrap();
stdout.reset().unwrap();
s.set_color(&red).unwrap();
write!(s, "error: ").unwrap();
s.reset().unwrap();

writeln!(stdout, "{}", err).unwrap();
writeln!(stdout).unwrap();
writeln!(s, "{}", err).unwrap();
writeln!(s).unwrap();

command.print_info().unwrap();

if let Some(desc) = description {
let mut bold = ColorSpec::new();
bold.set_bold(true);

stdout.set_color(&bold).unwrap();
writeln!(stdout, "DESCRIPTION:").unwrap();
stdout.reset().unwrap();
s.set_color(&bold).unwrap();
writeln!(s, "DESCRIPTION:").unwrap();
s.reset().unwrap();

writeln!(stdout, " {}", desc).unwrap();
writeln!(stdout).unwrap();
writeln!(s, " {}", desc).unwrap();
writeln!(s).unwrap();
}

command.print_usage().unwrap();
Expand All @@ -201,8 +201,8 @@ impl Usage {
unrecognized: &str,
recognized: &[String],
) -> Result<(), io::Error> {
let mut stdout = STDOUT.lock();
stdout.reset().unwrap();
let mut s = stdout().lock();
s.reset().unwrap();

let mut unrecognized_items = recognized.iter().map(|s| s.to_string()).collect::<Vec<_>>();
unrecognized_items.push(unrecognized.to_owned());
Expand All @@ -221,98 +221,98 @@ impl Usage {
green.set_fg(Some(Color::Green));
green.set_bold(true);

stdout.set_color(&red)?;
write!(stdout, "error: ")?;
stdout.reset()?;
s.set_color(&red)?;
write!(s, "error: ")?;
s.reset()?;

write!(stdout, "The subcommand ")?;
write!(s, "The subcommand ")?;

stdout.set_color(&yellow)?;
write!(stdout, "{:?} ", &unrecognized_string)?;
stdout.reset()?;
s.set_color(&yellow)?;
write!(s, "{:?} ", &unrecognized_string)?;
s.reset()?;

writeln!(stdout, "wasn't recognized.")?;
writeln!(stdout)?;
writeln!(s, "wasn't recognized.")?;
writeln!(s)?;

let mut bold = ColorSpec::new();
bold.set_bold(true);

stdout.set_color(&yellow)?;
writeln!(stdout, "USAGE:")?;
stdout.reset()?;
s.set_color(&yellow)?;
writeln!(s, "USAGE:")?;
s.reset()?;

if self.subcommands.is_empty() {
writeln!(stdout, " {} <OPTIONS>", recognized.join(" "))?;
writeln!(s, " {} <OPTIONS>", recognized.join(" "))?;
} else {
writeln!(stdout, " {} <SUBCOMMAND>", recognized.join(" "))?;
writeln!(s, " {} <SUBCOMMAND>", recognized.join(" "))?;
}

writeln!(stdout)?;
writeln!(s)?;
self.print_usage()
}

/// Print program and usage information
pub fn print_info(&self) -> Result<(), io::Error> {
let mut stdout = STDOUT.lock();
stdout.reset()?;
let mut s = stdout().lock();
s.reset()?;

let mut bold = ColorSpec::new();
bold.set_bold(true);

stdout.set_color(&bold)?;
writeln!(stdout, "{} {}", &self.package_name, &self.package_version)?;
stdout.reset()?;
s.set_color(&bold)?;
writeln!(s, "{} {}", &self.package_name, &self.package_version)?;
s.reset()?;

if !self.package_authors.is_empty() {
writeln!(stdout, "{}", self.package_authors.join(", "))?;
writeln!(s, "{}", self.package_authors.join(", "))?;
}

if let Some(ref description) = self.package_description {
writeln!(stdout, "{}", description)?;
writeln!(s, "{}", description)?;
}

writeln!(stdout)?;
writeln!(s)?;
Ok(())
}

/// Print usage information only
pub fn print_usage(&self) -> Result<(), io::Error> {
let mut stdout = STDOUT.lock();
let mut s = stdout().lock();

let mut bold = ColorSpec::new();
bold.set_bold(true);

if !self.positionals.is_empty() {
stdout.set_color(&bold)?;
writeln!(stdout, "POSITIONAL ARGUMENTS:")?;
stdout.reset()?;
s.set_color(&bold)?;
writeln!(s, "POSITIONAL ARGUMENTS:")?;
s.reset()?;

for positional in &self.positionals {
positional.print(&mut stdout)?;
positional.print(&mut s)?;
}

// writeln!(stdout)?;
}

if !self.flags.is_empty() {
stdout.set_color(&bold)?;
writeln!(stdout, "FLAGS:")?;
stdout.reset()?;
s.set_color(&bold)?;
writeln!(s, "FLAGS:")?;
s.reset()?;

for flag in &self.flags {
flag.print(&mut stdout)?;
flag.print(&mut s)?;
}

writeln!(stdout)?;
writeln!(s)?;
}

if !self.subcommands.is_empty() {
stdout.set_color(&bold)?;
writeln!(stdout, "SUBCOMMANDS:")?;
stdout.reset()?;
s.set_color(&bold)?;
writeln!(s, "SUBCOMMANDS:")?;
s.reset()?;

for command in &self.subcommands {
command.print_brief(&mut stdout)?;
command.print_brief(&mut s)?;
}
}

Expand Down
39 changes: 30 additions & 9 deletions core/src/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,36 @@
pub mod component;
#[macro_use]
pub mod status;
pub(crate) mod stream;
pub mod streams;

pub use termcolor::{Color, ColorChoice};
pub use self::streams::Streams;
pub use termcolor::{Color, ColorChoice, StandardStream};

/// Initialize the terminal subsystem manually, using automatic color
/// detection.
///
/// This is useful when Abscissa internally leverages the terminal subsystem
/// without booting a full application, such as displaying usage information.
pub(crate) fn init() {
self::component::Terminal::new(ColorChoice::Auto);
use once_cell::sync::OnceCell;

/// Terminal streams
static STREAMS: OnceCell<Streams> = OnceCell::new();

/// Initialize the terminal subsystem, registering the [`Streams`] static
pub(crate) fn init(color_choice: ColorChoice) {
STREAMS
.set(Streams::new(color_choice))
.unwrap_or_else(|_| panic!("terminal streams already initialized!"));
}

/// Get the terminal [`Streams`].
pub fn streams() -> &'static Streams {
STREAMS
.get()
.expect("terminal streams not yet initialized!")
}

/// Get the standard output stream
pub fn stdout() -> &'static StandardStream {
&streams().stdout
}

/// Get the standard error stream
pub fn stderr() -> &'static StandardStream {
&streams().stderr
}
3 changes: 1 addition & 2 deletions core/src/terminal/component.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Terminal component

use super::stream;
use crate::Component;
use std::fmt;
use termcolor::ColorChoice;
Expand All @@ -14,7 +13,7 @@ impl Terminal {
/// Create a new `TerminalComponent` with the given `ColorChoice`
pub fn new(color_choice: ColorChoice) -> Terminal {
// TODO(tarcieri): handle terminal reinit (without panicking)
stream::set_color_choice(color_choice);
super::init(color_choice);

if color_choice != ColorChoice::Never {
color_backtrace::install();
Expand Down
6 changes: 3 additions & 3 deletions core/src/terminal/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
//! # }
//! ```

use super::stream::{STDERR, STDOUT};
use super::{stderr, stdout};
use crate::FrameworkError;
use std::io::Write;
use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
Expand Down Expand Up @@ -264,15 +264,15 @@ impl Status {
where
S: AsRef<str>,
{
self.print(&*STDOUT, msg)
self.print(stdout(), msg)
}

/// Print the given message to stderr
pub fn print_stderr<S>(self, msg: S) -> Result<(), FrameworkError>
where
S: AsRef<str>,
{
self.print(&*STDERR, msg)
self.print(stderr(), msg)
}

/// Print the given message
Expand Down
Loading