Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add workspace mode, enable if in git repo #1053

Merged
merged 5 commits into from
Jul 14, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 18 additions & 1 deletion atuin-client/src/database.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)]
Expand Down Expand Up @@ -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(),
}
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions atuin-client/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ pub enum FilterMode {

#[serde(rename = "directory")]
Directory = 3,

#[serde(rename = "workspace")]
Workspace = 4,
}

impl FilterMode {
Expand All @@ -81,6 +84,7 @@ impl FilterMode {
FilterMode::Host => "HOST",
FilterMode::Session => "SESSION",
FilterMode::Directory => "DIRECTORY",
FilterMode::Workspace => "WORKSPACE",
}
}
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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("_")
Expand Down
25 changes: 25 additions & 0 deletions atuin-common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 9 additions & 2 deletions atuin/src/command/client/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
34 changes: 24 additions & 10 deletions atuin/src/command/client/search/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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] = [
FilterMode::Global,
FilterMode::Host,
FilterMode::Session,
FilterMode::Directory,
];
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;
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions atuin/src/command/client/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down