1
0

Implement tools

This commit is contained in:
Jeff 2023-10-21 16:38:20 -04:00
parent 00d40f4525
commit 6f3e62e555
5 changed files with 5389 additions and 4172 deletions

View File

@ -1,17 +1,40 @@
use std::{fs::File, io::Write};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Result, Value, VariableMap}; use crate::{AbstractTree, Error, Expression, Result, Table, Value, VariableMap};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Tool { pub enum Tool {
// General
Assert(Vec<Expression>),
AssertEqual(Vec<Expression>),
Help(Option<Expression>),
Length(Expression),
Output(Vec<Expression>), Output(Vec<Expression>),
OutputError(Vec<Expression>), OutputError(Vec<Expression>),
Assert(Vec<Expression>), // Filesystem
AssertEqual(Vec<Expression>), Append(Vec<Expression>),
Metadata(Vec<Expression>),
Move(Option<Expression>),
Read(Expression),
Remove(Vec<Expression>),
Trash(Vec<Expression>),
Write(Vec<Expression>),
Length(Expression), // Format conversion
FromJson(Expression),
ToJson(Expression),
ToString(Expression),
// Command
Bash(Expression),
Fish(Expression),
Raw(Expression),
Sh(Expression),
Zsh(Expression),
} }
impl AbstractTree for Tool { impl AbstractTree for Tool {
@ -22,27 +45,20 @@ impl AbstractTree for Tool {
let mut expressions = Vec::new(); let mut expressions = Vec::new();
for index in 2..node.child_count() - 1 { for index in 2..node.child_count() - 1 {
let expression_node = node.child(index).unwrap(); let child_node = node.child(index).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?;
if child_node.is_named() {
let expression = Expression::from_syntax_node(source, child_node)?;
expressions.push(expression); expressions.push(expression);
} }
}
Ok(expressions) Ok(expressions)
} }
let tool_node = node.child(1).unwrap(); let tool_node = node.child(1).unwrap();
let tool = match tool_node.kind() { let tool = match tool_node.kind() {
"output" => {
let expressions = parse_expressions(source, node)?;
Tool::Output(expressions)
}
"output_error" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"assert" => { "assert" => {
let expressions = parse_expressions(source, node)?; let expressions = parse_expressions(source, node)?;
@ -53,15 +69,112 @@ impl AbstractTree for Tool {
Tool::AssertEqual(expressions) Tool::AssertEqual(expressions)
} }
"help" => {
let child_node = node.child(2).unwrap();
let expression = if child_node.is_named() {
Some(Expression::from_syntax_node(source, child_node)?)
} else {
None
};
Tool::Help(expression)
}
"length" => { "length" => {
let expression_node = node.child(2).unwrap(); let expression_node = node.child(2).unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
Tool::Length(expression) Tool::Length(expression)
} }
"output" => {
let expressions = parse_expressions(source, node)?;
Tool::Output(expressions)
}
"output_error" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"append" => {
let expressions = parse_expressions(source, node)?;
Error::expect_tool_argument_amount("append", 2, expressions.len())?;
Tool::Append(expressions)
}
"metadata" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"move" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"read" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"remove" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"trash" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"write" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"from_json" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"to_json" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"to_string" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"bash" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"fish" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"raw" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"sh" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
"zsh" => {
let expressions = parse_expressions(source, node)?;
Tool::OutputError(expressions)
}
_ => { _ => {
return Err(Error::UnexpectedSyntaxNode { return Err(Error::UnexpectedSyntaxNode {
expected: "output, output_error, assert, assert_equal or length", expected: "built-in tool",
actual: tool_node.kind(), actual: tool_node.kind(),
location: tool_node.start_position(), location: tool_node.start_position(),
relevant_source: source[tool_node.byte_range()].to_string(), relevant_source: source[tool_node.byte_range()].to_string(),
@ -74,24 +187,6 @@ impl AbstractTree for Tool {
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> { fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
match self { match self {
Tool::Output(expressions) => {
for expression in expressions {
let value = expression.run(source, context)?;
println!("{value}");
}
Ok(Value::Empty)
}
Tool::OutputError(expressions) => {
for expression in expressions {
let value = expression.run(source, context)?;
eprintln!("{value}");
}
Ok(Value::Empty)
}
Tool::Assert(expressions) => { Tool::Assert(expressions) => {
for expression in expressions { for expression in expressions {
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
@ -131,6 +226,59 @@ impl AbstractTree for Tool {
Ok(Value::Integer(length as i64)) Ok(Value::Integer(length as i64))
} }
Tool::Help(_expression) => {
let mut help_table =
Table::new(vec!["tool".to_string(), "description".to_string()]);
help_table.insert(vec![
Value::String("help".to_string()),
Value::String("Get info on tools.".to_string()),
])?;
Ok(Value::Table(help_table))
}
Tool::Output(expressions) => {
for expression in expressions {
let value = expression.run(source, context)?;
println!("{value}");
}
Ok(Value::Empty)
}
Tool::OutputError(expressions) => {
for expression in expressions {
let value = expression.run(source, context)?;
eprintln!("{value}");
}
Ok(Value::Empty)
}
Tool::Append(expressions) => {
let path_expression = expressions[0].run(source, context)?;
let path = path_expression.as_string()?;
let data = expressions[1].run(source, context)?.to_string();
let mut file = File::options().append(true).open(path)?;
file.write(data.as_bytes())?;
Ok(Value::Empty)
}
Tool::Metadata(_) => todo!(),
Tool::Move(_) => todo!(),
Tool::Read(_) => todo!(),
Tool::Remove(_) => todo!(),
Tool::Trash(_) => todo!(),
Tool::Write(_) => todo!(),
Tool::FromJson(_) => todo!(),
Tool::ToJson(_) => todo!(),
Tool::ToString(_) => todo!(),
Tool::Bash(_) => todo!(),
Tool::Fish(_) => todo!(),
Tool::Raw(_) => todo!(),
Tool::Sh(_) => todo!(),
Tool::Zsh(_) => todo!(),
} }
} }
} }

View File

@ -262,16 +262,34 @@ module.exports = grammar({
)), )),
_tool_kind: $ => choice( _tool_kind: $ => choice(
// General
'assert',
'assert_equal',
'help',
'length',
'output', 'output',
'output_error', 'output_error',
'assert', // Filesystem
'assert_equal', 'append',
'metadata',
'length', 'move',
'read', 'read',
'remove',
'trash',
'write', 'write',
// Format conversion
'from_json',
'to_json',
'to_string',
// Command
'bash',
'fish',
'raw',
'sh',
'zsh',
), ),
} }
}); });

View File

@ -1090,14 +1090,6 @@
"_tool_kind": { "_tool_kind": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{
"type": "STRING",
"value": "output"
},
{
"type": "STRING",
"value": "output_error"
},
{ {
"type": "STRING", "type": "STRING",
"value": "assert" "value": "assert"
@ -1106,17 +1098,81 @@
"type": "STRING", "type": "STRING",
"value": "assert_equal" "value": "assert_equal"
}, },
{
"type": "STRING",
"value": "help"
},
{ {
"type": "STRING", "type": "STRING",
"value": "length" "value": "length"
}, },
{
"type": "STRING",
"value": "output"
},
{
"type": "STRING",
"value": "output_error"
},
{
"type": "STRING",
"value": "append"
},
{
"type": "STRING",
"value": "metadata"
},
{
"type": "STRING",
"value": "move"
},
{ {
"type": "STRING", "type": "STRING",
"value": "read" "value": "read"
}, },
{
"type": "STRING",
"value": "remove"
},
{
"type": "STRING",
"value": "trash"
},
{ {
"type": "STRING", "type": "STRING",
"value": "write" "value": "write"
},
{
"type": "STRING",
"value": "from_json"
},
{
"type": "STRING",
"value": "to_json"
},
{
"type": "STRING",
"value": "to_string"
},
{
"type": "STRING",
"value": "bash"
},
{
"type": "STRING",
"value": "fish"
},
{
"type": "STRING",
"value": "raw"
},
{
"type": "STRING",
"value": "sh"
},
{
"type": "STRING",
"value": "zsh"
} }
] ]
} }

