mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Implement a rough version of 'hide'
'hide' command is used to undefine custom commands
This commit is contained in:
parent
3cbf99053f
commit
7488254cca
5 changed files with 150 additions and 13 deletions
|
@ -14,7 +14,7 @@ impl Command for Use {
|
|||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("use").required("module_name", SyntaxShape::String, "module name")
|
||||
Signature::build("use").required("pattern", SyntaxShape::String, "import pattern")
|
||||
}
|
||||
|
||||
fn run(
|
||||
|
|
|
@ -7,7 +7,7 @@ use nu_protocol::{
|
|||
|
||||
use crate::{
|
||||
Alias, Benchmark, BuildString, Def, Do, Each, ExportDef, External, For, From, FromJson, Git, GitCheckout,
|
||||
If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Sys, Table, Use, Where,
|
||||
Hide, If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Sys, Table, Use, Where,
|
||||
};
|
||||
|
||||
pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
|
@ -29,8 +29,8 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
|||
working_set.add_decl(Box::new(Alias));
|
||||
working_set.add_decl(Box::new(Benchmark));
|
||||
working_set.add_decl(Box::new(BuildString));
|
||||
|
||||
working_set.add_decl(Box::new(Def));
|
||||
|
||||
working_set.add_decl(Box::new(Def));
|
||||
working_set.add_decl(Box::new(Do));
|
||||
working_set.add_decl(Box::new(Each));
|
||||
working_set.add_decl(Box::new(ExportDef));
|
||||
|
@ -38,6 +38,7 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
|||
working_set.add_decl(Box::new(For));
|
||||
working_set.add_decl(Box::new(From));
|
||||
working_set.add_decl(Box::new(FromJson));
|
||||
working_set.add_decl(Box::new(Hide));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(Length));
|
||||
working_set.add_decl(Box::new(Let));
|
||||
|
@ -48,7 +49,7 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
|||
working_set.add_decl(Box::new(Sys));
|
||||
working_set.add_decl(Box::new(Table));
|
||||
working_set.add_decl(Box::new(Use));
|
||||
working_set.add_decl(Box::new(Where));
|
||||
working_set.add_decl(Box::new(Where));
|
||||
|
||||
// This is a WIP proof of concept
|
||||
working_set.add_decl(Box::new(ListGitBranches));
|
||||
|
|
|
@ -472,8 +472,6 @@ pub fn parse_use(
|
|||
let mut error = None;
|
||||
let bytes = working_set.get_span_contents(spans[0]);
|
||||
|
||||
// TODO: Currently, this directly imports the module's definitions into the current scope.
|
||||
// Later, we want to put them behind the module's name and add selective importing
|
||||
if bytes == b"use" && spans.len() >= 2 {
|
||||
let (module_name_expr, err) = parse_string(working_set, spans[1]);
|
||||
error = error.or(err);
|
||||
|
@ -482,8 +480,6 @@ pub fn parse_use(
|
|||
error = error.or(err);
|
||||
|
||||
let exports = if let Some(block_id) = working_set.find_module(&import_pattern.head) {
|
||||
// TODO: Since we don't use the Block at all, we might just as well create a separate
|
||||
// Module that holds only the exports, without having Blocks in the way.
|
||||
working_set.get_block(block_id).exports.clone()
|
||||
} else {
|
||||
return (
|
||||
|
@ -571,6 +567,65 @@ pub fn parse_use(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_hide(
|
||||
working_set: &mut StateWorkingSet,
|
||||
spans: &[Span],
|
||||
) -> (Statement, Option<ParseError>) {
|
||||
let mut error = None;
|
||||
let bytes = working_set.get_span_contents(spans[0]);
|
||||
|
||||
if bytes == b"hide" && spans.len() >= 2 {
|
||||
let (name_expr, err) = parse_string(working_set, spans[1]);
|
||||
error = error.or(err);
|
||||
|
||||
let name_bytes: Vec<u8> = working_set.get_span_contents(spans[1]).into();
|
||||
|
||||
// TODO: Do the import pattern stuff for bulk-hiding
|
||||
// TODO: move this error into error = error.or pattern
|
||||
let _decl_id = if let Some(id) = working_set.find_decl(&name_bytes) {
|
||||
id
|
||||
} else {
|
||||
return (
|
||||
garbage_statement(spans),
|
||||
Some(ParseError::UnknownCommand(spans[1])),
|
||||
);
|
||||
};
|
||||
|
||||
// Hide the definitions
|
||||
working_set.hide_decl(name_bytes);
|
||||
|
||||
// Create the Hide command call
|
||||
let hide_decl_id = working_set
|
||||
.find_decl(b"hide")
|
||||
.expect("internal error: missing hide command");
|
||||
|
||||
let call = Box::new(Call {
|
||||
head: spans[0],
|
||||
decl_id: hide_decl_id,
|
||||
positional: vec![name_expr],
|
||||
named: vec![],
|
||||
});
|
||||
|
||||
(
|
||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
||||
expr: Expr::Call(call),
|
||||
span: span(spans),
|
||||
ty: Type::Unknown,
|
||||
custom_completion: None,
|
||||
}])),
|
||||
error,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
garbage_statement(spans),
|
||||
Some(ParseError::UnknownState(
|
||||
"Expected structure: hide <name>".into(),
|
||||
span(spans),
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_let(
|
||||
working_set: &mut StateWorkingSet,
|
||||
spans: &[Span],
|
||||
|
|
|
@ -14,7 +14,7 @@ use nu_protocol::{
|
|||
};
|
||||
|
||||
use crate::parse_keywords::{
|
||||
parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_use,
|
||||
parse_alias, parse_def, parse_def_predecl, parse_hide, parse_let, parse_module, parse_use,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -2589,6 +2589,7 @@ pub fn parse_statement(
|
|||
garbage_statement(spans),
|
||||
Some(ParseError::UnexpectedKeyword("export".into(), spans[0])),
|
||||
),
|
||||
b"hide" => parse_hide(working_set, spans),
|
||||
_ => {
|
||||
let (expr, err) = parse_expression(working_set, spans);
|
||||
(Statement::Pipeline(Pipeline::from_vec(vec![expr])), err)
|
||||
|
|
|
@ -18,6 +18,7 @@ pub struct ScopeFrame {
|
|||
decls: HashMap<Vec<u8>, DeclId>,
|
||||
aliases: HashMap<Vec<u8>, Vec<Span>>,
|
||||
modules: HashMap<Vec<u8>, BlockId>,
|
||||
hiding: HashMap<Vec<u8>, usize>, // defines what is being hidden and its "hiding strength"
|
||||
}
|
||||
|
||||
impl ScopeFrame {
|
||||
|
@ -27,6 +28,7 @@ impl ScopeFrame {
|
|||
decls: HashMap::new(),
|
||||
aliases: HashMap::new(),
|
||||
modules: HashMap::new(),
|
||||
hiding: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +83,9 @@ impl EngineState {
|
|||
for item in first.modules.into_iter() {
|
||||
last.modules.insert(item.0, item.1);
|
||||
}
|
||||
for item in first.hiding.into_iter() {
|
||||
last.hiding.insert(item.0, item.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,9 +129,23 @@ impl EngineState {
|
|||
}
|
||||
|
||||
pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
|
||||
let mut hiding_strength = 0;
|
||||
// println!("state: starting finding {}", String::from_utf8_lossy(&name));
|
||||
|
||||
for scope in self.scope.iter().rev() {
|
||||
// println!("hiding map: {:?}", scope.hiding);
|
||||
// check if we're hiding the declin this scope
|
||||
if let Some(strength) = scope.hiding.get(name) {
|
||||
hiding_strength += strength;
|
||||
}
|
||||
|
||||
if let Some(decl_id) = scope.decls.get(name) {
|
||||
return Some(*decl_id);
|
||||
// if we're hiding this decl, do not return it and reduce the hiding strength
|
||||
if hiding_strength > 0 {
|
||||
hiding_strength -= 1;
|
||||
} else {
|
||||
return Some(*decl_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,10 +262,12 @@ impl StateDelta {
|
|||
}
|
||||
|
||||
pub fn enter_scope(&mut self) {
|
||||
// println!("enter scope");
|
||||
self.scope.push(ScopeFrame::new());
|
||||
}
|
||||
|
||||
pub fn exit_scope(&mut self) {
|
||||
// println!("exit scope");
|
||||
self.scope.pop();
|
||||
}
|
||||
}
|
||||
|
@ -280,6 +301,7 @@ impl<'a> StateWorkingSet<'a> {
|
|||
|
||||
pub fn add_decl(&mut self, decl: Box<dyn Command>) -> DeclId {
|
||||
let name = decl.name().as_bytes().to_vec();
|
||||
// println!("adding {}", String::from_utf8_lossy(&name));
|
||||
|
||||
self.delta.decls.push(decl);
|
||||
let decl_id = self.num_decls() - 1;
|
||||
|
@ -289,11 +311,36 @@ impl<'a> StateWorkingSet<'a> {
|
|||
.scope
|
||||
.last_mut()
|
||||
.expect("internal error: missing required scope frame");
|
||||
|
||||
// reset "hiding strength" to 0 => not hidden
|
||||
if let Some(strength) = scope_frame.hiding.get_mut(&name) {
|
||||
*strength = 0;
|
||||
// println!(" strength: {}", strength);
|
||||
}
|
||||
|
||||
scope_frame.decls.insert(name, decl_id);
|
||||
|
||||
decl_id
|
||||
}
|
||||
|
||||
pub fn hide_decl(&mut self, name: Vec<u8>) {
|
||||
let scope_frame = self
|
||||
.delta
|
||||
.scope
|
||||
.last_mut()
|
||||
.expect("internal error: missing required scope frame");
|
||||
|
||||
if let Some(strength) = scope_frame.hiding.get_mut(&name) {
|
||||
*strength += 1;
|
||||
// println!("hiding {}, strength: {}", String::from_utf8_lossy(&name), strength);
|
||||
} else {
|
||||
// println!("hiding {}, strength: 1", String::from_utf8_lossy(&name));
|
||||
scope_frame.hiding.insert(name, 1);
|
||||
}
|
||||
|
||||
// println!("hiding map: {:?}", scope_frame.hiding);
|
||||
}
|
||||
|
||||
pub fn add_block(&mut self, block: Block) -> BlockId {
|
||||
self.delta.blocks.push(block);
|
||||
|
||||
|
@ -401,15 +448,48 @@ impl<'a> StateWorkingSet<'a> {
|
|||
}
|
||||
|
||||
pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
|
||||
let mut hiding_strength = 0;
|
||||
// println!("set: starting finding {}", String::from_utf8_lossy(&name));
|
||||
|
||||
for scope in self.delta.scope.iter().rev() {
|
||||
// println!("delta frame");
|
||||
// println!("hiding map: {:?}", scope.hiding);
|
||||
// check if we're hiding the declin this scope
|
||||
if let Some(strength) = scope.hiding.get(name) {
|
||||
hiding_strength += strength;
|
||||
// println!(" was hiding, strength {}", hiding_strength);
|
||||
}
|
||||
|
||||
if let Some(decl_id) = scope.decls.get(name) {
|
||||
return Some(*decl_id);
|
||||
// if we're hiding this decl, do not return it and reduce the hiding strength
|
||||
if hiding_strength > 0 {
|
||||
hiding_strength -= 1;
|
||||
// println!(" decl found, strength {}", hiding_strength);
|
||||
} else {
|
||||
// println!(" decl found, return");
|
||||
return Some(*decl_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for scope in self.permanent_state.scope.iter().rev() {
|
||||
// println!("perma frame");
|
||||
// println!("hiding map: {:?}", scope.hiding);
|
||||
// check if we're hiding the declin this scope
|
||||
if let Some(strength) = scope.hiding.get(name) {
|
||||
hiding_strength += strength;
|
||||
// println!(" was hiding, strength {}", hiding_strength);
|
||||
}
|
||||
|
||||
if let Some(decl_id) = scope.decls.get(name) {
|
||||
return Some(*decl_id);
|
||||
// if we're hiding this decl, do not return it and reduce the hiding strength
|
||||
if hiding_strength > 0 {
|
||||
hiding_strength -= 1;
|
||||
// println!(" decl found, strength {}", hiding_strength);
|
||||
} else {
|
||||
// println!(" decl found, return");
|
||||
return Some(*decl_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue