Merge 806e995365 into c8a47a068b
This commit is contained in:
commit
8a55023e96
|
|
@ -1,11 +1,11 @@
|
|||
use std::io::{self, Write};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{Context, Result, bail};
|
||||
|
||||
use crate::cmd::{Query, Run};
|
||||
use crate::config;
|
||||
use crate::db::{Database, Epoch, Stream, StreamOptions};
|
||||
use crate::error::BrokenPipeHandler;
|
||||
use crate::error::{BrokenPipeHandler, SilentExit};
|
||||
use crate::util::{self, Fzf, FzfChild};
|
||||
|
||||
impl Run for Query {
|
||||
|
|
@ -31,16 +31,23 @@ impl Query {
|
|||
|
||||
fn query_interactive(&self, stream: &mut Stream, now: Epoch) -> Result<()> {
|
||||
let mut fzf = Self::get_fzf()?;
|
||||
let selection = loop {
|
||||
match stream.next() {
|
||||
Some(dir) if Some(dir.path.as_ref()) == self.exclude.as_deref() => continue,
|
||||
Some(dir) => {
|
||||
if let Some(selection) = fzf.write(dir, now)? {
|
||||
break selection;
|
||||
let selection = match (|| -> Result<String> {
|
||||
loop {
|
||||
match stream.next() {
|
||||
Some(dir) if Some(dir.path.as_ref()) == self.exclude.as_deref() => continue,
|
||||
Some(dir) => {
|
||||
if let Some(selection) = fzf.write(dir, now)? {
|
||||
break Ok(selection);
|
||||
}
|
||||
}
|
||||
None => break fzf.wait(),
|
||||
}
|
||||
None => break fzf.wait()?,
|
||||
}
|
||||
})() {
|
||||
Ok(selection) if selection.is_empty() => bail!(SilentExit { code: 1 }),
|
||||
Ok(selection) => selection,
|
||||
Err(err) if err.to_string() == "no match found" => bail!(SilentExit { code: 1 }),
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
if self.score {
|
||||
|
|
|
|||
28
src/shell.rs
28
src/shell.rs
|
|
@ -65,6 +65,22 @@ mod tests {
|
|||
.stderr("");
|
||||
}
|
||||
|
||||
#[apply(opts)]
|
||||
fn bash_init_guards_empty_completion(
|
||||
cmd: Option<&str>,
|
||||
hook: InitHook,
|
||||
echo: bool,
|
||||
resolve_symlinks: bool,
|
||||
) {
|
||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||
let source = Bash(&opts).render().unwrap();
|
||||
if cmd.is_some() {
|
||||
assert!(source.contains("[[ -n ${__zoxide_result} ]] || return"));
|
||||
} else {
|
||||
assert!(!source.contains("[[ -n ${__zoxide_result} ]] || return"));
|
||||
}
|
||||
}
|
||||
|
||||
#[apply(opts)]
|
||||
fn bash_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||
|
|
@ -141,6 +157,18 @@ mod tests {
|
|||
.stderr("");
|
||||
}
|
||||
|
||||
#[apply(opts)]
|
||||
fn fish_init_guards_empty_completion(
|
||||
cmd: Option<&str>,
|
||||
hook: InitHook,
|
||||
echo: bool,
|
||||
resolve_symlinks: bool,
|
||||
) {
|
||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||
let source = Fish(&opts).render().unwrap();
|
||||
assert!(source.contains("and test -n \"$result\""));
|
||||
}
|
||||
|
||||
#[apply(opts)]
|
||||
fn fish_fishindent(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) {
|
||||
let opts = Opts { cmd, hook, echo, resolve_symlinks };
|
||||
|
|
|
|||
|
|
@ -178,18 +178,19 @@ if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VER
|
|||
# If there is a space after the last word, use interactive selection.
|
||||
elif [[ -z ${COMP_WORDS[-1]} ]]; then
|
||||
# shellcheck disable=SC2312
|
||||
__zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" && {
|
||||
# In case the terminal does not respond to \e[5n or another
|
||||
# mechanism steals the response, it is still worth completing
|
||||
# the directory in the command line.
|
||||
COMPREPLY=("${__zoxide_z_prefix}${__zoxide_result}/")
|
||||
__zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" || return
|
||||
[[ -n ${__zoxide_result} ]] || return
|
||||
|
||||
# Note: We here call "bind" without prefixing "\builtin" to be
|
||||
# compatible with frameworks like ble.sh, which emulates Bash's
|
||||
# builtin "bind".
|
||||
bind -x '"\e[0n": __zoxide_z_complete_helper'
|
||||
\builtin printf '\e[5n' >/dev/tty
|
||||
}
|
||||
# In case the terminal does not respond to \e[5n or another
|
||||
# mechanism steals the response, it is still worth completing
|
||||
# the directory in the command line.
|
||||
COMPREPLY=("${__zoxide_z_prefix}${__zoxide_result}/")
|
||||
|
||||
# Note: We here call "bind" without prefixing "\builtin" to be
|
||||
# compatible with frameworks like ble.sh, which emulates Bash's
|
||||
# builtin "bind".
|
||||
bind -x '"\e[0n": __zoxide_z_complete_helper'
|
||||
\builtin printf '\e[5n' >/dev/tty
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ function __zoxide_z_complete
|
|||
# If the last argument is empty, use interactive selection.
|
||||
set -l query $tokens[2..-1]
|
||||
set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query)
|
||||
and test -n "$result"
|
||||
and __zoxide_cd $result
|
||||
and builtin commandline --function cancel-commandline repaint
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
#![cfg(not(windows))]
|
||||
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::{env, fs};
|
||||
|
||||
use assert_cmd::Command;
|
||||
|
||||
fn fake_path(script: &str) -> (tempfile::TempDir, String) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("fzf");
|
||||
fs::write(&path, script).unwrap();
|
||||
let mut perms = fs::metadata(&path).unwrap().permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(&path, perms).unwrap();
|
||||
let path_env = format!("{}:{}", dir.path().display(), env::var("PATH").unwrap_or_default());
|
||||
(dir, path_env)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interactive_query_is_silent_when_fzf_reports_no_match() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let (_bin_dir, path_env) = fake_path("#!/bin/sh\ncat >/dev/null\nexit 1\n");
|
||||
|
||||
Command::cargo_bin("zoxide")
|
||||
.unwrap()
|
||||
.env("HOME", home.path())
|
||||
.env("PATH", path_env)
|
||||
.args(["query", "--interactive"])
|
||||
.assert()
|
||||
.code(1)
|
||||
.stdout("")
|
||||
.stderr("");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interactive_query_is_silent_when_fzf_returns_empty_output() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let (_bin_dir, path_env) = fake_path("#!/bin/sh\ncat >/dev/null\nexit 0\n");
|
||||
|
||||
Command::cargo_bin("zoxide")
|
||||
.unwrap()
|
||||
.env("HOME", home.path())
|
||||
.env("PATH", path_env)
|
||||
.args(["query", "--interactive"])
|
||||
.assert()
|
||||
.code(1)
|
||||
.stdout("")
|
||||
.stderr("");
|
||||
}
|
||||
Loading…
Reference in New Issue