mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 22:50:14 +02:00
Plugin with evaluated call (#393)
* plugin trait * impl of trait * record and absolute path * plugin example crate * clippy error * correcting cargo * evaluated call for plugin
This commit is contained in:
@ -6,10 +6,9 @@ edition = "2018"
|
||||
[dependencies]
|
||||
miette = "3.0.0"
|
||||
thiserror = "1.0.29"
|
||||
nu-protocol = { path = "../nu-protocol"}
|
||||
nu-plugin = { path = "../nu-plugin", optional=true}
|
||||
serde_json = "1.0"
|
||||
nu-path = {path = "../nu-path"}
|
||||
nu-protocol = { path = "../nu-protocol"}
|
||||
|
||||
[features]
|
||||
plugin = ["nu-plugin"]
|
||||
plugin = []
|
||||
|
@ -191,7 +191,7 @@ pub enum ParseError {
|
||||
#[diagnostic(code(nu::parser::export_not_found), url(docsrs))]
|
||||
FileNotFound(String),
|
||||
|
||||
#[error("Plugin error")]
|
||||
#[diagnostic(code(nu::parser::plugin_error), url(docsrs))]
|
||||
PluginError(String),
|
||||
#[error("{0}")]
|
||||
#[diagnostic()]
|
||||
LabeledError(String, String, #[label("{1}")] Span),
|
||||
}
|
||||
|
@ -9,9 +9,6 @@ use nu_protocol::{
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
use nu_plugin::plugin::{get_signature, PluginDeclaration};
|
||||
|
||||
use crate::{
|
||||
lex, lite_parse,
|
||||
parser::{
|
||||
@ -1091,6 +1088,9 @@ pub fn parse_plugin(
|
||||
working_set: &mut StateWorkingSet,
|
||||
spans: &[Span],
|
||||
) -> (Statement, Option<ParseError>) {
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
use nu_path::canonicalize;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
let name = working_set.get_span_contents(spans[0]);
|
||||
@ -1117,51 +1117,55 @@ pub fn parse_plugin(
|
||||
)),
|
||||
2 => {
|
||||
let name_expr = working_set.get_span_contents(spans[1]);
|
||||
if let Ok(filename) = String::from_utf8(name_expr.to_vec()) {
|
||||
let source_file = Path::new(&filename);
|
||||
|
||||
if source_file.exists() & source_file.is_file() {
|
||||
// get signature from plugin
|
||||
match get_signature(source_file) {
|
||||
Err(err) => Some(ParseError::PluginError(format!("{}", err))),
|
||||
Ok(signatures) => {
|
||||
for signature in signatures {
|
||||
// create plugin command declaration (need struct impl Command)
|
||||
// store declaration in working set
|
||||
let plugin_decl =
|
||||
PluginDeclaration::new(filename.clone(), signature);
|
||||
|
||||
working_set.add_plugin_decl(Box::new(plugin_decl));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
String::from_utf8(name_expr.to_vec())
|
||||
.map_err(|_| ParseError::NonUtf8(spans[1]))
|
||||
.and_then(|name| {
|
||||
canonicalize(&name).map_err(|e| ParseError::FileNotFound(e.to_string()))
|
||||
})
|
||||
.and_then(|path| {
|
||||
if path.exists() & path.is_file() {
|
||||
working_set.add_plugin_signature(path, None);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ParseError::FileNotFound(format!("{:?}", path)))
|
||||
}
|
||||
} else {
|
||||
Some(ParseError::FileNotFound(filename))
|
||||
}
|
||||
} else {
|
||||
Some(ParseError::NonUtf8(spans[1]))
|
||||
}
|
||||
})
|
||||
.err()
|
||||
}
|
||||
3 => {
|
||||
let filename = working_set.get_span_contents(spans[1]);
|
||||
let filename_slice = working_set.get_span_contents(spans[1]);
|
||||
let signature = working_set.get_span_contents(spans[2]);
|
||||
let mut path = PathBuf::new();
|
||||
|
||||
if let Ok(filename) = String::from_utf8(filename.to_vec()) {
|
||||
if let Ok(signature) = serde_json::from_slice::<Signature>(signature) {
|
||||
let plugin_decl = PluginDeclaration::new(filename, signature);
|
||||
working_set.add_plugin_decl(Box::new(plugin_decl));
|
||||
|
||||
None
|
||||
} else {
|
||||
Some(ParseError::PluginError(
|
||||
"unable to deserialize signature".into(),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Some(ParseError::NonUtf8(spans[1]))
|
||||
}
|
||||
String::from_utf8(filename_slice.to_vec())
|
||||
.map_err(|_| ParseError::NonUtf8(spans[1]))
|
||||
.and_then(|name| {
|
||||
PathBuf::from_str(name.as_str()).map_err(|_| {
|
||||
ParseError::InternalError(
|
||||
format!("Unable to create path from string {}", name),
|
||||
spans[0],
|
||||
)
|
||||
})
|
||||
})
|
||||
.and_then(|path_inner| {
|
||||
path = path_inner;
|
||||
serde_json::from_slice::<Signature>(signature).map_err(|_| {
|
||||
ParseError::LabeledError(
|
||||
"Signature deserialization error".into(),
|
||||
"unable to deserialize signature".into(),
|
||||
spans[0],
|
||||
)
|
||||
})
|
||||
})
|
||||
.and_then(|signature| {
|
||||
if path.exists() & path.is_file() {
|
||||
working_set.add_plugin_signature(path, Some(signature));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ParseError::FileNotFound(format!("{:?}", path)))
|
||||
}
|
||||
})
|
||||
.err()
|
||||
}
|
||||
_ => {
|
||||
let span = spans[3..].iter().fold(spans[3], |acc, next| Span {
|
||||
|
Reference in New Issue
Block a user