diff --git a/src/main.rs b/src/main.rs index 696b5bc..1de2e75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,8 +17,8 @@ fn main() { eprintln!(); } - let options: Vec<(String, bool)> = nix::collect_nix_options_with_path(&ast.syntax(), ""); - for (path, value) in options { - println!("{} = {};", path, value); + let options: Vec<(String, String, bool)> = nix::collect_nix_options(&ast.syntax()); + for (category, path, value) in options { + println!("{}: {} = {};", category, path, value); } } diff --git a/src/nix.rs b/src/nix.rs index cfb3f79..fd650ba 100644 --- a/src/nix.rs +++ b/src/nix.rs @@ -1,66 +1,96 @@ -use rnix::{NodeOrToken, SyntaxKind, SyntaxNode}; +use rnix::{NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken}; -pub fn collect_nix_options_with_path(node: &SyntaxNode, current_path: &str) -> Vec<(String, bool)> { - let mut result: Vec<(String, bool)> = Vec::new(); +pub fn collect_nix_options(node: &SyntaxNode) -> Vec<(String, String, bool)> { + collect_nix_options_with_path(node, "", "") +} - for child in node.children_with_tokens() { - if let NodeOrToken::Node(child_node) = child { - match child_node.kind() { - SyntaxKind::NODE_ATTRPATH_VALUE => { - let mut attr_path: String = String::new(); - let mut value_node: Option = None; +fn collect_nix_options_with_path( + node: &SyntaxNode, + current_path: &str, + current_category: &str, +) -> Vec<(String, String, bool)> { + let mut result: Vec<(String, String, bool)> = Vec::new(); + let mut category: String = current_category.to_string(); - for grand in child_node.children_with_tokens() { - if let NodeOrToken::Node(grand_node) = grand { - match grand_node.kind() { - SyntaxKind::NODE_ATTRPATH => { - attr_path = grand_node.text().to_string(); - } - SyntaxKind::NODE_IDENT | SyntaxKind::NODE_LITERAL => { - let text: String = grand_node.text().to_string(); - if text == "true" || text == "false" { - value_node = Some(grand_node); - } - } - SyntaxKind::NODE_ATTR_SET => { - let new_path: String = if current_path.is_empty() { - attr_path.clone() - } else { - format!("{}.{}", current_path, attr_path) - }; + let children: Vec> = node.children_with_tokens().collect(); - result.extend(collect_nix_options_with_path( - &grand_node, - &new_path, - )); - } - _ => {} - } - } - } - - if let Some(value_node) = value_node { - let full_path: String = if current_path.is_empty() { - attr_path - } else { - format!("{}.{}", current_path, attr_path) - }; - - let value_text: String = value_node.text().to_string(); - let mut bool_value: bool = false; - - if value_text == "true" { - bool_value = true; - } - - result.push((full_path, bool_value)); - } - } - - _ => { - result.extend(collect_nix_options_with_path(&child_node, current_path)); + for i in 0..children.len() { + match &children[i] { + NodeOrToken::Token(token) if token.kind() == SyntaxKind::TOKEN_COMMENT => { + let text: &str = token.text(); + if text.starts_with("/*") && text.ends_with("*/") { + let content: String = text + .trim_start_matches("/*") + .trim_end_matches("*/") + .trim() + .to_string(); + category = content; } } + + NodeOrToken::Node(child_node) + if child_node.kind() == SyntaxKind::NODE_ATTRPATH_VALUE => + { + let mut attr_path: String = String::new(); + let mut value_node: Option = None; + + for grand in child_node.children_with_tokens() { + if let NodeOrToken::Node(grand_node) = grand { + match grand_node.kind() { + SyntaxKind::NODE_ATTRPATH => { + attr_path = grand_node.text().to_string(); + } + SyntaxKind::NODE_IDENT | SyntaxKind::NODE_LITERAL => { + let text: String = grand_node.text().to_string(); + if text == "true" || text == "false" { + value_node = Some(grand_node); + } + } + SyntaxKind::NODE_ATTR_SET => { + let new_path: String = if current_path.is_empty() { + attr_path.clone() + } else { + format!("{}.{}", current_path, attr_path) + }; + + result.extend(collect_nix_options_with_path( + &grand_node, + &new_path, + &category, + )); + } + _ => {} + } + } + } + + if let Some(value_node) = value_node { + let full_path: String = if current_path.is_empty() { + attr_path + } else { + format!("{}.{}", current_path, attr_path) + }; + + let value_text: String = value_node.text().to_string(); + let mut bool_value: bool = false; + + if value_text == "true" { + bool_value = true; + } + + result.push((category.clone(), full_path, bool_value)); + } + } + + NodeOrToken::Node(child_node) => { + result.extend(collect_nix_options_with_path( + child_node, + current_path, + &category, + )); + } + + _ => {} } }