diff --git a/docs/config/README.md b/docs/config/README.md index 122ca6e2..621b194a 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -1025,6 +1025,7 @@ The `git_branch` module shows the active branch of the repo in your current dire | Option | Default | Description | | ------------------- | -------------------------------- | ---------------------------------------------------------------------------------------- | +| `always_show_remote`| `false` | Shows the remote tracking branch name, even if it is equal to the local branch name. | | `format` | `"on [$symbol$branch]($style) "` | The format for the module. Use `"$branch"` to refer to the current branch name. | | `symbol` | `" "` | A format string representing the symbol of git branch. | | `style` | `"bold purple"` | The style for the module. | @@ -1038,6 +1039,7 @@ The `git_branch` module shows the active branch of the repo in your current dire | Variable | Example | Description | | -------- | -------- | ---------------------------------------------------------------------------------------------------- | | branch | `master` | The current branch name, falls back to `HEAD` if there's no current branch (e.g. git detached HEAD). | +| remote | `master` | The remote branch name. | | symbol | | Mirrors the value of option `symbol` | | style\* | | Mirrors the value of option `style` | diff --git a/src/configs/git_branch.rs b/src/configs/git_branch.rs index b3e8f7a3..8e4bb3ca 100644 --- a/src/configs/git_branch.rs +++ b/src/configs/git_branch.rs @@ -10,18 +10,20 @@ pub struct GitBranchConfig<'a> { pub truncation_length: i64, pub truncation_symbol: &'a str, pub only_attached: bool, + pub always_show_remote: bool, pub disabled: bool, } impl<'a> RootModuleConfig<'a> for GitBranchConfig<'a> { fn new() -> Self { GitBranchConfig { - format: "on [$symbol$branch]($style) ", + format: "on [$symbol$branch]($style)(:[$remote]($style)) ", symbol: " ", style: "bold purple", truncation_length: std::i64::MAX, truncation_symbol: "…", only_attached: false, + always_show_remote: false, disabled: false, } } diff --git a/src/context.rs b/src/context.rs index 3f78375a..1ad61a1c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -171,11 +171,12 @@ impl<'a> Context<'a> { .as_ref() .and_then(|repo| repo.workdir().map(Path::to_path_buf)); let state = repository.as_ref().map(|repo| repo.state()); - + let remote = repository.as_ref().and_then(|repo| get_remote_branch(repo)); Ok(Repo { branch, root, state, + remote, }) }) } @@ -310,6 +311,9 @@ pub struct Repo { /// State pub state: Option, + + /// Remote branch name + pub remote: Option, } // A struct of Criteria which will be used to verify current PathBuf is @@ -376,6 +380,21 @@ fn get_current_branch(repository: &Repository) -> Option { shorthand.map(std::string::ToString::to_string) } +fn get_remote_branch(repository: &Repository) -> Option { + if let Ok(head) = repository.head() { + if let Some(local_branch_ref) = head.name() { + let remote_ref = match repository.branch_upstream_name(local_branch_ref) { + Ok(remote_ref) => remote_ref.as_str()?.to_owned(), + Err(_) => return None, + }; + + let remote = remote_ref.split('/').last().map(|r| r.to_owned())?; + return Some(remote); + } + } + None +} + #[derive(Debug, Clone, Copy, PartialEq)] pub enum Shell { Bash, diff --git a/src/modules/git_branch.rs b/src/modules/git_branch.rs index 55d80866..77a38c3a 100644 --- a/src/modules/git_branch.rs +++ b/src/modules/git_branch.rs @@ -35,16 +35,30 @@ pub fn module<'a>(context: &'a Context) -> Option> { }; let branch_name = repo.branch.as_ref()?; - let mut graphemes: Vec<&str> = branch_name.graphemes(true).collect(); - let trunc_len = len.min(graphemes.len()); + let mut remote_graphemes: Vec<&str> = Vec::new(); + if let Some(remote_branch) = repo.remote.as_ref() { + remote_graphemes = remote_branch.graphemes(true).collect(); + } + + let trunc_len = len.min(graphemes.len()); if trunc_len < graphemes.len() { // The truncation symbol should only be added if we truncate graphemes[trunc_len] = truncation_symbol; graphemes.truncate(trunc_len + 1) } + let trunc_len = len.min(remote_graphemes.len()); + if trunc_len < remote_graphemes.len() { + // The truncation symbol should only be added if we truncate + remote_graphemes[trunc_len] = truncation_symbol; + remote_graphemes.truncate(trunc_len + 1); + } + + let show_remote = config.always_show_remote + || (!graphemes.eq(&remote_graphemes) && !remote_graphemes.is_empty()); + let parsed = StringFormatter::new(config.format).and_then(|formatter| { formatter .map_meta(|var, _| match var { @@ -57,6 +71,13 @@ pub fn module<'a>(context: &'a Context) -> Option> { }) .map(|variable| match variable { "branch" => Some(Ok(graphemes.concat())), + "remote" => { + if show_remote { + Some(Ok(remote_graphemes.concat())) + } else { + None + } + } _ => None, }) .parse(None)