Re-write in rust

This commit is contained in:
sharkdp 2017-05-12 11:50:03 +02:00
parent 04892d2290
commit 12bfee0bec
7 changed files with 244 additions and 105 deletions

8
.gitignore vendored
View file

@ -1,6 +1,2 @@
CMakeCache.txt
CMakeFiles
Makefile
cmake_install.cmake
build
fnd
target/
**/*.rs.bk

View file

@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 3.1.0)
project(fnd CXX)
find_package(Boost 1.60 REQUIRED COMPONENTS system filesystem)
include_directories( ${Boost_INCLUDE_DIR} )
file(GLOB SOURCES "src/*.cpp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
add_executable(fnd ${SOURCES})
target_compile_features(fnd PRIVATE cxx_range_for)
target_link_libraries(fnd ${Boost_LIBRARIES})
install(TARGETS fnd DESTINATION bin)

143
Cargo.lock generated Normal file
View file

@ -0,0 +1,143 @@
[root]
name = "fd"
version = "0.1.0"
dependencies = [
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "getopts"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread-id"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unreachable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

9
Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "fd"
version = "0.1.0"
authors = ["David Peter <mail@david-peter.de>"]
[dependencies]
getopts = "0.2"
regex = "0.2"
walkdir = "1"

View file

@ -1,36 +1,30 @@
# fnd
# fd
A modern, convenient and fast replacement for `find`.
**Features:**
* Easy syntax. `fnd PATTERN` instead of `find -iname '*PATTERN*'`.
* Easy syntax: `fd PATTERN` instead of `find -iname '*PATTERN*'`.
* Colored output.
* Regular expressions.
* The command name is *25%* shorter than `find` :-).
* The command name is *50%* shorter than `find` :-).
## Examples
``` bash
> fnd
> fd
README.md
src
src/fnd.cpp
README.md
src/main.rs
Cargo.toml
LICENSE
CMakeLists.txt
Cargo.lock
> fnd cpp
src/fnd.cpp
> fd rs
src/main.rs
> fnd '[A-Z].*'
README.md
> fd '^[A-Z]+$'
LICENSE
CMakeLists.txt
```
## Dependencies
* g++ `>=4.9`
* boost `>=1.60`
## Build
```bash
cmake .
make
cargo build
```

View file

@ -1,63 +0,0 @@
#include <iostream>
#include <regex>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
static const std::string ANSI_PURPLE = "\x1b[35;06m";
static const std::string ANSI_CYAN = "\x1b[36;01m";
static const std::string ANSI_RESET = "\x1b[0m";
void printPath(const fs::path& path) {
if (fs::is_symlink(path)) {
std::cout << ANSI_PURPLE;
} else if (fs::is_directory(path)) {
std::cout << ANSI_CYAN;
}
std::cout << path.string();
std::cout << ANSI_RESET << std::endl;
}
void findFiles(const std::regex& pattern) {
const fs::path& currentPath = fs::current_path();
for (auto& entry: fs::recursive_directory_iterator(currentPath)) {
const fs::path& path = entry.path().lexically_relative(currentPath);
if (std::regex_search(path.string(), pattern)) {
printPath(path);
}
}
}
int main(int argc, char* argv[]) {
std::string argument;
if (argc == 1) {
argument = "";
} else if (argc == 2) {
argument = argv[1];
}
if (argc > 2 || argument == "-h" || argument == "--help") {
std::cerr << "Usage: fnd [PATTERN]" << std::endl;
return 1;
}
// try to parse the argument as a regex
try {
std::regex::flag_type flags = std::regex_constants::ECMAScript
| std::regex_constants::icase;
std::regex re(argument, flags);
findFiles(re);
}
catch (const std::regex_error& e) {
std::cerr << "Regex error: " << e.what() << std::endl;
return 1;
}
return 0;
}

78
src/main.rs Normal file
View file

@ -0,0 +1,78 @@
extern crate walkdir;
extern crate regex;
extern crate getopts;
use std::env;
use std::path::Path;
use std::io::Write;
use std::process;
use std::error::Error;
use walkdir::{WalkDir, DirEntry, WalkDirIterator};
use regex::Regex;
use getopts::Options;
fn is_hidden(entry: &DirEntry) -> bool {
entry.file_name()
.to_str()
.map(|s| s.starts_with("."))
.unwrap_or(false)
}
fn scan(root: &Path, pattern: &Regex) {
let walker = WalkDir::new(root).into_iter();
for entry in walker.filter_entry(|e| !is_hidden(e))
.filter_map(|e| e.ok()) {
if entry.path() == root {
continue;
}
let path_relative = entry.path().strip_prefix(root).unwrap();
let path_str = match path_relative.to_str() {
Some(s) => s,
None => continue
};
match pattern.find(path_str) {
Some(_) =>
println!("{}", path_str),
None =>
continue
}
}
}
fn error<T: Error>(err: &T) -> ! {
writeln!(&mut std::io::stderr(), "{}", err.description())
.expect("Failed writing to stderr");
process::exit(1);
}
fn main() {
let args: Vec<String> = env::args().collect();
let mut opts = Options::new();
opts.optflag("h", "help", "print this help message");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => { error(&f) }
};
if matches.opt_present("h") {
let brief = "Usage: fd [PATTERN]";
print!("{}", opts.usage(&brief));
process::exit(1);
}
let empty = String::new();
let pattern = matches.free.get(0).unwrap_or(&empty);
let current_dir_buf = env::current_dir()
.expect("Could not get current directory!");
let current_dir = current_dir_buf.as_path();
match Regex::new(pattern) {
Ok(re) =>
scan(current_dir, &re),
Err(err) => error(&err)
}
}