|
1 | 1 | use std::cell::{RefCell, RefMut}; |
2 | | -use std::collections::HashMap; |
| 2 | +use std::collections::{HashMap, BTreeSet}; |
3 | 3 | use std::iter::zip; |
4 | 4 | use std::ops::Index; |
5 | 5 |
|
6 | 6 | use taplo::syntax::SyntaxKind::{ENTRY, IDENT, KEY, NEWLINE, TABLE_ARRAY_HEADER, TABLE_HEADER, VALUE}; |
7 | 7 | use taplo::syntax::{SyntaxElement, SyntaxNode}; |
8 | 8 | use taplo::HashSet; |
| 9 | +use taplo::{dom::node::DomNode as _, parser::parse}; |
9 | 10 |
|
10 | 11 | use crate::create::{make_empty_newline, make_key, make_newline, make_table_entry}; |
11 | 12 | use crate::string::load_text; |
@@ -296,6 +297,14 @@ pub fn collapse_sub_tables(tables: &mut Tables, name: &str, exclude: &[Vec<Strin |
296 | 297 | if main_positions.len() != 1 { |
297 | 298 | return; |
298 | 299 | } |
| 300 | + |
| 301 | + // remove `name` from `exclude`s (and skip if `name` is not a prefix) |
| 302 | + let prefix = parse_ident(name).expect("could not parse prefix"); |
| 303 | + let exclude: BTreeSet<_> = exclude.into_iter().filter_map(|id| { |
| 304 | + let (prefix_2, rest) = id.split_at(prefix.len()+1); |
| 305 | + (prefix == prefix_2).then_some(rest) |
| 306 | + }).collect(); |
| 307 | + |
299 | 308 | let mut main = tables.table_set[*main_positions.first().unwrap()].borrow_mut(); |
300 | 309 | for key in sub_table_keys { |
301 | 310 | let sub_positions = tables.header_to_pos[key].clone(); |
@@ -340,3 +349,35 @@ pub fn collapse_sub_tables(tables: &mut Tables, name: &str, exclude: &[Vec<Strin |
340 | 349 | sub.clear(); |
341 | 350 | } |
342 | 351 | } |
| 352 | + |
| 353 | +pub fn parse_ident(ident: &str) -> Result<Vec<String>, String> { |
| 354 | + let parsed = parse(&format!("{ident} = 1")); |
| 355 | + if let Some(e) = parsed.errors.first() { |
| 356 | + return Err(format!("syntax error: {e}")); |
| 357 | + } |
| 358 | + |
| 359 | + let root = parsed.into_dom(); |
| 360 | + let errors = root.errors(); |
| 361 | + if let Some(e) = errors.get().first() { |
| 362 | + return Err(format!("semantic error: {e}")); |
| 363 | + } |
| 364 | + |
| 365 | + dbg!(&root.errors()); |
| 366 | + |
| 367 | + // We cannot use `.into_syntax()` since only the DOM transformation |
| 368 | + // allows accessing ident `.value()`s without quotes. |
| 369 | + let mut node = root; |
| 370 | + let mut parts = vec![]; |
| 371 | + while let Ok(table) = node.try_into_table() { |
| 372 | + let entries = table.entries().get(); |
| 373 | + if entries.len() != 1 { |
| 374 | + return Err("expected exactly one entry".to_string()); |
| 375 | + } |
| 376 | + let mut it = entries.iter(); |
| 377 | + let (key, next_node) = it.next().unwrap(); // checked if len == 1 above |
| 378 | + |
| 379 | + parts.push(key.value().to_string()); |
| 380 | + node = next_node.clone(); |
| 381 | + } |
| 382 | + Ok(parts) |
| 383 | +} |
0 commit comments