Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ pub struct StyleConfig {
pub selection_line: StyleConfigEntry,
pub selection_area: StyleConfigEntry,

#[serde(default)]
pub search_match: StyleConfigEntry,

pub hash: StyleConfigEntry,
pub branch: StyleConfigEntry,
pub remote: StyleConfigEntry,
Expand Down Expand Up @@ -353,11 +356,14 @@ pub fn config_path() -> PathBuf {
.join("gitu/config.toml")
}

#[cfg(test)]
pub(crate) const TEST_SEARCH_HIGHLIGHT_BG: Color = Color::LightYellow;

#[cfg(test)]
pub(crate) fn init_test_config() -> Res<Config> {
let FigmentConfig {
mut general,
style,
mut style,
bindings: bindings_config,
} = Figment::new()
.merge(Toml::string(DEFAULT_CONFIG))
Expand All @@ -368,6 +374,12 @@ pub(crate) fn init_test_config() -> Res<Config> {
general.always_show_help.enabled = false;
general.refresh_on_file_change.enabled = false;

style.search_match = StyleConfigEntry {
fg: None,
bg: Some(TEST_SEARCH_HIGHLIGHT_BG),
mods: None,
};

Ok(Config {
general,
style,
Expand Down
6 changes: 6 additions & 0 deletions src/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ picker.info = { mods = "DIM" }
picker.selection_line = { mods = "BOLD" }
picker.matched = { fg = "yellow", mods = "BOLD" }

search_match = { mods = "REVERSED" }

cursor = { symbol = "▌", fg = "blue" }
selection_bar = { symbol = "▌", fg = "blue", mods = "DIM" }
selection_line = { mods = "BOLD" }
Expand Down Expand Up @@ -123,6 +125,10 @@ root.move_top = ["g+g"]
root.move_bottom = ["G"]
root.scroll_view_up = ["ctrl+y"]
root.scroll_view_down = ["ctrl+e"]
root.search = ["/"]
root.search_backward = []
root.search_next = ["n"]
root.search_previous = ["N"]
root.show_refs = ["Y"]
root.show = ["enter"]
root.discard = ["K"]
Expand Down
6 changes: 6 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub enum Error {
BaseCommitOid,
UpstreamCommitOid,
GitBlame(io::Error),
NoSearchMatch(String),
NoPreviousSearch,
InvalidSearchRegex(regex::Error),
}

impl std::error::Error for Error {}
Expand Down Expand Up @@ -166,6 +169,9 @@ impl Display for Error {
f.write_str("Could not resolve OID of upstream branch commit")
}
Error::GitBlame(e) => f.write_fmt(format_args!("Git blame error: {e}")),
Error::NoSearchMatch(query) => f.write_fmt(format_args!("No match: {query}")),
Error::NoPreviousSearch => f.write_str("No previous search"),
Error::InvalidSearchRegex(e) => f.write_fmt(format_args!("Invalid search: {e}")),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod ops;
pub mod picker;
mod prompt;
mod screen;
mod search;
pub mod style;
mod syntax_parser;
pub mod term;
Expand Down
10 changes: 10 additions & 0 deletions src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub(crate) mod remote;
pub(crate) mod reset;
pub(crate) mod reverse;
pub(crate) mod revert;
pub(crate) mod search;
pub(crate) mod show;
pub(crate) mod show_refs;
pub(crate) mod stage;
Expand Down Expand Up @@ -128,6 +129,11 @@ pub(crate) enum Op {
ScrollViewUp,
ScrollViewDown,

Search,
SearchBackward,
SearchNext,
SearchPrevious,

Refresh,
Quit,

Expand Down Expand Up @@ -161,6 +167,10 @@ impl Op {
Op::MoveBottom => Box::new(editor::MoveBottom),
Op::ScrollViewUp => Box::new(editor::ScrollViewUp),
Op::ScrollViewDown => Box::new(editor::ScrollViewDown),
Op::Search => Box::new(search::Search),
Op::SearchBackward => Box::new(search::SearchBackward),
Op::SearchNext => Box::new(search::SearchNext),
Op::SearchPrevious => Box::new(search::SearchPrevious),
Op::Checkout => Box::new(branch::Checkout),
Op::CheckoutNewBranch => Box::new(branch::CheckoutNewBranch),
Op::Spinoff => Box::new(branch::Spinoff),
Expand Down
86 changes: 86 additions & 0 deletions src/ops/search.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use super::{Action, OpTrait};
use crate::{
Res,
app::{App, PromptParams, State},
error::Error,
item_data::ItemData,
screen::SearchDirection,
term::Term,
};
use std::rc::Rc;

pub(crate) struct Search;
impl OpTrait for Search {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, term| {
prompt_search(app, term, SearchDirection::Forward)
}))
}

fn display(&self, _state: &State) -> String {
"Search".into()
}
}

pub(crate) struct SearchBackward;
impl OpTrait for SearchBackward {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, term| {
prompt_search(app, term, SearchDirection::Backward)
}))
}

fn display(&self, _state: &State) -> String {
"Search backward".into()
}
}

pub(crate) struct SearchNext;
impl OpTrait for SearchNext {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| app.screen_mut().search_repeat(false)))
}

fn display(&self, _state: &State) -> String {
"Next match".into()
}
}

pub(crate) struct SearchPrevious;
impl OpTrait for SearchPrevious {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| app.screen_mut().search_repeat(true)))
}

fn display(&self, _state: &State) -> String {
"Previous match".into()
}
}

fn prompt_search(app: &mut App, term: &mut Term, direction: SearchDirection) -> Res<()> {
let prompt = match direction {
SearchDirection::Forward => "Search",
SearchDirection::Backward => "Search backward",
};

let query = match app.prompt(
term,
&PromptParams {
prompt,
..Default::default()
},
) {
Ok(query) if query.is_empty() => {
app.screen_mut().clear_search();
return Ok(());
}
Ok(query) => query,
Err(Error::PromptAborted) => {
app.screen_mut().clear_search();
return Ok(());
}
Err(err) => return Err(err),
};

app.screen_mut().search(&query, direction)
}
Loading