diff --git a/contrib/completions/_zoxide b/contrib/completions/_zoxide index 2f4c9f0..6ed3bb9 100644 --- a/contrib/completions/_zoxide +++ b/contrib/completions/_zoxide @@ -32,6 +32,8 @@ _zoxide() { _arguments "${_arguments_options[@]}" : \ '-s+[The rank to increment the entry if it exists or initialize it with if it doesn'\''t]:SCORE:_default' \ '--score=[The rank to increment the entry if it exists or initialize it with if it doesn'\''t]:SCORE:_default' \ +'-a+[]:ALIAS:_default' \ +'--alias=[]:ALIAS:_default' \ '-h[Print help]' \ '--help[Print help]' \ '-V[Print version]' \ diff --git a/contrib/completions/_zoxide.ps1 b/contrib/completions/_zoxide.ps1 index a76c12c..8552066 100644 --- a/contrib/completions/_zoxide.ps1 +++ b/contrib/completions/_zoxide.ps1 @@ -36,6 +36,8 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock { 'zoxide;add' { [CompletionResult]::new('-s', '-s', [CompletionResultType]::ParameterName, 'The rank to increment the entry if it exists or initialize it with if it doesn''t') [CompletionResult]::new('--score', '--score', [CompletionResultType]::ParameterName, 'The rank to increment the entry if it exists or initialize it with if it doesn''t') + [CompletionResult]::new('-a', '-a', [CompletionResultType]::ParameterName, 'a') + [CompletionResult]::new('--alias', '--alias', [CompletionResultType]::ParameterName, 'alias') [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') diff --git a/contrib/completions/zoxide.bash b/contrib/completions/zoxide.bash index 1e6fdcf..76a67ee 100644 --- a/contrib/completions/zoxide.bash +++ b/contrib/completions/zoxide.bash @@ -85,7 +85,7 @@ _zoxide() { return 0 ;; zoxide__subcmd__add) - opts="-s -h -V --score --help --version ..." + opts="-s -a -h -V --score --alias --help --version ..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -99,6 +99,14 @@ _zoxide() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --alias) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -a) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; diff --git a/contrib/completions/zoxide.elv b/contrib/completions/zoxide.elv index 5ba33fa..1f5ba2f 100644 --- a/contrib/completions/zoxide.elv +++ b/contrib/completions/zoxide.elv @@ -32,6 +32,8 @@ set edit:completion:arg-completer[zoxide] = {|@words| &'zoxide;add'= { cand -s 'The rank to increment the entry if it exists or initialize it with if it doesn''t' cand --score 'The rank to increment the entry if it exists or initialize it with if it doesn''t' + cand -a 'a' + cand --alias 'alias' cand -h 'Print help' cand --help 'Print help' cand -V 'Print version' diff --git a/contrib/completions/zoxide.fish b/contrib/completions/zoxide.fish index 6d7e5b2..aa24023 100644 --- a/contrib/completions/zoxide.fish +++ b/contrib/completions/zoxide.fish @@ -33,6 +33,7 @@ complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "init" -d 'Generate sh complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "query" -d 'Search for a directory in the database' complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "remove" -d 'Remove a directory from the database' complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s s -l score -d 'The rank to increment the entry if it exists or initialize it with if it doesn\'t' -r +complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s a -l alias -r complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s h -l help -d 'Print help' complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_zoxide_using_subcommand edit; and not __fish_seen_subcommand_from decrement delete increment reload" -s h -l help -d 'Print help' diff --git a/contrib/completions/zoxide.nu b/contrib/completions/zoxide.nu index 4d07049..db0422c 100644 --- a/contrib/completions/zoxide.nu +++ b/contrib/completions/zoxide.nu @@ -9,6 +9,7 @@ module completions { # Add a new directory or increment its rank export extern "zoxide add" [ --score(-s): string # The rank to increment the entry if it exists or initialize it with if it doesn't + --alias(-a): string --help(-h) # Print help --version(-V) # Print version ...paths: path diff --git a/contrib/completions/zoxide.ts b/contrib/completions/zoxide.ts index 207da2f..080dae3 100644 --- a/contrib/completions/zoxide.ts +++ b/contrib/completions/zoxide.ts @@ -15,6 +15,14 @@ const completion: Fig.Spec = { isOptional: true, }, }, + { + name: ["-a", "--alias"], + isRepeatable: true, + args: { + name: "alias", + isOptional: true, + }, + }, { name: ["-h", "--help"], description: "Print help", diff --git a/src/cmd/add.rs b/src/cmd/add.rs index 302ae0a..403590b 100644 --- a/src/cmd/add.rs +++ b/src/cmd/add.rs @@ -18,6 +18,7 @@ impl Run for Add { let mut db = Database::open()?; + let mut first = true; for path in &self.paths { let path = if config::resolve_symlinks() { util::canonicalize } else { util::resolve_path }( @@ -35,7 +36,9 @@ impl Run for Add { } let by = self.score.unwrap_or(1.0); - db.add_update(path, by, now); + let alias = if first { self.alias.clone() } else { None }; + db.add_update(path, by, now, alias); + first = false; } if db.dirty() { diff --git a/src/cmd/cmd.rs b/src/cmd/cmd.rs index 0de2ee5..108df68 100644 --- a/src/cmd/cmd.rs +++ b/src/cmd/cmd.rs @@ -63,6 +63,9 @@ pub struct Add { /// doesn't #[clap(short, long)] pub score: Option, + + #[clap(short, long)] + pub alias: Option, } /// Edit the database diff --git a/src/cmd/edit.rs b/src/cmd/edit.rs index 0f37165..958b0fa 100644 --- a/src/cmd/edit.rs +++ b/src/cmd/edit.rs @@ -15,11 +15,15 @@ impl Run for Edit { match &self.cmd { Some(cmd) => { match cmd { - EditCommand::Decrement { path } => db.add(path, -1.0, now), + EditCommand::Decrement { path } => { + db.add(path, -1.0, now, Option::::None) + } EditCommand::Delete { path } => { db.remove(path); } - EditCommand::Increment { path } => db.add(path, 1.0, now), + EditCommand::Increment { path } => { + db.add(path, 1.0, now, Option::::None) + } EditCommand::Reload => {} } db.save()?; diff --git a/src/db/dir.rs b/src/db/dir.rs index 5d6d62c..cc51128 100644 --- a/src/db/dir.rs +++ b/src/db/dir.rs @@ -11,6 +11,8 @@ pub struct Dir<'a> { pub path: Cow<'a, str>, pub rank: Rank, pub last_accessed: Epoch, + #[serde(default)] + pub aliases: Vec>, } impl Dir<'_> { diff --git a/src/db/mod.rs b/src/db/mod.rs index 1856fda..d8a3841 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -65,11 +65,31 @@ impl Database { } /// Increments the rank of a directory, or creates it if it does not exist. - pub fn add(&mut self, path: impl AsRef + Into, by: Rank, now: Epoch) { + pub fn add( + &mut self, + path: impl AsRef + Into, + by: Rank, + now: Epoch, + alias: Option + Into>, + ) { self.with_dirs_mut(|dirs| match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) { - Some(dir) => dir.rank = (dir.rank + by).max(0.0), + Some(dir) => { + dir.rank = (dir.rank + by).max(0.0); + if let Some(al) = alias { + dir.aliases.push(al.into().into()); + } + } None => { - dirs.push(Dir { path: path.into().into(), rank: by.max(0.0), last_accessed: now }) + let mut aliases = Vec::new(); + if let Some(al) = alias { + aliases.push(al.into().into()); + } + dirs.push(Dir { + path: path.into().into(), + rank: by.max(0.0), + last_accessed: now, + aliases, + }) } }); self.with_dirty_mut(|dirty| *dirty = true); @@ -79,23 +99,51 @@ impl Database { /// directory is already in the database, it is expected that the user /// either does a check before calling this, or calls `dedup()` /// afterward. - pub fn add_unchecked(&mut self, path: impl AsRef + Into, rank: Rank, now: Epoch) { + pub fn add_unchecked( + &mut self, + path: impl AsRef + Into, + rank: Rank, + now: Epoch, + alias: Option + Into>, + ) { self.with_dirs_mut(|dirs| { - dirs.push(Dir { path: path.into().into(), rank, last_accessed: now }) + let mut aliases = Vec::new(); + if let Some(al) = alias { + aliases.push(al.into().into()); + } + dirs.push(Dir { path: path.into().into(), rank, last_accessed: now, aliases }) }); self.with_dirty_mut(|dirty| *dirty = true); } /// Increments the rank and updates the last_accessed of a directory, or /// creates it if it does not exist. - pub fn add_update(&mut self, path: impl AsRef + Into, by: Rank, now: Epoch) { + pub fn add_update( + &mut self, + path: impl AsRef + Into, + by: Rank, + now: Epoch, + alias: Option + Into>, + ) { self.with_dirs_mut(|dirs| match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) { Some(dir) => { dir.rank = (dir.rank + by).max(0.0); dir.last_accessed = now; + if let Some(al) = alias { + dir.aliases.push(al.into().into()); + } } None => { - dirs.push(Dir { path: path.into().into(), rank: by.max(0.0), last_accessed: now }) + let mut aliases = Vec::new(); + if let Some(al) = alias { + aliases.push(al.into().into()); + } + dirs.push(Dir { + path: path.into().into(), + rank: by.max(0.0), + last_accessed: now, + aliases, + }) } }); self.with_dirty_mut(|dirty| *dirty = true); @@ -244,8 +292,8 @@ mod tests { { let mut db = Database::open_dir(data_dir.path()).unwrap(); - db.add(path, 1.0, now); - db.add(path, 1.0, now); + db.add(path, 1.0, now, Option::::None); + db.add(path, 1.0, now, Some(String::from("foo"))); db.save().unwrap(); } @@ -268,7 +316,7 @@ mod tests { { let mut db = Database::open_dir(data_dir.path()).unwrap(); - db.add(path, 1.0, now); + db.add(path, 1.0, now, Option::::None); db.save().unwrap(); } diff --git a/src/import.rs b/src/import.rs index b68f564..2e468c8 100644 --- a/src/import.rs +++ b/src/import.rs @@ -60,7 +60,7 @@ pub(crate) fn run(importer: &impl Importer, db: &mut Database) -> Result<()> { if exclude_dirs.iter().any(|glob| glob.matches(&dir.path)) { continue; } - db.add_unchecked(dir.path, dir.rank, dir.last_accessed); + db.add_unchecked(dir.path, dir.rank, dir.last_accessed, Option::::None); } Err(e) => { let location = match &e.path { diff --git a/src/import/atuin.rs b/src/import/atuin.rs index 513efe5..8535ec9 100644 --- a/src/import/atuin.rs +++ b/src/import/atuin.rs @@ -64,6 +64,7 @@ impl Iter { path: Cow::Owned(path.to_string()), rank: 1.0, last_accessed: timestamp as Epoch, + aliases: Vec::new(), }; Ok(dir) } diff --git a/src/import/autojump.rs b/src/import/autojump.rs index f269e1f..2ff95f0 100644 --- a/src/import/autojump.rs +++ b/src/import/autojump.rs @@ -52,7 +52,7 @@ impl Iter { // take a while to normalize. let rank = sigmoid(rank); - Ok(Dir { path: Cow::Owned(path.to_string()), rank, last_accessed: 0 }) + Ok(Dir { path: Cow::Owned(path.to_string()), rank, last_accessed: 0, aliases: Vec::new() }) } } diff --git a/src/import/z.rs b/src/import/z.rs index 511980c..de24238 100644 --- a/src/import/z.rs +++ b/src/import/z.rs @@ -54,7 +54,7 @@ impl Iter { let path = split.next().ok_or_else(err)?; - Ok(Dir { path: Cow::Owned(path.to_string()), rank, last_accessed }) + Ok(Dir { path: Cow::Owned(path.to_string()), rank, last_accessed, aliases: Vec::new() }) } }