aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs43
1 files changed, 29 insertions, 14 deletions
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 @@
1use std::io::Result; 1use clap::Parser;
2use std::fs;
3use std::borrow::Cow;
4use std::path::{Path,PathBuf};
5use std::collections::HashMap;
6use lazy_static::lazy_static; 2use lazy_static::lazy_static;
7use regex::{Captures,Regex};
8use pandoc::{InputFormat,InputKind,OutputFormat,OutputKind,Pandoc}; 3use pandoc::{InputFormat,InputKind,OutputFormat,OutputKind,Pandoc};
9use pandoc_ast::Block; 4use pandoc_ast::Block;
5use regex::{Captures,Regex};
6use std::borrow::Cow;
7use std::collections::HashMap;
8use std::fs;
9use std::io::Result;
10use std::path::{Path,PathBuf};
11
12const BASE: &str = "code";
10 13
11type Blocks<'a> = HashMap<String,Cow<'a,str>>; 14type 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)]
19struct 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 */
14fn write_to_file<P: AsRef<Path>>(path: P, content: &str) -> std::io::Result<()> { 29fn 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 */
80fn build(blocks: &Blocks) { 94fn 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
102fn main() -> Result<()> { 116fn 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();