mirror of
https://github.com/Llewellynvdm/zoxide.git
synced 2024-12-29 12:32:40 +00:00
Handle early selection on fzf (#307)
This commit is contained in:
parent
3e03ccccd6
commit
2a2848f55c
@ -11,12 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Better defaults for `fzf`.
|
- fzf: better default options.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- PowerShell: use global scope for aliases.
|
- PowerShell: use global scope for aliases.
|
||||||
- Zsh: fix errors with `set -eu`.
|
- Zsh: fix errors with `set -eu`.
|
||||||
|
- fzf: handle early selection.
|
||||||
|
|
||||||
## [0.7.9] - 2021-11-02
|
## [0.7.9] - 2021-11-02
|
||||||
|
|
||||||
|
@ -32,11 +32,19 @@ impl Query {
|
|||||||
|
|
||||||
if self.interactive {
|
if self.interactive {
|
||||||
let mut fzf = Fzf::new(false)?;
|
let mut fzf = Fzf::new(false)?;
|
||||||
while let Some(dir) = stream.next() {
|
let selection = loop {
|
||||||
writeln!(fzf.stdin(), "{}", dir.display_score(now)).pipe_exit("fzf")?;
|
let dir = match stream.next() {
|
||||||
}
|
Some(dir) => dir,
|
||||||
|
None => break fzf.select()?,
|
||||||
|
};
|
||||||
|
|
||||||
|
match writeln!(fzf.stdin(), "{}", dir.display_score(now)) {
|
||||||
|
Ok(()) => (()),
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => break fzf.select()?,
|
||||||
|
Err(e) => Err(e).context("could not write to fzf")?,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let selection = fzf.wait_select()?;
|
|
||||||
if self.score {
|
if self.score {
|
||||||
print!("{}", selection);
|
print!("{}", selection);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::io::Write;
|
use std::io::{self, Write};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
|
||||||
use crate::app::{Remove, Run};
|
use crate::app::{Remove, Run};
|
||||||
use crate::db::DatabaseFile;
|
use crate::db::DatabaseFile;
|
||||||
use crate::error::BrokenPipeHandler;
|
|
||||||
use crate::fzf::Fzf;
|
use crate::fzf::Fzf;
|
||||||
use crate::{config, util};
|
use crate::{config, util};
|
||||||
|
|
||||||
@ -14,18 +13,25 @@ impl Run for Remove {
|
|||||||
let mut db = DatabaseFile::new(data_dir);
|
let mut db = DatabaseFile::new(data_dir);
|
||||||
let mut db = db.open()?;
|
let mut db = db.open()?;
|
||||||
|
|
||||||
let selection;
|
|
||||||
match &self.interactive {
|
match &self.interactive {
|
||||||
Some(keywords) => {
|
Some(keywords) => {
|
||||||
let now = util::current_time()?;
|
let now = util::current_time()?;
|
||||||
let mut stream = db.stream(now).with_keywords(keywords);
|
let mut stream = db.stream(now).with_keywords(keywords);
|
||||||
|
|
||||||
let mut fzf = Fzf::new(true)?;
|
let mut fzf = Fzf::new(true)?;
|
||||||
while let Some(dir) = stream.next() {
|
let selection = loop {
|
||||||
writeln!(fzf.stdin(), "{}", dir.display_score(now)).pipe_exit("fzf")?;
|
let dir = match stream.next() {
|
||||||
}
|
Some(dir) => dir,
|
||||||
|
None => break fzf.select()?,
|
||||||
|
};
|
||||||
|
|
||||||
|
match writeln!(fzf.stdin(), "{}", dir.display_score(now)) {
|
||||||
|
Ok(()) => (()),
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => break fzf.select()?,
|
||||||
|
Err(e) => Err(e).context("could not write to fzf")?,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
selection = fzf.wait_select()?;
|
|
||||||
let paths = selection.lines().filter_map(|line| line.get(5..));
|
let paths = selection.lines().filter_map(|line| line.get(5..));
|
||||||
for path in paths {
|
for path in paths {
|
||||||
if !db.remove(path) {
|
if !db.remove(path) {
|
||||||
|
23
src/fzf.rs
23
src/fzf.rs
@ -1,4 +1,4 @@
|
|||||||
use std::io;
|
use std::io::{self, Read};
|
||||||
use std::process::{Child, ChildStdin, Command, Stdio};
|
use std::process::{Child, ChildStdin, Command, Stdio};
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
@ -46,28 +46,21 @@ impl Fzf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn stdin(&mut self) -> &mut ChildStdin {
|
pub fn stdin(&mut self) -> &mut ChildStdin {
|
||||||
// unwrap is safe here because command.stdin() has been piped.
|
|
||||||
self.child.stdin.as_mut().unwrap()
|
self.child.stdin.as_mut().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_select(self) -> Result<String> {
|
pub fn select(mut self) -> Result<String> {
|
||||||
let output = self.child.wait_with_output().context("wait failed on fzf")?;
|
let mut output = String::new();
|
||||||
|
let stdout = self.child.stdout.as_mut().unwrap();
|
||||||
|
stdout.read_to_string(&mut output).context("failed to read from fzf")?;
|
||||||
|
|
||||||
match output.status.code() {
|
let status = self.child.wait().context("wait failed on fzf")?;
|
||||||
// normal exit
|
match status.code() {
|
||||||
Some(0) => String::from_utf8(output.stdout).context("invalid unicode in fzf output"),
|
Some(0) => Ok(output),
|
||||||
|
|
||||||
// no match
|
|
||||||
Some(1) => bail!("no match found"),
|
Some(1) => bail!("no match found"),
|
||||||
|
|
||||||
// error
|
|
||||||
Some(2) => bail!("fzf returned an error"),
|
Some(2) => bail!("fzf returned an error"),
|
||||||
|
|
||||||
// terminated by a signal
|
|
||||||
Some(code @ 130) => bail!(SilentExit { code }),
|
Some(code @ 130) => bail!(SilentExit { code }),
|
||||||
Some(128..=254) | None => bail!("fzf was terminated"),
|
Some(128..=254) | None => bail!("fzf was terminated"),
|
||||||
|
|
||||||
// unknown
|
|
||||||
_ => bail!("fzf returned an unknown error"),
|
_ => bail!("fzf returned an unknown error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user