From 022e0002e40d9286677ae59e751b4b873dce6e95 Mon Sep 17 00:00:00 2001 From: Matan Kushner Date: Fri, 19 Apr 2019 16:57:14 -0400 Subject: [PATCH] Use "context" to contain run details (#14) * Create "context" to contain run details * Use context in tests and benchmarks --- benches/my_benchmark.rs | 17 +++++++---------- src/context.rs | 30 ++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 1 + src/modules/character.rs | 11 ++++++----- src/modules/directory.rs | 9 +++++---- src/modules/line_break.rs | 5 ++--- src/modules/mod.rs | 13 ++++++------- src/modules/nodejs.rs | 9 +++++---- src/print.rs | 12 +++++------- tests/common.rs | 18 +++++++++++++----- 11 files changed, 81 insertions(+), 45 deletions(-) create mode 100644 src/context.rs diff --git a/benches/my_benchmark.rs b/benches/my_benchmark.rs index c357554dd..e16c8cab0 100644 --- a/benches/my_benchmark.rs +++ b/benches/my_benchmark.rs @@ -4,18 +4,17 @@ extern crate criterion; use criterion::Criterion; use clap::{App, Arg}; +use starship::context::Context; use starship::modules; -use std::path::Path; fn char_segment(c: &mut Criterion) { let args = App::new("starship") .arg(Arg::with_name("status_code")) .get_matches_from(vec!["starship", "0"]); - - let path = Path::new("~"); + let context = Context::new_with_dir(args, "~"); c.bench_function("char segment", move |b| { - b.iter(|| modules::handle("char", &path, &args)) + b.iter(|| modules::handle("char", &context)) }); } @@ -23,11 +22,10 @@ fn dir_segment(c: &mut Criterion) { let args = App::new("starship") .arg(Arg::with_name("status_code")) .get_matches_from(vec!["starship", "0"]); - - let path = Path::new("~"); + let context = Context::new_with_dir(args, "~"); c.bench_function("dir segment", move |b| { - b.iter(|| modules::handle("dir", &path, &args)) + b.iter(|| modules::handle("dir", &context)) }); } @@ -35,11 +33,10 @@ fn line_break_segment(c: &mut Criterion) { let args = App::new("starship") .arg(Arg::with_name("status_code")) .get_matches_from(vec!["starship", "0"]); - - let path = Path::new("~"); + let context = Context::new_with_dir(args, "~"); c.bench_function("line break segment", move |b| { - b.iter(|| modules::handle("line_break", &path, &args)) + b.iter(|| modules::handle("line_break", &context)) }); } diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 000000000..32e9fab11 --- /dev/null +++ b/src/context.rs @@ -0,0 +1,30 @@ +use clap::ArgMatches; +use std::env; +use std::path::PathBuf; + +pub struct Context<'a> { + pub current_dir: PathBuf, + pub arguments: ArgMatches<'a>, +} + +impl<'a> Context<'a> { + pub fn new(arguments: ArgMatches) -> Context { + // TODO: Currently gets the physical directory. Get the logical directory. + let current_dir = env::current_dir().expect("Unable to identify current directory."); + + Context { + current_dir, + arguments, + } + } + + pub fn new_with_dir(arguments: ArgMatches, dir: T) -> Context + where + T: Into, + { + Context { + current_dir: dir.into(), + arguments, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 4d3665457..3028646c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ // Lib is present to allow for benchmarking +pub mod context; pub mod modules; pub mod print; pub mod segment; diff --git a/src/main.rs b/src/main.rs index dfd328135..233f72179 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ extern crate ansi_term; extern crate dirs; extern crate git2; +mod context; mod modules; mod print; mod segment; diff --git a/src/modules/character.rs b/src/modules/character.rs index 359ff61fb..f624e19f2 100644 --- a/src/modules/character.rs +++ b/src/modules/character.rs @@ -1,7 +1,7 @@ -use super::Segment; use ansi_term::Color; -use clap::ArgMatches; -use std::path::Path; + +use super::Segment; +use crate::context::Context; /// Creates a segment for the prompt character /// @@ -11,14 +11,15 @@ use std::path::Path; /// (green by default) /// - If the exit-code was anything else, the arrow will be formatted with /// `COLOR_FAILURE` (red by default) -pub fn segment(_current_dir: &Path, args: &ArgMatches) -> Option { +pub fn segment(context: &Context) -> Option { const PROMPT_CHAR: &str = "➜"; const COLOR_SUCCESS: Color = Color::Green; const COLOR_FAILURE: Color = Color::Red; let mut segment = Segment::new("char"); + let arguments = &context.arguments; - if args.value_of("status_code").unwrap() == "0" { + if arguments.value_of("status_code").unwrap() == "0" { segment.set_style(COLOR_SUCCESS); } else { segment.set_style(COLOR_FAILURE); diff --git a/src/modules/directory.rs b/src/modules/directory.rs index 8048a3620..265b90a3c 100644 --- a/src/modules/directory.rs +++ b/src/modules/directory.rs @@ -1,10 +1,10 @@ -use super::Segment; use ansi_term::Color; -use clap::ArgMatches; -use dirs; use git2::Repository; use std::path::Path; +use super::Segment; +use crate::context::Context; + /// Creates a segment with the current directory /// /// Will perform path contraction and truncation. @@ -14,12 +14,13 @@ use std::path::Path; /// /// **Truncation** /// Paths will be limited in length to `3` path components by default. -pub fn segment(current_dir: &Path, _args: &ArgMatches) -> Option { +pub fn segment(context: &Context) -> Option { const HOME_SYMBOL: &str = "~"; const DIR_TRUNCATION_LENGTH: usize = 3; const SECTION_COLOR: Color = Color::Cyan; let mut segment = Segment::new("dir"); + let current_dir = &context.current_dir; let dir_string; if let Ok(repo) = git2::Repository::discover(current_dir) { diff --git a/src/modules/line_break.rs b/src/modules/line_break.rs index a7bda251e..de0e6f9be 100644 --- a/src/modules/line_break.rs +++ b/src/modules/line_break.rs @@ -1,9 +1,8 @@ use super::Segment; -use clap::ArgMatches; -use std::path::Path; +use crate::context::Context; /// Creates a segment for the line break -pub fn segment(_current_dir: &Path, _args: &ArgMatches) -> Option { +pub fn segment(_context: &Context) -> Option { const LINE_ENDING: &str = "\n"; let mut segment = Segment::new("line_break"); diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 9efdad46c..abc1e49f7 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -3,16 +3,15 @@ mod directory; mod line_break; mod nodejs; +use crate::context::Context; use crate::segment::Segment; -use clap::ArgMatches; -use std::path::Path; -pub fn handle(module: &str, current_dir: &Path, args: &ArgMatches) -> Option { +pub fn handle(module: &str, context: &Context) -> Option { match module { - "dir" | "directory" => directory::segment(current_dir, args), - "char" | "character" => character::segment(current_dir, args), - "node" | "nodejs" => nodejs::segment(current_dir, args), - "line_break" => line_break::segment(current_dir, args), + "dir" | "directory" => directory::segment(context), + "char" | "character" => character::segment(context), + "node" | "nodejs" => nodejs::segment(context), + "line_break" => line_break::segment(context), _ => panic!("Unknown module: {}", module), } diff --git a/src/modules/nodejs.rs b/src/modules/nodejs.rs index c3ba59f3f..aede7ba63 100644 --- a/src/modules/nodejs.rs +++ b/src/modules/nodejs.rs @@ -1,21 +1,22 @@ -use super::Segment; use ansi_term::Color; -use clap::ArgMatches; use std::fs::{self, DirEntry}; -use std::path::Path; use std::process::Command; +use super::Segment; +use crate::context::Context; + /// Creates a segment with the current Node.js version /// /// Will display the Node.js version if any of the following criteria are met: /// - Current directory contains a `.js` file /// - Current directory contains a `node_modules` directory /// - Current directory contains a `package.json` file -pub fn segment(current_dir: &Path, _args: &ArgMatches) -> Option { +pub fn segment(context: &Context) -> Option { const NODE_CHAR: &str = "⬢"; const SECTION_COLOR: Color = Color::Green; let mut segment = Segment::new("node"); + let current_dir = &context.current_dir; let files = fs::read_dir(current_dir).unwrap(); // Early return if there are no JS project files diff --git a/src/print.rs b/src/print.rs index c86083126..e2a371cb4 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,14 +1,12 @@ use clap::ArgMatches; -use std::env; use std::io::{self, Write}; +use crate::context::Context; use crate::modules; pub fn prompt(args: ArgMatches) { - let default_prompt = vec!["directory", "nodejs", "line_break", "character"]; - - // TODO: Currently gets the physical directory. Get the logical directory. - let current_path = env::current_dir().expect("Unable to identify current directory."); + let prompt_order = vec!["directory", "nodejs", "line_break", "character"]; + let context = Context::new(args); // TODO: // - List files in directory @@ -20,9 +18,9 @@ pub fn prompt(args: ArgMatches) { // Write a new line before the prompt writeln!(handle).unwrap(); - default_prompt + prompt_order .iter() - .map(|module| modules::handle(module, ¤t_path, &args)) // Compute segments + .map(|module| modules::handle(module, &context)) // Compute segments .flatten() // Remove segments set to `None` .enumerate() // Turn segment into tuple with index .map(|(index, segment)| segment.output_index(index)) // Generate string outputs diff --git a/tests/common.rs b/tests/common.rs index 4bc62a5fa..a4924ab74 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -1,18 +1,26 @@ use clap::{App, Arg}; +use starship::context::Context; use starship::modules; -use std::path::Path; +use std::path::PathBuf; -pub fn render_segment(module: &str, path: &Path) -> String { - render_segment_with_status(module, path, "0") +pub fn render_segment(module: &str, path: T) -> String +where + T: Into, +{ + render_segment_with_status(module, &path.into(), "0") } -pub fn render_segment_with_status(module: &str, path: &Path, status: &str) -> String { +pub fn render_segment_with_status(module: &str, path: T, status: &str) -> String +where + T: Into, +{ // Create an `Arg` with status_code of "0" let args = App::new("starship") .arg(Arg::with_name("status_code")) .get_matches_from(vec!["starship", status]); + let context = Context::new_with_dir(args, path.into()); - let segment = modules::handle(module, path, &args); + let segment = modules::handle(module, &context); segment.unwrap().output() }