mirror of
https://github.com/tealdeer-rs/tealdeer.git
synced 2026-08-21 15:44:18 +02:00
Run rustfmt
This commit is contained in:
parent
7fdf10cd44
commit
ac9db25691
7 changed files with 263 additions and 134 deletions
88
src/cache.rs
88
src/cache.rs
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
148
src/main.rs
148
src/main.rs
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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("#") {
|
||||
|
|
|
|||
62
src/types.rs
62
src/types.rs
|
|
@ -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())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
tests/lib.rs
22
tests/lib.rs
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue