This commit is contained in:
alcremieow 2026-06-30 12:29:22 -05:00 committed by GitHub
commit a3d8c91405
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 209 additions and 1 deletions

View File

@ -208,6 +208,18 @@ _arguments "${_arguments_options[@]}" : \
'--version[Print version]' \
'*::paths:_files -/' \
&& ret=0
;;
(rename)
_arguments "${_arguments_options[@]}" : \
'--old-name=[]:old_name:_files -/' \
'--new-name=[]:new_name:_files -/' \
'-f[skip y/n]' \
'--force[skip y/n]' \
'-h[Print help]' \
'--help[Print help]' \
'-V[Print version]' \
'--version[Print version]' \
&& ret=0
;;
esac
;;
@ -223,6 +235,7 @@ _zoxide_commands() {
'init:Generate shell configuration' \
'query:Search for a directory in the database' \
'remove:Remove a directory from the database' \
'rename:Batch rename paths by replacing <old-name> with <new-name>' \
)
_describe -t commands 'zoxide commands' commands "$@"
}
@ -318,6 +331,11 @@ _zoxide__subcmd__remove_commands() {
local commands; commands=()
_describe -t commands 'zoxide remove commands' commands "$@"
}
(( $+functions[_zoxide__subcmd__rename_commands] )) ||
_zoxide__subcmd__rename_commands() {
local commands; commands=()
_describe -t commands 'zoxide rename commands' commands "$@"
}
if [ "$funcstack[1]" = "_zoxide" ]; then
_zoxide "$@"

View File

@ -31,6 +31,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('rename', 'rename', [CompletionResultType]::ParameterValue, 'Batch rename paths by replacing <old-name> with <new-name>')
break
}
'zoxide;add' {
@ -177,6 +178,17 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
break
}
'zoxide;rename' {
[CompletionResult]::new('--old-name', '--old-name', [CompletionResultType]::ParameterName, 'old-name')
[CompletionResult]::new('--new-name', '--new-name', [CompletionResultType]::ParameterName, 'new-name')
[CompletionResult]::new('-f', '-f', [CompletionResultType]::ParameterName, 'skip y/n')
[CompletionResult]::new('--force', '--force', [CompletionResultType]::ParameterName, 'skip y/n')
[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*" } |

View File

@ -34,6 +34,9 @@ _zoxide() {
zoxide,remove)
cmd="zoxide__subcmd__remove"
;;
zoxide,rename)
cmd="zoxide__subcmd__rename"
;;
zoxide__subcmd__edit,decrement)
cmd="zoxide__subcmd__edit__subcmd__decrement"
;;
@ -71,7 +74,7 @@ _zoxide() {
case "${cmd}" in
zoxide)
opts="-h -V --help --version add edit import init query remove"
opts="-h -V --help --version add edit import init query remove rename"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@ -338,6 +341,34 @@ _zoxide() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
zoxide__subcmd__rename)
opts="-f -h -V --old-name --new-name --force --help --version"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--old-name)
COMPREPLY=()
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
compopt -o plusdirs
fi
return 0
;;
--new-name)
COMPREPLY=()
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
compopt -o plusdirs
fi
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac
}

View File

@ -28,6 +28,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 rename 'Batch rename paths by replacing <old-name> with <new-name>'
}
&'zoxide;add'= {
cand -s 'The rank to increment the entry if it exists or initialize it with if it doesn''t'
@ -157,6 +158,16 @@ set edit:completion:arg-completer[zoxide] = {|@words|
cand -V 'Print version'
cand --version 'Print version'
}
&'zoxide;rename'= {
cand --old-name 'old-name'
cand --new-name 'new-name'
cand -f 'skip y/n'
cand --force 'skip y/n'
cand -h 'Print help'
cand --help 'Print help'
cand -V 'Print version'
cand --version 'Print version'
}
]
$completions[$command]
}

View File

