-
-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add a config file at ~/.config/comrak/config #157
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,25 +5,51 @@ extern crate comrak; | |
#[macro_use] | ||
extern crate clap; | ||
|
||
extern crate xdg; | ||
extern crate shell_words; | ||
|
||
use comrak::{Arena, ComrakOptions, ComrakExtensionOptions, ComrakParseOptions, ComrakRenderOptions}; | ||
|
||
use std::boxed::Box; | ||
use std::collections::BTreeSet; | ||
use std::env; | ||
use std::error::Error; | ||
use std::fs; | ||
use std::io::Read; | ||
use std::process; | ||
|
||
const EXIT_SUCCESS: i32 = 0; | ||
const EXIT_UNKNOWN_EXTENSION: i32 = 1; | ||
const EXIT_PARSE_CONFIG: i32 = 2; | ||
const EXIT_READ_INPUT: i32 = 3; | ||
|
||
fn main() -> Result<(), Box<dyn Error>> { | ||
let matches = clap::App::new(crate_name!()) | ||
let default_config_path = get_default_config_path(); | ||
|
||
let app = clap::App::new(crate_name!()) | ||
.version(crate_version!()) | ||
.author(crate_authors!()) | ||
.about(crate_description!()) | ||
.after_help("\ | ||
By default, Comrak will attempt to read command-line options from a config file specified by \ | ||
--config-file. This behaviour can be disabled by passing --config-file none. It is not an error \ | ||
if the file does not exist.\ | ||
") | ||
.arg( | ||
clap::Arg::with_name("file") | ||
.value_name("FILE") | ||
.multiple(true) | ||
.help("The CommonMark file to parse; or standard input if none passed"), | ||
) | ||
.arg( | ||
clap::Arg::with_name("config-file") | ||
.short("c") | ||
.long("config-file") | ||
.help("Path to config file containing command-line arguments, or `none'") | ||
.value_name("PATH") | ||
.takes_value(true) | ||
.default_value(&default_config_path), | ||
) | ||
.arg( | ||
clap::Arg::with_name("hardbreaks") | ||
.long("hardbreaks") | ||
|
@@ -105,8 +131,29 @@ fn main() -> Result<(), Box<dyn Error>> { | |
.takes_value(true) | ||
.value_name("PREFIX") | ||
.help("Use the Comrak header IDs extension, with the given ID prefix"), | ||
) | ||
.get_matches(); | ||
); | ||
|
||
let mut matches = app.clone().get_matches(); | ||
|
||
let config_file_path = matches.value_of("config-file").unwrap(); | ||
if config_file_path != "none" { | ||
if let Ok(args) = fs::read_to_string(config_file_path) { | ||
match shell_words::split(&args) { | ||
Ok(mut args) => { | ||
for (i, arg) in env::args_os().enumerate() { | ||
if let Some(s) = arg.to_str() { | ||
args.insert(i, s.into()); | ||
} | ||
} | ||
matches = app.get_matches_from(args); | ||
}, | ||
Err(e) => { | ||
eprintln!("failed to parse {}: {}", config_file_path, e); | ||
process::exit(EXIT_PARSE_CONFIG); | ||
}, | ||
} | ||
} | ||
} | ||
|
||
let mut exts = matches | ||
.values_of("extension") | ||
|
@@ -145,7 +192,7 @@ fn main() -> Result<(), Box<dyn Error>> { | |
|
||
if !exts.is_empty() { | ||
eprintln!("unknown extensions: {:?}", exts); | ||
process::exit(1); | ||
process::exit(EXIT_UNKNOWN_EXTENSION); | ||
} | ||
|
||
let mut s: Vec<u8> = Vec::with_capacity(2048); | ||
|
@@ -155,8 +202,15 @@ fn main() -> Result<(), Box<dyn Error>> { | |
std::io::stdin().read_to_end(&mut s)?; | ||
} | ||
Some(fs) => for f in fs { | ||
let mut io = std::fs::File::open(f)?; | ||
io.read_to_end(&mut s)?; | ||
match fs::File::open(f) { | ||
Ok(mut io) => { | ||
io.read_to_end(&mut s)?; | ||
} | ||
Err(e) => { | ||
eprintln!("failed to read {}: {}", f, e); | ||
process::exit(EXIT_READ_INPUT); | ||
} | ||
} | ||
}, | ||
}; | ||
|
||
|
@@ -171,5 +225,17 @@ fn main() -> Result<(), Box<dyn Error>> { | |
|
||
formatter(root, &options, &mut std::io::stdout())?; | ||
|
||
process::exit(0); | ||
process::exit(EXIT_SUCCESS); | ||
} | ||
|
||
fn get_default_config_path() -> String { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at https://github.com/whitequark/rust-xdg/blob/master/src/lib.rs I thought that this might not handle windows, but following through to https://crates.io/crates/dirs, it looks like it is cross-platform after all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! Rust libraries have been pretty good at Windows compat in my experience. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, actually. Nope. >_< Missed the first line: #![cfg(any(unix, target_os = "redox"))] This doesn't work on Windows at all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do something like this: https://github.com/DanielKeep/cargo-script/blob/614e60e5932e218ebff1e471303eb0d59870d03b/src/platform.rs#L309-L363 But for now I'm defaulting to |
||
if let Ok(xdg_dirs) = xdg::BaseDirectories::with_prefix("comrak") { | ||
if let Ok(path) = xdg_dirs.place_config_file("config") { | ||
if let Some(path_str) = path.to_str() { | ||
return path_str.into(); | ||
} | ||
} | ||
} | ||
|
||
return "comrak.config".into(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps the documentation should show
~/.config/comrak/config
? Or is the --help output dynamic?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The output is dynamic, yeah — it'll show the actual default based on their XDG config path. The README excerpt is generated from running the actual binary on my machine, so it shows mine as a sample. :)