mirror of
https://github.com/nushell/nushell.git
synced 2025-07-01 07:00:37 +02:00
Plugin repeated (#417)
* not repeated decl in file and help * implemented heashmap for repeated * sorted scope commands
This commit is contained in:
@ -48,7 +48,7 @@ pub trait Command: Send + Sync + CommandClone {
|
||||
self.name().contains(' ')
|
||||
}
|
||||
|
||||
// Is a plugin command
|
||||
// Is a plugin command (returns plugin's name if yes)
|
||||
fn is_plugin(&self) -> Option<&PathBuf> {
|
||||
None
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use std::{
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
use std::path::PathBuf;
|
||||
|
||||
// Tells whether a decl etc. is visible or not
|
||||
#[derive(Debug, Clone)]
|
||||
struct Visibility {
|
||||
@ -197,17 +198,14 @@ impl EngineState {
|
||||
last.visibility.merge_with(first.visibility);
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
if !delta.plugin_decls.is_empty() {
|
||||
for decl in delta.plugin_decls {
|
||||
let name = decl.name().as_bytes().to_vec();
|
||||
self.decls.push_back(decl);
|
||||
let decl_id = self.decls.len() - 1;
|
||||
if delta.plugins_changed {
|
||||
let result = self.update_plugin_file();
|
||||
|
||||
last.decls.insert(name, decl_id);
|
||||
last.visibility.use_decl_id(&decl_id);
|
||||
if result.is_ok() {
|
||||
delta.plugins_changed = false;
|
||||
}
|
||||
|
||||
return self.update_plugin_file();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +228,7 @@ impl EngineState {
|
||||
let file_name = path.to_str().expect("path should be a str");
|
||||
|
||||
let line = serde_json::to_string_pretty(&decl.signature())
|
||||
.map(|signature| format!("register {} {}\n", file_name, signature))
|
||||
.map(|signature| format!("register {} {}\n\n", file_name, signature))
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
|
||||
plugin_file
|
||||
@ -250,6 +248,40 @@ impl EngineState {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn update_plugin_file_1(&self) -> Result<(), ShellError> {
|
||||
use std::io::Write;
|
||||
|
||||
// Updating the signatures plugin file with the added signatures
|
||||
if let Some(plugin_path) = &self.plugin_signatures {
|
||||
// Always creating the file which will erase previous signatures
|
||||
let mut plugin_file = std::fs::File::create(plugin_path.as_path())
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
|
||||
// Plugin definitions with parsed signature
|
||||
for decl in self.plugin_decls() {
|
||||
// A successful plugin registration already includes the plugin filename
|
||||
// No need to check the None option
|
||||
let path = decl.is_plugin().expect("plugin should have file name");
|
||||
let file_name = path.to_str().expect("path should be a str");
|
||||
|
||||
let line = serde_json::to_string_pretty(&decl.signature())
|
||||
.map(|signature| format!("register {} {}\n\n", file_name, signature))
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
|
||||
plugin_file
|
||||
.write_all(line.as_bytes())
|
||||
.map_err(|err| ShellError::PluginFailedToLoad(err.to_string()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ShellError::PluginFailedToLoad(
|
||||
"Plugin file not found".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_files(&self) -> usize {
|
||||
self.files.len()
|
||||
}
|
||||
@ -311,8 +343,21 @@ impl EngineState {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn plugin_decls(&self) -> impl Iterator<Item = &Box<dyn Command + 'static>> {
|
||||
self.decls.iter().filter(|decl| decl.is_plugin().is_some())
|
||||
let mut unique_plugin_decls = HashMap::new();
|
||||
|
||||
// Make sure there are no duplicate decls: Newer one overwrites the older one
|
||||
for decl in self.decls.iter().filter(|d| d.is_plugin().is_some()) {
|
||||
unique_plugin_decls.insert(decl.name(), decl);
|
||||
}
|
||||
|
||||
let mut plugin_decls: Vec<(&str, &Box<dyn Command>)> =
|
||||
unique_plugin_decls.into_iter().collect();
|
||||
|
||||
// Sort the plugins by name so we don't end up with a random plugin file each time
|
||||
plugin_decls.sort_by(|a, b| a.0.cmp(b.0));
|
||||
plugin_decls.into_iter().map(|(_, decl)| decl)
|
||||
}
|
||||
|
||||
pub fn find_overlay(&self, name: &[u8]) -> Option<OverlayId> {
|
||||
@ -423,6 +468,8 @@ impl EngineState {
|
||||
}
|
||||
|
||||
output.sort_by(|a, b| a.0.name.cmp(&b.0.name));
|
||||
output.dedup_by(|a, b| a.0.name.cmp(&b.0.name).is_eq());
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
@ -519,9 +566,7 @@ pub struct StateDelta {
|
||||
overlays: Vec<Overlay>, // indexed by OverlayId
|
||||
pub scope: Vec<ScopeFrame>,
|
||||
#[cfg(feature = "plugin")]
|
||||
pub plugin_signatures: Vec<(PathBuf, Option<Signature>)>,
|
||||
#[cfg(feature = "plugin")]
|
||||
plugin_decls: Vec<Box<dyn Command>>,
|
||||
plugins_changed: bool, // marks whether plugin file should be updated
|
||||
}
|
||||
|
||||
impl StateDelta {
|
||||
@ -562,9 +607,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||
overlays: vec![],
|
||||
scope: vec![ScopeFrame::new()],
|
||||
#[cfg(feature = "plugin")]
|
||||
plugin_signatures: vec![],
|
||||
#[cfg(feature = "plugin")]
|
||||
plugin_decls: vec![],
|
||||
plugins_changed: false,
|
||||
},
|
||||
permanent_state,
|
||||
}
|
||||
@ -633,20 +676,8 @@ impl<'a> StateWorkingSet<'a> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn add_plugin_decls(&mut self, decls: Vec<Box<dyn Command>>) {
|
||||
for decl in decls {
|
||||
self.delta.plugin_decls.push(decl);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn add_plugin_signature(&mut self, path: PathBuf, signature: Option<Signature>) {
|
||||
self.delta.plugin_signatures.push((path, signature));
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn get_signatures(&self) -> impl Iterator<Item = &(PathBuf, Option<Signature>)> {
|
||||
self.delta.plugin_signatures.iter()
|
||||
pub fn mark_plugins_file_dirty(&mut self) {
|
||||
self.delta.plugins_changed = true;
|
||||
}
|
||||
|
||||
pub fn merge_predecl(&mut self, name: &[u8]) -> Option<DeclId> {
|
||||
|
Reference in New Issue
Block a user