fix: Lazy load git repo and only run module if not disabled (#306)
A couple of optimizations are done in this PR. One, we now will check config ahead of time to see if a module is disabled before running any module code. Also, we won't try to discover a git repository unless the module requests access to it.
This commit is contained in:
parent
dc8409333e
commit
9f70ffb7a7
|
@ -466,6 +466,11 @@ name = "numtoa"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -756,8 +761,8 @@ dependencies = [
|
||||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"git2 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"git2 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"once_cell 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1031,6 +1036,7 @@ dependencies = [
|
||||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
||||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||||
|
"checksum once_cell 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"
|
||||||
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||||
"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f"
|
"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f"
|
||||||
"checksum path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0858af4d9136275541f4eac7be1af70add84cf356d901799b065ac1b8ff6e2f"
|
"checksum path-slash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0858af4d9136275541f4eac7be1af70add84cf356d901799b065ac1b8ff6e2f"
|
||||||
|
|
|
@ -37,10 +37,10 @@ log = "0.4.8"
|
||||||
# battery is optional (on by default) because the crate doesn't currently build for Termux
|
# battery is optional (on by default) because the crate doesn't currently build for Termux
|
||||||
# see: https://github.com/svartalf/rust-battery/issues/33
|
# see: https://github.com/svartalf/rust-battery/issues/33
|
||||||
battery = { version = "0.7.4", optional = true }
|
battery = { version = "0.7.4", optional = true }
|
||||||
lazy_static = "1.4.0"
|
|
||||||
path-slash = "0.1.1"
|
path-slash = "0.1.1"
|
||||||
unicode-segmentation = "1.3.0"
|
unicode-segmentation = "1.3.0"
|
||||||
gethostname = "0.2.0"
|
gethostname = "0.2.0"
|
||||||
|
once_cell = "1.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
|
@ -2,11 +2,12 @@ use crate::config::Config;
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
|
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use git2::Repository;
|
use git2::{Repository, RepositoryState};
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
/// Context contains data or common methods that may be used by multiple modules.
|
/// Context contains data or common methods that may be used by multiple modules.
|
||||||
/// The data contained within Context will be relevant to this particular rendering
|
/// The data contained within Context will be relevant to this particular rendering
|
||||||
|
@ -24,13 +25,8 @@ pub struct Context<'a> {
|
||||||
/// The map of arguments that were passed when starship was called.
|
/// The map of arguments that were passed when starship was called.
|
||||||
pub arguments: ArgMatches<'a>,
|
pub arguments: ArgMatches<'a>,
|
||||||
|
|
||||||
/// If `current_dir` is a git repository or is contained within one,
|
/// Private field to store Git information for modules who need it
|
||||||
/// this is the path to the root of that repo.
|
repo: OnceCell<Repo>,
|
||||||
pub repo_root: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// If `current_dir` is a git repository or is contained within one,
|
|
||||||
/// this is the current branch name of that repo.
|
|
||||||
pub branch_name: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
|
@ -67,21 +63,12 @@ impl<'a> Context<'a> {
|
||||||
.map(|entry| entry.path())
|
.map(|entry| entry.path())
|
||||||
.collect::<Vec<PathBuf>>();
|
.collect::<Vec<PathBuf>>();
|
||||||
|
|
||||||
let repository = Repository::discover(¤t_dir).ok();
|
|
||||||
let repo_root = repository
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|repo| repo.workdir().map(std::path::Path::to_path_buf));
|
|
||||||
let branch_name = repository
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|repo| get_current_branch(repo));
|
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
config,
|
config,
|
||||||
arguments,
|
arguments,
|
||||||
current_dir,
|
current_dir,
|
||||||
dir_files,
|
dir_files,
|
||||||
repo_root,
|
repo: OnceCell::new(),
|
||||||
branch_name,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,20 +82,20 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new module
|
/// Create a new module
|
||||||
///
|
pub fn new_module(&self, name: &str) -> Module {
|
||||||
/// Will return `None` if the module is disabled by configuration, by setting
|
let config = self.config.get_module_config(name);
|
||||||
/// the `disabled` key to `true` in the configuration for that module.
|
|
||||||
pub fn new_module(&self, name: &str) -> Option<Module> {
|
Module::new(name, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the `disabled` configuration of the module
|
||||||
|
pub fn is_module_enabled(&self, name: &str) -> bool {
|
||||||
let config = self.config.get_module_config(name);
|
let config = self.config.get_module_config(name);
|
||||||
|
|
||||||
// If the segment has "disabled" set to "true", don't show it
|
// If the segment has "disabled" set to "true", don't show it
|
||||||
let disabled = config.and_then(|table| table.get_as_bool("disabled"));
|
let disabled = config.and_then(|table| table.get_as_bool("disabled"));
|
||||||
|
|
||||||
if disabled == Some(true) {
|
disabled != Some(true)
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Module::new(name, config))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a new ScanDir struct with reference to current dir_files of context
|
// returns a new ScanDir struct with reference to current dir_files of context
|
||||||
|
@ -121,6 +108,43 @@ impl<'a> Context<'a> {
|
||||||
extensions: &[],
|
extensions: &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Will lazily get repo root and branch when a module requests it.
|
||||||
|
pub fn get_repo(&self) -> Result<&Repo, std::io::Error> {
|
||||||
|
let repo = self
|
||||||
|
.repo
|
||||||
|
.get_or_try_init(|| -> Result<Repo, std::io::Error> {
|
||||||
|
let repository = Repository::discover(&self.current_dir).ok();
|
||||||
|
let branch = repository
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|repo| get_current_branch(repo));
|
||||||
|
let root = repository
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|repo| repo.workdir().map(Path::to_path_buf));
|
||||||
|
let state = repository.as_ref().map(|repo| repo.state());
|
||||||
|
|
||||||
|
Ok(Repo {
|
||||||
|
branch,
|
||||||
|
root,
|
||||||
|
state,
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(repo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Repo {
|
||||||
|
/// If `current_dir` is a git repository or is contained within one,
|
||||||
|
/// this is the current branch name of that repo.
|
||||||
|
pub branch: Option<String>,
|
||||||
|
|
||||||
|
/// If `current_dir` is a git repository or is contained within one,
|
||||||
|
/// this is the path to the root of that repo.
|
||||||
|
pub root: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// State
|
||||||
|
pub state: Option<RepositoryState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A struct of Criteria which will be used to verify current PathBuf is
|
// A struct of Criteria which will be used to verify current PathBuf is
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Set style based on percentage when threshold is modifiable
|
// TODO: Set style based on percentage when threshold is modifiable
|
||||||
let mut module = context.new_module("battery")?;
|
let mut module = context.new_module("battery");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Red.bold());
|
.unwrap_or_else(|| Color::Red.bold());
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
const ASSUMED_MODE: ShellEditMode = ShellEditMode::Insert;
|
const ASSUMED_MODE: ShellEditMode = ShellEditMode::Insert;
|
||||||
// TODO: extend config to more modes
|
// TODO: extend config to more modes
|
||||||
|
|
||||||
let mut module = context.new_module("character")?;
|
let mut module = context.new_module("character");
|
||||||
module.get_prefix().set_value("");
|
module.get_prefix().set_value("");
|
||||||
|
|
||||||
let style_success = module
|
let style_success = module
|
||||||
|
|
|
@ -7,7 +7,7 @@ use super::{Context, Module};
|
||||||
/// Will only print if last command took more than a certain amount of time to
|
/// Will only print if last command took more than a certain amount of time to
|
||||||
/// execute. Default is two seconds, but can be set by config option `min_time`.
|
/// execute. Default is two seconds, but can be set by config option `min_time`.
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("cmd_duration")?;
|
let mut module = context.new_module("cmd_duration");
|
||||||
|
|
||||||
let arguments = &context.arguments;
|
let arguments = &context.arguments;
|
||||||
let elapsed = arguments
|
let elapsed = arguments
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
const DIR_TRUNCATION_LENGTH: i64 = 3;
|
const DIR_TRUNCATION_LENGTH: i64 = 3;
|
||||||
const FISH_STYLE_PWD_DIR_LENGTH: i64 = 0;
|
const FISH_STYLE_PWD_DIR_LENGTH: i64 = 0;
|
||||||
|
|
||||||
let mut module = context.new_module("directory")?;
|
let mut module = context.new_module("directory");
|
||||||
let module_color = module
|
let module_color = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Cyan.bold());
|
.unwrap_or_else(|| Color::Cyan.bold());
|
||||||
|
@ -36,7 +36,9 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let current_dir = &context.current_dir;
|
let current_dir = &context.current_dir;
|
||||||
log::debug!("Current directory: {:?}", current_dir);
|
log::debug!("Current directory: {:?}", current_dir);
|
||||||
|
|
||||||
let dir_string = match &context.repo_root {
|
let repo = &context.get_repo().ok()?;
|
||||||
|
|
||||||
|
let dir_string = match &repo.root {
|
||||||
Some(repo_root) if truncate_to_repo => {
|
Some(repo_root) if truncate_to_repo => {
|
||||||
let repo_folder_name = repo_root.file_name().unwrap().to_str().unwrap();
|
let repo_folder_name = repo_root.file_name().unwrap().to_str().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use super::{Context, Module};
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
const GIT_BRANCH_CHAR: &str = " ";
|
const GIT_BRANCH_CHAR: &str = " ";
|
||||||
|
|
||||||
let mut module = context.new_module("git_branch")?;
|
let mut module = context.new_module("git_branch");
|
||||||
|
|
||||||
let segment_color = module
|
let segment_color = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
|
@ -38,7 +38,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
} else {
|
} else {
|
||||||
unsafe_truncation_length as usize
|
unsafe_truncation_length as usize
|
||||||
};
|
};
|
||||||
let branch_name = context.branch_name.as_ref()?;
|
let repo = context.get_repo().ok()?;
|
||||||
|
let branch_name = repo.branch.as_ref()?;
|
||||||
let truncated_graphemes = get_graphemes(&branch_name, len);
|
let truncated_graphemes = get_graphemes(&branch_name, len);
|
||||||
// The truncation symbol should only be added if we truncated
|
// The truncation symbol should only be added if we truncated
|
||||||
let truncated_and_symbol = if len < graphemes_len(&branch_name) {
|
let truncated_and_symbol = if len < graphemes_len(&branch_name) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use git2::{Repository, RepositoryState};
|
use git2::RepositoryState;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::{Context, Module};
|
use super::{Context, Module};
|
||||||
|
|
||||||
|
@ -9,11 +9,12 @@ use super::{Context, Module};
|
||||||
/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
|
/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
|
||||||
/// If the progress information is available (e.g. rebasing 3/10), it will show that too.
|
/// If the progress information is available (e.g. rebasing 3/10), it will show that too.
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("git_state")?;
|
let mut module = context.new_module("git_state");
|
||||||
|
|
||||||
let repo_root = context.repo_root.as_ref()?;
|
let repo = context.get_repo().ok()?;
|
||||||
let mut repository = Repository::open(repo_root).ok()?;
|
let repo_root = repo.root.as_ref()?;
|
||||||
let state_description = get_state_description(&mut repository);
|
let repo_state = repo.state?;
|
||||||
|
let state_description = get_state_description(repo_state, repo_root);
|
||||||
|
|
||||||
if let StateDescription::Clean = state_description {
|
if let StateDescription::Clean = state_description {
|
||||||
return None;
|
return None;
|
||||||
|
@ -79,8 +80,11 @@ static AM_OR_REBASE_LABEL: StateLabel = StateLabel {
|
||||||
message_default: "AM/REBASE",
|
message_default: "AM/REBASE",
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_state_description(repository: &mut Repository) -> StateDescription {
|
/// Returns the state of the current repository
|
||||||
match repository.state() {
|
///
|
||||||
|
/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
|
||||||
|
fn get_state_description(state: RepositoryState, root: &PathBuf) -> StateDescription {
|
||||||
|
match state {
|
||||||
RepositoryState::Clean => StateDescription::Clean,
|
RepositoryState::Clean => StateDescription::Clean,
|
||||||
RepositoryState::Merge => StateDescription::Label(&MERGE_LABEL),
|
RepositoryState::Merge => StateDescription::Label(&MERGE_LABEL),
|
||||||
RepositoryState::Revert => StateDescription::Label(&REVERT_LABEL),
|
RepositoryState::Revert => StateDescription::Label(&REVERT_LABEL),
|
||||||
|
@ -90,13 +94,13 @@ fn get_state_description(repository: &mut Repository) -> StateDescription {
|
||||||
RepositoryState::Bisect => StateDescription::Label(&BISECT_LABEL),
|
RepositoryState::Bisect => StateDescription::Label(&BISECT_LABEL),
|
||||||
RepositoryState::ApplyMailbox => StateDescription::Label(&AM_LABEL),
|
RepositoryState::ApplyMailbox => StateDescription::Label(&AM_LABEL),
|
||||||
RepositoryState::ApplyMailboxOrRebase => StateDescription::Label(&AM_OR_REBASE_LABEL),
|
RepositoryState::ApplyMailboxOrRebase => StateDescription::Label(&AM_OR_REBASE_LABEL),
|
||||||
RepositoryState::Rebase => describe_rebase(repository),
|
RepositoryState::Rebase => describe_rebase(root),
|
||||||
RepositoryState::RebaseInteractive => describe_rebase(repository),
|
RepositoryState::RebaseInteractive => describe_rebase(root),
|
||||||
RepositoryState::RebaseMerge => describe_rebase(repository),
|
RepositoryState::RebaseMerge => describe_rebase(root),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describe_rebase(repository: &mut Repository) -> StateDescription {
|
fn describe_rebase(root: &PathBuf) -> StateDescription {
|
||||||
/*
|
/*
|
||||||
* Sadly, libgit2 seems to have some issues with reading the state of
|
* Sadly, libgit2 seems to have some issues with reading the state of
|
||||||
* interactive rebases. So, instead, we'll poke a few of the .git files
|
* interactive rebases. So, instead, we'll poke a few of the .git files
|
||||||
|
@ -107,18 +111,7 @@ fn describe_rebase(repository: &mut Repository) -> StateDescription {
|
||||||
|
|
||||||
let just_label = StateDescription::Label(&REBASE_LABEL);
|
let just_label = StateDescription::Label(&REBASE_LABEL);
|
||||||
|
|
||||||
let dot_git = repository
|
let dot_git = root.join(".git");
|
||||||
.workdir()
|
|
||||||
.and_then(|d| Some(d.join(Path::new(".git"))));
|
|
||||||
|
|
||||||
let dot_git = match dot_git {
|
|
||||||
None => {
|
|
||||||
// We didn't find the .git directory.
|
|
||||||
// Something very odd is going on. We'll just back away slowly.
|
|
||||||
return just_label;
|
|
||||||
}
|
|
||||||
Some(path) => path,
|
|
||||||
};
|
|
||||||
|
|
||||||
let has_path = |relative_path: &str| {
|
let has_path = |relative_path: &str| {
|
||||||
let path = dot_git.join(Path::new(relative_path));
|
let path = dot_git.join(Path::new(relative_path));
|
||||||
|
|
|
@ -30,11 +30,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
const GIT_STATUS_RENAMED: &str = "»";
|
const GIT_STATUS_RENAMED: &str = "»";
|
||||||
const GIT_STATUS_DELETED: &str = "✘";
|
const GIT_STATUS_DELETED: &str = "✘";
|
||||||
|
|
||||||
let branch_name = context.branch_name.as_ref()?;
|
let repo = context.get_repo().ok()?;
|
||||||
let repo_root = context.repo_root.as_ref()?;
|
let branch_name = repo.branch.as_ref()?;
|
||||||
|
let repo_root = repo.root.as_ref()?;
|
||||||
let repository = Repository::open(repo_root).ok()?;
|
let repository = Repository::open(repo_root).ok()?;
|
||||||
|
|
||||||
let mut module = context.new_module("git_status")?;
|
let mut module = context.new_module("git_status");
|
||||||
let show_sync_count = module.config_value_bool("show_sync_count").unwrap_or(false);
|
let show_sync_count = module.config_value_bool("show_sync_count").unwrap_or(false);
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
|
@ -133,10 +134,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if module.is_empty() {
|
if module.is_empty() {
|
||||||
None
|
return None;
|
||||||
} else {
|
|
||||||
Some(module)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the bitflags associated with the repo's git status
|
/// Gets the bitflags associated with the repo's git status
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
Some(go_version) => {
|
Some(go_version) => {
|
||||||
const GO_CHAR: &str = "🐹 ";
|
const GO_CHAR: &str = "🐹 ";
|
||||||
|
|
||||||
let mut module = context.new_module("golang")?;
|
let mut module = context.new_module("golang");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Cyan.bold());
|
.unwrap_or_else(|| Color::Cyan.bold());
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::ffi::OsString;
|
||||||
/// - hostname.disabled is absent or false
|
/// - hostname.disabled is absent or false
|
||||||
/// - hostname.ssh_only is false OR the user is currently connected as an SSH session (`$SSH_CONNECTION`)
|
/// - hostname.ssh_only is false OR the user is currently connected as an SSH session (`$SSH_CONNECTION`)
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("hostname")?;
|
let mut module = context.new_module("hostname");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Green.bold().dimmed());
|
.unwrap_or_else(|| Color::Green.bold().dimmed());
|
||||||
|
|
|
@ -4,7 +4,7 @@ use super::{Context, Module};
|
||||||
|
|
||||||
/// Creates a segment to show if there are any active jobs running
|
/// Creates a segment to show if there are any active jobs running
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("jobs")?;
|
let mut module = context.new_module("jobs");
|
||||||
|
|
||||||
let threshold = module.config_value_i64("threshold").unwrap_or(1);
|
let threshold = module.config_value_i64("threshold").unwrap_or(1);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use super::{Context, Module};
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
const LINE_ENDING: &str = "\n";
|
const LINE_ENDING: &str = "\n";
|
||||||
|
|
||||||
let mut module = context.new_module("line_break")?;
|
let mut module = context.new_module("line_break");
|
||||||
|
|
||||||
module.get_prefix().set_value("");
|
module.get_prefix().set_value("");
|
||||||
module.get_suffix().set_value("");
|
module.get_suffix().set_value("");
|
||||||
|
|
|
@ -22,7 +22,7 @@ use super::{Context, Module};
|
||||||
/// - pure // use_name == false in a pure nix-shell
|
/// - pure // use_name == false in a pure nix-shell
|
||||||
/// - impure // use_name == false in an impure nix-shell
|
/// - impure // use_name == false in an impure nix-shell
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("nix_shell")?;
|
let mut module = context.new_module("nix_shell");
|
||||||
|
|
||||||
env::var("IN_NIX_SHELL")
|
env::var("IN_NIX_SHELL")
|
||||||
.ok()
|
.ok()
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
Some(node_version) => {
|
Some(node_version) => {
|
||||||
const NODE_CHAR: &str = "⬢ ";
|
const NODE_CHAR: &str = "⬢ ";
|
||||||
|
|
||||||
let mut module = context.new_module("nodejs")?;
|
let mut module = context.new_module("nodejs");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Green.bold());
|
.unwrap_or_else(|| Color::Green.bold());
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
Some(package_version) => {
|
Some(package_version) => {
|
||||||
const PACKAGE_CHAR: &str = "📦 ";
|
const PACKAGE_CHAR: &str = "📦 ";
|
||||||
|
|
||||||
let mut module = context.new_module("package")?;
|
let mut module = context.new_module("package");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Red.bold());
|
.unwrap_or_else(|| Color::Red.bold());
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut module = context.new_module("python")?;
|
let mut module = context.new_module("python");
|
||||||
let pyenv_version_name = module
|
let pyenv_version_name = module
|
||||||
.config_value_bool("pyenv_version_name")
|
.config_value_bool("pyenv_version_name")
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
Some(ruby_version) => {
|
Some(ruby_version) => {
|
||||||
const RUBY_CHAR: &str = "💎 ";
|
const RUBY_CHAR: &str = "💎 ";
|
||||||
|
|
||||||
let mut module = context.new_module("ruby")?;
|
let mut module = context.new_module("ruby");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Red.bold());
|
.unwrap_or_else(|| Color::Red.bold());
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
Some(rust_version) => {
|
Some(rust_version) => {
|
||||||
const RUST_CHAR: &str = "🦀 ";
|
const RUST_CHAR: &str = "🦀 ";
|
||||||
|
|
||||||
let mut module = context.new_module("rust")?;
|
let mut module = context.new_module("rust");
|
||||||
let module_style = module
|
let module_style = module
|
||||||
.config_value_style("style")
|
.config_value_style("style")
|
||||||
.unwrap_or_else(|| Color::Red.bold());
|
.unwrap_or_else(|| Color::Red.bold());
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
const ROOT_UID: Option<u32> = Some(0);
|
const ROOT_UID: Option<u32> = Some(0);
|
||||||
let user_uid = get_uid();
|
let user_uid = get_uid();
|
||||||
if user != logname || ssh_connection.is_some() || user_uid == ROOT_UID {
|
if user != logname || ssh_connection.is_some() || user_uid == ROOT_UID {
|
||||||
let mut module = context.new_module("username")?;
|
let mut module = context.new_module("username");
|
||||||
let module_style = get_mod_style(user_uid, &module);
|
let module_style = get_mod_style(user_uid, &module);
|
||||||
module.set_style(module_style);
|
module.set_style(module_style);
|
||||||
module.new_segment("username", &user?);
|
module.new_segment("username", &user?);
|
||||||
|
|
|
@ -81,6 +81,7 @@ pub fn prompt(args: ArgMatches) {
|
||||||
|
|
||||||
let modules = &prompt_order
|
let modules = &prompt_order
|
||||||
.par_iter()
|
.par_iter()
|
||||||
|
.filter(|module| context.is_module_enabled(module))
|
||||||
.map(|module| modules::handle(module, &context)) // Compute modules
|
.map(|module| modules::handle(module, &context)) // Compute modules
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<Module>>(); // Remove segments set to `None`
|
.collect::<Vec<Module>>(); // Remove segments set to `None`
|
||||||
|
|
|
@ -58,20 +58,3 @@ fn config_5s_duration_10s() -> io::Result<()> {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn config_disabled() -> io::Result<()> {
|
|
||||||
let output = common::render_module("cmd_duration")
|
|
||||||
.use_config(toml::toml! {
|
|
||||||
[cmd_duration]
|
|
||||||
disabled = true
|
|
||||||
min_time = 5
|
|
||||||
})
|
|
||||||
.arg("--cmd-duration=10")
|
|
||||||
.output()?;
|
|
||||||
let actual = String::from_utf8(output.stdout).unwrap();
|
|
||||||
|
|
||||||
let expected = "";
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
use lazy_static::lazy_static;
|
use once_cell::sync::Lazy;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{env, fs, io, process};
|
use std::{env, fs, io, process};
|
||||||
|
|
||||||
lazy_static! {
|
static MANIFEST_DIR: Lazy<&'static Path> = Lazy::new(|| Path::new(env!("CARGO_MANIFEST_DIR")));
|
||||||
static ref MANIFEST_DIR: &'static Path = Path::new(env!("CARGO_MANIFEST_DIR"));
|
static EMPTY_CONFIG: Lazy<PathBuf> = Lazy::new(|| MANIFEST_DIR.join("empty_config.toml"));
|
||||||
pub static ref FIXTURES_DIR: PathBuf = MANIFEST_DIR.join("tests/fixtures");
|
|
||||||
static ref EMPTY_CONFIG: PathBuf = MANIFEST_DIR.join("empty_config.toml");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render the full starship prompt
|
/// Render the full starship prompt
|
||||||
pub fn render_prompt() -> process::Command {
|
pub fn render_prompt() -> process::Command {
|
||||||
|
|
|
@ -19,20 +19,6 @@ fn char_symbol_configuration() -> io::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn disabled_module() -> io::Result<()> {
|
|
||||||
let output = common::render_module("package")
|
|
||||||
.use_config(toml::toml! {
|
|
||||||
[package]
|
|
||||||
disabled = true
|
|
||||||
})
|
|
||||||
.output()?;
|
|
||||||
let actual = String::from_utf8(output.stdout).unwrap();
|
|
||||||
assert_eq!("", actual);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_newline_configuration() -> io::Result<()> {
|
fn add_newline_configuration() -> io::Result<()> {
|
||||||
// Start prompt with newline
|
// Start prompt with newline
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use git2::Repository;
|
use git2::Repository;
|
||||||
use std::env;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use git2::Repository;
|
use git2::Repository;
|
||||||
use std::env;
|
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use ansi_term::Color;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::common::{self, TestCommand};
|
use crate::common;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn folder_without_go_files() -> io::Result<()> {
|
fn folder_without_go_files() -> io::Result<()> {
|
||||||
|
@ -138,24 +138,3 @@ fn folder_with_gopkg_lock() -> io::Result<()> {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn config_disabled() -> io::Result<()> {
|
|
||||||
let dir = common::new_tempdir()?;
|
|
||||||
File::create(dir.path().join("main.go"))?;
|
|
||||||
|
|
||||||
let output = common::render_module("golang")
|
|
||||||
.use_config(toml::toml! {
|
|
||||||
[golang]
|
|
||||||
disabled = true
|
|
||||||
})
|
|
||||||
.arg("--path")
|
|
||||||
.arg(dir.path())
|
|
||||||
.output()?;
|
|
||||||
let actual = String::from_utf8(output.stdout).unwrap();
|
|
||||||
|
|
||||||
let expected = "";
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -64,19 +64,3 @@ fn config_2_job_3() -> io::Result<()> {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn config_disabled() -> io::Result<()> {
|
|
||||||
let output = common::render_module("jobs")
|
|
||||||
.use_config(toml::toml! {
|
|
||||||
[jobs]
|
|
||||||
disabled = true
|
|
||||||
})
|
|
||||||
.arg("--jobs=1")
|
|
||||||
.output()?;
|
|
||||||
let actual = String::from_utf8(output.stdout).unwrap();
|
|
||||||
|
|
||||||
let expected = "";
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use ansi_term::Color;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::common::{self, TestCommand};
|
use crate::common;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn folder_without_node_files() -> io::Result<()> {
|
fn folder_without_node_files() -> io::Result<()> {
|
||||||
|
@ -70,24 +70,3 @@ fn folder_with_node_modules() -> io::Result<()> {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
fn config_disabled() -> io::Result<()> {
|
|
||||||
let dir = common::new_tempdir()?;
|
|
||||||
File::create(dir.path().join("package.json"))?;
|
|
||||||
|
|
||||||
let output = common::render_module("nodejs")
|
|
||||||
.use_config(toml::toml! {
|
|
||||||
[nodejs]
|
|
||||||
disabled = true
|
|
||||||
})
|
|
||||||
.arg("--path")
|
|
||||||
.arg(dir.path())
|
|
||||||
.output()?;
|
|
||||||
let actual = String::from_utf8(output.stdout).unwrap();
|
|
||||||
|
|
||||||
let expected = "";
|
|
||||||
assert_eq!(expected, actual);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue