mirror of
https://github.com/starship/starship
synced 2024-11-02 04:08:02 +00:00
Implement directory scanner (#34)
This commit is contained in:
parent
d3ce00c516
commit
5fd715e7c3
5 changed files with 184 additions and 86 deletions
135
src/context.rs
135
src/context.rs
|
@ -1,6 +1,7 @@
|
|||
use clap::ArgMatches;
|
||||
use git2::Repository;
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -56,4 +57,138 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
dir
|
||||
}
|
||||
|
||||
// returns a new ScanDir struct with reference to current dir_files of context
|
||||
// see ScanDir for methods
|
||||
pub fn new_scan_dir(&'a self) -> ScanDir<'a> {
|
||||
ScanDir {
|
||||
dir_files: self.dir_files.as_ref(),
|
||||
files: &[],
|
||||
folders: &[],
|
||||
extensions: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A struct of Criteria which will be used to verify current PathBuf is
|
||||
// of X language, criteria can be set via the builder pattern
|
||||
pub struct ScanDir<'a> {
|
||||
dir_files: &'a Vec<PathBuf>, // Replace with reference
|
||||
files: &'a [&'a str],
|
||||
folders: &'a [&'a str],
|
||||
extensions: &'a [&'a str],
|
||||
}
|
||||
|
||||
impl<'a> ScanDir<'a> {
|
||||
pub fn set_files(mut self, files: &'a [&'a str]) -> Self {
|
||||
self.files = files;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_extensions(mut self, extensions: &'a [&'a str]) -> Self {
|
||||
self.extensions = extensions;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_folders(mut self, folders: &'a [&'a str]) -> Self {
|
||||
self.folders = folders;
|
||||
self
|
||||
}
|
||||
|
||||
/// based on the current Pathbuf check to see
|
||||
/// if any of this criteria match or exist and returning a boolean
|
||||
pub fn scan(&mut self) -> bool {
|
||||
self.dir_files.iter().any(|path| {
|
||||
path_has_name(&path, &self.folders)
|
||||
|| path_has_name(&path, &self.files)
|
||||
|| has_extension(&path, &self.extensions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// checks to see if the pathbuf matches a file or folder name
|
||||
pub fn path_has_name<'a>(dir_entry: &PathBuf, names: &'a [&'a str]) -> bool {
|
||||
let found_file_or_folder_name = names.into_iter().find(|file_or_folder_name| {
|
||||
dir_entry
|
||||
.file_name()
|
||||
.and_then(OsStr::to_str)
|
||||
.unwrap_or_default()
|
||||
== **file_or_folder_name
|
||||
});
|
||||
|
||||
match found_file_or_folder_name {
|
||||
Some(name) => !name.is_empty(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// checks if pathbuf matches the extension provided
|
||||
pub fn has_extension<'a>(dir_entry: &PathBuf, extensions: &'a [&'a str]) -> bool {
|
||||
let found_ext = extensions.into_iter().find(|ext| {
|
||||
dir_entry
|
||||
.extension()
|
||||
.and_then(OsStr::to_str)
|
||||
.unwrap_or_default()
|
||||
== **ext
|
||||
});
|
||||
|
||||
match found_ext {
|
||||
Some(extension) => !extension.is_empty(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_path_has_name() {
|
||||
let mut buf = PathBuf::from("/");
|
||||
let files = vec!["package.json"];
|
||||
|
||||
assert_eq!(path_has_name(&buf, &files), false);
|
||||
|
||||
buf.set_file_name("some-file.js");
|
||||
assert_eq!(path_has_name(&buf, &files), false);
|
||||
|
||||
buf.set_file_name("package.json");
|
||||
assert_eq!(path_has_name(&buf, &files), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_has_extension() {
|
||||
let mut buf = PathBuf::from("/");
|
||||
let extensions = vec!["js"];
|
||||
|
||||
assert_eq!(has_extension(&buf, &extensions), false);
|
||||
|
||||
buf.set_file_name("some-file.rs");
|
||||
assert_eq!(has_extension(&buf, &extensions), false);
|
||||
|
||||
buf.set_file_name("some-file.js");
|
||||
assert_eq!(has_extension(&buf, &extensions), true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_criteria_scan() {
|
||||
let mut failing_criteria = ScanDir {
|
||||
dir_files: &vec![PathBuf::new()],
|
||||
files: &["package.json"],
|
||||
extensions: &["js"],
|
||||
folders: &["node_modules"],
|
||||
};
|
||||
|
||||
// fails if buffer does not match any criteria
|
||||
assert_eq!(failing_criteria.scan(), false);
|
||||
|
||||
let mut passing_criteria = ScanDir {
|
||||
dir_files: &vec![PathBuf::from("package.json")],
|
||||
files: &["package.json"],
|
||||
extensions: &["js"],
|
||||
folders: &["node_modules"],
|
||||
};
|
||||
|
||||
assert_eq!(passing_criteria.scan(), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,59 +4,44 @@ use std::process::Command;
|
|||
|
||||
use super::{Context, Module};
|
||||
|
||||
/// Creates a segment with the current Python version
|
||||
/// Creates a segment with the current Go version
|
||||
///
|
||||
/// Will display the Python version if any of the following criteria are met:
|
||||
/// - Current directory contains a `.go` file
|
||||
/// Will display the Go version if any of the following criteria are met:
|
||||
/// - Current directory contains a `go.mod` file
|
||||
/// - Current directory contains a `go.sum` file
|
||||
/// - Current directory contains a `Godeps` directory
|
||||
/// - Current directory contains a `glide.yaml` file
|
||||
/// - Current directory contains a `Gopkg.yml` file
|
||||
/// - Current directory contains a `Gopkg.lock` file
|
||||
/// - Current directory contains a `.go` file
|
||||
/// - Current directory contains a `Godeps` directory
|
||||
pub fn segment(context: &Context) -> Option<Module> {
|
||||
let is_go_project = context.dir_files.iter().any(has_go_files);
|
||||
let is_go_project = context
|
||||
.new_scan_dir()
|
||||
.set_files(&["go.mod", "go.sum", "glide.yaml", "Gopkg.yml", "Gopkg.lock"])
|
||||
.set_extensions(&["go"])
|
||||
.set_folders(&["Godeps"])
|
||||
.scan();
|
||||
|
||||
if !is_go_project {
|
||||
return None;
|
||||
}
|
||||
|
||||
const GO_CHAR: &str = "🐹 ";
|
||||
let module_color = Color::Cyan.bold();
|
||||
match get_go_version() {
|
||||
Some(go_version) => {
|
||||
const GO_CHAR: &str = "🐹 ";
|
||||
let module_color = Color::Cyan.bold();
|
||||
|
||||
let mut module = Module::new("go");
|
||||
module.set_style(module_color);
|
||||
let mut module = Module::new("go");
|
||||
module.set_style(module_color);
|
||||
|
||||
let go_version = get_go_version()?;
|
||||
let formatted_version = format_go_version(go_version)?;
|
||||
module.new_segment("symbol", GO_CHAR);
|
||||
module.new_segment("version", formatted_version);
|
||||
let formatted_version = format_go_version(go_version)?;
|
||||
module.new_segment("symbol", GO_CHAR);
|
||||
module.new_segment("version", formatted_version);
|
||||
|
||||
Some(module)
|
||||
}
|
||||
|
||||
fn has_go_files(dir_entry: &PathBuf) -> bool {
|
||||
let is_go_mod =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "go.mod" };
|
||||
let is_go_sum =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "go.sum" };
|
||||
let is_godeps =
|
||||
|d: &PathBuf| -> bool { d.is_dir() && d.file_name().unwrap_or_default() == "Godeps" };
|
||||
let is_glide_yaml =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "glide.yaml" };
|
||||
let is_go_file =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.extension().unwrap_or_default() == "go" };
|
||||
let is_gopkg_yml =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "Gopkg.yml" };
|
||||
let is_gopkg_lock =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "Gopkg.lock" };
|
||||
|
||||
is_go_mod(&dir_entry)
|
||||
|| is_go_sum(&dir_entry)
|
||||
|| is_godeps(&dir_entry)
|
||||
|| is_glide_yaml(&dir_entry)
|
||||
|| is_go_file(&dir_entry)
|
||||
|| is_gopkg_yml(&dir_entry)
|
||||
|| is_gopkg_lock(&dir_entry)
|
||||
Some(module)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_go_version() -> Option<String> {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use ansi_term::Color;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
@ -11,7 +10,13 @@ use super::{Context, Module};
|
|||
/// - Current directory contains a `package.json` file
|
||||
/// - Current directory contains a `node_modules` directory
|
||||
pub fn segment(context: &Context) -> Option<Module> {
|
||||
let is_js_project = context.dir_files.iter().any(has_js_files);
|
||||
let is_js_project = context
|
||||
.new_scan_dir()
|
||||
.set_files(&["package.json"])
|
||||
.set_extensions(&["js"])
|
||||
.set_folders(&["node_modules"])
|
||||
.scan();
|
||||
|
||||
if !is_js_project {
|
||||
return None;
|
||||
}
|
||||
|
@ -34,18 +39,6 @@ pub fn segment(context: &Context) -> Option<Module> {
|
|||
}
|
||||
}
|
||||
|
||||
fn has_js_files(dir_entry: &PathBuf) -> bool {
|
||||
let is_js_file =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.extension().unwrap_or_default() == "js" };
|
||||
let is_node_modules =
|
||||
|d: &PathBuf| -> bool { d.is_dir() && d.file_name().unwrap_or_default() == "node_modules" };
|
||||
let is_package_json = |d: &PathBuf| -> bool {
|
||||
d.is_file() && d.file_name().unwrap_or_default() == "package.json"
|
||||
};
|
||||
|
||||
is_js_file(&dir_entry) || is_node_modules(&dir_entry) || is_package_json(&dir_entry)
|
||||
}
|
||||
|
||||
fn get_node_version() -> Option<String> {
|
||||
match Command::new("node").arg("--version").output() {
|
||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use ansi_term::Color;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
@ -12,7 +11,17 @@ use super::{Context, Module};
|
|||
/// - Current directory contains a `requirements.txt` file
|
||||
/// - Current directory contains a `pyproject.toml` file
|
||||
pub fn segment(context: &Context) -> Option<Module> {
|
||||
let is_py_project = context.dir_files.iter().any(has_py_files);
|
||||
let is_py_project = context
|
||||
.new_scan_dir()
|
||||
.set_files(&[
|
||||
"requirements.txt",
|
||||
".python-version",
|
||||
"pyproject.toml",
|
||||
"pyproject.toml",
|
||||
])
|
||||
.set_extensions(&["py"])
|
||||
.scan();
|
||||
|
||||
if !is_py_project {
|
||||
return None;
|
||||
}
|
||||
|
@ -35,25 +44,6 @@ pub fn segment(context: &Context) -> Option<Module> {
|
|||
}
|
||||
}
|
||||
|
||||
fn has_py_files(dir_entry: &PathBuf) -> bool {
|
||||
let is_py_file =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.extension().unwrap_or_default() == "py" };
|
||||
let is_python_version = |d: &PathBuf| -> bool {
|
||||
d.is_file() && d.file_name().unwrap_or_default() == ".python-version"
|
||||
};
|
||||
let is_requirements_txt = |d: &PathBuf| -> bool {
|
||||
d.is_file() && d.file_name().unwrap_or_default() == "requirements.txt"
|
||||
};
|
||||
let is_py_project = |d: &PathBuf| -> bool {
|
||||
d.is_file() && d.file_name().unwrap_or_default() == "pyproject.toml"
|
||||
};
|
||||
|
||||
is_py_file(&dir_entry)
|
||||
|| is_python_version(&dir_entry)
|
||||
|| is_requirements_txt(&dir_entry)
|
||||
|| is_py_project(&dir_entry)
|
||||
}
|
||||
|
||||
fn get_python_version() -> Option<String> {
|
||||
match Command::new("python").arg("--version").output() {
|
||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use ansi_term::Color;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use super::{Context, Module};
|
||||
|
@ -7,10 +6,15 @@ use super::{Context, Module};
|
|||
/// Creates a segment with the current Rust version
|
||||
///
|
||||
/// Will display the Rust version if any of the following criteria are met:
|
||||
/// - Current directory contains a `.rs` file
|
||||
/// - Current directory contains a file with a `.rs` extension
|
||||
/// - Current directory contains a `Cargo.toml` file
|
||||
pub fn segment(context: &Context) -> Option<Module> {
|
||||
let is_rs_project = context.dir_files.iter().any(has_rs_files);
|
||||
let is_rs_project = context
|
||||
.new_scan_dir()
|
||||
.set_files(&["Cargo.toml"])
|
||||
.set_extensions(&["rs"])
|
||||
.scan();
|
||||
|
||||
if !is_rs_project {
|
||||
return None;
|
||||
}
|
||||
|
@ -33,15 +37,6 @@ pub fn segment(context: &Context) -> Option<Module> {
|
|||
}
|
||||
}
|
||||
|
||||
fn has_rs_files(dir_entry: &PathBuf) -> bool {
|
||||
let is_rs_file =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.extension().unwrap_or_default() == "rs" };
|
||||
let is_cargo_toml =
|
||||
|d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "Cargo.toml" };
|
||||
|
||||
is_rs_file(&dir_entry) || is_cargo_toml(&dir_entry)
|
||||
}
|
||||
|
||||
fn get_rust_version() -> Option<String> {
|
||||
match Command::new("rustc").arg("-V").output() {
|
||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||
|
|
Loading…
Reference in a new issue