mirror of
https://github.com/ellie/atuin.git
synced 2024-10-26 15:23:31 +03:00
parent
95c9168944
commit
29fb01c527
@ -40,10 +40,15 @@
|
||||
## possible values: prefix, fulltext, fuzzy, skim
|
||||
# search_mode = "fuzzy"
|
||||
|
||||
## which filter mode to use
|
||||
## which filter mode to use by default
|
||||
## possible values: global, host, session, directory
|
||||
## defaults to the first element of 'filter_modes'
|
||||
# filter_mode = "global"
|
||||
|
||||
## which filter modes are available in which order.
|
||||
## 'workspace' is skipped when not in a workspace or disabled
|
||||
# filter_modes = [ "workspace", "global", "host", "session", "directory" ]
|
||||
|
||||
## With workspace filtering enabled, Atuin will filter for commands executed
|
||||
## in any directory within a git repository tree (default: false)
|
||||
# workspaces = false
|
||||
|
@ -404,7 +404,8 @@ pub struct Settings {
|
||||
pub key_path: String,
|
||||
pub session_path: String,
|
||||
pub search_mode: SearchMode,
|
||||
pub filter_mode: FilterMode,
|
||||
pub filter_mode: Option<FilterMode>,
|
||||
pub filter_modes: Vec<FilterMode>,
|
||||
pub filter_mode_shell_up_key_binding: Option<FilterMode>,
|
||||
pub search_mode_shell_up_key_binding: Option<SearchMode>,
|
||||
pub shell_up_key_binding: bool,
|
||||
@ -671,7 +672,11 @@ impl Settings {
|
||||
.set_default("sync_address", "https://api.atuin.sh")?
|
||||
.set_default("sync_frequency", "10m")?
|
||||
.set_default("search_mode", "fuzzy")?
|
||||
.set_default("filter_mode", "global")?
|
||||
.set_default("filter_mode", None::<String>)?
|
||||
.set_default(
|
||||
"filter_modes",
|
||||
vec!["workspace", "global", "host", "session"],
|
||||
)?
|
||||
.set_default("style", "auto")?
|
||||
.set_default("inline_height", 0)?
|
||||
.set_default("show_preview", true)?
|
||||
|
@ -443,7 +443,12 @@ impl Cmd {
|
||||
(true, true) => [Session, Directory],
|
||||
(true, false) => [Session, Global],
|
||||
(false, true) => [Global, Directory],
|
||||
(false, false) => [settings.filter_mode, Global],
|
||||
(false, false) => [
|
||||
settings
|
||||
.filter_mode
|
||||
.unwrap_or(*settings.filter_modes.first().unwrap_or(&Global)),
|
||||
Global,
|
||||
],
|
||||
};
|
||||
|
||||
let history = db
|
||||
|
@ -175,7 +175,7 @@ impl Cmd {
|
||||
settings.search_mode = self.search_mode.unwrap();
|
||||
}
|
||||
if self.filter_mode.is_some() {
|
||||
settings.filter_mode = self.filter_mode.unwrap();
|
||||
settings.filter_mode = self.filter_mode;
|
||||
}
|
||||
if self.inline_height.is_some() {
|
||||
settings.inline_height = self.inline_height.unwrap();
|
||||
@ -287,11 +287,17 @@ async fn run_non_interactive(
|
||||
};
|
||||
|
||||
let dir = dir.unwrap_or_else(|| "/".to_string());
|
||||
let filter_mode = if settings.workspaces && utils::has_git_dir(dir.as_str()) {
|
||||
FilterMode::Workspace
|
||||
} else {
|
||||
settings.filter_mode
|
||||
};
|
||||
let filter_mode = settings.filter_mode.unwrap_or(
|
||||
*settings
|
||||
.filter_modes
|
||||
.iter()
|
||||
.find(|item| {
|
||||
*item != &FilterMode::Workspace
|
||||
|| !settings.workspaces
|
||||
|| utils::has_git_dir(dir.as_str())
|
||||
})
|
||||
.unwrap_or(&FilterMode::Global),
|
||||
);
|
||||
|
||||
let results = db
|
||||
.search(
|
||||
|
@ -20,7 +20,8 @@ pub fn engine(search_mode: SearchMode) -> Box<dyn SearchEngine> {
|
||||
|
||||
pub struct SearchState {
|
||||
pub input: Cursor,
|
||||
pub filter_mode: FilterMode,
|
||||
pub filter_mode_index: usize,
|
||||
pub available_filter_modes: Vec<FilterMode>,
|
||||
pub context: Context,
|
||||
}
|
||||
|
||||
@ -35,7 +36,13 @@ pub trait SearchEngine: Send + Sync + 'static {
|
||||
async fn query(&mut self, state: &SearchState, db: &mut dyn Database) -> Result<Vec<History>> {
|
||||
if state.input.as_str().is_empty() {
|
||||
Ok(db
|
||||
.list(&[state.filter_mode], &state.context, Some(200), true, false)
|
||||
.list(
|
||||
&[state.available_filter_modes[state.filter_mode_index]],
|
||||
&state.context,
|
||||
Some(200),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>())
|
||||
|
@ -18,7 +18,7 @@ impl SearchEngine for Search {
|
||||
Ok(db
|
||||
.search(
|
||||
self.0,
|
||||
state.filter_mode,
|
||||
state.available_filter_modes[state.filter_mode_index],
|
||||
&state.context,
|
||||
state.input.as_str(),
|
||||
OptFilters {
|
||||
|
@ -59,25 +59,26 @@ async fn fuzzy_search(
|
||||
.as_ref()
|
||||
.and_then(|git_root| git_root.to_str())
|
||||
.unwrap_or(&context.cwd);
|
||||
match state.filter_mode {
|
||||
FilterMode::Global => {}
|
||||
match state.available_filter_modes.get(state.filter_mode_index) {
|
||||
Some(FilterMode::Global) => {}
|
||||
// we aggregate host by ',' separating them
|
||||
FilterMode::Host
|
||||
Some(FilterMode::Host)
|
||||
if history
|
||||
.hostname
|
||||
.split(',')
|
||||
.contains(&context.hostname.as_str()) => {}
|
||||
// we aggregate session by concattenating them.
|
||||
// sessions are 32 byte simple uuid formats
|
||||
FilterMode::Session
|
||||
Some(FilterMode::Session)
|
||||
if history
|
||||
.session
|
||||
.as_bytes()
|
||||
.chunks(32)
|
||||
.contains(&context.session.as_bytes()) => {}
|
||||
// we aggregate directory by ':' separating them
|
||||
FilterMode::Directory if history.cwd.split(':').contains(&context.cwd.as_str()) => {}
|
||||
FilterMode::Workspace if history.cwd.split(':').contains(&git_root) => {}
|
||||
Some(FilterMode::Directory)
|
||||
if history.cwd.split(':').contains(&context.cwd.as_str()) => {}
|
||||
Some(FilterMode::Workspace) if history.cwd.split(':').contains(&git_root) => {}
|
||||
_ => continue,
|
||||
}
|
||||
#[allow(clippy::cast_lossless, clippy::cast_precision_loss)]
|
||||
|
@ -452,27 +452,8 @@ impl State {
|
||||
}
|
||||
KeyCode::Char('u') if ctrl => self.search.input.clear(),
|
||||
KeyCode::Char('r') if ctrl => {
|
||||
let filter_modes = if settings.workspaces && self.search.context.git_root.is_some()
|
||||
{
|
||||
vec![
|
||||
FilterMode::Global,
|
||||
FilterMode::Host,
|
||||
FilterMode::Session,
|
||||
FilterMode::Directory,
|
||||
FilterMode::Workspace,
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
FilterMode::Global,
|
||||
FilterMode::Host,
|
||||
FilterMode::Session,
|
||||
FilterMode::Directory,
|
||||
]
|
||||
};
|
||||
|
||||
let i = self.search.filter_mode as usize;
|
||||
let i = (i + 1) % filter_modes.len();
|
||||
self.search.filter_mode = filter_modes[i];
|
||||
self.search.filter_mode_index =
|
||||
(self.search.filter_mode_index + 1) % self.search.available_filter_modes.len();
|
||||
}
|
||||
KeyCode::Char('s') if ctrl => {
|
||||
self.switched_search_mode = true;
|
||||
@ -848,7 +829,10 @@ impl State {
|
||||
let (pref, mode) = if self.switched_search_mode {
|
||||
(" SRCH:", self.search_mode.as_str())
|
||||
} else {
|
||||
("", self.search.filter_mode.as_str())
|
||||
(
|
||||
"",
|
||||
self.search.available_filter_modes[self.search.filter_mode_index].as_str(),
|
||||
)
|
||||
};
|
||||
let mode_width = MAX_WIDTH - pref.len();
|
||||
// sanity check to ensure we don't exceed the layout limits
|
||||
@ -1018,6 +1002,28 @@ pub async fn history(
|
||||
} else {
|
||||
settings.search_mode
|
||||
};
|
||||
let mut available_filter_modes = settings
|
||||
.filter_modes
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|item| {
|
||||
*item != FilterMode::Workspace || !settings.workspaces || context.git_root.is_some()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if available_filter_modes.is_empty() {
|
||||
available_filter_modes = vec![
|
||||
FilterMode::Workspace,
|
||||
FilterMode::Global,
|
||||
FilterMode::Host,
|
||||
FilterMode::Session,
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|item| {
|
||||
*item != FilterMode::Workspace || !settings.workspaces || context.git_root.is_some()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
}
|
||||
|
||||
let mut app = State {
|
||||
history_count,
|
||||
results_state: ListState::default(),
|
||||
@ -1027,15 +1033,24 @@ pub async fn history(
|
||||
tab_index: 0,
|
||||
search: SearchState {
|
||||
input,
|
||||
filter_mode: if settings.workspaces && context.git_root.is_some() {
|
||||
FilterMode::Workspace
|
||||
} else if settings.shell_up_key_binding {
|
||||
settings
|
||||
.filter_mode_shell_up_key_binding
|
||||
.unwrap_or(settings.filter_mode)
|
||||
filter_mode_index: if settings.shell_up_key_binding {
|
||||
available_filter_modes
|
||||
.iter()
|
||||
.position(|&item| {
|
||||
item == settings
|
||||
.filter_mode_shell_up_key_binding
|
||||
.unwrap_or(FilterMode::Global)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
} else if let Some(filter_mode) = settings.filter_mode {
|
||||
available_filter_modes
|
||||
.iter()
|
||||
.position(|&item| item == filter_mode)
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
settings.filter_mode
|
||||
0
|
||||
},
|
||||
available_filter_modes,
|
||||
context,
|
||||
},
|
||||
engine: engines::engine(search_mode),
|
||||
@ -1065,7 +1080,7 @@ pub async fn history(
|
||||
terminal.draw(|f| app.draw(f, &results, stats.clone(), settings))?;
|
||||
|
||||
let initial_input = app.search.input.as_str().to_owned();
|
||||
let initial_filter_mode = app.search.filter_mode;
|
||||
let initial_filter_mode = app.search.available_filter_modes[app.search.filter_mode_index];
|
||||
let initial_search_mode = app.search_mode;
|
||||
|
||||
let event_ready = tokio::task::spawn_blocking(|| event::poll(Duration::from_millis(250)));
|
||||
@ -1115,7 +1130,8 @@ pub async fn history(
|
||||
}
|
||||
|
||||
if initial_input != app.search.input.as_str()
|
||||
|| initial_filter_mode != app.search.filter_mode
|
||||
|| initial_filter_mode
|
||||
!= app.search.available_filter_modes[app.search.filter_mode_index]
|
||||
|| initial_search_mode != app.search_mode
|
||||
{
|
||||
results = app.query_results(&mut db, settings.smart_sort).await?;
|
||||
|
Loading…
Reference in New Issue
Block a user