From cad40d17eea23089d8efa0d4c939ad1f2fb5050f Mon Sep 17 00:00:00 2001 From: Denis Maximov Date: Sun, 1 Nov 2020 02:22:03 +0200 Subject: [PATCH 1/8] feat: xclip fallback for linux with xsel #352 (#390) closes #352 --- Cargo.lock | 11 +++++++++++ Cargo.toml | 3 +++ src/clipboard.rs | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8237ec762..cd1fa97fa5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,6 +461,7 @@ dependencies = [ "textwrap 0.12.1", "tui", "unicode-width", + "which", ] [[package]] @@ -1358,6 +1359,16 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "which" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c14ef7e1b8b8ecfc75d5eca37949410046e66f15d185c01d70824f1f8111ef" +dependencies = [ + "libc", + "thiserror", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index e5107541e8..997e2b0631 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,9 @@ anyhow = "1.0.33" unicode-width = "0.1" textwrap = "0.12" +[target.'cfg(target_os = "linux")'.dependencies] +which = "4.0.2" + [target.'cfg(not(windows))'.dependencies] pprof = { version = "0.3", features = ["flamegraph"], optional = true } diff --git a/src/clipboard.rs b/src/clipboard.rs index 6730ceb1ba..5f15e11f76 100644 --- a/src/clipboard.rs +++ b/src/clipboard.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use std::ffi::OsStr; use std::io::Write; use std::process::{Command, Stdio}; @@ -27,10 +28,37 @@ fn execute_copy_command(command: Command, text: &str) -> Result<()> { Ok(()) } +fn gen_command( + path: impl AsRef, + xclip_syntax: bool, +) -> Command { + let mut c = Command::new(path); + if xclip_syntax { + c.arg("-selection"); + c.arg("clipboard"); + } else { + c.arg("--clipboard"); + } + c +} + #[cfg(target_os = "linux")] pub fn copy_string(string: &str) -> Result<()> { - let mut cmd = Command::new("xclip"); - cmd.arg("-selection").arg("clipboard"); + use std::path::PathBuf; + use which::which; + let (path, xclip_syntax) = which("xclip").ok().map_or_else( + || { + ( + which("xsel") + .ok() + .unwrap_or_else(|| PathBuf::from("xsel")), + false, + ) + }, + |path| (path, true), + ); + + let cmd = gen_command(path, xclip_syntax); execute_copy_command(cmd, string) } From 632f2555487efb52ee3543de0be03f16d49e9a46 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 02:11:44 +0100 Subject: [PATCH 2/8] cleanup some more expects --- asyncgit/src/error.rs | 3 +++ asyncgit/src/lib.rs | 2 ++ asyncgit/src/sync/diff.rs | 7 ++++--- asyncgit/src/sync/hooks.rs | 9 ++++----- asyncgit/src/sync/hunks.rs | 10 +++++----- asyncgit/src/sync/ignore.rs | 2 +- asyncgit/src/sync/utils.rs | 6 +++--- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/asyncgit/src/error.rs b/asyncgit/src/error.rs index 1b7c8adc75..989a2416f1 100644 --- a/asyncgit/src/error.rs +++ b/asyncgit/src/error.rs @@ -12,6 +12,9 @@ pub enum Error { #[error("git: remote url not found")] UnknownRemote, + #[error("git: work dir error")] + NoWorkDir, + #[error("io error:{0}")] Io(#[from] std::io::Error), diff --git a/asyncgit/src/lib.rs b/asyncgit/src/lib.rs index 70ebf658ab..3ca6d2a393 100644 --- a/asyncgit/src/lib.rs +++ b/asyncgit/src/lib.rs @@ -7,6 +7,8 @@ #![deny(clippy::unwrap_used)] #![deny(clippy::panic)] #![deny(clippy::perf)] +//TODO: get this in someday since expect still leads us to crashes sometimes +// #![deny(clippy::expect_used)] pub mod cached; mod commit_files; diff --git a/asyncgit/src/sync/diff.rs b/asyncgit/src/sync/diff.rs index cbeb05675a..cdc55473f0 100644 --- a/asyncgit/src/sync/diff.rs +++ b/asyncgit/src/sync/diff.rs @@ -132,7 +132,7 @@ pub fn get_diff( scope_time!("get_diff"); let repo = utils::repo(repo_path)?; - let work_dir = work_dir(&repo); + let work_dir = work_dir(&repo)?; let diff = get_diff_raw(&repo, &p, stage, false)?; raw_diff_to_file_diff(&diff, work_dir) @@ -148,7 +148,7 @@ pub fn get_diff_commit( scope_time!("get_diff_commit"); let repo = utils::repo(repo_path)?; - let work_dir = work_dir(&repo); + let work_dir = work_dir(&repo)?; let diff = get_commit_diff(&repo, id, Some(p))?; raw_diff_to_file_diff(&diff, work_dir) @@ -284,7 +284,8 @@ fn raw_diff_to_file_diff<'a>( res.borrow_mut().untracked = true; } } - let res = Rc::try_unwrap(res).expect("rc error"); + let res = Rc::try_unwrap(res) + .map_err(|_| Error::Generic("".to_owned()))?; Ok(res.into_inner()) } diff --git a/asyncgit/src/sync/hooks.rs b/asyncgit/src/sync/hooks.rs index 021fd2573a..18819ed7c6 100644 --- a/asyncgit/src/sync/hooks.rs +++ b/asyncgit/src/sync/hooks.rs @@ -77,14 +77,13 @@ pub fn hooks_post_commit(repo_path: &str) -> Result { fn work_dir_as_string(repo_path: &str) -> Result { let repo = repo(repo_path)?; - work_dir(&repo) - .to_str() - .map(|s| s.to_string()) - .ok_or_else(|| { + work_dir(&repo)?.to_str().map(|s| s.to_string()).ok_or_else( + || { Error::Generic( "workdir contains invalid utf8".to_string(), ) - }) + }, + ) } fn hook_runable(path: &str, hook: &str) -> bool { diff --git a/asyncgit/src/sync/hunks.rs b/asyncgit/src/sync/hunks.rs index 99a72de3b2..a37d7c2832 100644 --- a/asyncgit/src/sync/hunks.rs +++ b/asyncgit/src/sync/hunks.rs @@ -105,9 +105,10 @@ pub fn unstage_hunk( let diff_count_positive = diff.deltas().len(); let hunk_index = find_hunk_index(&diff, hunk_hash); - if hunk_index.is_none() { - return Err(Error::Generic("hunk not found".to_string())); - } + let hunk_index = hunk_index.map_or_else( + || Err(Error::Generic("hunk not found".to_string())), + Ok, + )?; let diff = get_diff_raw(&repo, &file_path, true, true)?; @@ -124,8 +125,7 @@ pub fn unstage_hunk( let mut hunk_idx = 0; let mut opt = ApplyOptions::new(); opt.hunk_callback(|_hunk| { - let res = if hunk_idx == hunk_index.expect("invalid hunk") - { + let res = if hunk_idx == hunk_index { count += 1; true } else { diff --git a/asyncgit/src/sync/ignore.rs b/asyncgit/src/sync/ignore.rs index c71ad46251..62e383ea00 100644 --- a/asyncgit/src/sync/ignore.rs +++ b/asyncgit/src/sync/ignore.rs @@ -18,7 +18,7 @@ pub fn add_to_ignore( let repo = repo(repo_path)?; - let ignore_file = work_dir(&repo).join(GITIGNORE); + let ignore_file = work_dir(&repo)?.join(GITIGNORE); let optional_newline = ignore_file.exists() && !file_ends_with_newline(&ignore_file)?; diff --git a/asyncgit/src/sync/utils.rs b/asyncgit/src/sync/utils.rs index 1cf090d24f..639830ba85 100644 --- a/asyncgit/src/sync/utils.rs +++ b/asyncgit/src/sync/utils.rs @@ -52,14 +52,14 @@ pub(crate) fn repo(repo_path: &str) -> Result { } /// -pub(crate) fn work_dir(repo: &Repository) -> &Path { - repo.workdir().expect("unable to query workdir") +pub(crate) fn work_dir(repo: &Repository) -> Result<&Path> { + repo.workdir().map_or(Err(Error::NoWorkDir), |dir| Ok(dir)) } /// pub fn repo_work_dir(repo_path: &str) -> Result { let repo = repo(repo_path)?; - if let Some(workdir) = work_dir(&repo).to_str() { + if let Some(workdir) = work_dir(&repo)?.to_str() { Ok(workdir.to_string()) } else { Err(Error::Generic("invalid workdir".to_string())) From 33de4f3f771a1be8927192274d026d085a778e25 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 11:39:55 +0100 Subject: [PATCH 3/8] fix warnings --- src/clipboard.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/clipboard.rs b/src/clipboard.rs index 5f15e11f76..7270d89b9f 100644 --- a/src/clipboard.rs +++ b/src/clipboard.rs @@ -1,4 +1,5 @@ use anyhow::Result; +#[cfg(target_os = "linux")] use std::ffi::OsStr; use std::io::Write; use std::process::{Command, Stdio}; @@ -28,6 +29,7 @@ fn execute_copy_command(command: Command, text: &str) -> Result<()> { Ok(()) } +#[cfg(target_os = "linux")] fn gen_command( path: impl AsRef, xclip_syntax: bool, From 2dab9de273b6c602e3b5b3b4af30cae5ea1b4fbf Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 12:16:40 +0100 Subject: [PATCH 4/8] cleanup some more expects --- asyncgit/src/sync/branch.rs | 21 ++++++++++----------- asyncgit/src/sync/commit_files.rs | 9 +++++++-- asyncgit/src/sync/tags.rs | 1 + asyncgit/src/sync/utils.rs | 8 ++++++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/asyncgit/src/sync/branch.rs b/asyncgit/src/sync/branch.rs index 8126385580..ec46cf7900 100644 --- a/asyncgit/src/sync/branch.rs +++ b/asyncgit/src/sync/branch.rs @@ -8,6 +8,8 @@ use git2::BranchType; use scopetime::scope_time; use utils::get_head_repo; +use super::utils::bytes2string; + /// returns the branch-name head is currently pointing to /// this might be expensive, see `cached::BranchName` pub(crate) fn get_branch_name(repo_path: &str) -> Result { @@ -58,15 +60,11 @@ pub fn get_branches_to_display( let top_commit = branch.get().peel_to_commit()?; Ok(BranchForDisplay { - name: String::from_utf8(Vec::from( - branch.name_bytes()?, - ))?, - reference: String::from_utf8(Vec::from( - branch.get().name_bytes(), - ))?, - top_commit_message: String::from_utf8(Vec::from( + name: bytes2string(branch.name_bytes()?)?, + reference: bytes2string(branch.get().name_bytes())?, + top_commit_message: bytes2string( top_commit.summary_bytes().unwrap_or_default(), - ))?, + )?, top_commit: top_commit.id().into(), is_head: branch.is_head(), }) @@ -132,7 +130,9 @@ pub fn checkout_branch( git2::build::CheckoutBuilder::new().force(), )) { // This is safe beacuse cur_ref was just found - repo.set_head(cur_ref.name().expect("utf8 error"))?; + repo.set_head( + bytes2string(cur_ref.name_bytes())?.as_str(), + )?; return Err(Error::Git(e)); } Ok(()) @@ -188,8 +188,7 @@ pub fn create_branch(repo_path: &str, name: &str) -> Result<()> { let branch = repo.branch(name, &head_commit, false)?; let branch_ref = branch.into_reference(); - let branch_ref_name = - String::from_utf8(branch_ref.name_bytes().to_vec())?; + let branch_ref_name = bytes2string(branch_ref.name_bytes())?; repo.set_head(branch_ref_name.as_str())?; Ok(()) diff --git a/asyncgit/src/sync/commit_files.rs b/asyncgit/src/sync/commit_files.rs index 6d0e9aa6c3..f988a3d9e3 100644 --- a/asyncgit/src/sync/commit_files.rs +++ b/asyncgit/src/sync/commit_files.rs @@ -1,5 +1,7 @@ use super::{stash::is_stash_commit, utils::repo, CommitId}; -use crate::{error::Result, StatusItem, StatusItemType}; +use crate::{ + error::Error, error::Result, StatusItem, StatusItemType, +}; use git2::{Diff, DiffDelta, DiffOptions, Repository}; use scopetime::scope_time; @@ -66,7 +68,10 @@ pub(crate) fn get_commit_diff( )?; if is_stash_commit( - repo.path().to_str().expect("repo path utf8 err"), + repo.path().to_str().map_or_else( + || Err(Error::Generic("repo path utf8 err".to_owned())), + Ok, + )?, &id, )? { if let Ok(untracked_commit) = commit.parent_id(2) { diff --git a/asyncgit/src/sync/tags.rs b/asyncgit/src/sync/tags.rs index 4c98dc0290..ebe7a2744c 100644 --- a/asyncgit/src/sync/tags.rs +++ b/asyncgit/src/sync/tags.rs @@ -25,6 +25,7 @@ pub fn get_tags(repo_path: &str) -> Result { repo.tag_foreach(|id, name| { if let Ok(name) = + // skip the `refs/tags/` part String::from_utf8(name[10..name.len()].into()) { //NOTE: find_tag (git_tag_lookup) only works on annotated tags diff --git a/asyncgit/src/sync/utils.rs b/asyncgit/src/sync/utils.rs index 639830ba85..ecb45813f6 100644 --- a/asyncgit/src/sync/utils.rs +++ b/asyncgit/src/sync/utils.rs @@ -84,8 +84,7 @@ pub fn get_head_tuple(repo_path: &str) -> Result { /// pub fn get_head_refname(repo: &Repository) -> Result { let head = repo.head()?; - let name_bytes = head.name_bytes(); - let ref_name = String::from_utf8(name_bytes.to_vec())?; + let ref_name = bytes2string(head.name_bytes())?; Ok(ref_name) } @@ -145,6 +144,11 @@ pub fn stage_addremoved(repo_path: &str, path: &Path) -> Result<()> { Ok(()) } +/// helper function +pub(crate) fn bytes2string(bytes: &[u8]) -> Result { + Ok(String::from_utf8(bytes.to_vec())?) +} + #[cfg(test)] mod tests { use super::*; From 6e6832da2175e70f9a75a3ad65e859c7d0bed1cd Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 12:37:07 +0100 Subject: [PATCH 5/8] cleanup one more expect --- asyncgit/src/sync/diff.rs | 64 ++++++++++++++++++++------------------ asyncgit/src/sync/hunks.rs | 9 ++++-- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/asyncgit/src/sync/diff.rs b/asyncgit/src/sync/diff.rs index cdc55473f0..88c43ca7ca 100644 --- a/asyncgit/src/sync/diff.rs +++ b/asyncgit/src/sync/diff.rs @@ -219,40 +219,39 @@ fn raw_diff_to_file_diff<'a>( }; let new_file_diff = if diff.deltas().len() == 1 { - let delta: DiffDelta = diff - .deltas() - .next() - .expect("it's safe to unwrap here because we check first that diff.deltas has a single element"); - - if delta.status() == Delta::Untracked { - let relative_path = - delta.new_file().path().ok_or_else(|| { - Error::Generic( - "new file path is unspecified." - .to_string(), - ) - })?; - - let newfile_path = work_dir.join(relative_path); - - if let Some(newfile_content) = - new_file_content(&newfile_path) - { - let mut patch = Patch::from_buffers( - &[], - None, - newfile_content.as_slice(), - Some(&newfile_path), - None, - )?; - - patch + if let Some(delta) = diff.deltas().next() { + if delta.status() == Delta::Untracked { + let relative_path = + delta.new_file().path().ok_or_else(|| { + Error::Generic( + "new file path is unspecified." + .to_string(), + ) + })?; + + let newfile_path = work_dir.join(relative_path); + + if let Some(newfile_content) = + new_file_content(&newfile_path) + { + let mut patch = Patch::from_buffers( + &[], + None, + newfile_content.as_slice(), + Some(&newfile_path), + None, + )?; + + patch .print(&mut |delta, hunk:Option, line: git2::DiffLine| { put(delta,hunk,line); true })?; - true + true + } else { + false + } } else { false } @@ -275,7 +274,10 @@ fn raw_diff_to_file_diff<'a>( if !current_lines.is_empty() { adder( - ¤t_hunk.expect("invalid hunk"), + ¤t_hunk.map_or_else( + || Err(Error::Generic("invalid hunk".to_owned())), + Ok, + )?, ¤t_lines, ); } @@ -285,7 +287,7 @@ fn raw_diff_to_file_diff<'a>( } } let res = Rc::try_unwrap(res) - .map_err(|_| Error::Generic("".to_owned()))?; + .map_err(|_| Error::Generic("rc unwrap error".to_owned()))?; Ok(res.into_inner()) } diff --git a/asyncgit/src/sync/hunks.rs b/asyncgit/src/sync/hunks.rs index a37d7c2832..19cda65bb0 100644 --- a/asyncgit/src/sync/hunks.rs +++ b/asyncgit/src/sync/hunks.rs @@ -23,9 +23,12 @@ pub fn stage_hunk( let mut opt = ApplyOptions::new(); opt.hunk_callback(|hunk| { - let header = - HunkHeader::from(hunk.expect("hunk unavailable")); - hash(&header) == hunk_hash + if let Some(hunk) = hunk { + let header = HunkHeader::from(hunk); + hash(&header) == hunk_hash + } else { + false + } }); repo.apply(&diff, ApplyLocation::Index, Some(&mut opt))?; From 00073cbdd754f237c3bed12a6d3fc1def61439ca Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 01:30:09 +0100 Subject: [PATCH 6/8] fix hook panicking (#393) --- asyncgit/src/sync/hooks.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/asyncgit/src/sync/hooks.rs b/asyncgit/src/sync/hooks.rs index 18819ed7c6..b81bca1be0 100644 --- a/asyncgit/src/sync/hooks.rs +++ b/asyncgit/src/sync/hooks.rs @@ -34,7 +34,7 @@ pub fn hooks_commit_msg( work_dir.as_str(), HOOK_COMMIT_MSG, &[HOOK_COMMIT_MSG_TEMP_FILE], - ); + )?; // load possibly altered msg msg.clear(); @@ -54,9 +54,7 @@ pub fn hooks_pre_commit(repo_path: &str) -> Result { let work_dir = work_dir_as_string(repo_path)?; if hook_runable(work_dir.as_str(), HOOK_PRE_COMMIT) { - let res = run_hook(work_dir.as_str(), HOOK_PRE_COMMIT, &[]); - - Ok(res) + Ok(run_hook(work_dir.as_str(), HOOK_PRE_COMMIT, &[])?) } else { Ok(HookResult::Ok) } @@ -69,7 +67,7 @@ pub fn hooks_post_commit(repo_path: &str) -> Result { let work_dir_str = work_dir.as_str(); if hook_runable(work_dir_str, HOOK_POST_COMMIT) { - Ok(run_hook(work_dir_str, HOOK_POST_COMMIT, &[])) + Ok(run_hook(work_dir_str, HOOK_POST_COMMIT, &[])?) } else { Ok(HookResult::Ok) } @@ -108,7 +106,7 @@ fn run_hook( path: &str, hook_script: &str, args: &[&str], -) -> HookResult { +) -> Result { let arg_str = format!("{} {}", hook_script, args.join(" ")); let bash_args = vec!["-c".to_string(), arg_str]; @@ -122,18 +120,16 @@ fn run_hook( "DUMMY_ENV_TO_FIX_WINDOWS_CMD_RUNS", "FixPathHandlingOnWindows", ) - .output(); - - let output = output.expect("general hook error"); + .output()?; if output.status.success() { - HookResult::Ok + Ok(HookResult::Ok) } else { let err = String::from_utf8_lossy(&output.stderr); let out = String::from_utf8_lossy(&output.stdout); let formatted = format!("{}{}", out, err); - HookResult::NotOk(formatted) + Ok(HookResult::NotOk(formatted)) } } From c4fdbf7aba9b6925b941816e84f4459746cbeb89 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 12:49:11 +0100 Subject: [PATCH 7/8] make sync part of lib expect safe --- asyncgit/src/sync/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/asyncgit/src/sync/mod.rs b/asyncgit/src/sync/mod.rs index f9baea63f1..653248c809 100644 --- a/asyncgit/src/sync/mod.rs +++ b/asyncgit/src/sync/mod.rs @@ -1,5 +1,8 @@ //! sync git api +//TODO: remove once we have this activated on the toplevel +#![deny(clippy::expect_used)] + mod branch; mod commit; mod commit_details; From 88813381daaefb74139e3e49aab6b6f73db44ccd Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 1 Nov 2020 19:43:19 +0100 Subject: [PATCH 8/8] indicate if branch has an upstream and some cleanup --- asyncgit/src/sync/branch.rs | 3 + src/components/select_branch.rs | 101 ++++++++++++-------------------- src/ui/style.rs | 14 +++++ 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/asyncgit/src/sync/branch.rs b/asyncgit/src/sync/branch.rs index ec46cf7900..6c3310e885 100644 --- a/asyncgit/src/sync/branch.rs +++ b/asyncgit/src/sync/branch.rs @@ -43,6 +43,8 @@ pub struct BranchForDisplay { pub top_commit: CommitId, /// pub is_head: bool, + /// + pub has_upstream: bool, } /// Used to return only the nessessary information for displaying a branch @@ -67,6 +69,7 @@ pub fn get_branches_to_display( )?, top_commit: top_commit.id().into(), is_head: branch.is_head(), + has_upstream: branch.upstream().is_ok(), }) }) .filter_map(Result::ok) diff --git a/src/components/select_branch.rs b/src/components/select_branch.rs index d0f6984531..297aab5c9c 100644 --- a/src/components/select_branch.rs +++ b/src/components/select_branch.rs @@ -228,7 +228,7 @@ impl SelectBranchComponent { } /// Get all the names of the branches in the repo pub fn get_branch_names() -> Result> { - get_branches_to_display(CWD).map_err(anyhow::Error::new) + Ok(get_branches_to_display(CWD)?) } /// @@ -325,70 +325,47 @@ impl SelectBranchComponent { branch_name += "..."; } + let selected = + self.selection as usize - self.scroll_top.get() == i; + let is_head_str = if displaybranch.is_head { "*" } else { " " }; + let has_upstream_str = if displaybranch.has_upstream { + "\u{2191}" + } else { + " " + }; + + let span_prefix = Span::styled( + format!("{}{} ", is_head_str, has_upstream_str), + theme.commit_author(selected), + ); + let span_hash = Span::styled( + format!( + "{} ", + displaybranch.top_commit.get_short_string() + ), + theme.commit_hash(selected), + ); + let span_msg = Span::styled( + commit_message.to_string(), + theme.text(true, selected), + ); + let span_name = Span::styled( + format!( + "{:w$} ", + branch_name, + w = branch_name_length + ), + theme.branch(selected, displaybranch.is_head), + ); - txt.push(Spans::from( - if self.selection as usize - self.scroll_top.get() - == i - { - vec![ - Span::styled( - format!("{} ", is_head_str), - theme.commit_author(true), - ), - Span::styled( - format!( - ">{:w$} ", - branch_name, - w = branch_name_length - ), - theme.commit_author(true), - ), - Span::styled( - format!( - "{} ", - displaybranch - .top_commit - .get_short_string() - ), - theme.commit_hash(true), - ), - Span::styled( - commit_message.to_string(), - theme.text(true, true), - ), - ] - } else { - vec![ - Span::styled( - format!("{} ", is_head_str), - theme.commit_author(false), - ), - Span::styled( - format!( - " {:w$} ", - branch_name, - w = branch_name_length - ), - theme.commit_author(false), - ), - Span::styled( - format!( - "{} ", - displaybranch - .top_commit - .get_short_string() - ), - theme.commit_hash(false), - ), - Span::styled( - commit_message.to_string(), - theme.text(true, false), - ), - ] - }, - )); + txt.push(Spans::from(vec![ + span_prefix, + span_name, + span_hash, + span_msg, + ])); } Ok(Text::from(txt)) diff --git a/src/ui/style.rs b/src/ui/style.rs index 390c5767a9..8708dc0181 100644 --- a/src/ui/style.rs +++ b/src/ui/style.rs @@ -70,6 +70,20 @@ impl Theme { } } + pub fn branch(&self, selected: bool, head: bool) -> Style { + let branch = if head { + Style::default().add_modifier(Modifier::BOLD) + } else { + Style::default() + }; + + if selected { + branch.patch(Style::default().bg(self.selection_bg)) + } else { + branch + } + } + pub fn tab(&self, selected: bool) -> Style { if selected { self.text(true, false)