Add workspace mode, enable if in git repo (#1053)
* Add workspace mode, enable if in git repo * Fix tests * Should now be good * Page filter modes correctly if in workspace
This commit is contained in:
parent
5d26d3f47a
commit
465faca6d1
6 changed files with 83 additions and 13 deletions
|
@ -1,4 +1,8 @@
|
|||
use std::{env, path::Path, str::FromStr};
|
||||
use std::{
|
||||
env,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use atuin_common::utils;
|
||||
|
@ -25,6 +29,7 @@ pub struct Context {
|
|||
pub cwd: String,
|
||||
pub hostname: String,
|
||||
pub host_id: String,
|
||||
pub git_root: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
|
@ -52,11 +57,13 @@ pub fn current_context() -> Context {
|
|||
);
|
||||
let cwd = utils::get_current_dir();
|
||||
let host_id = Settings::host_id().expect("failed to load host ID");
|
||||
let git_root = utils::in_git_repo(cwd.as_str());
|
||||
|
||||
Context {
|
||||
session,
|
||||
hostname,
|
||||
cwd,
|
||||
git_root,
|
||||
host_id: host_id.0.as_simple().to_string(),
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +268,7 @@ impl Database for Sqlite {
|
|||
FilterMode::Host => query.and_where_eq("hostname", quote(&context.hostname)),
|
||||
FilterMode::Session => query.and_where_eq("session", quote(&context.session)),
|
||||
FilterMode::Directory => query.and_where_eq("cwd", quote(&context.cwd)),
|
||||
FilterMode::Workspace => query.and_where_like_any("cwd", context.cwd.clone()),
|
||||
};
|
||||
|
||||
if unique {
|
||||
|
@ -380,11 +388,18 @@ impl Database for Sqlite {
|
|||
sql.order_desc("timestamp");
|
||||
}
|
||||
|
||||
let git_root = if let Some(git_root) = context.git_root.clone() {
|
||||
git_root.to_str().unwrap_or("/").to_string()
|
||||
} else {
|
||||
context.cwd.clone()
|
||||
};
|
||||
|
||||
match filter {
|
||||
FilterMode::Global => &mut sql,
|
||||
FilterMode::Host => sql.and_where_eq("hostname", quote(&context.hostname)),
|
||||
FilterMode::Session => sql.and_where_eq("session", quote(&context.session)),
|
||||
FilterMode::Directory => sql.and_where_eq("cwd", quote(&context.cwd)),
|
||||
FilterMode::Workspace => sql.and_where_like_left("cwd", git_root),
|
||||
};
|
||||
|
||||
let orig_query = query;
|
||||
|
@ -556,6 +571,7 @@ mod test {
|
|||
session: "beepboopiamasession".to_string(),
|
||||
cwd: "/home/ellie".to_string(),
|
||||
host_id: "test-host".to_string(),
|
||||
git_root: None,
|
||||
};
|
||||
|
||||
let results = db
|
||||
|
@ -765,6 +781,7 @@ mod test {
|
|||
session: "beepboopiamasession".to_string(),
|
||||
cwd: "/home/ellie".to_string(),
|
||||
host_id: "test-host".to_string(),
|
||||
git_root: None,
|
||||
};
|
||||
|
||||
let mut db = Sqlite::new("sqlite::memory:").await.unwrap();
|
||||
|
|
|
@ -72,6 +72,9 @@ pub enum FilterMode {
|
|||
|
||||
#[serde(rename = "directory")]
|
||||
Directory = 3,
|
||||
|
||||
#[serde(rename = "workspace")]
|
||||
Workspace = 4,
|
||||
}
|
||||
|
||||
impl FilterMode {
|
||||
|
@ -81,6 +84,7 @@ impl FilterMode {
|
|||
FilterMode::Host => "HOST",
|
||||
FilterMode::Session => "SESSION",
|
||||
FilterMode::Directory => "DIRECTORY",
|
||||
FilterMode::Workspace => "WORKSPACE",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +167,7 @@ pub struct Settings {
|
|||
pub history_filter: RegexSet,
|
||||
#[serde(with = "serde_regex", default = "RegexSet::empty")]
|
||||
pub cwd_filter: RegexSet,
|
||||
pub workspaces: bool,
|
||||
|
||||
// This is automatically loaded when settings is created. Do not set in
|
||||
// config! Keep secrets and settings apart.
|
||||
|
@ -374,6 +379,7 @@ impl Settings {
|
|||
.set_default("scroll_context_lines", 1)?
|
||||
.set_default("shell_up_key_binding", false)?
|
||||
.set_default("session_token", "")?
|
||||
.set_default("workspaces", false)?
|
||||
.add_source(
|
||||
Environment::with_prefix("atuin")
|
||||
.prefix_separator("_")
|
||||
|
|
|
@ -46,6 +46,31 @@ pub fn uuid_v4() -> String {
|
|||
Uuid::new_v4().as_simple().to_string()
|
||||
}
|
||||
|
||||
pub fn has_git_dir(path: &str) -> bool {
|
||||
let mut gitdir = PathBuf::from(path);
|
||||
gitdir.push(".git");
|
||||
|
||||
gitdir.exists()
|
||||
}
|
||||
|
||||
// detect if any parent dir has a git repo in it
|
||||
// I really don't want to bring in libgit for something simple like this
|
||||
// If we start to do anything more advanced, then perhaps
|
||||
pub fn in_git_repo(path: &str) -> Option<PathBuf> {
|
||||
let mut gitdir = PathBuf::from(path);
|
||||
|
||||
while gitdir.parent().is_some() && !has_git_dir(gitdir.to_str().unwrap()) {
|
||||
gitdir.pop();
|
||||
}
|
||||
|
||||
// No parent? then we hit root, finding no git
|
||||
if gitdir.parent().is_some() {
|
||||
return Some(gitdir);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// TODO: more reliable, more tested
|
||||
// I don't want to use ProjectDirs, it puts config in awkward places on
|
||||
// mac. Data too. Seems to be more intended for GUI apps.
|
||||
|
|
|
@ -194,14 +194,21 @@ async fn run_non_interactive(
|
|||
let context = current_context();
|
||||
|
||||
let opt_filter = OptFilters {
|
||||
cwd: dir,
|
||||
cwd: dir.clone(),
|
||||
..filter_options
|
||||
};
|
||||
|
||||
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 results = db
|
||||
.search(
|
||||
settings.search_mode,
|
||||
settings.filter_mode,
|
||||
filter_mode,
|
||||
&context,
|
||||
query.join(" ").as_str(),
|
||||
opt_filter,
|
||||
|
|
|
@ -184,15 +184,27 @@ impl State {
|
|||
}
|
||||
KeyCode::Char('u') if ctrl => self.search.input.clear(),
|
||||
KeyCode::Char('r') if ctrl => {
|
||||
pub static FILTER_MODES: [FilterMode; 4] = [
|
||||
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];
|
||||
let i = (i + 1) % filter_modes.len();
|
||||
self.search.filter_mode = filter_modes[i];
|
||||
}
|
||||
KeyCode::Char('s') if ctrl => {
|
||||
self.switched_search_mode = true;
|
||||
|
@ -586,14 +598,16 @@ pub async fn history(
|
|||
search_mode: settings.search_mode,
|
||||
search: SearchState {
|
||||
input,
|
||||
context,
|
||||
filter_mode: if settings.shell_up_key_binding {
|
||||
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)
|
||||
} else {
|
||||
settings.filter_mode
|
||||
},
|
||||
context,
|
||||
},
|
||||
engine: engines::engine(settings.search_mode),
|
||||
results_len: 0,
|
||||
|
|
|
@ -80,6 +80,7 @@ impl Cmd {
|
|||
} else {
|
||||
self.period.join(" ")
|
||||
};
|
||||
|
||||
let history = if words.as_str() == "all" {
|
||||
db.list(FilterMode::Global, &context, None, false).await?
|
||||
} else if words.trim() == "today" {
|
||||
|
|
Loading…
Reference in a new issue