fix(dotfiles): allow clearing aliases, disable import (#1995)

* fix(dotfiles): allow clearing aliases, disable import

At the moment there are far too many edge cases to handle importing
aliases.

1. We need an interactive shell to print aliases. Without it, most
   shells won't report much.
2. Many people have their shells print things on startup (graphics,
   fortunes, etc). This could be detected as an attempt to set an alias.

 Rather than spend the next year finding import edge cases, I'm
 disabling it for now. There's probably a better way we can do this?

* clippy
This commit is contained in:
Ellie Huxtable 2024-05-02 16:53:38 +01:00 committed by GitHub
parent 831dd783ed
commit 0639ff4960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 39 additions and 24 deletions

1
Cargo.lock generated
View File

@ -207,6 +207,7 @@ dependencies = [
"itertools",
"log",
"ratatui",
"regex",
"rpassword",
"runtime-format",
"rustix",

View File

@ -9,7 +9,7 @@ exclude = ["ui/backend"]
[workspace.package]
version = "18.2.0"
authors = ["Ellie Huxtable <ellie@elliehuxtable.com>"]
rust-version = "1.67"
rust-version = "1.70"
license = "MIT"
homepage = "https://atuin.sh"
repository = "https://github.com/atuinsh/atuin"

View File

@ -37,7 +37,7 @@ async fn sync_download(
key: &Key,
force: bool,
client: &api_client::Client<'_>,
db: &(impl Database + Send),
db: &impl Database,
) -> Result<(i64, i64)> {
debug!("starting sync download");
@ -127,7 +127,7 @@ async fn sync_upload(
key: &Key,
_force: bool,
client: &api_client::Client<'_>,
db: &(impl Database + Send),
db: &impl Database,
) -> Result<()> {
debug!("starting sync upload");
@ -188,7 +188,7 @@ async fn sync_upload(
Ok(())
}
pub async fn sync(settings: &Settings, force: bool, db: &(impl Database + Send)) -> Result<()> {
pub async fn sync(settings: &Settings, force: bool, db: &impl Database) -> Result<()> {
let client = api_client::Client::new(
&settings.sync_address,
&settings.session_token,

View File

@ -136,7 +136,7 @@ pub fn existing_aliases(shell: Option<Shell>) -> Result<Vec<Alias>, ShellError>
/// Import aliases from the current shell
/// This will not import aliases already in the store
/// Returns aliases that were set
pub async fn import_aliases(store: AliasStore) -> Result<Vec<Alias>> {
pub async fn import_aliases(store: &AliasStore) -> Result<Vec<Alias>> {
let shell_aliases = existing_aliases(None)?;
let store_aliases = store.aliases().await?;

View File

@ -82,6 +82,7 @@ uuid = { workspace = true }
unicode-segmentation = "1.11.0"
serde_yaml = "0.9.32"
sysinfo = "0.30.7"
regex="1.10.4"
[target.'cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))'.dependencies]
cli-clipboard = { version = "0.4.0", optional = true }

View File

@ -1,5 +1,5 @@
use clap::Subcommand;
use eyre::{Context, Result};
use eyre::{eyre, Context, Result};
use atuin_client::{encryption, record::sqlite_store::SqliteStore, settings::Settings};
@ -17,12 +17,19 @@ pub enum Cmd {
/// List all aliases
List,
/// Import aliases set in the current shell
Import,
/// Delete all aliases
Clear,
// There are too many edge cases to parse at the moment. Disable for now.
// Import,
}
impl Cmd {
async fn set(&self, store: AliasStore, name: String, value: String) -> Result<()> {
async fn set(&self, store: &AliasStore, name: String, value: String) -> Result<()> {
let illegal_char = regex::Regex::new("[ \t\n&();<>|\\\"'`$/]").unwrap();
if illegal_char.is_match(name.as_str()) {
return Err(eyre!("Illegal character in alias name"));
}
let aliases = store.aliases().await?;
let found: Vec<Alias> = aliases.into_iter().filter(|a| a.name == name).collect();
@ -40,7 +47,7 @@ impl Cmd {
Ok(())
}
async fn list(&self, store: AliasStore) -> Result<()> {
async fn list(&self, store: &AliasStore) -> Result<()> {
let aliases = store.aliases().await?;
for i in aliases {
@ -50,7 +57,17 @@ impl Cmd {
Ok(())
}
async fn delete(&self, store: AliasStore, name: String) -> Result<()> {
async fn clear(&self, store: &AliasStore) -> Result<()> {
let aliases = store.aliases().await?;
for i in aliases {
self.delete(store, i.name).await?;
}
Ok(())
}
async fn delete(&self, store: &AliasStore, name: String) -> Result<()> {
let mut aliases = store.aliases().await?.into_iter();
if let Some(alias) = aliases.find(|alias| alias.name == name) {
println!("Deleting '{name}={}'.", alias.value);
@ -61,7 +78,8 @@ impl Cmd {
Ok(())
}
async fn import(&self, store: AliasStore) -> Result<()> {
/*
async fn import(&self, store: &AliasStore) -> Result<()> {
let aliases = atuin_dotfiles::shell::import_aliases(store).await?;
for i in aliases {
@ -70,6 +88,7 @@ impl Cmd {
Ok(())
}
*/
pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> {
if !settings.dotfiles.enabled {
@ -86,10 +105,10 @@ impl Cmd {
let alias_store = AliasStore::new(store, host_id, encryption_key);
match self {
Self::Set { name, value } => self.set(alias_store, name.clone(), value.clone()).await,
Self::Delete { name } => self.delete(alias_store, name.clone()).await,
Self::List => self.list(alias_store).await,
Self::Import => self.import(alias_store).await,
Self::Set { name, value } => self.set(&alias_store, name.clone(), value.clone()).await,
Self::Delete { name } => self.delete(&alias_store, name.clone()).await,
Self::List => self.list(&alias_store).await,
Self::Clear => self.clear(&alias_store).await,
}
}
}

View File

@ -308,13 +308,7 @@ impl State {
// handle keymap specific keybindings.
match self.keymap_mode {
KeymapMode::VimNormal => match input.code {
KeyCode::Char('/') if !ctrl => {
self.search.input.clear();
self.set_keymap_cursor(settings, "vim_insert");
self.keymap_mode = KeymapMode::VimInsert;
return InputAction::Continue;
}
KeyCode::Char('?') if !ctrl => {
KeyCode::Char('?' | '/') if !ctrl => {
self.search.input.clear();
self.set_keymap_cursor(settings, "vim_insert");
self.keymap_mode = KeymapMode::VimInsert;

View File

@ -13,7 +13,7 @@ use atuin_history::stats::{compute, pretty_print};
#[derive(Parser, Debug)]
#[command(infer_subcommands = true)]
pub struct Cmd {
/// Compute statistics for the specified period, leave blank for statistics since the beginning. See https://docs.atuin.sh/reference/stats/ for more details.
/// Compute statistics for the specified period, leave blank for statistics since the beginning. See [this](https://docs.atuin.sh/reference/stats/) for more details.
period: Vec<String>,
/// How many top commands to list