diff --git a/contrib/completions/_zoxide b/contrib/completions/_zoxide index 312adb6..e0ca960 100644 --- a/contrib/completions/_zoxide +++ b/contrib/completions/_zoxide @@ -37,6 +37,61 @@ _arguments "${_arguments_options[@]}" \ '*::paths:_files -/' \ && ret=0 ;; +(edit) +_arguments "${_arguments_options[@]}" \ +'-h[Print help information]' \ +'--help[Print help information]' \ +'-V[Print version information]' \ +'--version[Print version information]' \ +":: :_zoxide__edit_commands" \ +"*::: :->edit" \ +&& ret=0 + + case $state in + (edit) + words=($line[1] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:zoxide-edit-command-$line[1]:" + case $line[1] in + (decrement) +_arguments "${_arguments_options[@]}" \ +'-h[Print help information]' \ +'--help[Print help information]' \ +'-V[Print version information]' \ +'--version[Print version information]' \ +':path:' \ +&& ret=0 +;; +(delete) +_arguments "${_arguments_options[@]}" \ +'-h[Print help information]' \ +'--help[Print help information]' \ +'-V[Print version information]' \ +'--version[Print version information]' \ +':path:' \ +&& ret=0 +;; +(increment) +_arguments "${_arguments_options[@]}" \ +'-h[Print help information]' \ +'--help[Print help information]' \ +'-V[Print version information]' \ +'--version[Print version information]' \ +':path:' \ +&& ret=0 +;; +(reload) +_arguments "${_arguments_options[@]}" \ +'-h[Print help information]' \ +'--help[Print help information]' \ +'-V[Print version information]' \ +'--version[Print version information]' \ +&& ret=0 +;; + esac + ;; +esac +;; (import) _arguments "${_arguments_options[@]}" \ '--from=[Application to import from]:FROM:(autojump z)' \ @@ -97,6 +152,7 @@ esac _zoxide_commands() { local commands; commands=( 'add:Add a new directory or increment its rank' \ +'edit:Edit the database' \ 'import:Import entries from another application' \ 'init:Generate shell configuration' \ 'query:Search for a directory in the database' \ @@ -109,11 +165,36 @@ _zoxide__add_commands() { local commands; commands=() _describe -t commands 'zoxide add commands' commands "$@" } +(( $+functions[_zoxide__edit__decrement_commands] )) || +_zoxide__edit__decrement_commands() { + local commands; commands=() + _describe -t commands 'zoxide edit decrement commands' commands "$@" +} +(( $+functions[_zoxide__edit__delete_commands] )) || +_zoxide__edit__delete_commands() { + local commands; commands=() + _describe -t commands 'zoxide edit delete commands' commands "$@" +} +(( $+functions[_zoxide__edit_commands] )) || +_zoxide__edit_commands() { + local commands; commands=( +'decrement:' \ +'delete:' \ +'increment:' \ +'reload:' \ + ) + _describe -t commands 'zoxide edit commands' commands "$@" +} (( $+functions[_zoxide__import_commands] )) || _zoxide__import_commands() { local commands; commands=() _describe -t commands 'zoxide import commands' commands "$@" } +(( $+functions[_zoxide__edit__increment_commands] )) || +_zoxide__edit__increment_commands() { + local commands; commands=() + _describe -t commands 'zoxide edit increment commands' commands "$@" +} (( $+functions[_zoxide__init_commands] )) || _zoxide__init_commands() { local commands; commands=() @@ -124,6 +205,11 @@ _zoxide__query_commands() { local commands; commands=() _describe -t commands 'zoxide query commands' commands "$@" } +(( $+functions[_zoxide__edit__reload_commands] )) || +_zoxide__edit__reload_commands() { + local commands; commands=() + _describe -t commands 'zoxide edit reload commands' commands "$@" +} (( $+functions[_zoxide__remove_commands] )) || _zoxide__remove_commands() { local commands; commands=() diff --git a/contrib/completions/_zoxide.ps1 b/contrib/completions/_zoxide.ps1 index f1e0571..a065513 100644 --- a/contrib/completions/_zoxide.ps1 +++ b/contrib/completions/_zoxide.ps1 @@ -26,6 +26,7 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock { [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information') [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') [CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, 'Add a new directory or increment its rank') + [CompletionResult]::new('edit', 'edit', [CompletionResultType]::ParameterValue, 'Edit the database') [CompletionResult]::new('import', 'import', [CompletionResultType]::ParameterValue, 'Import entries from another application') [CompletionResult]::new('init', 'init', [CompletionResultType]::ParameterValue, 'Generate shell configuration') [CompletionResult]::new('query', 'query', [CompletionResultType]::ParameterValue, 'Search for a directory in the database') @@ -39,6 +40,45 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock { [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') break } + 'zoxide;edit' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') + [CompletionResult]::new('decrement', 'decrement', [CompletionResultType]::ParameterValue, 'decrement') + [CompletionResult]::new('delete', 'delete', [CompletionResultType]::ParameterValue, 'delete') + [CompletionResult]::new('increment', 'increment', [CompletionResultType]::ParameterValue, 'increment') + [CompletionResult]::new('reload', 'reload', [CompletionResultType]::ParameterValue, 'reload') + break + } + 'zoxide;edit;decrement' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') + break + } + 'zoxide;edit;delete' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') + break + } + 'zoxide;edit;increment' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') + break + } + 'zoxide;edit;reload' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information') + break + } 'zoxide;import' { [CompletionResult]::new('--from', 'from', [CompletionResultType]::ParameterName, 'Application to import from') [CompletionResult]::new('--merge', 'merge', [CompletionResultType]::ParameterName, 'Merge into existing database') diff --git a/contrib/completions/zoxide.bash b/contrib/completions/zoxide.bash index f606b60..ac5ea86 100644 --- a/contrib/completions/zoxide.bash +++ b/contrib/completions/zoxide.bash @@ -15,6 +15,9 @@ _zoxide() { zoxide,add) cmd="zoxide__add" ;; + zoxide,edit) + cmd="zoxide__edit" + ;; zoxide,import) cmd="zoxide__import" ;; @@ -27,6 +30,18 @@ _zoxide() { zoxide,remove) cmd="zoxide__remove" ;; + zoxide__edit,decrement) + cmd="zoxide__edit__decrement" + ;; + zoxide__edit,delete) + cmd="zoxide__edit__delete" + ;; + zoxide__edit,increment) + cmd="zoxide__edit__increment" + ;; + zoxide__edit,reload) + cmd="zoxide__edit__reload" + ;; *) ;; esac @@ -34,7 +49,7 @@ _zoxide() { case "${cmd}" in zoxide) - opts="-h -V --help --version add import init query remove" + opts="-h -V --help --version add edit import init query remove" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -61,6 +76,76 @@ _zoxide() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zoxide__edit) + opts="-h -V --help --version decrement delete increment reload" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__edit__decrement) + opts="-h -V --help --version " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__edit__delete) + opts="-h -V --help --version " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__edit__increment) + opts="-h -V --help --version " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + zoxide__edit__reload) + opts="-h -V --help --version" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zoxide__import) opts="-h -V --from --merge --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then diff --git a/contrib/completions/zoxide.elv b/contrib/completions/zoxide.elv index 2e98e78..ebf560c 100644 --- a/contrib/completions/zoxide.elv +++ b/contrib/completions/zoxide.elv @@ -23,6 +23,7 @@ set edit:completion:arg-completer[zoxide] = {|@words| cand -V 'Print version information' cand --version 'Print version information' cand add 'Add a new directory or increment its rank' + cand edit 'Edit the database' cand import 'Import entries from another application' cand init 'Generate shell configuration' cand query 'Search for a directory in the database' @@ -34,6 +35,40 @@ set edit:completion:arg-completer[zoxide] = {|@words| cand -V 'Print version information' cand --version 'Print version information' } + &'zoxide;edit'= { + cand -h 'Print help information' + cand --help 'Print help information' + cand -V 'Print version information' + cand --version 'Print version information' + cand decrement 'decrement' + cand delete 'delete' + cand increment 'increment' + cand reload 'reload' + } + &'zoxide;edit;decrement'= { + cand -h 'Print help information' + cand --help 'Print help information' + cand -V 'Print version information' + cand --version 'Print version information' + } + &'zoxide;edit;delete'= { + cand -h 'Print help information' + cand --help 'Print help information' + cand -V 'Print version information' + cand --version 'Print version information' + } + &'zoxide;edit;increment'= { + cand -h 'Print help information' + cand --help 'Print help information' + cand -V 'Print version information' + cand --version 'Print version information' + } + &'zoxide;edit;reload'= { + cand -h 'Print help information' + cand --help 'Print help information' + cand -V 'Print version information' + cand --version 'Print version information' + } &'zoxide;import'= { cand --from 'Application to import from' cand --merge 'Merge into existing database' diff --git a/contrib/completions/zoxide.fish b/contrib/completions/zoxide.fish index 16bf84a..b85412f 100644 --- a/contrib/completions/zoxide.fish +++ b/contrib/completions/zoxide.fish @@ -1,12 +1,27 @@ complete -c zoxide -n "__fish_use_subcommand" -s h -l help -d 'Print help information' complete -c zoxide -n "__fish_use_subcommand" -s V -l version -d 'Print version information' complete -c zoxide -n "__fish_use_subcommand" -f -a "add" -d 'Add a new directory or increment its rank' +complete -c zoxide -n "__fish_use_subcommand" -f -a "edit" -d 'Edit the database' complete -c zoxide -n "__fish_use_subcommand" -f -a "import" -d 'Import entries from another application' complete -c zoxide -n "__fish_use_subcommand" -f -a "init" -d 'Generate shell configuration' complete -c zoxide -n "__fish_use_subcommand" -f -a "query" -d 'Search for a directory in the database' complete -c zoxide -n "__fish_use_subcommand" -f -a "remove" -d 'Remove a directory from the database' complete -c zoxide -n "__fish_seen_subcommand_from add" -s h -l help -d 'Print help information' complete -c zoxide -n "__fish_seen_subcommand_from add" -s V -l version -d 'Print version information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -s h -l help -d 'Print help information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -s V -l version -d 'Print version information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "decrement" +complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "delete" +complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "increment" +complete -c zoxide -n "__fish_seen_subcommand_from edit; and not __fish_seen_subcommand_from decrement; and not __fish_seen_subcommand_from delete; and not __fish_seen_subcommand_from increment; and not __fish_seen_subcommand_from reload" -f -a "reload" +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from decrement" -s h -l help -d 'Print help information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from decrement" -s V -l version -d 'Print version information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from delete" -s h -l help -d 'Print help information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from delete" -s V -l version -d 'Print version information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from increment" -s h -l help -d 'Print help information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from increment" -s V -l version -d 'Print version information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s h -l help -d 'Print help information' +complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s V -l version -d 'Print version information' complete -c zoxide -n "__fish_seen_subcommand_from import" -l from -d 'Application to import from' -r -f -a "{autojump ,z }" complete -c zoxide -n "__fish_seen_subcommand_from import" -l merge -d 'Merge into existing database' complete -c zoxide -n "__fish_seen_subcommand_from import" -s h -l help -d 'Print help information' diff --git a/contrib/completions/zoxide.ts b/contrib/completions/zoxide.ts index dd37351..9b6cf63 100644 --- a/contrib/completions/zoxide.ts +++ b/contrib/completions/zoxide.ts @@ -21,6 +21,83 @@ const completion: Fig.Spec = { template: "folders", }, }, + { + name: "edit", + description: "Edit the database", + subcommands: [ + { + name: "decrement", + options: [ + { + name: ["-h", "--help"], + description: "Print help information", + }, + { + name: ["-V", "--version"], + description: "Print version information", + }, + ], + args: { + name: "path", + }, + }, + { + name: "delete", + options: [ + { + name: ["-h", "--help"], + description: "Print help information", + }, + { + name: ["-V", "--version"], + description: "Print version information", + }, + ], + args: { + name: "path", + }, + }, + { + name: "increment", + options: [ + { + name: ["-h", "--help"], + description: "Print help information", + }, + { + name: ["-V", "--version"], + description: "Print version information", + }, + ], + args: { + name: "path", + }, + }, + { + name: "reload", + options: [ + { + name: ["-h", "--help"], + description: "Print help information", + }, + { + name: ["-V", "--version"], + description: "Print version information", + }, + ], + }, + ], + options: [ + { + name: ["-h", "--help"], + description: "Print help information", + }, + { + name: ["-V", "--version"], + description: "Print version information", + }, + ], + }, { name: "import", description: "Import entries from another application", diff --git a/src/cmd/cmd.rs b/src/cmd/cmd.rs index c22a283..34d1aaf 100644 --- a/src/cmd/cmd.rs +++ b/src/cmd/cmd.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; -use clap::{Parser, ValueEnum, ValueHint}; +use clap::{Parser, Subcommand, ValueEnum, ValueHint}; const ENV_HELP: &str = "Environment variables: _ZO_DATA_DIR Path for zoxide data files @@ -24,6 +24,7 @@ const ENV_HELP: &str = "Environment variables: )] pub enum Cmd { Add(Add), + Edit(Edit), Import(Import), Init(Init), Query(Query), @@ -37,6 +38,21 @@ pub struct Add { pub paths: Vec, } +/// Edit the database +#[derive(Debug, Parser)] +pub struct Edit { + #[clap(subcommand)] + pub cmd: Option, +} + +#[derive(Clone, Debug, Subcommand)] +pub enum EditCommand { + Decrement { path: String }, + Delete { path: String }, + Increment { path: String }, + Reload, +} + /// Import entries from another application #[derive(Debug, Parser)] pub struct Import { diff --git a/src/cmd/edit.rs b/src/cmd/edit.rs new file mode 100644 index 0000000..f16c661 --- /dev/null +++ b/src/cmd/edit.rs @@ -0,0 +1,94 @@ +use std::io::{self, Write}; +use std::process::Command; + +use anyhow::Result; + +use crate::cmd::{Edit, EditCommand, Run}; +use crate::db::{Database, DatabaseFile, Epoch}; +use crate::{config, util}; + +impl Run for Edit { + fn run(&self) -> Result<()> { + let now = util::current_time()?; + + let data_dir = config::data_dir()?; + let mut db = DatabaseFile::new(data_dir); + let db = &mut db.open()?; + + match &self.cmd { + Some(EditCommand::Decrement { path }) => { + if let Some(dir) = db.dirs.iter_mut().find(|dir| &dir.path == path) { + dir.rank = (dir.rank - 1.0).max(0.0); + } + db.modified = true; + db.save()?; + print_dirs(db, now); + } + Some(EditCommand::Delete { path }) => { + if let Some(idx) = db.dirs.iter().position(|dir| &dir.path == path) { + db.dirs.remove(idx); + } + db.modified = true; + db.save()?; + print_dirs(db, now); + } + Some(EditCommand::Increment { path }) => { + if let Some(dir) = db.dirs.iter_mut().find(|dir| &dir.path == path) { + dir.rank += 1.0; + } + db.modified = true; + db.save()?; + print_dirs(db, now); + } + Some(EditCommand::Reload) => print_dirs(db, now), + None => { + db.dirs.sort_unstable_by(|dir1, dir2| dir2.score(now).total_cmp(&dir1.score(now))); + db.modified = true; + db.save()?; + + let mut fzf = Command::new("fzf"); + fzf.args([ + "--bind=\ +ctrl-r:reload(zoxide edit reload),\ +ctrl-w:reload(zoxide edit delete {2..}),\ +ctrl-a:reload(zoxide edit increment {2..}),\ +ctrl-d:reload(zoxide edit decrement {2..}),\ +double-click:ignore,\ +enter:abort", + "--header=\ +ctrl-r:reload ctrl-w:delete +ctrl-a:increment ctrl-d:decrement + +SCORE PATH", + // + // Search mode + "--delimiter=\\x00 ", + "--nth=2", + // Search result + "--no-sort", + // Interface + "--cycle", + "--keep-right", + // Layout + "--info=inline", + "--layout=reverse", + // Key/Event bindings + "--bind=ctrl-z:ignore", + ]) + .envs([("FZF_DEFAULT_COMMAND", "zoxide edit reload")]); + + let mut fzf = fzf.spawn().unwrap(); + fzf.wait().unwrap(); + } + } + + Ok(()) + } +} + +fn print_dirs(db: &Database, now: Epoch) { + let stdout = &mut io::stdout().lock(); + for dir in db.dirs.iter() { + writeln!(stdout, "{:>5}\x00 {}", dir.score(now), &dir.path).unwrap(); + } +} diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 876a6aa..5c17474 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -1,5 +1,6 @@ mod add; mod cmd; +mod edit; mod import; mod init; mod query; @@ -17,6 +18,7 @@ impl Run for Cmd { fn run(&self) -> Result<()> { match self { Cmd::Add(cmd) => cmd.run(), + Cmd::Edit(cmd) => cmd.run(), Cmd::Import(cmd) => cmd.run(), Cmd::Init(cmd) => cmd.run(), Cmd::Query(cmd) => cmd.run(),