1use std::{collections::HashMap, fmt::Write};
2
3use rnix::{self, SyntaxKind, SyntaxNode};
4
5use crate::read::ReadError;
6
7pub fn findattr(configbase: &SyntaxNode, name: &str) -> Option<SyntaxNode> {
8 let mut childvec: Vec<(String, String)> = Vec::new();
9 for child in configbase.children() {
10 if child.kind() == SyntaxKind::NODE_ATTRPATH_VALUE {
11 let qkey = name
12 .split('.')
13 .map(|s| s.to_string())
14 .collect::<Vec<String>>();
15 for subchild in child.children() {
17 if subchild.kind() == SyntaxKind::NODE_ATTRPATH {
18 let key = getkey(&subchild);
20 if qkey == key {
21 if child
22 .children()
23 .any(|x| x.kind() == SyntaxKind::NODE_ATTR_SET)
24 {
25 if let Some(x) = child.children().last() {
26 if x.kind() == SyntaxKind::NODE_ATTR_SET {
27 for n in x.children() {
28 let i = n.children().count();
29 if let (Some(k), Some(v)) =
30 (n.children().nth(i - 2), n.last_child())
31 {
32 let f = n.to_string().find(&k.to_string()).unwrap()
33 + k.to_string().len();
34 childvec.push((
35 n.to_string()[0..f].to_string(),
36 v.to_string(),
37 ));
38 }
39 }
40 }
41 }
42 } else {
43 return Some(child);
44 }
45 } else if qkey.len() > key.len() {
46 if key == qkey[0..key.len()] {
48 let subkey = &qkey[key.len()..].join(".").to_string();
50 if let Some(newbase) = getcfgbase(&child) {
51 if let Some(subattr) = findattr(&newbase, subkey) {
52 return Some(subattr);
53 }
54 }
55 }
56 } else if qkey.len() < key.len() && qkey == key[0..qkey.len()] {
57 if let Some(x) = child.last_child() {
58 childvec.push((key[qkey.len()..].join("."), x.to_string()));
59 }
60 }
61 }
62 }
63 }
64 }
65 if childvec.is_empty() {
66 None
67 } else {
68 let s;
69 if childvec.len() == 1 {
70 s = format!("{{{} = {{ {} = {}; }}; }}", name, childvec[0].0, childvec[0].1);
71 } else {
72 let mut list = String::new();
73 for (k, v) in childvec.iter() {
74 let _ = writeln!(list, " {} = {};", k, v);
75 }
76 list = list.strip_suffix('\n').unwrap_or(&list).to_string();
77 s = format!("{{ {} = {{\n{}\n}}; }}", name, list);
78 }
79 let ast = rnix::Root::parse(&s);
80 if let Some(x) = ast.syntax().children().next() {
81 if x.kind() == SyntaxKind::NODE_ATTR_SET {
82 if let Some(y) = x.children().next() {
83 if y.kind() == SyntaxKind::NODE_ATTRPATH_VALUE {
84 return Some(y);
85 }
86 }
87 }
88 }
89 None
90 }
91}
92
93pub fn get_collection(f: String) -> Result<HashMap<String, String>, ReadError> {
94 let mut map = HashMap::new();
95 let ast = rnix::Root::parse(&f);
96 let configbase = match getcfgbase(&ast.syntax()) {
97 Some(x) => x,
98 None => {
99 return Err(ReadError::ParseError);
100 }
101 };
102 collectattrs(&configbase, &mut map);
103 Ok(map)
104}
105
106pub fn collectattrs(configbase: &SyntaxNode, map: &mut HashMap<String, String>)
107{
108 for child in configbase.children() {
109 if child.kind() == SyntaxKind::NODE_ATTRPATH_VALUE {
110 let children = child.children().collect::<Vec<SyntaxNode>>();
111 let nodekey = children.get(0).unwrap();
112 let value = children.get(1).unwrap();
113 if nodekey.kind() == SyntaxKind::NODE_ATTRPATH {
114 if value.kind() == SyntaxKind::NODE_ATTR_SET {
115 let mut childmap = HashMap::new();
116 collectattrs(value, &mut childmap);
117 for (nk, v) in &childmap {
118 map.insert(format!("{}.{}", nodekey, nk), v.clone());
119 }
120 } else {
121 map.insert(nodekey.to_string(), value.to_string());
122 }
123 }
124 }
125 }
126}
127
128pub fn getkey(node: &SyntaxNode) -> Vec<String> {
129 let mut key = vec![];
130 for child in node.children() {
131 if child.kind() == SyntaxKind::NODE_IDENT || child.kind() == SyntaxKind::NODE_STRING {
132 key.push(child.text().to_string());
133 }
134 }
135 key
136}
137
138pub fn getcfgbase(node: &SyntaxNode) -> Option<SyntaxNode> {
139 if node.kind() == SyntaxKind::NODE_ATTR_SET {
141 return Some(node.clone());
142 }
143 for child in node.children() {
145 if child.kind() == SyntaxKind::NODE_ATTR_SET {
146 return Some(child);
147 }
148 }
149 for child in node.children() {
150 if let Some(x) = getcfgbase(&child) {
151 return Some(x);
152 }
153 }
154 None
155}