View File

@ -713,6 +713,10 @@
"type": "]", "type": "]",
"named": false "named": false
}, },
{
"type": "append",
"named": false
},
{ {
"type": "assert", "type": "assert",
"named": false "named": false
@ -725,6 +729,10 @@
"type": "async", "type": "async",
"named": false "named": false
}, },
{
"type": "bash",
"named": false
},
{ {
"type": "else", "type": "else",
"named": false "named": false
@ -745,6 +753,10 @@
"type": "find", "type": "find",
"named": false "named": false
}, },
{
"type": "fish",
"named": false
},
{ {
"type": "float", "type": "float",
"named": true "named": true
@ -757,10 +769,18 @@
"type": "from", "type": "from",
"named": false "named": false
}, },
{
"type": "from_json",
"named": false
},
{ {
"type": "function", "type": "function",
"named": false "named": false
}, },
{
"type": "help",
"named": false
},
{ {
"type": "identifier", "type": "identifier",
"named": true "named": true
@ -789,6 +809,14 @@
"type": "length", "type": "length",
"named": false "named": false
}, },
{
"type": "metadata",
"named": false
},
{
"type": "move",
"named": false
},
{ {
"type": "output", "type": "output",
"named": false "named": false
@ -797,6 +825,10 @@
"type": "output_error", "type": "output_error",
"named": false "named": false
}, },
{
"type": "raw",
"named": false
},
{ {
"type": "read", "type": "read",
"named": false "named": false
@ -809,6 +841,10 @@
"type": "select", "type": "select",
"named": false "named": false
}, },
{
"type": "sh",
"named": false
},
{ {
"type": "string", "type": "string",
"named": true "named": true
@ -817,10 +853,22 @@
"type": "table", "type": "table",
"named": false "named": false
}, },
{
"type": "to_json",
"named": false
},
{
"type": "to_string",
"named": false
},
{ {
"type": "transform", "type": "transform",
"named": false "named": false
}, },
{
"type": "trash",
"named": false
},
{ {
"type": "true", "type": "true",
"named": false "named": false
@ -837,6 +885,10 @@
"type": "write", "type": "write",
"named": false "named": false
}, },
{
"type": "zsh",
"named": false
},
{ {
"type": "{", "type": "{",
"named": false "named": false

File diff suppressed because it is too large Load Diff