diff --git a/docs/config/README.md b/docs/config/README.md index 59151dd5..76190e9e 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -1031,17 +1031,18 @@ The `git_branch` module shows the active branch of the repo in your current dire | `style` | `"bold purple"` | The style for the module. | | `truncation_length` | `2^63 - 1` | Truncates a git branch to X graphemes. | | `truncation_symbol` | `"…"` | The symbol used to indicate a branch name was truncated. You can use `""` for no symbol. | -| `only_attached` | `false` | Only show the branch name when not in a detached HEAD state. | +| `only_attached` | `false` | Only show the branch name when not in a detached HEAD state. | | `disabled` | `false` | Disables the `git_branch` module. | ### Variables -| 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` | +| 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_name | `origin` | The remote name. | +| remote_branch | `master` | The name of the branch tracked on `remote_name`. | +| symbol | | Mirrors the value of option `symbol` | +| style\* | | Mirrors the value of option `style` | \*: This variable can only be used as a part of a style string diff --git a/src/context.rs b/src/context.rs index 1ad61a1c..576f4623 100644 --- a/src/context.rs +++ b/src/context.rs @@ -171,7 +171,9 @@ 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)); + let remote = repository + .as_ref() + .and_then(|repo| get_remote_repository_info(repo)); Ok(Repo { branch, root, @@ -312,8 +314,14 @@ pub struct Repo { /// State pub state: Option, - /// Remote branch name - pub remote: Option, + /// Remote repository + pub remote: Option, +} + +/// Remote repository +pub struct Remote { + pub branch: Option, + pub name: Option, } // A struct of Criteria which will be used to verify current PathBuf is @@ -380,7 +388,7 @@ fn get_current_branch(repository: &Repository) -> Option { shorthand.map(std::string::ToString::to_string) } -fn get_remote_branch(repository: &Repository) -> Option { +fn get_remote_repository_info(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) { @@ -388,8 +396,14 @@ fn get_remote_branch(repository: &Repository) -> Option { Err(_) => return None, }; - let remote = remote_ref.split('/').last().map(|r| r.to_owned())?; - return Some(remote); + let mut v = remote_ref.splitn(4, '/'); + let remote_name = v.nth(2)?.to_owned(); + let remote_branch = v.last()?.to_owned(); + + return Some(Remote { + branch: Some(remote_branch), + name: Some(remote_name), + }); } } None diff --git a/src/modules/git_branch.rs b/src/modules/git_branch.rs index 77a38c3a..2456a9d5 100644 --- a/src/modules/git_branch.rs +++ b/src/modules/git_branch.rs @@ -37,27 +37,33 @@ 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 mut remote_graphemes: Vec<&str> = Vec::new(); - if let Some(remote_branch) = repo.remote.as_ref() { - remote_graphemes = remote_branch.graphemes(true).collect(); + let mut remote_branch_graphemes: Vec<&str> = Vec::new(); + let mut remote_name_graphemes: Vec<&str> = Vec::new(); + if let Some(remote) = repo.remote.as_ref() { + if let Some(branch) = &remote.branch { + remote_branch_graphemes = branch.graphemes(true).collect() + }; + if let Some(name) = &remote.name { + remote_name_graphemes = name.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); + // Truncate fields if need be + for e in vec![ + &mut graphemes, + &mut remote_branch_graphemes, + &mut remote_name_graphemes, + ] { + let trunc_len = len.min(e.len()); + if trunc_len < e.len() { + // The truncation symbol should only be added if we truncate + e[trunc_len] = truncation_symbol; + e.truncate(trunc_len + 1); + } } let show_remote = config.always_show_remote - || (!graphemes.eq(&remote_graphemes) && !remote_graphemes.is_empty()); + || (!graphemes.eq(&remote_branch_graphemes) && !remote_branch_graphemes.is_empty()); let parsed = StringFormatter::new(config.format).and_then(|formatter| { formatter @@ -71,9 +77,16 @@ 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())) + "remote_branch" => { + if show_remote && !remote_branch_graphemes.is_empty() { + Some(Ok(remote_branch_graphemes.concat())) + } else { + None + } + } + "remote_name" => { + if show_remote && !remote_name_graphemes.is_empty() { + Some(Ok(remote_name_graphemes.concat())) } else { None }