From 1b1100821f9e70f653536a53cbeecef4493d0c37 Mon Sep 17 00:00:00 2001 From: Tahaa-Dev Date: Tue, 21 Jul 2026 05:00:17 +0300 Subject: [PATCH] Add remove-alias command --- contrib/completions/_zoxide | 17 +++++++++++++++++ contrib/completions/_zoxide.ps1 | 10 ++++++++++ contrib/completions/zoxide.bash | 33 ++++++++++++++++++++++++++++++++- contrib/completions/zoxide.elv | 9 +++++++++ contrib/completions/zoxide.fish | 4 ++++ contrib/completions/zoxide.nu | 8 ++++++++ contrib/completions/zoxide.ts | 26 ++++++++++++++++++++++++++ src/cmd/cmd.rs | 15 +++++++++++++++ src/cmd/mod.rs | 2 ++ src/cmd/remove_alias.rs | 21 +++++++++++++++++++++ src/db/mod.rs | 24 ++++++++++++++++++++++++ 11 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/cmd/remove_alias.rs diff --git a/contrib/completions/_zoxide b/contrib/completions/_zoxide index d033796..f34310d 100644 --- a/contrib/completions/_zoxide +++ b/contrib/completions/_zoxide @@ -220,6 +220,17 @@ _arguments "${_arguments_options[@]}" : \ '--version[Print version]' \ '*::paths:_files -/' \ && ret=0 +;; +(remove-alias) +_arguments "${_arguments_options[@]}" : \ +'-p+[]:PATH:_files -/' \ +'--path=[]:PATH:_files -/' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +'*::aliases:_default' \ +&& ret=0 ;; esac ;; @@ -236,6 +247,7 @@ _zoxide_commands() { 'init:Generate shell configuration' \ 'query:Search for a directory in the database' \ 'remove:Remove a directory from the database' \ +'remove-alias:Remove aliases from a directory' \ ) _describe -t commands 'zoxide commands' commands "$@" } @@ -336,6 +348,11 @@ _zoxide__subcmd__remove_commands() { local commands; commands=() _describe -t commands 'zoxide remove commands' commands "$@" } +(( $+functions[_zoxide__subcmd__remove-alias_commands] )) || +_zoxide__subcmd__remove-alias_commands() { + local commands; commands=() + _describe -t commands 'zoxide remove-alias commands' commands "$@" +} if [ "$funcstack[1]" = "_zoxide" ]; then _zoxide "$@" diff --git a/contrib/completions/_zoxide.ps1 b/contrib/completions/_zoxide.ps1 index c282274..1d248cf 100644 --- a/contrib/completions/_zoxide.ps1 +++ b/contrib/completions/_zoxide.ps1 @@ -32,6 +32,7 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock { [CompletionResult]::new('init', 'init', [CompletionResultType]::ParameterValue, 'Generate shell configuration') [CompletionResult]::new('query', 'query', [CompletionResultType]::ParameterValue, 'Search for a directory in the database') [CompletionResult]::new('remove', 'remove', [CompletionResultType]::ParameterValue, 'Remove a directory from the database') + [CompletionResult]::new('remove-alias', 'remove-alias', [CompletionResultType]::ParameterValue, 'Remove aliases from a directory') break } 'zoxide;add' { @@ -188,6 +189,15 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock { [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') break } + 'zoxide;remove-alias' { + [CompletionResult]::new('-p', '-p', [CompletionResultType]::ParameterName, 'p') + [CompletionResult]::new('--path', '--path', [CompletionResultType]::ParameterName, 'path') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } }) $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | diff --git a/contrib/completions/zoxide.bash b/contrib/completions/zoxide.bash index 5e99429..1af8e12 100644 --- a/contrib/completions/zoxide.bash +++ b/contrib/completions/zoxide.bash @@ -37,6 +37,9 @@ _zoxide() { zoxide,remove) cmd="zoxide__subcmd__remove" ;; + zoxide,remove-alias) + cmd="zoxide__subcmd__remove__subcmd__alias" + ;; zoxide__subcmd__edit,decrement) cmd="zoxide__subcmd__edit__subcmd__decrement" ;; @@ -74,7 +77,7 @@ _zoxide() { case "${cmd}" in zoxide) - opts="-h -V --help --version add add-alias edit import init query remove" + opts="-h -V --help --version add add-alias edit import init query remove remove-alias" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -369,6 +372,34 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zoxide__subcmd__remove__subcmd__alias) + opts="-p -h -V --path --help --version ..." + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --path) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi + return 0 + ;; + -p) + COMPREPLY=() + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o plusdirs + fi + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; esac } diff --git a/contrib/completions/zoxide.elv b/contrib/completions/zoxide.elv index 7294b26..7c5d301 100644 --- a/contrib/completions/zoxide.elv +++ b/contrib/completions/zoxide.elv @@ -29,6 +29,7 @@ set edit:completion:arg-completer[zoxide] = {|@words| cand init 'Generate shell configuration' cand query 'Search for a directory in the database' cand remove 'Remove a directory from the database' + cand remove-alias 'Remove aliases from a directory' } &'zoxide;add'= { cand -s 'The rank to increment the entry if it exists or initialize it with if it doesn''t' @@ -167,6 +168,14 @@ set edit:completion:arg-completer[zoxide] = {|@words| cand -V 'Print version' cand --version 'Print version' } + &'zoxide;remove-alias'= { + cand -p 'p' + cand --path 'path' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } ] $completions[$command] } diff --git a/contrib/completions/zoxide.fish b/contrib/completions/zoxide.fish index 9eda694..8a3da15 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 "import" -d 'Import en complete -c zoxide -n "__fish_zoxide_needs_command" -f -a "init" -d 'Generate shell configuration' 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_needs_command" -f -a "remove-alias" -d 'Remove aliases from a directory' 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 h -l help -d 'Print help' complete -c zoxide -n "__fish_zoxide_using_subcommand add" -s V -l version -d 'Print version' @@ -98,3 +99,6 @@ complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s h -l help -d 'Pr complete -c zoxide -n "__fish_zoxide_using_subcommand query" -s V -l version -d 'Print version' complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s h -l help -d 'Print help' complete -c zoxide -n "__fish_zoxide_using_subcommand remove" -s V -l version -d 'Print version' +complete -c zoxide -n "__fish_zoxide_using_subcommand remove-alias" -s p -l path -r -f -a "(__fish_complete_directories)" +complete -c zoxide -n "__fish_zoxide_using_subcommand remove-alias" -s h -l help -d 'Print help' +complete -c zoxide -n "__fish_zoxide_using_subcommand remove-alias" -s V -l version -d 'Print version' diff --git a/contrib/completions/zoxide.nu b/contrib/completions/zoxide.nu index e25b011..d882076 100644 --- a/contrib/completions/zoxide.nu +++ b/contrib/completions/zoxide.nu @@ -139,6 +139,14 @@ module completions { ...paths: path ] + # Remove aliases from a directory + export extern "zoxide remove-alias" [ + --path(-p): path + --help(-h) # Print help + --version(-V) # Print version + ...aliases: string + ] + } export use completions * diff --git a/contrib/completions/zoxide.ts b/contrib/completions/zoxide.ts index f34b4a1..e42b3bd 100644 --- a/contrib/completions/zoxide.ts +++ b/contrib/completions/zoxide.ts @@ -407,6 +407,32 @@ const completion: Fig.Spec = { template: "folders", }, }, + { + name: "remove-alias", + description: "Remove aliases from a directory", + options: [ + { + name: ["-p", "--path"], + isRepeatable: true, + args: { + name: "path", + template: "folders", + }, + }, + { + name: ["-h", "--help"], + description: "Print help", + }, + { + name: ["-V", "--version"], + description: "Print version", + }, + ], + args: { + name: "aliases", + isVariadic: true, + }, + }, ], options: [ { diff --git a/src/cmd/cmd.rs b/src/cmd/cmd.rs index 1d4052c..f30353c 100644 --- a/src/cmd/cmd.rs +++ b/src/cmd/cmd.rs @@ -48,6 +48,7 @@ pub enum Cmd { Init(Init), Query(Query), Remove(Remove), + RemoveAlias(RemoveAlias), } /// Add a new directory or increment its rank @@ -228,3 +229,17 @@ pub struct Remove { #[clap(value_hint = ValueHint::DirPath)] pub paths: Vec, } + +/// Remove aliases from a directory +#[derive(Debug, Parser)] +#[clap( + author, + help_template = HelpTemplate, +)] +pub struct RemoveAlias { + #[clap(num_args = 1.., required = true)] + pub aliases: Vec, + + #[clap(short, long, required = true, value_hint = ValueHint::DirPath)] + pub path: String, +} diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 3b05c87..3b93fe8 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -6,6 +6,7 @@ mod import; mod init; mod query; mod remove; +mod remove_alias; use anyhow::Result; @@ -25,6 +26,7 @@ impl Run for Cmd { Cmd::Init(cmd) => cmd.run(), Cmd::Query(cmd) => cmd.run(), Cmd::Remove(cmd) => cmd.run(), + Cmd::RemoveAlias(cmd) => cmd.run(), } } } diff --git a/src/cmd/remove_alias.rs b/src/cmd/remove_alias.rs new file mode 100644 index 0000000..7ef3832 --- /dev/null +++ b/src/cmd/remove_alias.rs @@ -0,0 +1,21 @@ +use anyhow::{Result, bail}; + +use crate::cmd::{RemoveAlias, Run}; +use crate::db::Database; +use crate::util; + +impl Run for RemoveAlias { + fn run(&self) -> Result<()> { + let mut db = Database::open()?; + + if !db.remove_alias(&self.path, self.aliases.iter()) { + let path_abs = util::resolve_path(&self.path)?; + let path_abs = util::path_to_str(&path_abs)?; + if path_abs == self.path || !db.remove_alias(path_abs, self.aliases.iter()) { + bail!("path not found in database: {}", &self.path) + } + } + + db.save() + } +} diff --git a/src/db/mod.rs b/src/db/mod.rs index e81dd2f..5f13bf0 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -144,6 +144,7 @@ impl Database { }); self.with_dirty_mut(|dirty| *dirty = true); } + /// Removes the directory with `path` from the store. This does not preserve /// ordering, but is O(1). pub fn remove(&mut self, path: impl AsRef) -> bool { @@ -161,6 +162,29 @@ impl Database { self.with_dirty_mut(|dirty| *dirty = true); } + /// Removes aliases from a directory + pub fn remove_alias( + &mut self, + path: impl AsRef, + aliases: impl Iterator>, + ) -> bool { + let res = self.with_dirs_mut(|dirs| { + match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) { + Some(dir) => { + let mut res = false; + aliases.for_each(|alias| { + dir.aliases.remove(alias.as_ref()); + res = true; + }); + res + } + None => false, + } + }); + self.with_dirty_mut(|dirty| *dirty |= res); + res + } + pub fn age(&mut self, max_age: Rank) { let mut dirty = false; self.with_dirs_mut(|dirs| {