diff --git a/src/fshelper/mod.rs b/src/fshelper/mod.rs index b473a76..28a73a0 100644 --- a/src/fshelper/mod.rs +++ b/src/fshelper/mod.rs @@ -7,8 +7,8 @@ // according to those terms. use std::env::current_dir; -use std::path::{Path, PathBuf}; use std::io; +use std::path::{Path, PathBuf}; pub fn path_absolute_form(path: &Path) -> io::Result { if path.is_absolute() { @@ -42,3 +42,42 @@ pub fn is_dir(path: &Path) -> bool { path.is_dir() && path.canonicalize().is_ok() } } + +/// Remove the `./` prefix from a path. +/// +/// This code is an adapted version of the `pathutil::strip_prefix` +/// helper function in ripgrep (https://github.com/BurntSushi/ripgrep). +#[cfg(unix)] +pub fn strip_current_dir<'a>(path: &'a Path) -> &'a Path { + use std::os::unix::ffi::OsStrExt; + use std::ffi::OsStr; + + let prefix = b"./"; + let path_raw = path.as_os_str().as_bytes(); + if path_raw.len() < 2 || &path_raw[0..2] != prefix { + path + } else { + Path::new(OsStr::from_bytes(&path_raw[2..])) + } +} + +/// Remove the `./` prefix from a path. +#[cfg(not(unix))] +pub fn strip_current_dir<'a>(path: &'a Path) -> &'a Path { + path.strip_prefix("./").unwrap_or(&path) +} + +#[test] +fn test_strip_current_dir() { + let expect_stripped = |expected, input| { + let stripped = Path::new(expected); + let base = Path::new(input); + assert_eq!(stripped, strip_current_dir(&base)); + }; + + expect_stripped("foo/bar.txt", "./foo/bar.txt"); + expect_stripped("", "./"); + expect_stripped("foo", "./foo"); + expect_stripped("foo.txt", "foo.txt"); + expect_stripped("../foo", "../foo"); +} diff --git a/src/output.rs b/src/output.rs index 115b31a..fc2aedd 100644 --- a/src/output.rs +++ b/src/output.rs @@ -8,6 +8,7 @@ use internal::{FdOptions, EXITCODE_ERROR, EXITCODE_SIGINT}; use lscolors::LsColors; +use fshelper::strip_current_dir; use std::{fs, process}; use std::io::{self, Write}; @@ -20,16 +21,6 @@ use std::os::unix::fs::PermissionsExt; use ansi_term; -/// Remove the `./` prefix from a path. -fn strip_current_dir<'a>(pathbuf: &'a PathBuf) -> &'a Path { - let mut iter = pathbuf.components(); - let mut iter_next = iter.clone(); - if iter_next.next() == Some(Component::CurDir) { - iter.next(); - } - iter.as_path() -} - pub fn print_entry(entry: &PathBuf, config: &FdOptions, wants_to_quit: &Arc) { let path = if entry.is_absolute() { entry.as_path()