mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 01:35:02 +02:00
Overlay keep (#5629)
* Allow env vars to be kept from removed overlay * Rename --keep to --keep-custom; Add new test * Rename some symbols * (WIP) Start working on --keep for defs and aliases * Fix decls/aliases not melting properly * Use id instead of the whole cloned overlay * Rewrite overlay remove for no reason Doesn't fix the bug but at least looks better. * Rename variable * Fix adding overlay env vars * Add more tests; Fmt + Clippy
This commit is contained in:
@ -1692,6 +1692,56 @@ impl<'a> StateWorkingSet<'a> {
|
||||
.expect("internal error: missing added overlay")
|
||||
}
|
||||
|
||||
/// Collect all decls that belong to an overlay
|
||||
pub fn decls_of_overlay(&self, name: &[u8]) -> HashMap<Vec<u8>, DeclId> {
|
||||
let mut result = HashMap::new();
|
||||
|
||||
if let Some(overlay_id) = self.permanent_state.find_overlay(name) {
|
||||
let overlay_frame = self.permanent_state.get_overlay(overlay_id);
|
||||
|
||||
for (decl_name, decl_id) in &overlay_frame.decls {
|
||||
result.insert(decl_name.to_owned(), *decl_id);
|
||||
}
|
||||
}
|
||||
|
||||
for scope_frame in self.delta.scope.iter() {
|
||||
if let Some(overlay_id) = scope_frame.find_overlay(name) {
|
||||
let overlay_frame = scope_frame.get_overlay(overlay_id);
|
||||
|
||||
for (decl_name, decl_id) in &overlay_frame.decls {
|
||||
result.insert(decl_name.to_owned(), *decl_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Collect all aliases that belong to an overlay
|
||||
pub fn aliases_of_overlay(&self, name: &[u8]) -> HashMap<Vec<u8>, DeclId> {
|
||||
let mut result = HashMap::new();
|
||||
|
||||
if let Some(overlay_id) = self.permanent_state.find_overlay(name) {
|
||||
let overlay_frame = self.permanent_state.get_overlay(overlay_id);
|
||||
|
||||
for (alias_name, alias_id) in &overlay_frame.aliases {
|
||||
result.insert(alias_name.to_owned(), *alias_id);
|
||||
}
|
||||
}
|
||||
|
||||
for scope_frame in self.delta.scope.iter() {
|
||||
if let Some(overlay_id) = scope_frame.find_overlay(name) {
|
||||
let overlay_frame = scope_frame.get_overlay(overlay_id);
|
||||
|
||||
for (alias_name, alias_id) in &overlay_frame.aliases {
|
||||
result.insert(alias_name.to_owned(), *alias_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn add_overlay(
|
||||
&mut self,
|
||||
name: Vec<u8>,
|
||||
@ -1712,7 +1762,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||
} else {
|
||||
last_scope_frame
|
||||
.overlays
|
||||
.push((name, OverlayFrame::from(origin)));
|
||||
.push((name, OverlayFrame::from_origin(origin)));
|
||||
last_scope_frame.overlays.len() - 1
|
||||
};
|
||||
|
||||
@ -1727,33 +1777,43 @@ impl<'a> StateWorkingSet<'a> {
|
||||
self.use_aliases(aliases);
|
||||
}
|
||||
|
||||
pub fn remove_overlay(&mut self, name: &[u8]) {
|
||||
pub fn remove_overlay(&mut self, name: &[u8], keep_custom: bool) {
|
||||
let last_scope_frame = self.delta.last_scope_frame_mut();
|
||||
|
||||
let removed_overlay = if let Some(overlay_id) = last_scope_frame.find_overlay(name) {
|
||||
let removed_overlay_origin = if let Some(overlay_id) = last_scope_frame.find_overlay(name) {
|
||||
last_scope_frame
|
||||
.active_overlays
|
||||
.retain(|id| id != &overlay_id);
|
||||
|
||||
Some(last_scope_frame.get_overlay(overlay_id).clone())
|
||||
Some(last_scope_frame.get_overlay(overlay_id).origin)
|
||||
} else {
|
||||
self.permanent_state
|
||||
.find_overlay(name)
|
||||
.map(|id| self.permanent_state.get_overlay(id).clone())
|
||||
.map(|id| self.permanent_state.get_overlay(id).origin)
|
||||
};
|
||||
|
||||
if removed_overlay.is_some() {
|
||||
if let Some(module_id) = removed_overlay_origin {
|
||||
last_scope_frame.removed_overlays.push(name.to_owned());
|
||||
|
||||
if keep_custom {
|
||||
let origin_module = self.get_module(module_id);
|
||||
|
||||
let decls = self
|
||||
.decls_of_overlay(name)
|
||||
.into_iter()
|
||||
.filter(|(n, _)| !origin_module.has_decl(n))
|
||||
.collect();
|
||||
|
||||
let aliases = self
|
||||
.aliases_of_overlay(name)
|
||||
.into_iter()
|
||||
.filter(|(n, _)| !origin_module.has_alias(n))
|
||||
.collect();
|
||||
|
||||
self.use_decls(decls);
|
||||
self.use_aliases(aliases);
|
||||
}
|
||||
}
|
||||
|
||||
// if let Some(module) = original_module {
|
||||
// let last_overlay_name = self.last_overlay_name().to_owned();
|
||||
|
||||
// if let Some(overlay) = removed_overlay {
|
||||
// let (diff_decls, diff_aliases) = overlay.diff(&module);
|
||||
// self.add_overlay(last_overlay_name, diff_decls, diff_aliases);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn render(self) -> StateDelta {
|
||||
|
@ -101,7 +101,7 @@ impl ScopeFrame {
|
||||
|
||||
pub fn with_empty_overlay(name: Vec<u8>, origin: ModuleId) -> Self {
|
||||
Self {
|
||||
overlays: vec![(name, OverlayFrame::from(origin))],
|
||||
overlays: vec![(name, OverlayFrame::from_origin(origin))],
|
||||
active_overlays: vec![0],
|
||||
removed_overlays: vec![],
|
||||
predecls: HashMap::new(),
|
||||
@ -195,8 +195,6 @@ impl ScopeFrame {
|
||||
}
|
||||
}
|
||||
|
||||
// type OverlayDiff = (Vec<(Vec<u8>, DeclId)>, Vec<(Vec<u8>, AliasId)>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OverlayFrame {
|
||||
pub vars: HashMap<Vec<u8>, VarId>,
|
||||
@ -209,7 +207,7 @@ pub struct OverlayFrame {
|
||||
}
|
||||
|
||||
impl OverlayFrame {
|
||||
pub fn from(origin: ModuleId) -> Self {
|
||||
pub fn from_origin(origin: ModuleId) -> Self {
|
||||
Self {
|
||||
vars: HashMap::new(),
|
||||
predecls: HashMap::new(),
|
||||
@ -220,45 +218,4 @@ impl OverlayFrame {
|
||||
origin,
|
||||
}
|
||||
}
|
||||
|
||||
// Find out which definitions are custom compared to the origin module
|
||||
// pub fn diff(&self, engine_state: &EngineState) -> OverlayDiff {
|
||||
// let module = engine_state.get_module(self.origin);
|
||||
|
||||
// let decls = self
|
||||
// .decls
|
||||
// .iter()
|
||||
// .filter(|(name, decl_id)| {
|
||||
// if self.visibility.is_decl_id_visible(decl_id) {
|
||||
// if let Some(original_id) = module.get_decl_id(name) {
|
||||
// &original_id != *decl_id
|
||||
// } else {
|
||||
// true
|
||||
// }
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// })
|
||||
// .map(|(name, decl_id)| (name.to_owned(), *decl_id))
|
||||
// .collect();
|
||||
|
||||
// let aliases = self
|
||||
// .aliases
|
||||
// .iter()
|
||||
// .filter(|(name, alias_id)| {
|
||||
// if self.visibility.is_alias_id_visible(alias_id) {
|
||||
// if let Some(original_id) = module.get_alias_id(name) {
|
||||
// &original_id != *alias_id
|
||||
// } else {
|
||||
// true
|
||||
// }
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// })
|
||||
// .map(|(name, alias_id)| (name.to_owned(), *alias_id))
|
||||
// .collect();
|
||||
|
||||
// (decls, aliases)
|
||||
// }
|
||||
}
|
||||
|
@ -178,6 +178,39 @@ impl Stack {
|
||||
result
|
||||
}
|
||||
|
||||
/// Flatten the env var scope frames into one frame, only from one overlay
|
||||
pub fn get_overlay_env_vars(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
overlay_name: &str,
|
||||
) -> HashMap<String, Value> {
|
||||
let mut result = HashMap::new();
|
||||
|
||||
// for active_overlay in self.active_overlays.iter() {
|
||||
if let Some(active_overlay) = self.active_overlays.iter().find(|n| n == &overlay_name) {
|
||||
if let Some(env_vars) = engine_state.env_vars.get(active_overlay) {
|
||||
result.extend(
|
||||
env_vars
|
||||
.iter()
|
||||
.filter(|(k, _)| {
|
||||
if let Some(env_hidden) = self.env_hidden.get(active_overlay) {
|
||||
!env_hidden.contains(*k)
|
||||
} else {
|
||||
// nothing has been hidden in this overlay
|
||||
true
|
||||
}
|
||||
})
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect::<HashMap<String, Value>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
result.extend(self.get_stack_overlay_env_vars(overlay_name));
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Get flattened environment variables only from the stack
|
||||
pub fn get_stack_env_vars(&self) -> HashMap<String, Value> {
|
||||
let mut result = HashMap::new();
|
||||
@ -193,6 +226,21 @@ impl Stack {
|
||||
result
|
||||
}
|
||||
|
||||
/// Get flattened environment variables only from the stack and one overlay
|
||||
pub fn get_stack_overlay_env_vars(&self, overlay_name: &str) -> HashMap<String, Value> {
|
||||
let mut result = HashMap::new();
|
||||
|
||||
for scope in &self.env_vars {
|
||||
if let Some(active_overlay) = self.active_overlays.iter().find(|n| n == &overlay_name) {
|
||||
if let Some(env_vars) = scope.get(active_overlay) {
|
||||
result.extend(env_vars.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Same as get_env_vars, but returns only the names as a HashSet
|
||||
pub fn get_env_var_names(&self, engine_state: &EngineState) -> HashSet<String> {
|
||||
let mut result = HashSet::new();
|
||||
@ -326,6 +374,10 @@ impl Stack {
|
||||
engine_state.env_vars.contains_key(name)
|
||||
}
|
||||
|
||||
pub fn is_overlay_active(&self, name: &String) -> bool {
|
||||
self.active_overlays.contains(name)
|
||||
}
|
||||
|
||||
pub fn add_overlay(&mut self, name: String) {
|
||||
self.env_hidden.remove(&name);
|
||||
|
||||
@ -333,14 +385,8 @@ impl Stack {
|
||||
self.active_overlays.push(name);
|
||||
}
|
||||
|
||||
pub fn remove_overlay(&mut self, name: &String, span: &Span) -> Result<(), ShellError> {
|
||||
if !self.active_overlays.contains(name) {
|
||||
return Err(ShellError::OverlayNotFoundAtRuntime(name.into(), *span));
|
||||
}
|
||||
|
||||
pub fn remove_overlay(&mut self, name: &String) {
|
||||
self.active_overlays.retain(|o| o != name);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ pub enum ShellError {
|
||||
///
|
||||
/// Check the module name. Did you typo it? Did you forget to declare it? Is the casing right?
|
||||
#[error("Module or overlay'{0}' not found")]
|
||||
#[diagnostic(code(nu::shell::module_not_found), url(docsrs))]
|
||||
#[diagnostic(code(nu::shell::module_or_overlay_not_found), url(docsrs))]
|
||||
ModuleOrOverlayNotFoundAtRuntime(String, #[label = "not a module or overlay"] Span),
|
||||
|
||||
/// A referenced overlay was not found at runtime.
|
||||
|
Reference in New Issue
Block a user