cmd/query: Add `--sort-by` option
Added the option `--sort-by [score|path|last-accessed]` for the `query` subcommand with default value `score` i.e: ```bash $ zoxide query --list --score --sort-by last-accessed 4.0 /home/martin/playground/scala/scala-3-project-template 3.5 /home/martin/playground/rust 3.8 /home/martin/playground/python 12.0 /home/martin/projects/zoxide 11.8 /home/martin/playground 16.5 /home/martin/projects/thesis 6.0 /home/martin/projects/thesis/frontend ... ``` ```bash $ zoxide query --list --score --sort-by path 0.2 /home/martin/.local/state 0.2 /home/martin/.local/share/zoxide 0.2 /home/martin/.local/share 0.2 /home/martin/.config/protonmail/bridge-v3 0.2 /home/martin/.config/protonmail 0.5 /home 0.5 /etc/nixos/lib/lisp 0.8 / ... ``` ```bash $ zoxide query --list --score 16.5 /home/martin/projects/thesis 16.0 /home/martin/projects/zoxide 8.0 /home/martin/projects/egcd 8.0 /persist 6.0 /home/martin/projects/thesis/frontend ... ``` Fixes #784 as well as #815.
This commit is contained in:
parent
8da8f50eaa
commit
ac98f4044c
|
|
@ -117,6 +117,7 @@ _arguments "${_arguments_options[@]}" \
|
||||||
;;
|
;;
|
||||||
(query)
|
(query)
|
||||||
_arguments "${_arguments_options[@]}" \
|
_arguments "${_arguments_options[@]}" \
|
||||||
|
'--sort-by=[Sort result]:SORT_BY:(path score last-accessed)' \
|
||||||
'--exclude=[Exclude the current directory]:path:_files -/' \
|
'--exclude=[Exclude the current directory]:path:_files -/' \
|
||||||
'-a[Show unavailable directories]' \
|
'-a[Show unavailable directories]' \
|
||||||
'--all[Show unavailable directories]' \
|
'--all[Show unavailable directories]' \
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ Register-ArgumentCompleter -Native -CommandName 'zoxide' -ScriptBlock {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
'zoxide;query' {
|
'zoxide;query' {
|
||||||
|
[CompletionResult]::new('--sort-by', 'sort-by', [CompletionResultType]::ParameterName, 'Sort result')
|
||||||
[CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'Exclude the current directory')
|
[CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'Exclude the current directory')
|
||||||
[CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Show unavailable directories')
|
[CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Show unavailable directories')
|
||||||
[CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'Show unavailable directories')
|
[CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'Show unavailable directories')
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,16 @@ _zoxide() {
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
zoxide__query)
|
zoxide__query)
|
||||||
opts="-a -i -l -s -h -V --all --interactive --list --score --exclude --help --version [KEYWORDS]..."
|
opts="-a -i -l -s -h -V --all --interactive --list --sort-by --score --exclude --help --version [KEYWORDS]..."
|
||||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
|
--sort-by)
|
||||||
|
COMPREPLY=($(compgen -W "path score last-accessed" -- "${cur}"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
--exclude)
|
--exclude)
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
|
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ set edit:completion:arg-completer[zoxide] = {|@words|
|
||||||
cand --version 'Print version'
|
cand --version 'Print version'
|
||||||
}
|
}
|
||||||
&'zoxide;query'= {
|
&'zoxide;query'= {
|
||||||
|
cand --sort-by 'Sort result'
|
||||||
cand --exclude 'Exclude the current directory'
|
cand --exclude 'Exclude the current directory'
|
||||||
cand -a 'Show unavailable directories'
|
cand -a 'Show unavailable directories'
|
||||||
cand --all 'Show unavailable directories'
|
cand --all 'Show unavailable directories'
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ complete -c zoxide -n "__fish_seen_subcommand_from init" -l hook -d 'Changes how
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from init" -l no-cmd -d 'Prevents zoxide from defining the `z` and `zi` commands'
|
complete -c zoxide -n "__fish_seen_subcommand_from init" -l no-cmd -d 'Prevents zoxide from defining the `z` and `zi` commands'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from init" -s h -l help -d 'Print help'
|
complete -c zoxide -n "__fish_seen_subcommand_from init" -s h -l help -d 'Print help'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from init" -s V -l version -d 'Print version'
|
complete -c zoxide -n "__fish_seen_subcommand_from init" -s V -l version -d 'Print version'
|
||||||
|
complete -c zoxide -n "__fish_seen_subcommand_from query" -l sort-by -d 'Sort result' -r -f -a "{path '',score '',last-accessed ''}"
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from query" -l exclude -d 'Exclude the current directory' -r -f -a "(__fish_complete_directories)"
|
complete -c zoxide -n "__fish_seen_subcommand_from query" -l exclude -d 'Exclude the current directory' -r -f -a "(__fish_complete_directories)"
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from query" -s a -l all -d 'Show unavailable directories'
|
complete -c zoxide -n "__fish_seen_subcommand_from query" -s a -l all -d 'Show unavailable directories'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from query" -s i -l interactive -d 'Use interactive selection'
|
complete -c zoxide -n "__fish_seen_subcommand_from query" -s i -l interactive -d 'Use interactive selection'
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,20 @@ const completion: Fig.Spec = {
|
||||||
name: "query",
|
name: "query",
|
||||||
description: "Search for a directory in the database",
|
description: "Search for a directory in the database",
|
||||||
options: [
|
options: [
|
||||||
|
{
|
||||||
|
name: "--sort-by",
|
||||||
|
description: "Sort result",
|
||||||
|
isRepeatable: true,
|
||||||
|
args: {
|
||||||
|
name: "sort_by",
|
||||||
|
isOptional: true,
|
||||||
|
suggestions: [
|
||||||
|
"path",
|
||||||
|
"score",
|
||||||
|
"last-accessed",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "--exclude",
|
name: "--exclude",
|
||||||
description: "Exclude the current directory",
|
description: "Exclude the current directory",
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,10 @@ pub struct Query {
|
||||||
#[clap(long, short, conflicts_with = "interactive")]
|
#[clap(long, short, conflicts_with = "interactive")]
|
||||||
pub list: bool,
|
pub list: bool,
|
||||||
|
|
||||||
|
/// Sort result
|
||||||
|
#[clap(long)]
|
||||||
|
pub sort_by: Option<Ordering>,
|
||||||
|
|
||||||
/// Print score with results
|
/// Print score with results
|
||||||
#[clap(long, short)]
|
#[clap(long, short)]
|
||||||
pub score: bool,
|
pub score: bool,
|
||||||
|
|
@ -174,6 +178,13 @@ pub struct Query {
|
||||||
pub exclude: Option<String>,
|
pub exclude: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(ValueEnum, Debug, Clone, Copy)]
|
||||||
|
pub enum Ordering {
|
||||||
|
Path,
|
||||||
|
Score,
|
||||||
|
LastAccessed,
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove a directory from the database
|
/// Remove a directory from the database
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[clap(
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use std::io::{self, Write};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
|
use super::Ordering;
|
||||||
use crate::cmd::{Query, Run};
|
use crate::cmd::{Query, Run};
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::db::{Database, Epoch, Stream, StreamOptions};
|
use crate::db::{Database, Epoch, Stream, StreamOptions};
|
||||||
|
|
@ -18,7 +19,8 @@ impl Run for Query {
|
||||||
impl Query {
|
impl Query {
|
||||||
fn query(&self, db: &mut Database) -> Result<()> {
|
fn query(&self, db: &mut Database) -> Result<()> {
|
||||||
let now = util::current_time()?;
|
let now = util::current_time()?;
|
||||||
let mut stream = self.get_stream(db, now)?;
|
let ordering = self.sort_by;
|
||||||
|
let mut stream = self.get_stream(db, now, ordering)?;
|
||||||
|
|
||||||
if self.interactive {
|
if self.interactive {
|
||||||
self.query_interactive(&mut stream, now)
|
self.query_interactive(&mut stream, now)
|
||||||
|
|
@ -76,10 +78,16 @@ impl Query {
|
||||||
writeln!(handle, "{dir}").pipe_exit("stdout")
|
writeln!(handle, "{dir}").pipe_exit("stdout")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stream<'a>(&self, db: &'a mut Database, now: Epoch) -> Result<Stream<'a>> {
|
fn get_stream<'a>(
|
||||||
|
&self,
|
||||||
|
db: &'a mut Database,
|
||||||
|
now: Epoch,
|
||||||
|
ordering: Option<Ordering>,
|
||||||
|
) -> Result<Stream<'a>> {
|
||||||
let mut options = StreamOptions::new(now)
|
let mut options = StreamOptions::new(now)
|
||||||
.with_keywords(self.keywords.iter().map(|s| s.as_str()))
|
.with_keywords(self.keywords.iter().map(|s| s.as_str()))
|
||||||
.with_exclude(config::exclude_dirs()?);
|
.with_exclude(config::exclude_dirs()?)
|
||||||
|
.sort_by(ordering);
|
||||||
if !self.all {
|
if !self.all {
|
||||||
let resolve_symlinks = config::resolve_symlinks();
|
let resolve_symlinks = config::resolve_symlinks();
|
||||||
options = options.with_exists(true).with_resolve_symlinks(resolve_symlinks);
|
options = options.with_exists(true).with_resolve_symlinks(resolve_symlinks);
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,15 @@ impl Database {
|
||||||
self.with_dirty_mut(|dirty| *dirty = true);
|
self.with_dirty_mut(|dirty| *dirty = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sort_by_last_accessed(&mut self) {
|
||||||
|
self.with_dirs_mut(|dirs| {
|
||||||
|
dirs.sort_unstable_by(|dir1: &Dir, dir2: &Dir| {
|
||||||
|
dir1.last_accessed.cmp(&dir2.last_accessed)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
self.with_dirty_mut(|dirty| *dirty = true);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dirty(&self) -> bool {
|
pub fn dirty(&self) -> bool {
|
||||||
*self.borrow_dirty()
|
*self.borrow_dirty()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::{fs, path};
|
||||||
|
|
||||||
use glob::Pattern;
|
use glob::Pattern;
|
||||||
|
|
||||||
|
use crate::cmd::Ordering;
|
||||||
use crate::db::{Database, Dir, Epoch};
|
use crate::db::{Database, Dir, Epoch};
|
||||||
use crate::util::{self, MONTH};
|
use crate::util::{self, MONTH};
|
||||||
|
|
||||||
|
|
@ -15,7 +16,11 @@ pub struct Stream<'a> {
|
||||||
|
|
||||||
impl<'a> Stream<'a> {
|
impl<'a> Stream<'a> {
|
||||||
pub fn new(db: &'a mut Database, options: StreamOptions) -> Self {
|
pub fn new(db: &'a mut Database, options: StreamOptions) -> Self {
|
||||||
db.sort_by_score(options.now);
|
match options.sort_by {
|
||||||
|
Ordering::Path => db.sort_by_path(),
|
||||||
|
Ordering::Score => db.sort_by_score(options.now),
|
||||||
|
Ordering::LastAccessed => db.sort_by_last_accessed(),
|
||||||
|
}
|
||||||
let idxs = (0..db.dirs().len()).rev();
|
let idxs = (0..db.dirs().len()).rev();
|
||||||
Stream { db, idxs, options }
|
Stream { db, idxs, options }
|
||||||
}
|
}
|
||||||
|
|
@ -108,6 +113,9 @@ pub struct StreamOptions {
|
||||||
/// Directories that do not exist and haven't been accessed since TTL will
|
/// Directories that do not exist and haven't been accessed since TTL will
|
||||||
/// be lazily removed.
|
/// be lazily removed.
|
||||||
ttl: Epoch,
|
ttl: Epoch,
|
||||||
|
|
||||||
|
/// Ordering of the stream entries
|
||||||
|
sort_by: Ordering,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StreamOptions {
|
impl StreamOptions {
|
||||||
|
|
@ -119,6 +127,7 @@ impl StreamOptions {
|
||||||
exists: false,
|
exists: false,
|
||||||
resolve_symlinks: false,
|
resolve_symlinks: false,
|
||||||
ttl: now.saturating_sub(3 * MONTH),
|
ttl: now.saturating_sub(3 * MONTH),
|
||||||
|
sort_by: Ordering::Score,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,6 +154,13 @@ impl StreamOptions {
|
||||||
self.resolve_symlinks = resolve_symlinks;
|
self.resolve_symlinks = resolve_symlinks;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sort_by(mut self, ordering: Option<Ordering>) -> Self {
|
||||||
|
if let Some(o) = ordering {
|
||||||
|
self.sort_by = o
|
||||||
|
};
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue