aboutsummaryrefslogtreecommitdiff
path: root/lib/src/make.rs
blob: 2c33ac889d8490de6b63e4f49b0c529dc299c294 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::{fmt::Write, iter::IntoIterator};

use rnix::{
    types::{self, TokenWrapper, TypedNode},
    SyntaxNode,
};

fn ast_from_text<N: TypedNode>(text: &str) -> N {
    let parse = rnix::parse(text);
    let node = match parse.node().descendants().find_map(N::cast) {
        Some(it) => it,
        None => {
            panic!(
                "Failed to make ast node `{}` from text `{}`",
                std::any::type_name::<N>(),
                text
            )
        }
    };
    node
}

pub fn parenthesize(node: &SyntaxNode) -> types::Paren {
    ast_from_text(&format!("({})", node))
}

pub fn quote(node: &SyntaxNode) -> types::Str {
    ast_from_text(&format!("\"{}\"", node))
}

pub fn unary_not(node: &SyntaxNode) -> types::UnaryOp {
    ast_from_text(&format!("!{}", node))
}

pub fn inherit_stmt<'a>(nodes: impl IntoIterator<Item = &'a types::Ident>) -> types::Inherit {
    let inherited_idents = nodes
        .into_iter()
        .map(|i| i.as_str().to_owned())
        .collect::<Vec<_>>()
        .join(" ");
    ast_from_text(&format!("{{ inherit {}; }}", inherited_idents))
}

pub fn inherit_from_stmt<'a>(
    from: SyntaxNode,
    nodes: impl IntoIterator<Item = &'a types::Ident>,
) -> types::Inherit {
    let inherited_idents = nodes
        .into_iter()
        .map(|i| i.as_str().to_owned())
        .collect::<Vec<_>>()
        .join(" ");
    ast_from_text(&format!("{{ inherit ({}) {}; }}", from, inherited_idents))
}

pub fn attrset(
    inherits: impl IntoIterator<Item = types::Inherit>,
    entries: impl IntoIterator<Item = types::KeyValue>,
    recursive: bool,
) -> types::AttrSet {
    let mut buffer = String::new();

    writeln!(buffer, "{}{{", if recursive { "rec " } else { "" }).unwrap();
    for inherit in inherits.into_iter() {
        writeln!(buffer, "  {}", inherit.node().text()).unwrap();
    }
    for entry in entries.into_iter() {
        writeln!(buffer, "  {}", entry.node().text()).unwrap();
    }
    write!(buffer, "}}").unwrap();

    ast_from_text(&buffer)
}

pub fn select(set: &SyntaxNode, index: &SyntaxNode) -> types::Select {
    ast_from_text(&format!("{}.{}", set, index))
}

pub fn ident(text: &str) -> types::Ident {
    ast_from_text(text)
}

pub fn empty() -> types::Root {
    ast_from_text("")
}

// TODO: make `op` strongly typed here
pub fn binary(lhs: &SyntaxNode, op: &str, rhs: &SyntaxNode) -> types::BinOp {
    ast_from_text(&format!("{} {} {}", lhs, op, rhs))
}

pub fn or_default(set: &SyntaxNode, index: &SyntaxNode, default: &SyntaxNode) -> types::OrDefault {
    ast_from_text(&format!("{}.{} or {}", set, index, default))
}