Refactor color handling (#204)
Color logic is fairly complicated, so moved it into its own module. A `Color` object now encapsulates the --color setting, which stream we are printing to, and what color we are painting. This way, Color::paint can just do the right thing when asked to paint text. Also added tests to make sure that --list and --highlight colors are using the correct color codes.
This commit is contained in:
parent
5af2e4ae5e
commit
1b1a155dda
74
src/app.rs
74
src/app.rs
@ -1,9 +1,8 @@
|
|||||||
extern crate ansi_term;
|
|
||||||
extern crate atty;
|
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
use ::prelude::*;
|
use color::Color;
|
||||||
|
use prelude::*;
|
||||||
use std::{convert, ffi};
|
use std::{convert, ffi};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use self::clap::{App, Arg, ArgGroup, AppSettings};
|
use self::clap::{App, Arg, ArgGroup, AppSettings};
|
||||||
@ -25,54 +24,6 @@ macro_rules! die {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum UseColor {
|
|
||||||
Auto,
|
|
||||||
Always,
|
|
||||||
Never,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for UseColor {
|
|
||||||
fn default() -> UseColor {
|
|
||||||
UseColor::Never
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UseColor {
|
|
||||||
fn from_argument(use_color: &str) -> Option<UseColor> {
|
|
||||||
match use_color {
|
|
||||||
"auto" => Some(UseColor::Auto),
|
|
||||||
"always" => Some(UseColor::Always),
|
|
||||||
"never" => Some(UseColor::Never),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_color_stream(self, stream: atty::Stream) -> bool {
|
|
||||||
match self {
|
|
||||||
UseColor::Auto => atty::is(stream),
|
|
||||||
UseColor::Always => true,
|
|
||||||
UseColor::Never => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn should_color_stdout(self) -> bool {
|
|
||||||
self.should_color_stream(atty::Stream::Stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn should_color_stderr(self) -> bool {
|
|
||||||
self.should_color_stream(atty::Stream::Stderr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn blue(self, stream: atty::Stream) -> ansi_term::Style {
|
|
||||||
if self.should_color_stream(stream) {
|
|
||||||
ansi_term::Style::new().fg(ansi_term::Color::Blue)
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn edit<P: convert::AsRef<ffi::OsStr>>(path: P) -> ! {
|
fn edit<P: convert::AsRef<ffi::OsStr>>(path: P) -> ! {
|
||||||
let editor = env::var_os("EDITOR")
|
let editor = env::var_os("EDITOR")
|
||||||
.unwrap_or_else(|| die!("Error getting EDITOR environment variable"));
|
.unwrap_or_else(|| die!("Error getting EDITOR environment variable"));
|
||||||
@ -167,10 +118,11 @@ pub fn app() {
|
|||||||
.args(&["DUMP", "EDIT", "LIST", "SHOW", "SUMMARY", "ARGUMENTS", "EVALUATE"]))
|
.args(&["DUMP", "EDIT", "LIST", "SHOW", "SUMMARY", "ARGUMENTS", "EVALUATE"]))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let use_color_argument = matches.value_of("COLOR").expect("--color had no value");
|
let color = match matches.value_of("COLOR").expect("`--color` had no value") {
|
||||||
let use_color = match UseColor::from_argument(use_color_argument) {
|
"auto" => Color::auto(),
|
||||||
Some(use_color) => use_color,
|
"always" => Color::always(),
|
||||||
None => die!("Invalid argument to --color. This is a bug in just."),
|
"never" => Color::never(),
|
||||||
|
other => die!("Invalid argument `{}` to --color. This is a bug in just.", other),
|
||||||
};
|
};
|
||||||
|
|
||||||
let set_count = matches.occurrences_of("SET");
|
let set_count = matches.occurrences_of("SET");
|
||||||
@ -274,7 +226,7 @@ pub fn app() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let justfile = compile(&text).unwrap_or_else(|error|
|
let justfile = compile(&text).unwrap_or_else(|error|
|
||||||
if use_color.should_color_stderr() {
|
if color.stderr().active() {
|
||||||
die!("{:#}", error);
|
die!("{:#}", error);
|
||||||
} else {
|
} else {
|
||||||
die!("{}", error);
|
die!("{}", error);
|
||||||
@ -296,19 +248,19 @@ pub fn app() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if matches.is_present("LIST") {
|
if matches.is_present("LIST") {
|
||||||
let blue = use_color.blue(atty::Stream::Stdout);
|
let doc_color = color.stdout().doc();
|
||||||
println!("Available recipes:");
|
println!("Available recipes:");
|
||||||
for (name, recipe) in &justfile.recipes {
|
for (name, recipe) in &justfile.recipes {
|
||||||
print!(" {}", name);
|
print!(" {}", name);
|
||||||
for parameter in &recipe.parameters {
|
for parameter in &recipe.parameters {
|
||||||
if use_color.should_color_stdout() {
|
if color.stdout().active() {
|
||||||
print!(" {:#}", parameter);
|
print!(" {:#}", parameter);
|
||||||
} else {
|
} else {
|
||||||
print!(" {}", parameter);
|
print!(" {}", parameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(doc) = recipe.doc {
|
if let Some(doc) = recipe.doc {
|
||||||
print!(" {} {}", blue.paint("#"), blue.paint(doc));
|
print!(" {} {}", doc_color.paint("#"), doc_color.paint(doc));
|
||||||
}
|
}
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
@ -351,13 +303,13 @@ pub fn app() {
|
|||||||
overrides: overrides,
|
overrides: overrides,
|
||||||
quiet: matches.is_present("QUIET"),
|
quiet: matches.is_present("QUIET"),
|
||||||
shell: matches.value_of("SHELL"),
|
shell: matches.value_of("SHELL"),
|
||||||
use_color: use_color,
|
color: color,
|
||||||
verbose: matches.is_present("VERBOSE"),
|
verbose: matches.is_present("VERBOSE"),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(run_error) = justfile.run(&arguments, &options) {
|
if let Err(run_error) = justfile.run(&arguments, &options) {
|
||||||
if !options.quiet {
|
if !options.quiet {
|
||||||
if use_color.should_color_stderr() {
|
if color.stderr().active() {
|
||||||
warn!("{:#}", run_error);
|
warn!("{:#}", run_error);
|
||||||
} else {
|
} else {
|
||||||
warn!("{}", run_error);
|
warn!("{}", run_error);
|
||||||
|
145
src/color.rs
Normal file
145
src/color.rs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
extern crate ansi_term;
|
||||||
|
extern crate atty;
|
||||||
|
|
||||||
|
use prelude::*;
|
||||||
|
use self::ansi_term::{Style, Prefix, Suffix, ANSIGenericString};
|
||||||
|
use self::ansi_term::Color::*;
|
||||||
|
use self::atty::is as is_atty;
|
||||||
|
use self::atty::Stream;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum UseColor {
|
||||||
|
Auto,
|
||||||
|
Always,
|
||||||
|
Never,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Color {
|
||||||
|
use_color: UseColor,
|
||||||
|
atty: bool,
|
||||||
|
style: Style,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Color {
|
||||||
|
fn default() -> Color {
|
||||||
|
Color {
|
||||||
|
use_color: UseColor::Never,
|
||||||
|
atty: false,
|
||||||
|
style: Style::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
fn restyle(self, style: Style) -> Color {
|
||||||
|
Color {
|
||||||
|
style: style,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn redirect(self, stream: Stream) -> Color {
|
||||||
|
Color {
|
||||||
|
atty: is_atty(stream),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn effective_style(&self) -> Style {
|
||||||
|
if self.active() {
|
||||||
|
self.style
|
||||||
|
} else {
|
||||||
|
Style::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fmt(fmt: &fmt::Formatter) -> Color {
|
||||||
|
if fmt.alternate() {
|
||||||
|
Color::always()
|
||||||
|
} else {
|
||||||
|
Color::never()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auto() -> Color {
|
||||||
|
Color {
|
||||||
|
use_color: UseColor::Auto,
|
||||||
|
..default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn always() -> Color {
|
||||||
|
Color {
|
||||||
|
use_color: UseColor::Always,
|
||||||
|
..default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn never() -> Color {
|
||||||
|
Color {
|
||||||
|
use_color: UseColor::Never,
|
||||||
|
..default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stderr(self) -> Color {
|
||||||
|
self.redirect(Stream::Stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdout(self) -> Color {
|
||||||
|
self.redirect(Stream::Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn doc(self) -> Color {
|
||||||
|
self.restyle(Style::new().fg(Blue))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(self) -> Color {
|
||||||
|
self.restyle(Style::new().fg(Red).bold())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn banner(self) -> Color {
|
||||||
|
self.restyle(Style::new().fg(Cyan).bold())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn command(self) -> Color {
|
||||||
|
self.restyle(Style::new().bold())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter(self) -> Color {
|
||||||
|
self.restyle(Style::new().fg(Cyan))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message(self) -> Color {
|
||||||
|
self.restyle(Style::new().bold())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn annotation(self) -> Color {
|
||||||
|
self.restyle(Style::new().fg(Purple))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string(self) -> Color {
|
||||||
|
self.restyle(Style::new().fg(Green))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active(&self) -> bool {
|
||||||
|
match self.use_color {
|
||||||
|
UseColor::Always => true,
|
||||||
|
UseColor::Never => false,
|
||||||
|
UseColor::Auto => self.atty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paint<'a>(&self, text: &'a str) -> ANSIGenericString<'a, str> {
|
||||||
|
self.effective_style().paint(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prefix(&self) -> Prefix {
|
||||||
|
self.effective_style().prefix()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suffix(&self) -> Suffix {
|
||||||
|
self.effective_style().suffix()
|
||||||
|
}
|
||||||
|
}
|
@ -1586,3 +1586,29 @@ a: x y
|
|||||||
",
|
",
|
||||||
status: EXIT_FAILURE,
|
status: EXIT_FAILURE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
integration_test! {
|
||||||
|
name: list_colors,
|
||||||
|
justfile: "
|
||||||
|
# comment
|
||||||
|
a B C +D='hello':
|
||||||
|
echo {{B}} {{C}} {{D}}
|
||||||
|
",
|
||||||
|
args: ("--color", "always", "--list"),
|
||||||
|
stdout: "Available recipes:\n a \u{1b}[36mB\u{1b}[0m \u{1b}[36mC\u{1b}[0m \u{1b}[35m+\u{1b}[0m\u{1b}[36mD\u{1b}[0m=\'\u{1b}[32mhello\u{1b}[0m\' \u{1b}[34m#\u{1b}[0m \u{1b}[34mcomment\u{1b}[0m\n",
|
||||||
|
stderr: "",
|
||||||
|
status: EXIT_SUCCESS,
|
||||||
|
}
|
||||||
|
|
||||||
|
integration_test! {
|
||||||
|
name: run_colors,
|
||||||
|
justfile: "
|
||||||
|
# comment
|
||||||
|
a:
|
||||||
|
echo hi
|
||||||
|
",
|
||||||
|
args: ("--color", "always", "--highlight", "--verbose"),
|
||||||
|
stdout: "hi\n",
|
||||||
|
stderr: "\u{1b}[1;36m===> Running recipe `a`...\u{1b}[0m\n\u{1b}[1mecho hi\u{1b}[0m\n",
|
||||||
|
status: EXIT_SUCCESS,
|
||||||
|
}
|
||||||
|
106
src/lib.rs
106
src/lib.rs
@ -25,20 +25,26 @@ mod platform;
|
|||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
|
|
||||||
|
mod color;
|
||||||
|
|
||||||
mod prelude {
|
mod prelude {
|
||||||
pub use std::io::prelude::*;
|
|
||||||
pub use libc::{EXIT_FAILURE, EXIT_SUCCESS};
|
pub use libc::{EXIT_FAILURE, EXIT_SUCCESS};
|
||||||
pub use regex::Regex;
|
pub use regex::Regex;
|
||||||
|
pub use std::io::prelude::*;
|
||||||
pub use std::path::{Path, PathBuf};
|
pub use std::path::{Path, PathBuf};
|
||||||
pub use std::{cmp, env, fs, fmt, io, iter, process};
|
pub use std::{cmp, env, fs, fmt, io, iter, process};
|
||||||
|
|
||||||
|
pub fn default<T: Default>() -> T {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
||||||
pub use app::app;
|
pub use app::app;
|
||||||
|
|
||||||
use app::UseColor;
|
|
||||||
use brev::{output, OutputError};
|
use brev::{output, OutputError};
|
||||||
|
use color::Color;
|
||||||
use platform::{Platform, PlatformInterface};
|
use platform::{Platform, PlatformInterface};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{BTreeMap as Map, BTreeSet as Set};
|
use std::collections::{BTreeMap as Map, BTreeSet as Set};
|
||||||
@ -129,16 +135,14 @@ struct Parameter<'a> {
|
|||||||
|
|
||||||
impl<'a> Display for Parameter<'a> {
|
impl<'a> Display for Parameter<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
let green = maybe_green(f.alternate());
|
let color = Color::fmt(f);
|
||||||
let cyan = maybe_cyan(f.alternate());
|
|
||||||
let purple = maybe_purple(f.alternate());
|
|
||||||
if self.variadic {
|
if self.variadic {
|
||||||
write!(f, "{}", purple.paint("+"))?;
|
write!(f, "{}", color.annotation().paint("+"))?;
|
||||||
}
|
}
|
||||||
write!(f, "{}", cyan.paint(self.name))?;
|
write!(f, "{}", color.parameter().paint(self.name))?;
|
||||||
if let Some(ref default) = self.default {
|
if let Some(ref default) = self.default {
|
||||||
let escaped = default.chars().flat_map(char::escape_default).collect::<String>();;
|
let escaped = default.chars().flat_map(char::escape_default).collect::<String>();;
|
||||||
write!(f, r#"='{}'"#, green.paint(escaped))?;
|
write!(f, r#"='{}'"#, color.string().paint(&escaped))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -285,8 +289,8 @@ impl<'a> Recipe<'a> {
|
|||||||
options: &RunOptions,
|
options: &RunOptions,
|
||||||
) -> Result<(), RunError<'a>> {
|
) -> Result<(), RunError<'a>> {
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
let cyan = maybe_cyan(options.use_color.should_color_stderr());
|
let color = options.color.stderr().banner();
|
||||||
warn!("{}===> Running recipe `{}`...{}", cyan.prefix(), self.name, cyan.suffix());
|
warn!("{}===> Running recipe `{}`...{}", color.prefix(), self.name, color.suffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut argument_map = Map::new();
|
let mut argument_map = Map::new();
|
||||||
@ -430,12 +434,13 @@ impl<'a> Recipe<'a> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.dry_run
|
if options.dry_run || options.verbose || !((quiet_command ^ self.quiet) || options.quiet) {
|
||||||
|| options.verbose
|
let color = if options.highlight {
|
||||||
|| !((quiet_command ^ self.quiet) || options.quiet) {
|
options.color.command()
|
||||||
let highlight = maybe_highlight(options.highlight
|
} else {
|
||||||
&& options.use_color.should_color_stderr());
|
options.color
|
||||||
warn!("{}", highlight.paint(command));
|
};
|
||||||
|
warn!("{}", color.stderr().paint(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.dry_run {
|
if options.dry_run {
|
||||||
@ -946,7 +951,7 @@ fn write_error_context(
|
|||||||
width: Option<usize>,
|
width: Option<usize>,
|
||||||
) -> Result<(), fmt::Error> {
|
) -> Result<(), fmt::Error> {
|
||||||
let line_number = line + 1;
|
let line_number = line + 1;
|
||||||
let red = maybe_red(f.alternate());
|
let red = Color::fmt(f).error();
|
||||||
match text.lines().nth(line) {
|
match text.lines().nth(line) {
|
||||||
Some(line) => {
|
Some(line) => {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
@ -1003,61 +1008,13 @@ fn write_token_error_context(f: &mut fmt::Formatter, token: &Token) -> Result<()
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_red(colors: bool) -> ansi_term::Style {
|
|
||||||
if colors {
|
|
||||||
ansi_term::Style::new().fg(ansi_term::Color::Red).bold()
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_green(colors: bool) -> ansi_term::Style {
|
|
||||||
if colors {
|
|
||||||
ansi_term::Style::new().fg(ansi_term::Color::Green)
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_cyan(colors: bool) -> ansi_term::Style {
|
|
||||||
if colors {
|
|
||||||
ansi_term::Style::new().fg(ansi_term::Color::Cyan)
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_purple(colors: bool) -> ansi_term::Style {
|
|
||||||
if colors {
|
|
||||||
ansi_term::Style::new().fg(ansi_term::Color::Purple)
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_bold(colors: bool) -> ansi_term::Style {
|
|
||||||
if colors {
|
|
||||||
ansi_term::Style::new().bold()
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_highlight(colors: bool) -> ansi_term::Style {
|
|
||||||
if colors {
|
|
||||||
ansi_term::Style::new().fg(ansi_term::Color::Cyan).bold()
|
|
||||||
} else {
|
|
||||||
ansi_term::Style::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Display for CompileError<'a> {
|
impl<'a> Display for CompileError<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
use ErrorKind::*;
|
use ErrorKind::*;
|
||||||
let red = maybe_red(f.alternate());
|
let error = Color::fmt(f).error();
|
||||||
let bold = maybe_bold(f.alternate());
|
let message = Color::fmt(f).message();
|
||||||
|
|
||||||
write!(f, "{} {}", red.paint("error:"), bold.prefix())?;
|
write!(f, "{} {}", error.paint("error:"), message.prefix())?;
|
||||||
|
|
||||||
match self.kind {
|
match self.kind {
|
||||||
CircularRecipeDependency{recipe, ref circle} => {
|
CircularRecipeDependency{recipe, ref circle} => {
|
||||||
@ -1148,7 +1105,7 @@ impl<'a> Display for CompileError<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "{}", bold.suffix())?;
|
write!(f, "{}", message.suffix())?;
|
||||||
|
|
||||||
write_error_context(f, self.text, self.index, self.line, self.column, self.width)
|
write_error_context(f, self.text, self.index, self.line, self.column, self.width)
|
||||||
}
|
}
|
||||||
@ -1168,7 +1125,7 @@ struct RunOptions<'a> {
|
|||||||
overrides: Map<&'a str, &'a str>,
|
overrides: Map<&'a str, &'a str>,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
shell: Option<&'a str>,
|
shell: Option<&'a str>,
|
||||||
use_color: UseColor,
|
color: Color,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1347,9 +1304,10 @@ impl<'a> RunError<'a> {
|
|||||||
impl<'a> Display for RunError<'a> {
|
impl<'a> Display for RunError<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
use RunError::*;
|
use RunError::*;
|
||||||
let red = maybe_red(f.alternate());
|
let color = if f.alternate() { Color::always() } else { Color::never() };
|
||||||
let bold = maybe_bold(f.alternate());
|
let error = color.error();
|
||||||
write!(f, "{} {}", red.paint("error:"), bold.prefix())?;
|
let message = color.message();
|
||||||
|
write!(f, "{} {}", error.paint("error:"), message.prefix())?;
|
||||||
|
|
||||||
let mut error_token = None;
|
let mut error_token = None;
|
||||||
|
|
||||||
@ -1491,7 +1449,7 @@ impl<'a> Display for RunError<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "{}", bold.suffix())?;
|
write!(f, "{}", message.suffix())?;
|
||||||
|
|
||||||
if let Some(token) = error_token {
|
if let Some(token) = error_token {
|
||||||
write_token_error_context(f, token)?;
|
write_token_error_context(f, token)?;
|
||||||
|
@ -3,22 +3,12 @@ extern crate glob;
|
|||||||
use ::prelude::*;
|
use ::prelude::*;
|
||||||
|
|
||||||
pub fn just_binary_path() -> PathBuf {
|
pub fn just_binary_path() -> PathBuf {
|
||||||
let exe = String::from("just") + env::consts::EXE_SUFFIX;
|
let mut path = env::current_exe().unwrap();
|
||||||
|
path.pop();
|
||||||
let mut path = env::current_dir().unwrap();
|
if path.ends_with("deps") {
|
||||||
path.push("target");
|
path.pop();
|
||||||
path.push("debug");
|
|
||||||
path.push(&exe);
|
|
||||||
|
|
||||||
if !path.is_file() {
|
|
||||||
let mut pattern = env::current_dir().unwrap();
|
|
||||||
pattern.push("target");
|
|
||||||
pattern.push("*");
|
|
||||||
pattern.push("debug");
|
|
||||||
pattern.push(&exe);
|
|
||||||
path = glob::glob(pattern.to_str().unwrap()).unwrap()
|
|
||||||
.take_while(Result::is_ok).nth(0).unwrap().unwrap();
|
|
||||||
}
|
}
|
||||||
|
let exe = String::from("just") + env::consts::EXE_SUFFIX;
|
||||||
|
path.push(exe);
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user