org_rust_parser/element/
table.rs1use crate::constants::{HYPHEN, NEWLINE};
2use crate::node_pool::NodeID;
3use crate::object::TableCell;
4use crate::types::{Cursor, Expr, MarkupKind, ParseOpts, Parseable, Parser, Result};
5
6#[derive(Debug, Clone)]
11pub struct Table {
12 pub rows: usize,
13 pub cols: usize,
14 pub children: Vec<NodeID>,
15}
16
17#[derive(Debug, Clone)]
35pub enum TableRow {
36 Rule, Standard(Vec<NodeID>),
38}
39
40impl<'a> Parseable<'a> for Table {
41 fn parse(
42 parser: &mut Parser<'a>,
43 mut cursor: Cursor<'a>,
44 parent: Option<NodeID>,
45 mut parse_opts: ParseOpts,
46 ) -> Result<NodeID> {
47 let start = cursor.index;
48
49 parse_opts.markup.insert(MarkupKind::Table);
51 let reserve_id = parser.pool.reserve_id();
52 let mut children: Vec<NodeID> = Vec::new();
53 let mut rows = 0;
54 let mut cols = 0;
55 while let Ok(row_id) = TableRow::parse(parser, cursor, Some(reserve_id), parse_opts) {
56 let obj = &parser.pool[row_id];
57
58 children.push(row_id);
59 rows += 1;
60 if let Expr::TableRow(TableRow::Standard(node_ids)) = &obj.obj {
61 cols = cols.max(node_ids.len());
62 }
63
64 cursor.index = parser.pool[row_id].end;
65 }
66
67 Ok(parser.alloc_with_id(
68 Self {
69 rows,
70 cols,
71 children,
72 },
73 start,
74 cursor.index,
75 parent,
76 reserve_id,
77 ))
78 }
79}
80
81impl<'a> Parseable<'a> for TableRow {
82 fn parse(
83 parser: &mut Parser<'a>,
84 mut cursor: Cursor<'a>,
85 parent: Option<NodeID>,
86 parse_opts: ParseOpts,
87 ) -> Result<NodeID> {
88 let start = cursor.index;
89
90 cursor.curr_valid()?;
94 cursor.skip_ws();
95 cursor.word("|")?;
96
97 if let Ok(val) = cursor.try_curr() {
105 if val == HYPHEN {
106 cursor.adv_till_byte(b'\n');
108 return Ok(parser
110 .pool
111 .alloc(Self::Rule, start, cursor.index + 1, parent));
112 }
113 }
114
115 let mut children: Vec<NodeID> = Vec::new();
116 while let Ok(table_cell_id) = TableCell::parse(parser, cursor, parent, parse_opts) {
117 let node_item = &parser.pool[table_cell_id];
118 children.push(table_cell_id);
119
120 cursor.index = node_item.end;
121 if let Ok(val) = cursor.try_curr() {
122 if val == NEWLINE {
123 cursor.next();
124 break;
125 }
126 } else {
127 break;
128 }
129 }
130
131 Ok(parser
132 .pool
133 .alloc(Self::Standard(children), start, cursor.index, parent))
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use crate::{expr_in_pool, parse_org, Expr};
140
141 #[test]
142 fn basic_table() {
143 let input = r"
144|one|two|
145|three|four|
146";
147 let pool = parse_org(input);
148
149 pool.print_tree();
150 }
151
152 #[test]
153 fn table_eof_1() {
154 let input = r"
155|one|two|
156|three|four|
157";
158 let pool = parse_org(input);
159
160 pool.print_tree();
161 }
162
163 #[test]
164 fn table_eof_2() {
165 let input = r"
166|one|two|
167|three|four|";
168 let pool = parse_org(input);
169
170 pool.print_tree();
171 }
172
173 #[test]
174 fn table_no_nl() {
175 let input = r"
176|one|two
177|three|four
178
179";
180 let pool = parse_org(input);
181
182 pool.print_tree();
183 }
184
185 #[test]
186 fn table_with_hrule() {
187 let input = r"
188|one|two
189|--------|
190|three|four
191
192";
193 let pool = parse_org(input);
194
195 pool.print_tree();
196 }
197
198 #[test]
199 fn table_markup_1() {
200 let input = r"
201|one|tw *o* |
202|three|four|
203";
204 let pool = parse_org(input);
205
206 pool.print_tree();
207 }
208
209 #[test]
210 fn table_empty_cells() {
211 let input = r"
212||a|
213|b||
214";
215 let pool = parse_org(input);
216
217 pool.print_tree();
218 }
219
220 #[test]
222 fn table_aligned_cells() {
223 let input = r"
224|one two |three|
225|s | |
226";
227
228 let pool = parse_org(input);
229
230 pool.print_tree();
231 }
232
233 #[test]
234 fn table_uneven_cols() {
235 let input = r"
236|one two |three|||||
237|s | |
238";
239
240 let pool = parse_org(input);
241
242 pool.print_tree();
243 }
244
245 #[test]
246 fn table_indented() {
247 let input = r"
248word
249 |one two |three|
250 |s | |
251 |four | five|
252word
253
254";
255
256 let pool = parse_org(input);
257 pool.print_tree();
258 }
259
260 #[test]
261 fn table_indented_list() {
262 let input = r"
263- one
264 - two
265 |one two |three|
266 |s | |
267 |four | five|
268- three
269";
270
271 let pool = parse_org(input);
272
273 pool.print_tree();
274 }
275
276 #[test]
277 fn table_no_start() {
278 let input = r"|";
279
280 let pool = parse_org(input);
281 let tab = expr_in_pool!(pool, Table).unwrap();
282 assert_eq!(tab.rows, 1);
283 }
284}