Skip to content

Commit ea1dfef

Browse files
authored
Merge pull request #4 from paytonward6/nested_testing
Nested testing
2 parents c3f25a0 + e1f7bab commit ea1dfef

File tree

7 files changed

+173
-170
lines changed

7 files changed

+173
-170
lines changed

run.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/usr/bin/env bash
22

3-
cargo run -- -i tests/notes.md -o tests/TeX/main.tex
4-
#cargo run -- -i tests/test.md -o tests/TeX/main.tex
3+
#cargo run -- -i tests/notes.md -o tests/TeX/main.tex
4+
cargo run -- -i tests/test.md -o tests/TeX/main.tex

src/transpiler.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ pub fn run(file_str: &str, path: &PathBuf) {
2323
fn write(path: &PathBuf, parser: parser::Parser) -> Result<(), Error> {
2424
let mut file = fs::File::create(path)?;
2525
writeln!(file, "{}", generator::documentclass())?;
26-
writeln!(
27-
file,
28-
"{}",
29-
generator::packages(parser.contains_code_block)
30-
)?;
26+
writeln!(file, "{}", generator::packages(parser.contains_code_block))?;
3127
for line in parser.results.into_iter() {
3228
if let Some(line) = generator::generate_line(line) {
3329
writeln!(file, "{}", line)?;

src/transpiler/generator.rs

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,42 @@ use crate::transpiler::{lexer, parser, re};
22

33
pub fn generate_line(mut contents: parser::Contents) -> Option<String> {
44
type Token = lexer::Token;
5-
match contents.kind {
6-
Token::FileStart => Some(format!("\\begin{{document}}\n {}", qol_customizations())),
7-
Token::FileEnd => Some(format!("\\end{{document}}")),
8-
Token::Blank => None,
9-
_ => {
10-
// Can unwrap since any other Token's line will not be None
11-
// by Parser's design
12-
let line = transpile_line(&mut contents.line).unwrap();
13-
match contents.kind {
14-
Token::Heading(level) => match level {
15-
1 => Some(format!("\\section{{{}}}\n", line)),
16-
2 => Some(format!("\\subsection{{{}}}\n", line)),
17-
3 => Some(format!("\\subsubsection{{{}}}\n", line)),
18-
_ => Some(format!("\\subsubsection{{{}}}\n", line)),
19-
},
20-
Token::UnorderedList | Token::OrderedList(_) => Some(listify(contents)),
21-
Token::Text => Some(line),
22-
Token::CodeBlock => Some(code_block(contents)),
23-
Token::BlockQuote => Some(block_quote(&mut contents)),
24-
_ => None
5+
if let None = contents.line {
6+
match contents.kind {
7+
Token::FileStart => Some(format!("\\begin{{document}}\n {}", qol_customizations())),
8+
Token::FileEnd => Some(format!("\\end{{document}}")),
9+
Token::OrderedList(_) => Some(format!(
10+
"{}\\end{{enumerate}}",
11+
indent(contents.indent_level)
12+
)),
13+
Token::UnorderedList => {
14+
Some(format!("{}\\end{{itemize}}", indent(contents.indent_level)))
2515
}
16+
_ => None,
17+
}
18+
} else {
19+
// Can unwrap since line is not None
20+
let line = transpile_line(&mut contents.line).unwrap();
21+
match contents.kind {
22+
Token::Heading(level) => match level {
23+
1 => Some(format!("\\section{{{}}}\n", line)),
24+
2 => Some(format!("\\subsection{{{}}}\n", line)),
25+
3 => Some(format!("\\subsubsection{{{}}}\n", line)),
26+
_ => Some(format!("\\subsubsection{{{}}}\n", line)),
27+
},
28+
Token::UnorderedList | Token::OrderedList(_) => Some(listify(contents)),
29+
Token::Text => Some(line),
30+
Token::CodeBlock => Some(code_block(contents)),
31+
Token::BlockQuote => Some(block_quote(&mut contents)),
32+
_ => None,
2633
}
2734
}
2835
}
2936

37+
pub fn indent(indent_level: usize) -> String {
38+
return " ".repeat(indent_level);
39+
}
40+
3041
fn transpile_line(line: &mut Option<String>) -> Option<String> {
3142
if let Some(line) = line {
3243
*line = re::bold(line);
@@ -44,7 +55,7 @@ fn transpile_line(line: &mut Option<String>) -> Option<String> {
4455
fn block_quote(contents: &mut parser::Contents) -> String {
4556
// Can unwrap since any group item will not be None per Parser's
4657
// design
47-
let line = re::replace_block_quote(&contents.line.as_ref().unwrap());
58+
let line = re::replace_block_quote(&contents.line.as_ref().unwrap());
4859
type Chronology = parser::Chronology;
4960
match contents.chron {
5061
Chronology::Start => {
@@ -63,15 +74,23 @@ fn listify(contents: parser::Contents) -> String {
6374
// design
6475
let line = contents.line.unwrap();
6576
if let Token::UnorderedList = contents.kind {
77+
let indent = indent(contents.indent_level);
78+
println!("{:?} => \"{}\"", line, indent);
6679
match contents.chron {
6780
Chronology::Start => {
68-
format!("\\begin{{itemize}}\n \\item {}", line)
81+
format!(
82+
"{}\\begin{{itemize}}\n {}\\item {}",
83+
indent, indent, line
84+
)
6985
}
70-
Chronology::Middle => format!(" \\item {}", line),
71-
Chronology::End => format!(" \\item {}\n\\end{{itemize}}\n", line),
86+
Chronology::Middle => format!("{} \\item {}", indent, line),
87+
Chronology::End => format!(
88+
"{} \\item {}\n{}\\end{{itemize}}\n",
89+
indent, line, indent
90+
),
7291
Chronology::None => format!(
73-
"\\begin{{enumerate}}\n \\item {}\n\\end{{enumerate}}\n",
74-
line
92+
"{}\\begin{{itemize}}\n {}\\item {}\n{}\\end{{itemize}}\n",
93+
indent, indent, line, indent,
7594
),
7695
}
7796
} else if let Token::OrderedList(num) = contents.kind {
@@ -105,13 +124,14 @@ fn code_block(content: parser::Contents) -> String {
105124
}
106125
}
107126

108-
const PACKAGES: [&str; 6] = [
127+
const PACKAGES: [&str; 7] = [
109128
"geometry",
110129
"ulem",
111130
"listings",
112131
"hyperref",
113132
"xcolor",
114133
"indentfirst",
134+
"enumitem",
115135
];
116136

117137
pub fn packages(contains_code_block: bool) -> String {

src/transpiler/lexer.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ impl Lexer {
6969
self.results
7070
.push(Info::new(Token::UnorderedList, Some(line), indent_level));
7171
} else if line.is_empty() {
72-
self.results
73-
.push(Info::new(Token::Blank, None, indent_level));
72+
continue;
73+
//self.results
74+
// .push(Info::new(Token::Blank, None, indent_level));
7475
} else if re::is_ordered_list(&line) {
7576
let (number, line) = re::replace_ordered_list(&line);
7677
self.results.push(Info::new(

src/transpiler/parser.rs

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,25 @@ use crate::transpiler::re;
77

88
#[derive(Debug)]
99
pub struct Parser {
10-
pub stack: Vec<lexer::Token>,
10+
pub records: Vec<usize>,
1111
pub results: Vec<Contents>,
12-
pub previous: Previous,
12+
pub previous: Record,
1313
pub contains_code_block: bool,
1414
}
1515

16-
#[derive(Debug)]
16+
#[derive(Debug, Clone)]
1717
pub struct Contents {
1818
pub line: Option<String>,
1919
pub kind: lexer::Token,
20+
pub indent_level: usize,
2021
pub chron: Chronology,
2122
}
2223

2324
#[derive(Debug)]
24-
pub struct Previous {
25+
pub struct Record {
2526
pub kind: lexer::Token,
2627
pub chron: Chronology,
28+
pub indent_level: usize,
2729
}
2830

2931
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -34,73 +36,103 @@ pub enum Chronology {
3436
None,
3537
}
3638

37-
impl From<&Contents> for Previous {
39+
impl From<&Contents> for Record {
3840
fn from(contents: &Contents) -> Self {
39-
Previous {
41+
Record {
4042
kind: contents.kind,
4143
chron: contents.chron,
44+
indent_level: contents.indent_level,
4245
}
4346
}
4447
}
4548

4649
impl Contents {
47-
fn new(line: Option<String>, kind: lexer::Token, chron: Chronology) -> Self {
48-
Contents { line, kind, chron }
50+
fn new(info: lexer::Info, chron: Chronology) -> Self {
51+
Contents {
52+
line: info.line,
53+
kind: info.token,
54+
indent_level: info.indent_level,
55+
chron,
56+
}
57+
}
58+
59+
fn new_with_line(line: Option<String>, info: lexer::Info, chron: Chronology) -> Self {
60+
Contents {
61+
line,
62+
kind: info.token,
63+
indent_level: info.indent_level,
64+
chron,
65+
}
4966
}
5067
}
5168

5269
impl Parser {
5370
pub fn new() -> Parser {
54-
let stack: Vec<lexer::Token> = Vec::new();
55-
let previous = Previous {
71+
let records: Vec<usize> = Vec::new();
72+
let previous = Record {
5673
kind: Token::FileStart,
5774
chron: Chronology::None,
75+
indent_level: 0,
5876
};
5977
let results: Vec<Contents> = Vec::new();
6078
let contains_code_block = false;
6179
Parser {
62-
stack,
80+
records,
6381
results,
6482
previous,
6583
contains_code_block,
6684
}
6785
}
6886

6987
pub fn run(&mut self, lexer: lexer::Lexer) {
70-
if lexer.results.iter().any(|item| item.token == Token::CodeBlock) {
88+
if lexer
89+
.results
90+
.iter()
91+
.any(|item| item.token == Token::CodeBlock)
92+
{
7193
self.contains_code_block = true;
7294
}
7395

74-
let mut iter = lexer.results.into_iter().peekable();
96+
let mut iter = lexer.results.into_iter().enumerate().peekable();
7597
while let Some(item) = iter.next() {
76-
let current = item;
77-
if current.token == Token::Blank {
78-
continue
79-
}
80-
else if let Some(next) = iter.peek() {
98+
let (number, current) = item;
99+
if let Some((_, next)) = iter.peek() {
81100
if lexer::Lexer::is_group(&current.token) {
82101
if let Some(contents) = self.group_to_contents(current, next) {
83-
self.previous = Previous::from(&contents);
102+
// Keep track of the indices of the open groups in results
103+
if contents.chron == Chronology::Start {
104+
self.records.push(number);
105+
} else if contents.chron == Chronology::End {
106+
self.records.pop();
107+
}
108+
109+
self.previous = Record::from(&contents);
84110
self.results.push(contents);
85111
}
86112
} else {
87-
let contents = Contents::new(
88-
current.line,
89-
current.token,
90-
Chronology::None,
91-
);
92-
self.previous = Previous::from(&contents);
113+
// Close open blocks up to that point since interrupted
114+
for record in self.records.iter() {
115+
let contents = self.results.get(*record).unwrap();
116+
self.results.push(Contents {
117+
line: None,
118+
kind: contents.kind,
119+
chron: Chronology::End,
120+
indent_level: contents.indent_level,
121+
});
122+
}
123+
self.records.clear();
124+
let contents = Contents::new(current, Chronology::None);
125+
self.previous = Record::from(&contents);
93126
self.results.push(contents);
94127
}
95-
} else {
96-
self.results.push(Contents::new(
97-
None,
98-
current.token,
99-
Chronology::None,
100-
));
101128
}
102-
println!("{:?}", self.previous);
103129
}
130+
self.results.push(Contents {
131+
line: None,
132+
kind: Token::FileEnd,
133+
indent_level: 0,
134+
chron: Chronology::None,
135+
});
104136
}
105137

106138
fn group_to_contents(&self, current: lexer::Info, next: &lexer::Info) -> Option<Contents> {
@@ -111,28 +143,39 @@ impl Parser {
111143
if let Token::CodeBlock = current.token {
112144
if let Some(language) = re::replace_code_block(current.line.as_ref().map(|x| &**x)) {
113145
let mut language = language;
114-
if code_blocks::is_invalid_language(&language)
115-
{
146+
if code_blocks::is_invalid_language(&language) {
116147
eprintln!(
117148
"Language \"{}\" not found. Using default of \"python\".",
118149
language
119150
);
120151
language = "python".to_string();
121152
};
122-
return Some(Contents::new(Some(language), current.token, Chronology::Start))
153+
return Some(Contents::new_with_line(
154+
Some(language),
155+
current,
156+
Chronology::Start,
157+
));
123158
} else {
124-
return Some(Contents::new(current.line, current.token, Chronology::End))
159+
return Some(Contents::new(current, Chronology::End));
125160
}
161+
} else if current.indent_level > self.previous.indent_level
162+
&& current.indent_level > next.indent_level
163+
{
164+
return Some(Contents::new(current, Chronology::None));
165+
} else if current.indent_level > self.previous.indent_level {
166+
return Some(Contents::new(current, Chronology::Start));
167+
} else if current.indent_level > next.indent_level {
168+
return Some(Contents::new(current, Chronology::End));
126169
} else if token_discrim != prev_discrim && token_discrim != next_discrim {
127-
return Some(Contents::new(current.line, current.token, Chronology::None));
170+
return Some(Contents::new(current, Chronology::None));
128171
} else if token_discrim != next_discrim {
129-
return Some(Contents::new(current.line, current.token, Chronology::End));
172+
return Some(Contents::new(current, Chronology::End));
130173
} else if token_discrim != prev_discrim
131-
|| (token_discrim == prev_discrim && self.previous.chron == Chronology::End)
174+
//|| (token_discrim == prev_discrim && self.previous.chron == Chronology::End)
132175
{
133-
return Some(Contents::new(current.line, current.token, Chronology::Start));
176+
return Some(Contents::new(current, Chronology::Start));
134177
} else if token_discrim == prev_discrim && token_discrim == next_discrim {
135-
return Some(Contents::new(current.line, current.token, Chronology::Middle));
178+
return Some(Contents::new(current, Chronology::Middle));
136179
}
137180
None
138181
}

0 commit comments

Comments
 (0)