mirror of https://github.com/sharkdp/fd.git
122 lines
3.6 KiB
Rust
122 lines
3.6 KiB
Rust
// Copyright (c) 2017 fd developers
|
|
// Licensed under the Apache License, Version 2.0
|
|
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
|
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
|
// at your option. All files in the project carrying such
|
|
// notice may not be copied, modified, or distributed except
|
|
// according to those terms.
|
|
|
|
use std::path::MAIN_SEPARATOR;
|
|
|
|
/// Removes the parent component of the path
|
|
pub fn basename(path: &str) -> &str {
|
|
let mut index = 0;
|
|
for (id, character) in path.char_indices() {
|
|
if character == MAIN_SEPARATOR {
|
|
index = id;
|
|
}
|
|
}
|
|
|
|
// FIXME: On Windows, should return what for C:file.txt D:file.txt and \\server\share ?
|
|
if index != 0 {
|
|
return &path[index + 1..];
|
|
}
|
|
|
|
path
|
|
}
|
|
|
|
/// Removes the extension from the path
|
|
pub fn remove_extension(path: &str) -> &str {
|
|
let mut has_dir = false;
|
|
let mut dir_index = 0;
|
|
let mut ext_index = 0;
|
|
|
|
for (id, character) in path.char_indices() {
|
|
if character == MAIN_SEPARATOR {
|
|
has_dir = true;
|
|
dir_index = id;
|
|
}
|
|
if character == '.' {
|
|
ext_index = id;
|
|
}
|
|
}
|
|
|
|
// Account for hidden files and directories
|
|
if ext_index != 0 && (!has_dir || dir_index + 2 <= ext_index) {
|
|
return &path[0..ext_index];
|
|
}
|
|
|
|
path
|
|
}
|
|
|
|
/// Removes the basename from the path.
|
|
pub fn dirname(path: &str) -> &str {
|
|
let mut has_dir = false;
|
|
let mut index = 0;
|
|
for (id, character) in path.char_indices() {
|
|
if character == MAIN_SEPARATOR {
|
|
has_dir = true;
|
|
index = id;
|
|
}
|
|
}
|
|
|
|
// FIXME: On Windows, return what for C:file.txt D:file.txt and \\server\share ?
|
|
if !has_dir {
|
|
"."
|
|
} else if index == 0 {
|
|
&path[..1]
|
|
} else {
|
|
&path[0..index]
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod path_tests {
|
|
use super::*;
|
|
|
|
fn correct(input: &str) -> String {
|
|
input.replace('/', &MAIN_SEPARATOR.to_string())
|
|
}
|
|
|
|
macro_rules! func_tests {
|
|
($($name:ident: $func:ident for $input:expr => $output:expr)+) => {
|
|
$(
|
|
#[test]
|
|
fn $name() {
|
|
assert_eq!($func(&correct($input)), correct($output));
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
|
|
func_tests! {
|
|
remove_ext_simple: remove_extension for "foo.txt" => "foo"
|
|
remove_ext_dir: remove_extension for "dir/foo.txt" => "dir/foo"
|
|
hidden: remove_extension for ".foo" => ".foo"
|
|
remove_ext_utf8: remove_extension for "💖.txt" => "💖"
|
|
remove_ext_empty: remove_extension for "" => ""
|
|
|
|
basename_simple: basename for "foo.txt" => "foo.txt"
|
|
basename_dir: basename for "dir/foo.txt" => "foo.txt"
|
|
basename_empty: basename for "" => ""
|
|
basename_utf8_0: basename for "💖/foo.txt" => "foo.txt"
|
|
basename_utf8_1: basename for "dir/💖.txt" => "💖.txt"
|
|
|
|
dirname_simple: dirname for "foo.txt" => "."
|
|
dirname_dir: dirname for "dir/foo.txt" => "dir"
|
|
dirname_utf8_0: dirname for "💖/foo.txt" => "💖"
|
|
dirname_utf8_1: dirname for "dir/💖.txt" => "dir"
|
|
dirname_empty: dirname for "" => "."
|
|
}
|
|
|
|
#[test]
|
|
fn dirname_root() {
|
|
#[cfg(windows)]
|
|
assert_eq!(dirname("C:\\"), "C:");
|
|
#[cfg(windows)]
|
|
assert_eq!(dirname("\\"), "\\");
|
|
#[cfg(not(windows))]
|
|
assert_eq!(dirname("/"), "/");
|
|
}
|
|
}
|