@ -32,6 +32,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 "rename" -d 'Batch rename paths by replacing <old-name> with <new-name>'
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'
@ -93,3 +94,8 @@ 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 rename" -l old-name -r -f -a "(__fish_complete_directories)"
complete -c zoxide -n "__fish_zoxide_using_subcommand rename" -l new-name -r -f -a "(__fish_complete_directories)"
complete -c zoxide -n "__fish_zoxide_using_subcommand rename" -s f -l force -d 'skip y/n'
complete -c zoxide -n "__fish_zoxide_using_subcommand rename" -s h -l help -d 'Print help'
complete -c zoxide -n "__fish_zoxide_using_subcommand rename" -s V -l version -d 'Print version'

View File

@ -130,6 +130,15 @@ module completions {
...paths: path
]
# Batch rename paths by replacing <old-name> with <new-name>
export extern "zoxide rename" [
--old-name: path
--new-name: path
--force(-f) # skip y/n
--help(-h) # Print help
--version(-V) # Print version
]
}
export use completions *

View File

@ -377,6 +377,40 @@ const completion: Fig.Spec = {
template: "folders",
},
},
{
name: "rename",
description: "Batch rename paths by replacing <old-name> with <new-name>",
options: [
{
name: "--old-name",
isRepeatable: true,
args: {
name: "old_name",
template: "folders",
},
},
{
name: "--new-name",
isRepeatable: true,
args: {
name: "new_name",
template: "folders",
},
},
{
name: ["-f", "--force"],
description: "skip y/n",
},
{
name: ["-h", "--help"],
description: "Print help",
},
{
name: ["-V", "--version"],
description: "Print version",
},
],
},
],
options: [
{

View File

@ -47,6 +47,7 @@ pub enum Cmd {
Init(Init),
Query(Query),
Remove(Remove),
Rename(Rename),
}
/// Add a new directory or increment its rank
@ -209,3 +210,23 @@ pub struct Remove {
#[clap(value_hint = ValueHint::DirPath)]
pub paths: Vec<String>,
}
/// Batch rename paths by replacing <old-name> with <new-name>
#[derive(Debug, Parser)]
#[clap(
author,
help_template = HelpTemplate,
)]
pub struct Rename {
// old name
#[clap(long, value_hint = ValueHint::DirPath, value_name = "old_name")]
pub old_name: String,
// new name
#[clap(long, value_hint = ValueHint::DirPath, value_name = "new_name")]
pub new_name: String,
/// skip y/n
#[clap(long, short)]
pub force: bool,
}

View File

@ -5,6 +5,7 @@ mod import;
mod init;
mod query;
mod remove;
mod rename;
use anyhow::Result;
@ -23,6 +24,7 @@ impl Run for Cmd {
Cmd::Init(cmd) => cmd.run(),
Cmd::Query(cmd) => cmd.run(),
Cmd::Remove(cmd) => cmd.run(),
Cmd::Rename(cmd) => cmd.run(),
}
}
}

64
src/cmd/rename.rs Normal file
View File

@ -0,0 +1,64 @@
use std::io::{self, Read, Write};
use anyhow::{Result, bail};
use crate::cmd::{Rename, Run};
use crate::db::{Database, Epoch, Rank};
use crate::error::BrokenPipeHandler;
struct Data {
pub old_path: String,
pub new_path: String,
pub rank: Rank,
pub last_accessed: Epoch,
}
impl Run for Rename {
fn run(&self) -> Result<()> {
let mut db = Database::open()?;
let mut to_edit = Vec::<Data>::new();
for path in db.dirs() {
let old = path.display().to_string();
let new = path.display().to_string().replace(&self.old_name, &self.new_name);
if new != old {
writeln!(io::stdout(), "{old} -> {new}")
.pipe_exit("stdout")
.expect("cannot write to stdout.");
to_edit.push(Data {
old_path: old,
new_path: new,
rank: path.rank,
last_accessed: path.last_accessed,
});
}
}
for item in to_edit.iter() {
db.remove(&item.old_path);
db.add(&item.new_path, item.rank, item.last_accessed);
}
if to_edit.is_empty() {
bail!("No entries to rename.");
}
if self.force {
return db.save();
}
writeln!(io::stdout(), "Rename {} entries? (y/n)", to_edit.len())
.pipe_exit("stdout")
.expect("cannot write to stdout.");
let mut buf = [0];
std::io::stdin().read_exact(&mut buf).expect("input expected");
match buf[0] as char {
'y' | 'Y' => db.save(),
_ => bail!("Rename aborted."),
}
}
}