From cdb15843563cd1a63464ed714276a2d1dec358a3 Mon Sep 17 00:00:00 2001 From: Asherah Connor Date: Thu, 13 Aug 2020 17:14:21 +1000 Subject: [PATCH 1/5] add a config file at ~/.config/comrak/config --- Cargo.toml | 2 ++ src/main.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index df683ae0..6bdc41e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/main.rs b/src/main.rs index 37162a68..18b75315 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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; fn main() -> Result<(), Box> { - 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 with --no-config-file. 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") + .value_name("PATH") + .takes_value(true) + .default_value(&default_config_path), + ) + .arg( + clap::Arg::with_name("no-config-file") + .long("no-config-file") + .help("Do not read config file"), + ) .arg( clap::Arg::with_name("hardbreaks") .long("hardbreaks") @@ -105,8 +131,29 @@ fn main() -> Result<(), Box> { .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(); + + if !matches.is_present("no-config-file") { + let config_file_path = matches.value_of("config-file").unwrap(); + 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(2); + }, + } + } + } let mut exts = matches .values_of("extension") @@ -173,3 +220,15 @@ fn main() -> Result<(), Box> { process::exit(0); } + +fn get_default_config_path() -> String { + 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(); +} From daff02625981fa4496cb549bbdc912530dccf64f Mon Sep 17 00:00:00 2001 From: Asherah Connor Date: Thu, 13 Aug 2020 17:16:00 +1000 Subject: [PATCH 2/5] update README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e6acf1c9..ccee03b5 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,14 @@ FLAGS: --github-pre-lang Use GitHub-style
 for code blocks
         --hardbreaks         Treat newlines as hard line breaks
     -h, --help               Prints help information
+        --no-config-file     Do not read config file
         --smart              Use smart punctuation
         --unsafe             Allow raw HTML and dangerous URLs
     -V, --version            Prints version information
 
 OPTIONS:
+    -c, --config-file             Path to config file containing command-line arguments [default:
+                                        /Users/kivikakk/.config/comrak/config]
         --default-info-string     Default value for fenced code block's info strings if none is given
     -e, --extension ...      Specify an extension name to use [possible values: strikethrough, tagfilter,
                                         table, autolink, tasklist, superscript, footnotes, description-lists]
@@ -59,6 +62,9 @@ OPTIONS:
 
 ARGS:
     ...    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 with --no-config-file.  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:

From 3998d9a36a7aab8281eb5d902ae5bdf231b4878c Mon Sep 17 00:00:00 2001
From: Asherah Connor 
Date: Thu, 13 Aug 2020 20:06:22 +1000
Subject: [PATCH 3/5] use --config-file none instead of --no-config-file

---
 src/main.rs | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 18b75315..ac237040 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -18,6 +18,11 @@ 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> {
     let default_config_path = get_default_config_path();
 
@@ -27,8 +32,8 @@ fn main() -> Result<(), Box> {
         .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 with --no-config-file.  It is not an error if the \
-file does not exist.\
+--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")
@@ -40,16 +45,11 @@ file does not exist.\
             clap::Arg::with_name("config-file")
                 .short("c")
                 .long("config-file")
-                .help("Path to config file containing command-line arguments")
+                .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("no-config-file")
-                .long("no-config-file")
-                .help("Do not read config file"),
-        )
         .arg(
             clap::Arg::with_name("hardbreaks")
                 .long("hardbreaks")
@@ -135,8 +135,8 @@ file does not exist.\
 
     let mut matches = app.clone().get_matches();
 
-    if !matches.is_present("no-config-file") {
-        let config_file_path = matches.value_of("config-file").unwrap();
+    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) => {
@@ -148,8 +148,8 @@ file does not exist.\
                     matches = app.get_matches_from(args);
                 },
                 Err(e) => {
-                    eprintln!("failed to parse {} -- {}", config_file_path, e);
-                    process::exit(2);
+                    eprintln!("failed to parse {}: {}", config_file_path, e);
+                    process::exit(EXIT_PARSE_CONFIG);
                 },
             }
         }
@@ -192,7 +192,7 @@ file does not exist.\
 
     if !exts.is_empty() {
         eprintln!("unknown extensions: {:?}", exts);
-        process::exit(1);
+        process::exit(EXIT_UNKNOWN_EXTENSION);
     }
 
     let mut s: Vec = Vec::with_capacity(2048);
@@ -202,8 +202,15 @@ file does not exist.\
             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);
+                }
+            }
         },
     };
 
@@ -218,7 +225,7 @@ file does not exist.\
 
     formatter(root, &options, &mut std::io::stdout())?;
 
-    process::exit(0);
+    process::exit(EXIT_SUCCESS);
 }
 
 fn get_default_config_path() -> String {

From cc717c9de69a3016dc4be681109107b26ae4b7f8 Mon Sep 17 00:00:00 2001
From: Asherah Connor 
Date: Thu, 13 Aug 2020 20:07:00 +1000
Subject: [PATCH 4/5] fix wrapping in help text

---
 src/main.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main.rs b/src/main.rs
index ac237040..60649ec3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -32,7 +32,7 @@ fn main() -> Result<(), Box> {
         .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
+--config-file.  This behaviour can be disabled by passing --config-file none.  It is not an error \
 if the file does not exist.\
         ")
         .arg(

From 2a224bb5bd6931f988be5c670082b1c893543c40 Mon Sep 17 00:00:00 2001
From: Asherah Connor 
Date: Thu, 13 Aug 2020 20:07:09 +1000
Subject: [PATCH 5/5] update README

---
 README.md | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index ccee03b5..2269528c 100644
--- a/README.md
+++ b/README.md
@@ -45,13 +45,12 @@ FLAGS:
         --github-pre-lang    Use GitHub-style 
 for code blocks
         --hardbreaks         Treat newlines as hard line breaks
     -h, --help               Prints help information
-        --no-config-file     Do not read config file
         --smart              Use smart punctuation
         --unsafe             Allow raw HTML and dangerous URLs
     -V, --version            Prints version information
 
 OPTIONS:
-    -c, --config-file             Path to config file containing command-line arguments [default:
+    -c, --config-file             Path to config file containing command-line arguments, or `none' [default:
                                         /Users/kivikakk/.config/comrak/config]
         --default-info-string     Default value for fenced code block's info strings if none is given
     -e, --extension ...      Specify an extension name to use [possible values: strikethrough, tagfilter,
@@ -64,7 +63,7 @@ ARGS:
     ...    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 with --no-config-file.  It is not an error if the file does not exist.
+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: