Skip to content
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

Merged
merged 5 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ clap = { version = "2.32.0", optional = true }
twoway = "0.2"
pest = "2"
pest_derive = "2"
xdg = "^2.1"
shell-words = "1.0"

[dev-dependencies]
timebomb = "0.1.2"
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ FLAGS:
-V, --version Prints version information

OPTIONS:
-c, --config-file <PATH> Path to config file containing command-line arguments, or `none' [default:
/Users/kivikakk/.config/comrak/config]
Copy link
Contributor

@coolaj86 coolaj86 Aug 13, 2020

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?

Copy link
Owner Author

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. :)

--default-info-string <INFO> Default value for fenced code block's info strings if none is given
-e, --extension <EXTENSION>... Specify an extension name to use [possible values: strikethrough, tagfilter,
table, autolink, tasklist, superscript, footnotes, description-lists]
Expand All @@ -59,6 +61,9 @@ OPTIONS:

ARGS:
<FILE>... The CommonMark file to parse; or standard input if none passed

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.
```

And there's a Rust interface. You can use `comrak::markdown_to_html` directly:
Expand Down
80 changes: 73 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}
},
};

Expand All @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Owner Author

Choose a reason for hiding this comment

The 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.

Copy link
Owner Author

Choose a reason for hiding this comment

The 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.

Copy link
Owner Author

Choose a reason for hiding this comment

The 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 none on Windows.

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();
}