Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/node insertion #17

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ anyhow = "1.0"
rust-nix-templater = { git = "https://github.com/yusdacra/rust-nix-templater.git", branch = "master" }
either = "1.6.1"
nixpkgs-fmt = "1.1.0"
regex = "1"

[package.metadata.nix]
app = true
Expand Down
14 changes: 3 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use nixpkgs_fmt::reformat_node;
use parser::file::{filename_to_node, write_to_node};
use parser::input_utils::{merge_attr_sets, Input};
use parser::utils::{get_node_idx, remove_input, search_for_attr, NixNode};
use rowan::GreenNode;
use rowan::NodeOrToken;
use rowan::SyntaxNode;
use rowan::{GreenNode, NodeOrToken, SyntaxNode};
use user::*;

struct ActionStack {
Expand All @@ -28,9 +26,7 @@ impl ActionStack {
}

fn push_seq(&mut self, actions: impl IntoIterator<Item = UserAction>) {
actions
.into_iter()
.for_each(|action| self.inner.push(action))
self.inner.extend(actions.into_iter());
}

fn pop(&mut self) -> UserAction {
Expand Down Expand Up @@ -137,11 +133,7 @@ fn main() {
UserPrompt::Bool(b) => match cur_action {
UserAction::IsInputFlake => {
action_stack.pop();
let mut i = user_data
.new_input
.as_ref()
.and_then(|x: &Input| Some(x.clone()))
.unwrap_or_default();
let mut i = user_data.new_input.as_ref().cloned().unwrap_or_default();
i.is_flake = Some(SyntaxStructure::Bool(b));
user_data.new_input = Some(i);
}
Expand Down
8 changes: 8 additions & 0 deletions src/parser/body.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Input {
pub(crate) name: Option<SyntaxStructure>,
pub(crate) url: Option<SyntaxStructure>,
pub(crate) is_flake: Option<SyntaxStructure>,
}


96 changes: 65 additions & 31 deletions src/parser/input_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::SmlStr;
use rnix::{NixLanguage, SyntaxKind::*};
use rowan::{api::SyntaxNode, GreenNode, GreenNodeBuilder, GreenToken, Language, NodeOrToken};
use std::string::ToString;
use NodeOrToken::{Node, Token};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
use rowan::{api::SyntaxNode, GreenNode, GreenNodeBuilder, GreenToken, Language, NodeOrToken};
use std::string::ToString;
use NodeOrToken::{Node, Token};
use rowan::{api::SyntaxNode, GreenNode, GreenNodeBuilder, GreenToken, Language, NodeOrToken::{self, Node, Token}};
use std::string::ToString;


#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Input {
Expand All @@ -13,7 +14,7 @@ pub struct Input {

pub fn wrap_root(node: GreenNode) -> NixNode {
let kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(NODE_ROOT);
let root = GreenNode::new(kind, vec![NodeOrToken::Node(node)]);
let root = GreenNode::new(kind, vec![Node(node)]);
SyntaxNode::new_root(root)
}

Expand Down Expand Up @@ -48,40 +49,34 @@ pub fn new_bool_literal(b: bool) -> GreenNode {
node.finish()
}

pub fn new_key(s: String) -> GreenNode {
let kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(NODE_KEY);
let children = vec![NodeOrToken::Node(new_string(s))];
GreenNode::new(kind, children)
}

pub fn new_key_value(key: GreenNode, value: GreenNode) -> GreenNode {
let kind = NixLanguage::kind_to_raw(NODE_KEY_VALUE);
let assign_kind = NixLanguage::kind_to_raw(TOKEN_ASSIGN);
let whitespace_kind = NixLanguage::kind_to_raw(TOKEN_WHITESPACE);
let semicolon_kind = NixLanguage::kind_to_raw(TOKEN_SEMICOLON);
let children = vec![
NodeOrToken::Node(key),
NodeOrToken::Token(GreenToken::new(whitespace_kind, " ")),
NodeOrToken::Token(GreenToken::new(assign_kind, "=")),
NodeOrToken::Token(GreenToken::new(whitespace_kind, " ")),
NodeOrToken::Node(value),
NodeOrToken::Token(GreenToken::new(semicolon_kind, ";")),
NodeOrToken::Token(GreenToken::new(whitespace_kind, "\n")),
Node(key),
Token(GreenToken::new(whitespace_kind, " ")),
Token(GreenToken::new(assign_kind, "=")),
Token(GreenToken::new(whitespace_kind, " ")),
Node(value),
Token(GreenToken::new(semicolon_kind, ";")),
Token(GreenToken::new(whitespace_kind, "\n")),
];
GreenNode::new(kind, children)
}

pub fn merge_attr_sets(a1: GreenNode, a2: GreenNode) -> GreenNode {
let whitespace_kind = NixLanguage::kind_to_raw(TOKEN_WHITESPACE);
let token = GreenToken::new(whitespace_kind, "\n");
let delimiter = NodeOrToken::Token(token);
let delimiter = Token(token);
let mut nodes = a2
.children()
.into_iter()
.filter(|node| node.kind() == NixLanguage::kind_to_raw(NODE_KEY_VALUE))
.map(|x| match x {
NodeOrToken::Node(x) => NodeOrToken::Node(x.clone()),
NodeOrToken::Token(x) => NodeOrToken::Token(x.clone()),
Node(x) => Node(x.clone()),
Token(x) => Token(x.clone()),
})
.flat_map(|x| vec![delimiter.clone(), x])
.collect::<Vec<_>>();
Expand All @@ -99,26 +94,17 @@ pub fn merge_attr_sets(a1: GreenNode, a2: GreenNode) -> GreenNode {
pub fn new_attr_set(attr_pairs: Vec<(GreenNode, GreenNode)>) -> GreenNode {
let pairs: Vec<NodeOrToken<_, _>> = attr_pairs
.iter()
.map(move |(k, v)| NodeOrToken::Node(new_key_value(k.clone(), v.clone())))
.map(move |(k, v)| Node(new_key_value(k.clone(), v.clone())))
.collect::<Vec<_>>();
let open_curly_kind = NixLanguage::kind_to_raw(TOKEN_CURLY_B_OPEN);
let close_curly_kind = NixLanguage::kind_to_raw(TOKEN_CURLY_B_CLOSE);
let attr_set_kind = NixLanguage::kind_to_raw(NODE_ATTR_SET);
let whitespace_kind = NixLanguage::kind_to_raw(TOKEN_WHITESPACE);
let mut token_vec = Vec::new();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: replace the complete following stuff with this:

    let mut token_vec = Vec::new();
    let mut tokens = vec![
        Token(GreenToken::new(open_curly_kind, "{")),
        Token(GreenToken::new(whitespace_kind, "\n")),
    ];
    tokens.extend(attr_pairs
        .into_iter()
        .map(move |(k, v)| Node(new_key_value(k, v))));
    tokens.push(Token(GreenToken::new(close_curly_kind, "}")));

token_vec.push(vec![NodeOrToken::Token(GreenToken::new(
open_curly_kind,
"{",
))]);
token_vec.push(vec![NodeOrToken::Token(GreenToken::new(
whitespace_kind,
"\n",
))]);
token_vec.push(vec![Token(GreenToken::new(open_curly_kind, "{"))]);
token_vec.push(vec![Token(GreenToken::new(whitespace_kind, "\n"))]);
token_vec.push(pairs);
token_vec.push(vec![NodeOrToken::Token(GreenToken::new(
close_curly_kind,
"}",
))]);
token_vec.push(vec![Token(GreenToken::new(close_curly_kind, "}"))]);
let tokens = token_vec
.iter()
.flatten()
Expand All @@ -127,8 +113,55 @@ pub fn new_attr_set(attr_pairs: Vec<(GreenNode, GreenNode)>) -> GreenNode {
GreenNode::new(attr_set_kind, tokens)
}

pub(crate) struct Key {
val: SmlStr,
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a simple newtype struct would be a better fit, unless you intend to add more fields.

Suggested change
pub(crate) struct Key {
val: SmlStr,
}
pub(crate) struct Key(SmlStr);


impl From<Key> for GreenNode {
fn from(item: Key) -> Self {
let kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(NODE_KEY);
let children = vec![Node(new_string(item.val.to_string()))];
GreenNode::new(kind, children)
}
}

pub(crate) struct StringLiteral {
val: SmlStr,
}

impl From<StringLiteral> for GreenNode {
fn from(item: StringLiteral) -> Self {
let mut node = GreenNodeBuilder::new();
let kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(NODE_STRING);
node.start_node(kind);
let start_string_kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(TOKEN_STRING_START);
node.token(start_string_kind, "\"");
let string_content: rowan::SyntaxKind = NixLanguage::kind_to_raw(TOKEN_STRING_CONTENT);
node.token(string_content, &item.val.to_string());
let end_string_kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(TOKEN_STRING_END);
node.token(end_string_kind, "\"");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(NODE_STRING);
node.start_node(kind);
let start_string_kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(TOKEN_STRING_START);
node.token(start_string_kind, "\"");
let string_content: rowan::SyntaxKind = NixLanguage::kind_to_raw(TOKEN_STRING_CONTENT);
node.token(string_content, &item.val.to_string());
let end_string_kind: rowan::SyntaxKind = NixLanguage::kind_to_raw(TOKEN_STRING_END);
node.token(end_string_kind, "\"");
node.start_node(NixLanguage::kind_to_raw(NODE_STRING));
node.token(NixLanguage::kind_to_raw(TOKEN_STRING_START), "\"");
node.token(NixLanguage::kind_to_raw(TOKEN_STRING_CONTENT), &item.val.to_string());
node.token(NixLanguage::kind_to_raw(TOKEN_STRING_END), "\"");

node.finish_node();
node.finish()
}
}

pub(crate) struct Bool {
val: bool,
}

pub(crate) struct KeyValue {
key: Key,
val: StringLiteral,
}

/// rnix::ParsedType is not good for node/creation since it literally wraps
/// SyntaxNode. This is a solution for that
/// This isn't quite a bijection, but we should make a tryFrom implementation
/// both ways (bijection) that fails if SyntaxStructure does not have an analogue ParsedType
/// FIXME this should be nearly trivial given the from implementation with greennode
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum SyntaxStructure {
KeyValue(Box<SyntaxStructure>, Box<SyntaxStructure>),
Key(SmlStr),
StringLiteral(SmlStr),
Bool(bool),
Expand All @@ -137,9 +170,10 @@ pub(crate) enum SyntaxStructure {
impl From<SyntaxStructure> for GreenNode {
fn from(ss: SyntaxStructure) -> Self {
match ss {
SyntaxStructure::Key(k) => new_key(k.to_string()),
SyntaxStructure::Key(k) => (Key { val: k }).into(),
SyntaxStructure::StringLiteral(sl) => new_string(sl.to_string()),
SyntaxStructure::Bool(b) => new_bool_literal(b),
SyntaxStructure::KeyValue(key, value) => new_key_value((*key).into(), (*value).into()),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod file;
pub mod utils;
// TODO better name
pub mod input_utils;
pub mod url;

#[cfg(test)]
mod utils_tests;
Expand Down
5 changes: 5 additions & 0 deletions src/parser/url.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use regex::Regex;

pub fn translate_url(s: String) {
let re = Regex::new(r"^(github|gitlab)$").unwrap();
}