Run rustfmt

This commit is contained in:
equal-l2 2018-10-21 14:49:01 +02:00 committed by Danilo Bargen
commit ac9db25691
7 changed files with 263 additions and 134 deletions

View file

@ -1,16 +1,17 @@
use std::io::Read;
use std::fs;
use std::env;
use std::fs;
use std::io::Read;
use std::path::PathBuf;
#[cfg(unix)] use std::os::unix::fs::MetadataExt;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
use xdg::BaseDirectories;
use curl::easy::Easy as CurlEasy;
use flate2::read::GzDecoder;
use tar::Archive;
use curl::easy::Easy as CurlEasy;
use walkdir::{WalkDir, DirEntry};
use time;
use walkdir::{DirEntry, WalkDir};
use xdg::BaseDirectories;
use error::TealdeerError::{self, CacheError, UpdateError};
use types::OsType;
@ -22,7 +23,10 @@ pub struct Cache {
}
impl Cache {
pub fn new<S>(url: S, os: OsType) -> Cache where S: Into<String> {
pub fn new<S>(url: S, os: OsType) -> Cache
where
S: Into<String>,
{
Cache {
url: url.into(),
os: os,
@ -37,11 +41,12 @@ impl Cache {
let path = PathBuf::from(value);
if path.exists() && path.is_dir() {
return Ok(path)
return Ok(path);
} else {
return Err(CacheError(
"Path specified by $TEALDEER_CACHE_DIR \
does not exist or is not a directory.".into()
does not exist or is not a directory."
.into(),
));
}
};
@ -90,9 +95,10 @@ impl Cache {
// Make sure that cache directory exists
debug!("Ensure cache directory {:?} exists", &cache_dir);
try!(fs::create_dir_all(&cache_dir).map_err(|e| {
UpdateError(format!("Could not create cache directory: {}", e))
}));
try!(
fs::create_dir_all(&cache_dir)
.map_err(|e| UpdateError(format!("Could not create cache directory: {}", e)))
);
// Clear cache directory
// Note: This is not the best solution. Ideally we would download the
@ -103,9 +109,11 @@ impl Cache {
try!(self.clear());
// Extract archive
try!(archive.unpack(&cache_dir).map_err(|e| {
UpdateError(format!("Could not unpack compressed data: {}", e))
}));
try!(
archive
.unpack(&cache_dir)
.map_err(|e| UpdateError(format!("Could not unpack compressed data: {}", e)))
);
Ok(())
}
@ -117,7 +125,7 @@ impl Cache {
if let Ok(metadata) = fs::metadata(cache_dir.join("tldr-master")) {
let mtime = metadata.mtime();
let now = time::now_utc().to_timespec();
return Some(now.sec - mtime)
return Some(now.sec - mtime);
};
};
None
@ -190,27 +198,28 @@ impl Cache {
return file_name == platform;
}
} else if file_type.is_file() {
return true
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>>();
.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)
@ -220,13 +229,20 @@ impl Cache {
pub fn clear(&self) -> Result<(), TealdeerError> {
let path = try!(self.get_cache_dir());
if path.exists() && path.is_dir() {
try!(fs::remove_dir_all(&path).map_err(|_| {
CacheError(format!("Could not remove cache directory ({}).", path.display()))
}));
try!(fs::remove_dir_all(&path).map_err(|_| CacheError(format!(
"Could not remove cache directory ({}).",
path.display()
))));
} else if path.exists() {
return Err(CacheError(format!("Cache path ({}) is not a directory.", path.display())));
return Err(CacheError(format!(
"Cache path ({}) is not a directory.",
path.display()
)));
} else {
return Err(CacheError(format!("Cache path ({}) does not exist.", path.display())));
return Err(CacheError(format!(
"Cache path ({}) does not exist.",
path.display()
)));
};
Ok(())
}

View file

@ -59,7 +59,7 @@ struct RawStyle {
impl Default for RawStyle {
fn default() -> RawStyle {
RawStyle{
RawStyle {
foreground: None,
background: None,
underline: false,
@ -106,7 +106,6 @@ struct RawStyleConfig {
pub example_variable: RawStyle,
}
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawConfig {
style: RawStyleConfig,
@ -143,14 +142,14 @@ pub struct Config {
impl From<RawConfig> for Config {
fn from(raw_config: RawConfig) -> Config {
Config{
style: StyleConfig{
Config {
style: StyleConfig {
command_name: raw_config.style.command_name.into(),
description: raw_config.style.description.into(),
example_text: raw_config.style.example_text.into(),
example_code: raw_config.style.example_code.into(),
example_variable: raw_config.style.example_variable.into(),
}
},
}
}
}
@ -163,17 +162,21 @@ impl Config {
pub fn load() -> Result<Config, TealdeerError> {
let raw_config = match get_config_path() {
Ok(config_file_path) => {
let mut config_file = fs::File::open(config_file_path)
.map_err(map_io_err_to_config_err)?;
let mut config_file =
fs::File::open(config_file_path).map_err(map_io_err_to_config_err)?;
let mut contents = String::new();
let _rc = config_file.read_to_string(&mut contents)
let _rc = config_file
.read_to_string(&mut contents)
.map_err(map_io_err_to_config_err)?;
toml::from_str(&contents).map_err(|err| ConfigError(format!("Failed to parse config file: {}", err)))?
toml::from_str(&contents)
.map_err(|err| ConfigError(format!("Failed to parse config file: {}", err)))?
}
Err(ConfigError(_)) => RawConfig::new(),
Err(_) => {
return Err(ConfigError("Unknown error while looking up config path".into()));
return Err(ConfigError(
"Unknown error while looking up config path".into(),
));
}
};
@ -189,11 +192,12 @@ pub fn get_config_dir() -> Result<PathBuf, TealdeerError> {
let path = PathBuf::from(value);
if path.exists() && path.is_dir() {
return Ok(path)
return Ok(path);
} else {
return Err(ConfigError(
"Path specified by $TEALDEER_CONFIG_DIR \
does not exist or is not a directory.".into()
does not exist or is not a directory."
.into(),
));
}
};
@ -201,7 +205,11 @@ pub fn get_config_dir() -> Result<PathBuf, TealdeerError> {
// Otherwise, fall back to $XDG_CONFIG_HOME/tealdeer.
let xdg_dirs = match BaseDirectories::with_prefix(::NAME) {
Ok(dirs) => dirs,
Err(_) => return Err(ConfigError("Could not determine XDG base directory.".into())),
Err(_) => {
return Err(ConfigError(
"Could not determine XDG base directory.".into(),
))
}
};
Ok(xdg_dirs.get_config_home())
}
@ -214,7 +222,10 @@ pub fn get_config_path() -> Result<PathBuf, TealdeerError> {
if config_file_path.is_file() {
Ok(config_file_path)
} else {
Err(ConfigError(format!("{} is not a file path", config_file_path.to_str().unwrap())))
Err(ConfigError(format!(
"{} is not a file path",
config_file_path.to_str().unwrap()
)))
}
}
@ -223,7 +234,10 @@ pub fn make_default_config() -> Result<PathBuf, TealdeerError> {
let config_dir = get_config_dir()?;
if !config_dir.is_dir() {
if let Err(e) = fs::create_dir_all(&config_dir) {
return Err(ConfigError(format!("Could not create config directory: {}", e)));
return Err(ConfigError(format!(
"Could not create config directory: {}",
e
)));
}
}
@ -238,9 +252,9 @@ pub fn make_default_config() -> Result<PathBuf, TealdeerError> {
let serialized_config = toml::to_string(&RawConfig::new())
.map_err(|err| ConfigError(format!("Failed to serialize default config: {}", err)))?;
let mut config_file = fs::File::create(&config_file_path)
.map_err(map_io_err_to_config_err)?;
let _wc = config_file.write(serialized_config.as_bytes())
let mut config_file = fs::File::create(&config_file_path).map_err(map_io_err_to_config_err)?;
let _wc = config_file
.write(serialized_config.as_bytes())
.map_err(map_io_err_to_config_err)?;
Ok(config_file_path)

View file

@ -12,7 +12,7 @@ fn highlight_command<'a>(
command: &'a str,
example_code: &'a str,
config: &Config,
parts: &mut Vec<ANSIString<'a>>
parts: &mut Vec<ANSIString<'a>>,
) {
let mut code_part_end_pos = 0;
while let Some(command_start) = example_code[code_part_end_pos..].find(&command) {
@ -22,7 +22,12 @@ fn highlight_command<'a>(
code_part_end_pos += command_start + command.len();
}
parts.push(config.style.example_code.paint(&example_code[code_part_end_pos..]));
parts.push(
config
.style
.example_code
.paint(&example_code[code_part_end_pos..]),
);
}
/// Format and highlight code examples including variables in {{ curly braces }}.
@ -44,7 +49,10 @@ fn format_code(command: &str, text: &str, config: &Config) -> String {
}
/// Print a token stream to an ANSI terminal.
pub fn print_lines<R>(tokenizer: &mut Tokenizer<R>, config: &Config) where R: BufRead {
pub fn print_lines<R>(tokenizer: &mut Tokenizer<R>, config: &Config)
where
R: BufRead,
{
let mut command = String::new();
while let Some(token) = tokenizer.next_token() {
match token {
@ -56,10 +64,12 @@ pub fn print_lines<R>(tokenizer: &mut Tokenizer<R>, config: &Config) where R: Bu
// and tokenizer yields values in order of appearance.
command = title;
debug!("Detected command name: {}", &command);
},
}
LineType::Description(text) => println!(" {}", config.style.description.paint(text)),
LineType::ExampleText(text) => println!(" {}", config.style.example_text.paint(text)),
LineType::ExampleCode(text) => println!(" {}", &format_code(&command, &text, &config)),
LineType::ExampleCode(text) => {
println!(" {}", &format_code(&command, &text, &config))
}
LineType::Other(text) => debug!("Unknown line type: {:?}", text),
}
}

View file

@ -8,54 +8,77 @@
// option. All files in the project carrying such notice may not be
// copied, modified, or distributed except according to those terms.
#![deny(missing_docs, missing_debug_implementations,
unsafe_code,
unused_import_braces, unused_qualifications)]
#![warn(trivial_casts, trivial_numeric_casts,
missing_copy_implementations,
unused_extern_crates, unused_results)]
#![deny(
missing_docs,
missing_debug_implementations,
unsafe_code,
unused_import_braces,
unused_qualifications
)]
#![warn(
trivial_casts,
trivial_numeric_casts,
missing_copy_implementations,
unused_extern_crates,
unused_results
)]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(feature = "dev", warn(cast_possible_truncation, cast_possible_wrap, cast_precision_loss, cast_sign_loss,
mut_mut, non_ascii_literal, option_unwrap_used, result_unwrap_used,
shadow_reuse, shadow_same, unicode_not_nfc,
wrong_self_convention, wrong_pub_self_convention))]
#![cfg_attr(
feature = "dev",
warn(
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
mut_mut,
non_ascii_literal,
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
shadow_same,
unicode_not_nfc,
wrong_self_convention,
wrong_pub_self_convention
)
)]
#[macro_use] extern crate log;
#[cfg(feature = "logging")] extern crate env_logger;
extern crate docopt;
#[macro_use]
extern crate log;
extern crate ansi_term;
extern crate curl;
extern crate docopt;
#[cfg(feature = "logging")]
extern crate env_logger;
extern crate flate2;
extern crate tar;
extern crate xdg;
extern crate curl;
extern crate time;
extern crate toml;
extern crate walkdir;
extern crate xdg;
#[macro_use]
extern crate serde_derive;
use std::io::BufReader;
use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::process;
use docopt::Docopt;
use ansi_term::Color;
use docopt::Docopt;
mod types;
mod tokenizer;
mod formatter;
mod cache;
mod config;
mod error;
mod formatter;
mod tokenizer;
mod types;
use tokenizer::Tokenizer;
use cache::Cache;
use config::{get_config_path, make_default_config, Config};
use error::TealdeerError::{CacheError, ConfigError, UpdateError};
use formatter::print_lines;
use tokenizer::Tokenizer;
use types::OsType;
const NAME: &'static str = "tealdeer";
@ -114,9 +137,7 @@ struct Args {
/// Print page by path
fn print_page(path: &Path) -> Result<(), String> {
// Open file
let file = try!(
File::open(path).map_err(|msg| format!("Could not open file: {}", msg))
);
let file = try!(File::open(path).map_err(|msg| format!("Could not open file: {}", msg)));
let reader = BufReader::new(file);
// Look up config file, if none is found fall back to default config.
@ -144,18 +165,23 @@ fn check_cache(args: &Args, cache: &Cache) {
if !args.flag_update {
match cache.last_update() {
Some(ago) if ago > MAX_CACHE_AGE => {
if args.flag_quiet { return; }
println!("{}", Color::Red.paint(format!(
"Cache wasn't updated in {} days.\n\
You should probably run `tldr --update` soon.",
MAX_CACHE_AGE / 24 / 3600
)));
},
if args.flag_quiet {
return;
}
println!(
"{}",
Color::Red.paint(format!(
"Cache wasn't updated in {} days.\n\
You should probably run `tldr --update` soon.",
MAX_CACHE_AGE / 24 / 3600
))
);
}
None => {
eprintln!("Cache not found. Please run `tldr --update`.");
process::exit(1);
},
_ => {},
}
_ => {}
}
};
}
@ -166,16 +192,22 @@ fn init_log() {
}
#[cfg(not(feature = "logging"))]
fn init_log() { }
fn init_log() {}
#[cfg(target_os = "linux")]
fn get_os() -> OsType { OsType::Linux }
fn get_os() -> OsType {
OsType::Linux
}
#[cfg(target_os = "macos")]
fn get_os() -> OsType { OsType::OsX }
fn get_os() -> OsType {
OsType::OsX
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_os() -> OsType { OsType::Other }
fn get_os() -> OsType {
OsType::Other
}
fn main() {
// Initialize logger
@ -183,8 +215,8 @@ fn main() {
// Parse arguments
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.deserialize())
.unwrap_or_else(|e| e.exit());
.and_then(|d| d.deserialize())
.unwrap_or_else(|e| e.exit());
// Show version and exit
if args.flag_version {
@ -205,8 +237,9 @@ fn main() {
if args.flag_clear_cache {
cache.clear().unwrap_or_else(|e| {
match e {
CacheError(msg) | ConfigError(msg) | UpdateError(msg) =>
eprintln!("Could not delete cache: {}", msg),
CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
eprintln!("Could not delete cache: {}", msg)
}
};
process::exit(1);
});
@ -219,8 +252,9 @@ fn main() {
if args.flag_update {
cache.update().unwrap_or_else(|e| {
match e {
CacheError(msg) | ConfigError(msg) | UpdateError(msg) =>
eprintln!("Could not update cache: {}", msg),
CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
eprintln!("Could not update cache: {}", msg)
}
};
process::exit(1);
});
@ -248,8 +282,9 @@ fn main() {
// Get list of pages
let pages = cache.list_pages().unwrap_or_else(|e| {
match e {
CacheError(msg) | ConfigError(msg) | UpdateError(msg) =>
eprintln!("Could not get list of pages: {}", msg),
CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
eprintln!("Could not get list of pages: {}", msg)
}
}
process::exit(1);
});
@ -288,15 +323,15 @@ fn main() {
Ok(config_file_path) => {
println!("Config path is: {}", config_file_path.to_str().unwrap());
process::exit(0);
},
}
Err(ConfigError(msg)) => {
eprintln!("Could not look up config_path: {}", msg);
process::exit(1);
},
}
Err(_) => {
eprintln!("Unknown error");
process::exit(1);
},
}
}
}
@ -304,17 +339,20 @@ fn main() {
if args.flag_seed_config {
match make_default_config() {
Ok(config_file_path) => {
println!("Successfully created seed config file here: {}", config_file_path.to_str().unwrap());
println!(
"Successfully created seed config file here: {}",
config_file_path.to_str().unwrap()
);
process::exit(0);
},
}
Err(ConfigError(msg)) => {
eprintln!("Could not create seed config: {}", msg);
process::exit(1);
},
}
Err(_) => {
eprintln!("Unkown error");
process::exit(1);
},
}
}
}
@ -327,11 +365,11 @@ fn main() {
#[cfg(test)]
mod test {
use docopt::Docopt;
use docopt::Error;
use Args;
use OsType;
use USAGE;
use docopt::Docopt;
use docopt::Error;
fn test_helper(argv: &[&str]) -> Result<Args, Error> {
Docopt::new(USAGE).and_then(|d| d.argv(argv.iter()).deserialize())

View file

@ -28,7 +28,10 @@ pub struct Tokenizer<R: BufRead> {
format: TldrFormat,
}
impl<R> Tokenizer<R> where R: BufRead {
impl<R> Tokenizer<R>
where
R: BufRead,
{
pub fn new(reader: R) -> Tokenizer<R> {
Tokenizer {
reader: reader,
@ -46,7 +49,7 @@ impl<R> Tokenizer<R> where R: BufRead {
Err(e) => {
warn!("Could not read line from token reader: {:?}", e);
None
},
}
Ok(_) => {
// Handle new titles
if self.first_line && !self.current_line.starts_with("#") {

View file

@ -27,9 +27,21 @@ impl<'a> From<&'a str> for LineType {
let mut chars = trimmed.chars();
match chars.next() {
None => LineType::Empty,
Some('#') => LineType::Title(trimmed.trim_left_matches(|chr: char| chr == '#' || chr.is_whitespace()).into()),
Some('>') => LineType::Description(trimmed.trim_left_matches(|chr: char| chr == '>' || chr.is_whitespace()).into()),
Some(' ') => LineType::ExampleCode(trimmed.trim_left_matches(|chr: char| chr.is_whitespace()).into()),
Some('#') => LineType::Title(
trimmed
.trim_left_matches(|chr: char| chr == '#' || chr.is_whitespace())
.into(),
),
Some('>') => LineType::Description(
trimmed
.trim_left_matches(|chr: char| chr == '>' || chr.is_whitespace())
.into(),
),
Some(' ') => LineType::ExampleCode(
trimmed
.trim_left_matches(|chr: char| chr.is_whitespace())
.into(),
),
_ => LineType::ExampleText(trimmed.into()),
}
}
@ -43,10 +55,26 @@ impl LineType {
let mut chars = trimmed.chars();
match chars.next() {
None => LineType::Empty,
Some('#') => LineType::Title(trimmed.trim_left_matches(|chr: char| chr == '#' || chr.is_whitespace()).into()),
Some('>') => LineType::Description(trimmed.trim_left_matches(|chr: char| chr == '>' || chr.is_whitespace()).into()),
Some('-') => LineType::ExampleText(trimmed.trim_left_matches(|chr: char| chr == '-' || chr.is_whitespace()).into()),
Some('`') if chars.last() == Some('`') => LineType::ExampleCode(trimmed.trim_matches(|chr: char| chr == '`' || chr.is_whitespace()).into()),
Some('#') => LineType::Title(
trimmed
.trim_left_matches(|chr: char| chr == '#' || chr.is_whitespace())
.into(),
),
Some('>') => LineType::Description(
trimmed
.trim_left_matches(|chr: char| chr == '>' || chr.is_whitespace())
.into(),
),
Some('-') => LineType::ExampleText(
trimmed
.trim_left_matches(|chr: char| chr == '-' || chr.is_whitespace())
.into(),
),
Some('`') if chars.last() == Some('`') => LineType::ExampleCode(
trimmed
.trim_matches(|chr: char| chr == '`' || chr.is_whitespace())
.into(),
),
_ => LineType::Other(trimmed.into()),
}
}
@ -60,9 +88,21 @@ mod test {
fn test_linetype_from_str() {
assert_eq!(LineType::from(""), LineType::Empty);
assert_eq!(LineType::from(" \n \r"), LineType::Empty);
assert_eq!(LineType::from("# Hello there"), LineType::Title("Hello there".into()));
assert_eq!(LineType::from("> tis a description \n"), LineType::Description("tis a description".into()));
assert_eq!(LineType::from("some command "), LineType::ExampleText("some command".into()));
assert_eq!(LineType::from(" $ cargo run "), LineType::ExampleCode("$ cargo run".into()));
assert_eq!(
LineType::from("# Hello there"),
LineType::Title("Hello there".into())
);
assert_eq!(
LineType::from("> tis a description \n"),
LineType::Description("tis a description".into())
);
assert_eq!(
LineType::from("some command "),
LineType::ExampleText("some command".into())
);
assert_eq!(
LineType::from(" $ cargo run "),
LineType::ExampleCode("$ cargo run".into())
);
}
}

View file

@ -50,19 +50,22 @@ fn test_missing_cache() {
fn test_update_cache() {
let testenv = TestEnv::new();
testenv.assert()
testenv
.assert()
.with_args(&["sl"])
.fails()
.stderr().contains("Cache not found. Please run `tldr --update`.")
.unwrap();
testenv.assert()
testenv
.assert()
.with_args(&["--update"])
.succeeds()
.stdout().contains("Successfully updated cache.")
.unwrap();
testenv.assert()
testenv
.assert()
.with_args(&["sl"])
.succeeds()
.unwrap();
@ -137,7 +140,8 @@ fn test_quiet_old_cache() {
fn test_setup_seed_config() {
let testenv = TestEnv::new();
testenv.assert()
testenv
.assert()
.with_args(&["--seed-config"])
.succeeds()
.stdout().contains("Successfully created seed config file")
@ -156,7 +160,8 @@ fn _test_correct_rendering(input_file: &str, filename: &str) {
// Load expected output
let expected = include_str!("inkscape-default.expected");
testenv.assert()
testenv
.assert()
.with_args(&["-f", &file_path.to_str().unwrap()])
.succeeds()
.stdout().is(expected)
@ -186,7 +191,9 @@ fn test_correct_rendering_with_config() {
println!("Config path: {:?}", &config_file_path);
let mut config_file = File::create(&config_file_path).unwrap();
config_file.write(include_str!("config.toml").as_bytes()).unwrap();
config_file
.write(include_str!("config.toml").as_bytes())
.unwrap();
// Create input file
let file_path = testenv.input_dir.path().join("inkscape-v2.md");
@ -198,7 +205,8 @@ fn test_correct_rendering_with_config() {
// Load expected output
let expected = include_str!("inkscape-with-config.expected");
testenv.assert()
testenv
.assert()
.with_args(&["-f", &file_path.to_str().unwrap()])
.succeeds()
.stdout().is(expected)