nix_editor/
read.rs

1use crate::parse::{findattr, getcfgbase};
2use rnix::{SyntaxKind, SyntaxNode};
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum ReadError {
7    #[error("Error while parsing")]
8    ParseError,
9    #[error("No attributes")]
10    NoAttr,
11    #[error("Error with array")]
12    ArrayError,
13}
14
15pub fn readvalue(f: &str, query: &str) -> Result<String, ReadError> {
16    let ast = rnix::Root::parse(f);
17    let configbase = match getcfgbase(&ast.syntax()) {
18        Some(x) => x,
19        None => {
20            return Err(ReadError::ParseError);
21        }
22    };
23    let outnode = match findattr(&configbase, query) {
24        Some(x) => {
25            match findvalue(&x) {
26                Some(y) => y.to_string(),
27                None => return Err(ReadError::NoAttr),
28            }
29        }
30        None => return Err(ReadError::NoAttr),
31    };
32    Ok(outnode.trim().to_string())
33}
34
35pub fn findvalue(node: &SyntaxNode) -> Option<SyntaxNode> {
36    // First find the IDENT node
37    for child in node.children() {
38        if child.kind() != SyntaxKind::NODE_ATTRPATH {
39            let x =
40                Some(rnix::Root::parse(&nixpkgs_fmt::reformat_string(&child.to_string())).syntax());
41            return x;
42        }
43    }
44    None
45}
46
47pub fn getarrvals(f: &str, query: &str) -> Result<Vec<String>, ReadError> {
48    let ast = rnix::Root::parse(f);
49    let configbase = match getcfgbase(&ast.syntax()) {
50        Some(x) => x,
51        None => {
52            return Err(ReadError::ParseError);
53        }
54    };
55    let output = match findattr(&configbase, query) {
56        Some(x) => match getarrvals_aux(&x) {
57            Some(y) => y,
58            None => return Err(ReadError::ArrayError),
59        },
60        None => return Err(ReadError::NoAttr),
61    };
62    Ok(output)
63}
64
65fn getarrvals_aux(node: &SyntaxNode) -> Option<Vec<String>> {
66    for child in node.children() {
67        if child.kind() == rnix::SyntaxKind::NODE_WITH {
68            return getarrvals_aux(&child);
69        }
70        if child.kind() == SyntaxKind::NODE_LIST {
71            let mut out = vec![];
72            for elem in child.children() {
73                out.push(elem.to_string());
74            }
75            return Some(out);
76        }
77    }
78    None
79}
80
81pub fn getwithvalue(f: &str, query: &str) -> Result<Vec<String>, ReadError> {
82    let ast = rnix::Root::parse(f);
83    let configbase = match getcfgbase(&ast.syntax()) {
84        Some(x) => x,
85        None => {
86            return Err(ReadError::ParseError);
87        }
88    };
89    let output = match findattr(&configbase, query) {
90        Some(x) => match getwithval_aux(&x, vec![]) {
91            Some(y) => y,
92            None => return Err(ReadError::NoAttr),
93        },
94        None => return Err(ReadError::NoAttr),
95    };
96    Ok(output)
97}
98
99fn getwithval_aux(node: &SyntaxNode, mut withvals: Vec<String>) -> Option<Vec<String>> {
100    for child in node.children() {
101        if child.kind() == rnix::SyntaxKind::NODE_WITH {
102            for c in child.children() {
103                if c.kind() == rnix::SyntaxKind::NODE_IDENT {
104                    let mut newvals = vec![];
105                    newvals.append(withvals.as_mut());
106                    newvals.push(c.to_string());
107                    match getwithval_aux(&child, newvals.clone()) {
108                        Some(x) => return Some(x),
109                        None => return Some(newvals),
110                    }
111                }
112            }
113        }
114    }
115    None
116}