Implement tools
This commit is contained in:
parent
00d40f4525
commit
6f3e62e555
@ -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,10 +45,13 @@ 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)?;
|
|
||||||
|
|
||||||
expressions.push(expression);
|
if child_node.is_named() {
|
||||||
|
let expression = Expression::from_syntax_node(source, child_node)?;
|
||||||
|
|
||||||
|
expressions.push(expression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expressions)
|
Ok(expressions)
|
||||||
@ -33,16 +59,6 @@ impl AbstractTree for Tool {
|
|||||||
|
|
||||||
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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user