mirror of
https://github.com/starship/starship.git
synced 2024-12-24 16:18:53 +01:00
Implement directory scanner (#34)
This commit is contained in:
parent
d3ce00c516
commit
5fd715e7c3
135
src/context.rs
135
src/context.rs
@ -1,6 +1,7 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use git2::Repository;
|
use git2::Repository;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -56,4 +57,138 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
dir
|
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};
|
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:
|
/// Will display the Go version if any of the following criteria are met:
|
||||||
/// - Current directory contains a `.go` file
|
|
||||||
/// - Current directory contains a `go.mod` file
|
/// - Current directory contains a `go.mod` file
|
||||||
/// - Current directory contains a `go.sum` 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 `glide.yaml` file
|
||||||
/// - Current directory contains a `Gopkg.yml` file
|
/// - Current directory contains a `Gopkg.yml` file
|
||||||
/// - Current directory contains a `Gopkg.lock` 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> {
|
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 {
|
if !is_go_project {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GO_CHAR: &str = "🐹 ";
|
match get_go_version() {
|
||||||
let module_color = Color::Cyan.bold();
|
Some(go_version) => {
|
||||||
|
const GO_CHAR: &str = "🐹 ";
|
||||||
|
let module_color = Color::Cyan.bold();
|
||||||
|
|
||||||
let mut module = Module::new("go");
|
let mut module = Module::new("go");
|
||||||
module.set_style(module_color);
|
module.set_style(module_color);
|
||||||
|
|
||||||
let go_version = get_go_version()?;
|
let formatted_version = format_go_version(go_version)?;
|
||||||
let formatted_version = format_go_version(go_version)?;
|
module.new_segment("symbol", GO_CHAR);
|
||||||
module.new_segment("symbol", GO_CHAR);
|
module.new_segment("version", formatted_version);
|
||||||
module.new_segment("version", formatted_version);
|
|
||||||
|
|
||||||
Some(module)
|
Some(module)
|
||||||
}
|
}
|
||||||
|
None => None,
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_go_version() -> Option<String> {
|
fn get_go_version() -> Option<String> {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use super::{Context, Module};
|
use super::{Context, Module};
|
||||||
@ -11,7 +10,13 @@ use super::{Context, Module};
|
|||||||
/// - Current directory contains a `package.json` file
|
/// - Current directory contains a `package.json` file
|
||||||
/// - Current directory contains a `node_modules` directory
|
/// - Current directory contains a `node_modules` directory
|
||||||
pub fn segment(context: &Context) -> Option<Module> {
|
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 {
|
if !is_js_project {
|
||||||
return None;
|
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> {
|
fn get_node_version() -> Option<String> {
|
||||||
match Command::new("node").arg("--version").output() {
|
match Command::new("node").arg("--version").output() {
|
||||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use super::{Context, Module};
|
use super::{Context, Module};
|
||||||
@ -12,7 +11,17 @@ use super::{Context, Module};
|
|||||||
/// - Current directory contains a `requirements.txt` file
|
/// - Current directory contains a `requirements.txt` file
|
||||||
/// - Current directory contains a `pyproject.toml` file
|
/// - Current directory contains a `pyproject.toml` file
|
||||||
pub fn segment(context: &Context) -> Option<Module> {
|
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 {
|
if !is_py_project {
|
||||||
return None;
|
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> {
|
fn get_python_version() -> Option<String> {
|
||||||
match Command::new("python").arg("--version").output() {
|
match Command::new("python").arg("--version").output() {
|
||||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use super::{Context, Module};
|
use super::{Context, Module};
|
||||||
@ -7,10 +6,15 @@ use super::{Context, Module};
|
|||||||
/// Creates a segment with the current Rust version
|
/// Creates a segment with the current Rust version
|
||||||
///
|
///
|
||||||
/// Will display the Rust version if any of the following criteria are met:
|
/// 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
|
/// - Current directory contains a `Cargo.toml` file
|
||||||
pub fn segment(context: &Context) -> Option<Module> {
|
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 {
|
if !is_rs_project {
|
||||||
return None;
|
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> {
|
fn get_rust_version() -> Option<String> {
|
||||||
match Command::new("rustc").arg("-V").output() {
|
match Command::new("rustc").arg("-V").output() {
|
||||||
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
Ok(output) => Some(String::from_utf8(output.stdout).unwrap()),
|
||||||
|
Loading…
Reference in New Issue
Block a user