Implement a rough version of 'hide'
'hide' command is used to undefine custom commands
This commit is contained in:
parent
3cbf99053f
commit
7488254cca
|
@ -14,7 +14,7 @@ impl Command for Use {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> nu_protocol::Signature {
|
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(
|
fn run(
|
||||||
|
|
|
@ -7,7 +7,7 @@ use nu_protocol::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Alias, Benchmark, BuildString, Def, Do, Each, ExportDef, External, For, From, FromJson, Git, GitCheckout,
|
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>> {
|
pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||||
|
@ -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(For));
|
||||||
working_set.add_decl(Box::new(From));
|
working_set.add_decl(Box::new(From));
|
||||||
working_set.add_decl(Box::new(FromJson));
|
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(If));
|
||||||
working_set.add_decl(Box::new(Length));
|
working_set.add_decl(Box::new(Length));
|
||||||
working_set.add_decl(Box::new(Let));
|
working_set.add_decl(Box::new(Let));
|
||||||
|
|
|
@ -472,8 +472,6 @@ pub fn parse_use(
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
let bytes = working_set.get_span_contents(spans[0]);
|
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 {
|
if bytes == b"use" && spans.len() >= 2 {
|
||||||
let (module_name_expr, err) = parse_string(working_set, spans[1]);
|
let (module_name_expr, err) = parse_string(working_set, spans[1]);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
@ -482,8 +480,6 @@ pub fn parse_use(
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let exports = if let Some(block_id) = working_set.find_module(&import_pattern.head) {
|
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()
|
working_set.get_block(block_id).exports.clone()
|
||||||
} else {
|
} else {
|
||||||
return (
|
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(
|
pub fn parse_let(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
|
|
|
@ -14,7 +14,7 @@ use nu_protocol::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parse_keywords::{
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -2589,6 +2589,7 @@ pub fn parse_statement(
|
||||||
garbage_statement(spans),
|
garbage_statement(spans),
|
||||||
Some(ParseError::UnexpectedKeyword("export".into(), spans[0])),
|
Some(ParseError::UnexpectedKeyword("export".into(), spans[0])),
|
||||||
),
|
),
|
||||||
|
b"hide" => parse_hide(working_set, spans),
|
||||||
_ => {
|
_ => {
|
||||||
let (expr, err) = parse_expression(working_set, spans);
|
let (expr, err) = parse_expression(working_set, spans);
|
||||||
(Statement::Pipeline(Pipeline::from_vec(vec![expr])), err)
|
(Statement::Pipeline(Pipeline::from_vec(vec![expr])), err)
|
||||||
|
|
|
@ -18,6 +18,7 @@ pub struct ScopeFrame {
|
||||||
decls: HashMap<Vec<u8>, DeclId>,
|
decls: HashMap<Vec<u8>, DeclId>,
|
||||||
aliases: HashMap<Vec<u8>, Vec<Span>>,
|
aliases: HashMap<Vec<u8>, Vec<Span>>,
|
||||||
modules: HashMap<Vec<u8>, BlockId>,
|
modules: HashMap<Vec<u8>, BlockId>,
|
||||||
|
hiding: HashMap<Vec<u8>, usize>, // defines what is being hidden and its "hiding strength"
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScopeFrame {
|
impl ScopeFrame {
|
||||||
|
@ -27,6 +28,7 @@ impl ScopeFrame {
|
||||||
decls: HashMap::new(),
|
decls: HashMap::new(),
|
||||||
aliases: HashMap::new(),
|
aliases: HashMap::new(),
|
||||||
modules: HashMap::new(),
|
modules: HashMap::new(),
|
||||||
|
hiding: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +83,9 @@ impl EngineState {
|
||||||
for item in first.modules.into_iter() {
|
for item in first.modules.into_iter() {
|
||||||
last.modules.insert(item.0, item.1);
|
last.modules.insert(item.0, item.1);
|
||||||
}
|
}
|
||||||
|
for item in first.hiding.into_iter() {
|
||||||
|
last.hiding.insert(item.0, item.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,11 +129,25 @@ impl EngineState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
|
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() {
|
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) {
|
if let Some(decl_id) = scope.decls.get(name) {
|
||||||
|
// 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);
|
return Some(*decl_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -243,10 +262,12 @@ impl StateDelta {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter_scope(&mut self) {
|
pub fn enter_scope(&mut self) {
|
||||||
|
// println!("enter scope");
|
||||||
self.scope.push(ScopeFrame::new());
|
self.scope.push(ScopeFrame::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit_scope(&mut self) {
|
pub fn exit_scope(&mut self) {
|
||||||
|
// println!("exit scope");
|
||||||
self.scope.pop();
|
self.scope.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,6 +301,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||||
|
|
||||||
pub fn add_decl(&mut self, decl: Box<dyn Command>) -> DeclId {
|
pub fn add_decl(&mut self, decl: Box<dyn Command>) -> DeclId {
|
||||||
let name = decl.name().as_bytes().to_vec();
|
let name = decl.name().as_bytes().to_vec();
|
||||||
|
// println!("adding {}", String::from_utf8_lossy(&name));
|
||||||
|
|
||||||
self.delta.decls.push(decl);
|
self.delta.decls.push(decl);
|
||||||
let decl_id = self.num_decls() - 1;
|
let decl_id = self.num_decls() - 1;
|
||||||
|
@ -289,11 +311,36 @@ impl<'a> StateWorkingSet<'a> {
|
||||||
.scope
|
.scope
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.expect("internal error: missing required scope frame");
|
.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);
|
scope_frame.decls.insert(name, decl_id);
|
||||||
|
|
||||||
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 {
|
pub fn add_block(&mut self, block: Block) -> BlockId {
|
||||||
self.delta.blocks.push(block);
|
self.delta.blocks.push(block);
|
||||||
|
|
||||||
|
@ -401,17 +448,50 @@ impl<'a> StateWorkingSet<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
|
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() {
|
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) {
|
if let Some(decl_id) = scope.decls.get(name) {
|
||||||
|
// 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);
|
return Some(*decl_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for scope in self.permanent_state.scope.iter().rev() {
|
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) {
|
if let Some(decl_id) = scope.decls.get(name) {
|
||||||
|
// 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);
|
return Some(*decl_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user