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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#![allow(dead_code, unused_variables)]
mod rustla_options;
pub mod parser;
use parser::Parser;
use parser::state_machine::State;
pub mod doctree;
use doctree::DocTree;
pub mod common;
mod utf8_to_latex;
use std::io::BufRead;
pub fn run() -> Result<(), MainError> {
copyright();
let args: Vec<String> = std::env::args().collect();
let args_len = args.len();
let rustla_options = crate::rustla_options::ruSTLaOptions::new(&args);
let mut src_lines = Vec::new();
let path: std::path::PathBuf = if let Some(arg) = args.last() {
if args_len == 1 {
let stdin = std::io::stdin();
for line in stdin.lock().lines() {
match line {
Ok(line) => src_lines.push(line),
Err(e) => {
return Err(MainError::InputError(format!(
"Error when reading stdin: {}",
e
)))
}
}
}
std::path::PathBuf::new()
} else if let Ok(pathbuf) = std::fs::canonicalize(arg) {
let line_iter = match crate::common::read_path_lines(&pathbuf) {
Ok(lines) => lines,
Err(e) => {
return Err(MainError::PathError(format!(
"Could not split file into lines: {}",
e
)))
}
};
for line in line_iter {
match line {
Ok(line) => src_lines.push(line),
Err(e) => {
return Err(MainError::InputError(String::from(
"Could not construct a line vector from input...",
)))
}
}
}
pathbuf
} else {
let stdin = std::io::stdin();
for line in stdin.lock().lines() {
match line {
Ok(line) => src_lines.push(line),
Err(e) => {
return Err(MainError::InputError(format!(
"Error when reading stdin: {}",
e
)))
}
}
}
std::path::PathBuf::new()
}
} else {
unreachable!("No arguments, not even the program itself? Computer says no...")
};
let mut doctree = DocTree::new(path);
let mut parser = Parser::new(src_lines, doctree, 0, 0, State::Body, 0);
use common::ParsingResult;
doctree = match parser.parse() {
ParsingResult::EOF { doctree, .. } | ParsingResult::EmptyStateStack { doctree, .. } => {
doctree
}
ParsingResult::Failure { message, doctree } => {
eprintln!("Parsing error: {}", message);
doctree
}
};
doctree = doctree.perform_restructuredtext_transforms();
doctree.write_to_larst(&rustla_options);
Ok(())
}
fn copyright() {
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const AUTHOR_NAME: &'static str = env!("AUTHOR_NAME");
const AUTHOR_YEAR: &'static str = env!("AUTHOR_YEAR");
eprintln!("\nThis is ruSTLa, version {}", VERSION);
eprintln!("Copyright © {} {}\n", AUTHOR_YEAR, AUTHOR_NAME);
}
fn usage() {
println!("Instructions");
println!("============");
println!("In order to transpile a document,");
println!("point ruSTLa to an rST file with");
println!("\n $ rustla path/to/file.rst\n");
println!("Capabilities to transpile an entire");
println!("toctree will be added later.");
}
#[derive(Debug)]
pub enum MainError {
PathError(String),
InputError(String),
ParseError(String),
PrintError(String),
ArgumentError(String),
}