summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQingping Hou <dave2008713@gmail.com>2019-12-06 08:57:42 -0800
committerMatan Kushner <hello@matchai.me>2019-12-06 11:57:42 -0500
commitc5a206e3cf5ea01eed98c3c7f79089a450d60b33 (patch)
tree38abdd7f7522210edac3471a2b9426e0493b9eaf
parent5b440c0bb01b35eff1ebd92af1a2c013668fed04 (diff)
feat: Add git_commit module (#673)
-rw-r--r--docs/config/README.md33
-rw-r--r--src/config.rs16
-rw-r--r--src/configs/git_commit.rs28
-rw-r--r--src/configs/mod.rs1
-rw-r--r--src/configs/starship_root.rs1
-rw-r--r--src/module.rs1
-rw-r--r--src/modules/git_commit.rs54
-rw-r--r--src/modules/mod.rs2
-rw-r--r--tests/testsuite/git_commit.rs68
-rw-r--r--tests/testsuite/main.rs1
10 files changed, 205 insertions, 0 deletions
diff --git a/docs/config/README.md b/docs/config/README.md
index 9b2973235..b9a766099 100644
--- a/docs/config/README.md
+++ b/docs/config/README.md
@@ -91,6 +91,7 @@ prompt_order = [
"kubernetes",
"directory",
"git_branch",
+ "git_commit",
"git_state",
"git_status",
"hg_branch",
@@ -438,6 +439,38 @@ truncation_length = 4
truncation_symbol = ""
```
+
+## Git Commit
+
+The `git_commit` module shows the active branch of the repo in your current directory.
+
+::: tip
+
+This module is disabled by default.
+To enable it, set `disabled` to `false` in your configuration file.
+
+:::
+
+### Options
+
+| Variable | Default | Description |
+| ------------ | ----------| -------------------------------------------------|
+| `commit_hash_length` | `7` | The length of the displayed git commit hash. |
+| `style` | `"green"` | The style for the module. |
+| `prefix` | `(` | Prefix to display immediately before git commit. |
+| `suffix` | `)` | Suffix to display immediately after git commit. |
+| `disabled` | `true` | Disables the `git_commit` module. |
+
+### Example
+
+```toml
+# ~/.config/starship.toml
+
+[git_commit]
+disabled = false
+commit_hash_length = 4
+```
+
## Git State
The `git_state` module will show in directories which are part of a git
diff --git a/src/config.rs b/src/config.rs
index 027ca75ac..c2c8c0a45 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -98,6 +98,22 @@ impl<'a> ModuleConfig<'a> for f64 {
}
}
+impl<'a> ModuleConfig<'a> for usize {
+ fn from_config(config: &Value) -> Option<Self> {
+ match config {
+ Value::Integer(value) => {
+ if *value > 0 {
+ Some(*value as usize)
+ } else {
+ None
+ }
+ }
+ Value::String(value) => value.parse::<usize>().ok(),
+ _ => None,
+ }
+ }
+}
+
impl<'a, T> ModuleConfig<'a> for Vec<T>
where
T: ModuleConfig<'a>,
diff --git a/src/configs/git_commit.rs b/src/configs/git_commit.rs
new file mode 100644
index 000000000..d6f65fdcb
--- /dev/null
+++ b/src/configs/git_commit.rs
@@ -0,0 +1,28 @@
+use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig};
+
+use ansi_term::{Color, Style};
+use starship_module_config_derive::ModuleConfig;
+
+#[derive(Clone, ModuleConfig)]
+pub struct GitCommitConfig<'a> {
+ pub commit_hash_length: usize,
+ pub hash: SegmentConfig<'a>,
+ pub prefix: &'a str,
+ pub suffix: &'a str,
+ pub style: Style,
+ pub disabled: bool,
+}
+
+impl<'a> RootModuleConfig<'a> for GitCommitConfig<'a> {
+ fn new() -> Self {
+ GitCommitConfig {
+ // be consistent with git by default, which has DEFAULT_ABBREV set to 7
+ commit_hash_length: 7,
+ hash: SegmentConfig::default(),
+ prefix: "(",
+ suffix: ") ",
+ style: Color::Green.bold(),
+ disabled: true,
+ }
+ }
+}
diff --git a/src/configs/mod.rs b/src/configs/mod.rs
index 553307895..c840f3bba 100644
--- a/src/configs/mod.rs
+++ b/src/configs/mod.rs
@@ -7,6 +7,7 @@ pub mod directory;
pub mod dotnet;
pub mod env_var;
pub mod git_branch;
+pub mod git_commit;
pub mod git_state;
pub mod git_status;
pub mod go;
diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs
index eb0523a29..293dcb17c 100644
--- a/src/configs/starship_root.rs
+++ b/src/configs/starship_root.rs
@@ -22,6 +22,7 @@ impl<'a> RootModuleConfig<'a> for StarshipRootConfig<'a> {
"kubernetes",
"directory",
"git_branch",
+ "git_commit",
"git_state",
"git_status",
"hg_branch",
diff --git a/src/module.rs b/src/module.rs
index 591934f29..71b25627f 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -18,6 +18,7 @@ pub const ALL_MODULES: &[&str] = &[
"dotnet",
"env_var",
"git_branch",
+ "git_commit",
"git_state",
"git_status",
"golang",
diff --git a/src/modules/git_commit.rs b/src/modules/git_commit.rs
new file mode 100644
index 000000000..cacfa3982
--- /dev/null
+++ b/src/modules/git_commit.rs
@@ -0,0 +1,54 @@
+use super::{Context, Module, RootModuleConfig};
+use git2::Repository;
+
+use crate::configs::git_commit::GitCommitConfig;
+
+/// Creates a module with the Git commit in the current directory
+///
+/// Will display the commit hash if the current directory is a git repo
+pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
+ let mut module = context.new_module("git_commit");
+ let config = GitCommitConfig::try_load(module.config);
+ if config.disabled {
+ return None;
+ };
+
+ module
+ .get_prefix()
+ .set_value(config.prefix)
+ .set_style(config.style);
+ module
+ .get_suffix()
+ .set_value(config.suffix)
+ .set_style(config.style);
+ module.set_style(config.style);
+
+ let repo = context.get_repo().ok()?;
+ let repo_root = repo.root.as_ref()?;
+ let git_repo = Repository::open(repo_root).ok()?;
+
+ let git_head = git_repo.head().ok()?;
+ let head_commit = git_head.peel_to_commit().ok()?;
+ let commit_oid = head_commit.id();
+ module.create_segment(
+ "hash",
+ &config.hash.with_value(&id_to_hex_abbrev(
+ commit_oid.as_bytes(),
+ config.commit_hash_length,
+ )),
+ );
+
+ Some(module)
+}
+
+/// len specifies length of hex encoded string
+pub fn id_to_hex_abbrev(bytes: &[u8], len: usize) -> String {
+ bytes
+ .iter()
+ .map(|b| format!("{:02x}", b))
+ .collect::<Vec<String>>()
+ .join("")
+ .chars()
+ .take(len)
+ .collect()
+}
diff --git a/src/modules/mod.rs b/src/modules/mod.rs
index f69c94653..42951324b 100644
--- a/src/modules/mod.rs
+++ b/src/modules/mod.rs
@@ -7,6 +7,7 @@ mod directory;
mod dotnet;
mod env_var;
mod git_branch;
+mod git_commit;
mod git_state;
mod git_status;
mod golang;
@@ -49,6 +50,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"dotnet" => dotnet::module(context),
"env_var" => env_var::module(context),
"git_branch" => git_branch::module(context),
+ "git_commit" => git_commit::module(context),
"git_state" => git_state::module(context),
"git_status" => git_status::module(context),
"golang" => golang::module(context),
diff --git a/tests/testsuite/git_commit.rs b/tests/testsuite/git_commit.rs
new file mode 100644
index 000000000..c7dd50bbe
--- /dev/null
+++ b/tests/testsuite/git_commit.rs
@@ -0,0 +1,68 @@
+use ansi_term::Color;
+use std::process::Command;
+use std::{io, str};
+
+use crate::common::{self, TestCommand};
+
+#[test]
+fn test_render_commit_hash() -> io::Result<()> {
+ let repo_dir = common::create_fixture_repo()?;
+
+ let mut git_output = Command::new("git")
+ .args(&["rev-parse", "HEAD"])
+ .current_dir(repo_dir.as_path())
+ .output()?
+ .stdout;
+ git_output.truncate(7);
+ let expected_hash = str::from_utf8(&git_output).unwrap();
+
+ let output = common::render_module("git_commit")
+ .use_config(toml::toml! {
+ [git_commit]
+ disabled = false
+ })
+ .arg("--path")
+ .arg(repo_dir)
+ .output()?;
+
+ let actual = String::from_utf8(output.stdout).unwrap();
+ let expected = Color::Green
+ .bold()
+ .paint(format!("({}) ", expected_hash))
+ .to_string();
+
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+fn test_render_commit_hash_len_override() -> io::Result<()> {
+ let repo_dir = common::create_fixture_repo()?;
+
+ let mut git_output = Command::new("git")
+ .args(&["rev-parse", "HEAD"])
+ .current_dir(repo_dir.as_path())
+ .output()?
+ .stdout;
+ git_output.truncate(14);
+ let expected_hash = str::from_utf8(&git_output).unwrap();
+
+ let output = common::render_module("git_commit")
+ .use_config(toml::toml! {
+ [git_commit]
+ disabled = false
+ commit_hash_length = 14
+ })
+ .arg("--path")
+ .arg(repo_dir)
+ .output()?;
+
+ let actual = String::from_utf8(output.stdout).unwrap();
+ let expected = Color::Green
+ .bold()
+ .paint(format!("({}) ", expected_hash))
+ .to_string();
+
+ assert_eq!(expected, actual);
+ Ok(())
+}
diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs
index c3e209262..214f8b013 100644
--- a/tests/testsuite/main.rs
+++ b/tests/testsuite/main.rs
@@ -8,6 +8,7 @@ mod directory;
mod dotnet;
mod env_var;
mod git_branch;
+mod git_commit;
mod git_state;
mod git_status;
mod golang;