Add script types

Signed-off-by: trivernis <trivernis@protonmail.com>
init-main
trivernis 2 years ago
parent 0c7bbe6034
commit f6ce57b5f6
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

2
Cargo.lock generated

@ -3277,6 +3277,8 @@ version = "0.1.0"
dependencies = [
"clap",
"color-eyre",
"lazy_static",
"miette 5.3.0",
"nu-cli",
"nu-command",
"nu-protocol",

@ -7,7 +7,7 @@ edition = "2021"
name = "tourmaline"
[[bin]]
name = "tml"
name = "trl"
path = "src/main.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -15,6 +15,8 @@ path = "src/main.rs"
[dependencies]
clap = "3.2.22"
color-eyre = "0.6.2"
lazy_static = "1.4.0"
miette = "5.3.0"
nu-cli = "0.68.1"
nu-command = "0.68.1"
nu-protocol = "0.68.1"

@ -0,0 +1,22 @@
use std::path::PathBuf;
use miette::Diagnostic;
use thiserror::Error;
pub type AppResult<T> = std::result::Result<T, AppError>;
#[derive(Error, Diagnostic, Debug)]
pub enum AppError {
#[error("Error while evaluating nu script")]
#[diagnostic()]
Nu(miette::Error),
#[error("Could not find the script file {0}")]
ScriptNotFound(PathBuf),
}
impl From<miette::Error> for AppError {
fn from(e: miette::Error) -> Self {
Self::Nu(e)
}
}

@ -1,7 +1,38 @@
use scripting::executor::NuExecutor;
use error::AppResult;
use scripting::{
loader::ScriptLoader,
script::{Script, ScriptArgs},
};
mod scripting;
pub mod error;
pub(crate) mod scripting;
pub(crate) mod utils;
pub fn test_execute(script: String) {
NuExecutor::new(script).execute();
pub struct TestScript;
impl Script for TestScript {
type Args = TestScriptArgs;
fn get_name() -> &'static str {
"test.nu"
}
}
pub struct TestScriptArgs {
pub msg: String,
}
impl ScriptArgs for TestScriptArgs {
fn get_args(self) -> Vec<String> {
vec![self.msg]
}
}
pub fn test_execute() -> AppResult<()> {
let loader = ScriptLoader::new();
let test_script = loader.load::<TestScript>()?;
test_script.execute(TestScriptArgs {
msg: "'Hello World'".to_string(),
})
}

@ -1,6 +1,4 @@
use std::env::args;
fn main() {
let script_path = args().skip(1).next().unwrap();
tourmaline::test_execute(script_path);
color_eyre::install().unwrap();
tourmaline::test_execute().unwrap();
}

@ -1,6 +1,10 @@
#![allow(unused)]
use std::path::Path;
use nu_protocol::{PipelineData, Span};
use crate::error::{AppError, AppResult};
/// An executor for nu scripts
pub struct NuExecutor {
script_path: String,
@ -8,9 +12,9 @@ pub struct NuExecutor {
}
impl NuExecutor {
pub fn new(script_path: String) -> Self {
pub fn new<P: AsRef<Path>>(script_path: P) -> Self {
Self {
script_path,
script_path: script_path.as_ref().to_string_lossy().into_owned(),
args: Vec::new(),
}
}
@ -28,7 +32,7 @@ impl NuExecutor {
self
}
pub fn execute(&mut self) {
pub fn execute(&mut self) -> AppResult<()> {
let mut engine_state = nu_command::create_default_context();
let mut stack = nu_protocol::engine::Stack::new();
let input = PipelineData::new(Span::new(0, 0));
@ -43,6 +47,6 @@ impl NuExecutor {
input,
false,
)
.unwrap();
.map_err(AppError::from)
}
}

@ -0,0 +1,30 @@
use std::path::PathBuf;
use crate::error::{AppError, AppResult};
use super::script::{NuScript, Script};
/// A loader for nu script files
pub struct ScriptLoader {
base_dir: PathBuf,
}
impl ScriptLoader {
/// Creates a new script loader with the default config dir
pub fn new() -> Self {
Self {
base_dir: crate::utils::SCRIPT_PATH.to_owned(),
}
}
/// Loads the given script file
pub fn load<S: Script>(&self) -> AppResult<NuScript<S>> {
let script_path = self.base_dir.join(S::get_name());
if !script_path.exists() {
Err(AppError::ScriptNotFound(script_path))
} else {
Ok(NuScript::new(script_path))
}
}
}

@ -1,2 +1,3 @@
pub mod executor;
mod loader;
pub mod loader;
pub mod script;

@ -0,0 +1,44 @@
use std::{marker::PhantomData, path::PathBuf};
use crate::error::AppResult;
use super::executor::NuExecutor;
/// A trait implemented for a given nu script type to
/// associate arguments
pub trait Script {
type Args: ScriptArgs;
/// Returns the (expected) name of the script file
/// This function is used by the loader to load the associated file
/// The name needs to include the file extension
fn get_name() -> &'static str;
}
/// Script arguments that can be collected in a Vec to
/// be passed to the script
pub trait ScriptArgs {
fn get_args(self) -> Vec<String>;
}
/// A nu script instance that can be executed
pub struct NuScript<S: Script> {
path: PathBuf,
__phantom: PhantomData<S>,
}
impl<S: Script> NuScript<S> {
pub(crate) fn new(path: PathBuf) -> Self {
Self {
path,
__phantom: PhantomData,
}
}
/// Executes the script with the given args
pub fn execute(&self, args: S::Args) -> AppResult<()> {
NuExecutor::new(&self.path)
.add_args(args.get_args())
.execute()
}
}

@ -0,0 +1,8 @@
use std::path::PathBuf;
const CONFIG_DIR: &str = "/etc";
lazy_static::lazy_static! {
pub static ref CFG_PATH: PathBuf = PathBuf::from(CONFIG_DIR).join("tourmaline");
pub static ref SCRIPT_PATH: PathBuf = CFG_PATH.join("scripts");
}
Loading…
Cancel
Save