mirror of
https://github.com/Llewellynvdm/zoxide.git
synced 2024-11-22 12:55:13 +00:00
Launch correct fzf binary on Windows
This commit is contained in:
parent
339a789261
commit
fd088b43db
@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Parse error on Cygwin/MSYS due to CRLF line endings.
|
||||
- Fzf: handle spaces correctly in preview window.
|
||||
- Bash: avoid initializing completions on older versions.
|
||||
- Fzf: avoid launching binary from current directory on Windows.
|
||||
|
||||
## [0.7.9] - 2021-11-02
|
||||
|
||||
|
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -679,6 +679,26 @@ version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.3"
|
||||
@ -792,4 +812,5 @@ dependencies = [
|
||||
"rstest",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
]
|
||||
|
@ -27,6 +27,7 @@ glob = "0.3.0"
|
||||
ordered-float = "2.0.0"
|
||||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0.30"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
rand = { version = "0.8.4", features = [
|
||||
|
@ -120,6 +120,12 @@ impl<'file> Database<'file> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn persist<P: AsRef<Path>>(file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
||||
file.persist(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
||||
use std::thread;
|
||||
@ -152,12 +158,6 @@ fn persist<P: AsRef<Path>>(mut file: NamedTempFile, path: P) -> Result<(), Persi
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn persist<P: AsRef<Path>>(file: NamedTempFile, path: P) -> Result<(), PersistError> {
|
||||
file.persist(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct DatabaseFile {
|
||||
buffer: Vec<u8>,
|
||||
data_dir: PathBuf,
|
||||
|
15
src/error.rs
15
src/error.rs
@ -1,20 +1,19 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::io;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("could not find fzf, is it installed?")]
|
||||
pub struct FzfNotFound;
|
||||
|
||||
/// Custom error type for early exit.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Error)]
|
||||
#[error("")]
|
||||
pub struct SilentExit {
|
||||
pub code: i32,
|
||||
}
|
||||
|
||||
impl Display for SilentExit {
|
||||
fn fmt(&self, _: &mut Formatter) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BrokenPipeHandler {
|
||||
fn pipe_exit(self, device: &str) -> Result<()>;
|
||||
}
|
||||
|
13
src/fzf.rs
13
src/fzf.rs
@ -1,11 +1,11 @@
|
||||
use std::io::{self, Read};
|
||||
use std::mem;
|
||||
use std::process::{Child, ChildStdin, Command, Stdio};
|
||||
use std::process::{Child, ChildStdin, Stdio};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
|
||||
use crate::config;
|
||||
use crate::error::SilentExit;
|
||||
use crate::error::{FzfNotFound, SilentExit};
|
||||
use crate::{config, util};
|
||||
|
||||
pub struct Fzf {
|
||||
child: Child,
|
||||
@ -13,7 +13,8 @@ pub struct Fzf {
|
||||
|
||||
impl Fzf {
|
||||
pub fn new(multiple: bool) -> Result<Self> {
|
||||
let mut command = Command::new("fzf");
|
||||
let bin = if cfg!(windows) { "fzf.exe" } else { "fzf" };
|
||||
let mut command = util::get_command(bin).map_err(|_| FzfNotFound)?;
|
||||
if multiple {
|
||||
command.arg("-m");
|
||||
}
|
||||
@ -37,9 +38,7 @@ impl Fzf {
|
||||
|
||||
let child = match command.spawn() {
|
||||
Ok(child) => child,
|
||||
Err(e) if e.kind() == io::ErrorKind::NotFound => {
|
||||
bail!("could not find fzf, is it installed?")
|
||||
}
|
||||
Err(e) if e.kind() == io::ErrorKind::NotFound => bail!(FzfNotFound),
|
||||
Err(e) => Err(e).context("could not launch fzf")?,
|
||||
};
|
||||
|
||||
|
30
src/util.rs
30
src/util.rs
@ -1,5 +1,6 @@
|
||||
use std::env;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
@ -21,6 +22,35 @@ pub fn current_time() -> Result<Epoch> {
|
||||
Ok(current_time)
|
||||
}
|
||||
|
||||
/// Constructs a new [`Command`] for launching the program with the name
|
||||
/// `program`.
|
||||
///
|
||||
/// On Windows, CreateProcess implicitly searches the current working directory
|
||||
/// for the executable, which is a potential security issue. Instead, we resolve
|
||||
/// the path to the executable and then pass it to CreateProcess.
|
||||
///
|
||||
/// On other platforms, this is a no-op.
|
||||
///
|
||||
pub fn get_command<P: AsRef<Path>>(program: P) -> Result<Command> {
|
||||
let program = program.as_ref();
|
||||
if !cfg!(windows) {
|
||||
return Ok(Command::new(program));
|
||||
}
|
||||
|
||||
let paths = env::var_os("PATH").context("PATH environment variable not set")?;
|
||||
for path in env::split_paths(&paths) {
|
||||
if path.as_os_str().is_empty() {
|
||||
continue;
|
||||
}
|
||||
let path = path.join(program);
|
||||
if path.metadata().map_or(false, |m| !m.is_dir()) {
|
||||
return Ok(Command::new(path));
|
||||
}
|
||||
}
|
||||
|
||||
bail!("executable not found in PATH: {}", program.display());
|
||||
}
|
||||
|
||||
pub fn path_to_str<P: AsRef<Path>>(path: &P) -> Result<&str> {
|
||||
let path = path.as_ref();
|
||||
path.to_str().with_context(|| format!("invalid unicode in path: {}", path.display()))
|
||||
|
Loading…
Reference in New Issue
Block a user