1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
pub mod atom;
pub mod html;
pub mod markdown;
pub mod syntax_highlight;
use atom::generate_atom;
use clap::{Parser, Subcommand};
use html::{article, index};
use laby::{internal::Buffer, Render};
use std::{
fs::File,
io::{BufRead, BufReader, Write},
path::PathBuf,
process::{Command, Stdio},
};
pub const BLOG_BASE: &'static str = "s.metamuffin.org/temp/blog-preview";
#[derive(Parser)]
pub struct Args {
#[clap(short, long)]
root: Option<String>,
#[clap(short, long)]
output: Option<String>,
#[clap(subcommand)]
action: ArgAction,
}
#[derive(Subcommand)]
pub enum ArgAction {
RenderArticle { input: String },
RenderIndex,
GenerateAtom,
}
fn main() {
let args = Args::parse();
match &args.action {
ArgAction::RenderArticle { input } => {
let mut out = Buffer::new();
article(input.to_owned()).render(&mut out);
write_output(&args, out.into_string());
}
ArgAction::RenderIndex => {
let mut out = Buffer::new();
index(&args.root.as_ref().unwrap()).render(&mut out);
write_output(&args, out.into_string());
}
ArgAction::GenerateAtom => {
write_output(&args, generate_atom(&args));
}
}
}
fn write_output(t: &Args, o: String) {
if let Some(f) = &t.output {
let mut f = File::create(f).unwrap();
f.write_fmt(format_args!("{o}")).unwrap()
} else {
println!("{o}")
}
}
pub fn get_articles(root: &str) -> Vec<ArticleMeta> {
let mut a = std::fs::read_dir(root)
.unwrap()
.map(|e| e.unwrap())
.map(|e| article_metadata(e.path()))
.collect::<Vec<_>>();
a.sort_by_cached_key(|e| -match e.date {
iso8601::Date::YMD { year, month, day } => day as i32 + month as i32 * 40 + year * 37,
_ => unreachable!(),
});
a
}
pub fn file_history(filename: &str) -> String {
String::from_utf8(
Command::new("/usr/bin/git")
.args(&["log", "--follow", "--pretty=tformat:%as %h %s", filename])
.stdout(Stdio::piped())
.output()
.unwrap()
.stdout,
)
.unwrap()
}
pub struct ArticleMeta {
title: String,
canonical_name: String,
date: iso8601::Date,
}
fn article_metadata(path: PathBuf) -> ArticleMeta {
let f = File::open(&path).unwrap();
let mut f = BufReader::new(f);
let mut buf = String::new();
f.read_line(&mut buf).unwrap(); // assume the 1st line has the title
ArticleMeta {
title: String::from(buf[2..].trim()),
canonical_name: path.file_stem().unwrap().to_str().unwrap().to_string(),
date: iso8601::date(&path.file_name().unwrap().to_str().unwrap()[0..10]).unwrap(),
}
}
|