Merge pull request #16 from dbrgn/list

Implement --list flag
This commit is contained in:
Danilo Bargen 2016-01-27 17:48:02 +01:00
commit ec28d48bea
5 changed files with 119 additions and 30 deletions

10
Cargo.lock generated
View file

@ -11,6 +11,7 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.3.2 (git+https://github.com/dbrgn/tar-rs?branch=pax_header)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -292,6 +293,15 @@ dependencies = [
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "walkdir"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.5"

View file

@ -16,3 +16,4 @@ env_logger = { version = "^0.3", optional = true }
rustc-serialize = "^0.3"
docopt = "^0.6"
time = "^0.1"
walkdir = "^0.1"

View file

@ -8,6 +8,7 @@ use std::path::PathBuf;
use flate2::read::GzDecoder;
use tar::Archive;
use curl::http;
use walkdir::{WalkDir, WalkDirIterator, DirEntry};
use time;
use error::TldrError::{self, CacheError, UpdateError};
@ -90,24 +91,29 @@ impl Cache {
None
}
/// Return the platform directory.
fn get_platform_dir(&self) -> Option<&'static str> {
match self.os {
OsType::Linux => Some("linux"),
OsType::OsX => Some("osx"),
OsType::SunOs => None, // TODO: Does Rust support SunOS?
OsType::Other => None,
}
}
/// Search for a page and return the path to it.
pub fn find_page(&self, name: &str) -> Option<PathBuf> {
// Build page file name
let page_filename = format!("{}.md", name);
// Get platform dir
let cache_dir = match self.get_cache_dir() {
Ok(dir) => dir,
Err(_) => return None,
let platforms_dir = match self.get_cache_dir() {
Ok(cache_dir) => cache_dir.join("tldr-master").join("pages"),
_ => return None,
};
let platforms_dir = cache_dir.join("tldr-master").join("pages");
// Determine platform
let platform = match self.os {
OsType::Linux => Some("linux"),
OsType::OsX => Some("osx"),
OsType::SunOs => None, // TODO: Does Rust support SunOS?
OsType::Other => None,
};
let platform = self.get_platform_dir();
// Search for the page in the platform specific directory
if let Some(pf) = platform {
@ -129,6 +135,56 @@ impl Cache {
}
}
/// Return the available pages.
pub fn list_pages(&self) -> Result<Vec<String>, TldrError> {
// Determine platforms directory and platform
let cache_dir = try!(self.get_cache_dir());
let platforms_dir = cache_dir.join("tldr-master").join("pages");
let platform_dir = self.get_platform_dir();
// Closure that allows the WalkDir instance to traverse platform
// specific and common page directories, but not others.
let should_walk = |entry: &DirEntry| -> bool {
let file_type = entry.file_type();
let file_name = match entry.file_name().to_str() {
Some(name) => name,
None => return false,
};
if file_type.is_dir() {
if file_name == "common" {
return true;
}
if let Some(platform) = platform_dir {
return file_name == platform;
}
} else if file_type.is_file() {
return true
}
false
};
// Recursively walk through common and (if applicable) platform specific directory
let mut pages = WalkDir::new(platforms_dir)
.min_depth(1) // Skip root directory
.into_iter()
.filter_entry(|e| should_walk(e)) // Filter out pages for other architectures
.filter_map(|e| e.ok()) // Convert results to options, filter out errors
.filter_map(|e| {
let path = e.path();
let extension = &path.extension().and_then(|s| s.to_str()).unwrap_or("");
if e.file_type().is_file() && extension == &"md" {
path.file_stem().and_then(|stem| stem.to_str().map(|s| s.into()))
} else {
None
}
})
.collect::<Vec<String>>();
pages.sort();
pages.dedup();
Ok(pages)
}
/// Delete the cache directory.
pub fn clear(&self) -> Result<(), TldrError> {
let path = try!(self.get_cache_dir());

View file

@ -9,6 +9,7 @@ extern crate tar;
extern crate curl;
extern crate rustc_serialize;
extern crate time;
extern crate walkdir;
use std::io::BufReader;
use std::fs::File;
@ -16,6 +17,7 @@ use std::path::{Path, PathBuf};
use std::process;
use docopt::Docopt;
use ansi_term::Colour;
mod types;
mod tokenizer;
@ -95,6 +97,27 @@ fn print_page(path: &Path) -> Result<(), String> {
}
/// Check the cache for freshness
fn check_cache(args: &Args, cache: &Cache) {
if !args.flag_update {
match cache.last_update() {
Some(ago) if ago > MAX_CACHE_AGE => {
println!("{}", Colour::Red.paint(format!(
"Cache wasn't updated in {} days.\n\
You should probably run `tldr --update` soon.\n",
MAX_CACHE_AGE / 24 / 3600
)));
},
None => {
println!("Cache not found. Please run `tldr --update`.");
process::exit(1);
},
_ => {},
}
};
}
#[cfg(feature = "logging")]
fn init_log() {
env_logger::init().unwrap();
@ -162,7 +185,7 @@ fn main() {
}
// Render local file and exit
if let Some(file) = args.flag_render {
if let Some(ref file) = args.flag_render {
let path = PathBuf::from(file);
if let Err(msg) = print_page(&path) {
println!("{}", msg);
@ -174,27 +197,26 @@ fn main() {
// List cached commands and exit
if args.flag_list {
println!("Flag --list not yet implemented.");
process::exit(1);
// Check cache for freshness
check_cache(&args, &cache);
// Get list of pages
let pages = cache.list_pages().unwrap_or_else(|e| {
match e {
UpdateError(msg) | CacheError(msg) => println!("Could not get list of pages: {}", msg),
}
process::exit(1);
});
// Print pages
println!("{}", pages.join(", "));
process::exit(0);
}
// Show command from cache
if let Some(command) = args.arg_command {
// Check cache
if !args.flag_update {
match cache.last_update() {
Some(ago) if ago > MAX_CACHE_AGE => {
println!("Cache wasn't updated in {} days.", MAX_CACHE_AGE / 24 / 3600);
println!("You should probably run `tldr --update` soon.");
},
None => {
println!("Cache not found. Please run `tldr --update`.");
process::exit(1);
},
_ => {},
}
}
if let Some(ref command) = args.arg_command {
// Check cache for freshness
check_cache(&args, &cache);
// Search for command in cache
if let Some(path) = cache.find_page(&command) {

View file

@ -3,7 +3,7 @@
use rustc_serialize::{Decodable, Decoder};
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[allow(dead_code)]
pub enum OsType {
Linux,