diff options
| author | Federico Igne <git@federicoigne.com> | 2022-05-26 23:50:07 +0100 |
|---|---|---|
| committer | Federico Igne <git@federicoigne.com> | 2022-05-27 00:48:45 +0100 |
| commit | e9bad57cbb1123fd3bdedde3ef154ab03f40eca6 (patch) | |
| tree | 8d080cab1536e7a36ef178a88b5dc4c22cec406f | |
| parent | ff6551e0d1124ed54fb02c464b07c6c1aeda6f16 (diff) | |
| download | pangler-e9bad57cbb1123fd3bdedde3ef154ab03f40eca6.tar.gz pangler-e9bad57cbb1123fd3bdedde3ef154ab03f40eca6.zip | |
feat(cli): simple command line interface
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/main.rs | 43 |
2 files changed, 30 insertions, 14 deletions
| @@ -10,4 +10,5 @@ lazy_static = "1.4" | |||
| 10 | regex = "1.5" | 10 | regex = "1.5" |
| 11 | pandoc = "0.8" | 11 | pandoc = "0.8" |
| 12 | pandoc_ast = "0.8" | 12 | pandoc_ast = "0.8" |
| 13 | clap = { version = "3.1", features = ["derive"] } | ||
| 13 | 14 | ||
diff --git a/src/main.rs b/src/main.rs index c28914f..2cfb962 100644 --- a/src/main.rs +++ b/src/main.rs | |||
| @@ -1,20 +1,34 @@ | |||
| 1 | use std::io::Result; | 1 | use clap::Parser; |
| 2 | use std::fs; | ||
| 3 | use std::borrow::Cow; | ||
| 4 | use std::path::{Path,PathBuf}; | ||
| 5 | use std::collections::HashMap; | ||
| 6 | use lazy_static::lazy_static; | 2 | use lazy_static::lazy_static; |
| 7 | use regex::{Captures,Regex}; | ||
| 8 | use pandoc::{InputFormat,InputKind,OutputFormat,OutputKind,Pandoc}; | 3 | use pandoc::{InputFormat,InputKind,OutputFormat,OutputKind,Pandoc}; |
| 9 | use pandoc_ast::Block; | 4 | use pandoc_ast::Block; |
| 5 | use regex::{Captures,Regex}; | ||
| 6 | use std::borrow::Cow; | ||
| 7 | use std::collections::HashMap; | ||
| 8 | use std::fs; | ||
| 9 | use std::io::Result; | ||
| 10 | use std::path::{Path,PathBuf}; | ||
| 11 | |||
| 12 | const BASE: &str = "code"; | ||
| 10 | 13 | ||
| 11 | type Blocks<'a> = HashMap<String,Cow<'a,str>>; | 14 | type Blocks<'a> = HashMap<String,Cow<'a,str>>; |
| 12 | 15 | ||
| 16 | /// A tangler for Literate Programming in Pandoc | ||
| 17 | #[derive(Parser, Debug)] | ||
| 18 | #[clap(author, version, about, long_about = None)] | ||
| 19 | struct Config { | ||
| 20 | /// Base output directory (default: './code') | ||
| 21 | #[clap(short, long)] | ||
| 22 | output: Option<PathBuf>, | ||
| 23 | |||
| 24 | /// Input files | ||
| 25 | input: Vec<PathBuf>, | ||
| 26 | } | ||
| 27 | |||
| 13 | /* Write code to target file */ | 28 | /* Write code to target file */ |
| 14 | fn write_to_file<P: AsRef<Path>>(path: P, content: &str) -> std::io::Result<()> { | 29 | fn write_to_file<P: AsRef<Path>>(base: &Option<PathBuf>, path: P, content: &str) -> std::io::Result<()> { |
| 15 | let base: PathBuf = PathBuf::from("code"); | ||
| 16 | if path.as_ref().is_relative() { | 30 | if path.as_ref().is_relative() { |
| 17 | let path = base.join(path); | 31 | let path = base.clone().unwrap_or(PathBuf::from(BASE)).join(path); |
| 18 | /* There is always *at least* the base directory as a parent */ | 32 | /* There is always *at least* the base directory as a parent */ |
| 19 | fs::create_dir_all(path.parent().unwrap())?; | 33 | fs::create_dir_all(path.parent().unwrap())?; |
| 20 | fs::write(path, content)?; | 34 | fs::write(path, content)?; |
| @@ -77,7 +91,7 @@ fn indent<'a>(input: Cow<'a,str>, indent: usize) -> Cow<'a,str> { | |||
| 77 | * of the borrowed value `text`. Moreover `text` takes ownership of `new_text: String` using | 91 | * of the borrowed value `text`. Moreover `text` takes ownership of `new_text: String` using |
| 78 | * the `Cow::from()` function. No heap allocation is performed, and the string is not copied. | 92 | * the `Cow::from()` function. No heap allocation is performed, and the string is not copied. |
| 79 | */ | 93 | */ |
| 80 | fn build(blocks: &Blocks) { | 94 | fn build(base: &Option<PathBuf>, blocks: &Blocks) { |
| 81 | lazy_static! { | 95 | lazy_static! { |
| 82 | static ref PATH: Regex = Regex::new(r"^(?:[[:word:]\.-]+/)*[[:word:]\.-]+\.[[:alpha:]]+$").unwrap(); | 96 | static ref PATH: Regex = Regex::new(r"^(?:[[:word:]\.-]+/)*[[:word:]\.-]+\.[[:alpha:]]+$").unwrap(); |
| 83 | static ref MACRO: Regex = Regex::new(r"(?m)^([[:blank:]]*)<<([^>\s]+)>>").unwrap(); | 97 | static ref MACRO: Regex = Regex::new(r"(?m)^([[:blank:]]*)<<([^>\s]+)>>").unwrap(); |
| @@ -95,20 +109,21 @@ fn build(blocks: &Blocks) { | |||
| 95 | }) { | 109 | }) { |
| 96 | code = Cow::from(step); | 110 | code = Cow::from(step); |
| 97 | } | 111 | } |
| 98 | write_to_file(k, &code).expect("Unable to write to file"); | 112 | write_to_file(base, k, &code).expect("Unable to write to file"); |
| 99 | }) | 113 | }) |
| 100 | } | 114 | } |
| 101 | 115 | ||
| 102 | fn main() -> Result<()> { | 116 | fn main() -> Result<()> { |
| 117 | let config = Config::parse(); | ||
| 103 | let mut pandoc = Pandoc::new(); | 118 | let mut pandoc = Pandoc::new(); |
| 104 | /* Pandoc input setup */ | 119 | /* Pandoc input setup */ |
| 105 | pandoc.set_input(InputKind::Files(vec![PathBuf::from("test.md")])); | 120 | pandoc.set_input(InputKind::Files(config.input)); |
| 106 | pandoc.set_input_format(InputFormat::Markdown, vec![]); | 121 | pandoc.set_input_format(InputFormat::Markdown, vec![]); |
| 107 | /* Pandoc output setup */ | 122 | /* Pandoc output setup */ |
| 108 | pandoc.set_output(OutputKind::Pipe); | 123 | pandoc.set_output(OutputKind::Pipe); |
| 109 | pandoc.set_output_format(OutputFormat::Json, vec![]); | 124 | pandoc.set_output_format(OutputFormat::Json, vec![]); |
| 110 | /* Process literate program */ | 125 | /* Process literate program */ |
| 111 | pandoc.add_filter(|json| pandoc_ast::filter(json, |pandoc| { | 126 | pandoc.add_filter(move |json| pandoc_ast::filter(json, |pandoc| { |
| 112 | let mut blocks: Blocks = HashMap::new(); | 127 | let mut blocks: Blocks = HashMap::new(); |
| 113 | pandoc.blocks.iter().for_each(|block| | 128 | pandoc.blocks.iter().for_each(|block| |
| 114 | if let Block::CodeBlock((id,classes,attrs), code) = block { | 129 | if let Block::CodeBlock((id,classes,attrs), code) = block { |
| @@ -138,7 +153,7 @@ fn main() -> Result<()> { | |||
| 138 | } | 153 | } |
| 139 | } | 154 | } |
| 140 | ); | 155 | ); |
| 141 | build(dbg!(&blocks)); | 156 | build(&config.output, &blocks); |
| 142 | pandoc | 157 | pandoc |
| 143 | })); | 158 | })); |
| 144 | pandoc.execute().unwrap(); | 159 | pandoc.execute().unwrap(); |
