2021-11-30 07:14:05 +01:00
use nu_protocol ::ast ::{ Call , Expr , Expression , ImportPatternMember } ;
2021-10-25 18:58:58 +02:00
use nu_protocol ::engine ::{ Command , EngineState , Stack } ;
2021-11-30 07:14:05 +01:00
use nu_protocol ::{ Category , PipelineData , ShellError , Signature , SyntaxShape } ;
2021-09-28 22:32:15 +02:00
2021-10-25 06:01:02 +02:00
#[ derive(Clone) ]
2021-09-28 22:32:15 +02:00
pub struct Hide ;
impl Command for Hide {
fn name ( & self ) -> & str {
" hide "
}
2021-11-17 05:22:37 +01:00
fn signature ( & self ) -> nu_protocol ::Signature {
Signature ::build ( " hide " )
. required ( " pattern " , SyntaxShape ::String , " import pattern " )
. category ( Category ::Core )
2021-09-28 22:32:15 +02:00
}
2021-11-17 05:22:37 +01:00
fn usage ( & self ) -> & str {
" Hide definitions in the current scope "
2021-09-28 22:32:15 +02:00
}
2021-11-30 07:14:05 +01:00
fn extra_usage ( & self ) -> & str {
" If there is a definition and an environment variable with the same name in the current scope, first the definition will be hidden, then the environment variable. "
}
2021-09-28 22:32:15 +02:00
fn run (
& self ,
2021-11-30 07:14:05 +01:00
engine_state : & EngineState ,
stack : & mut Stack ,
2021-11-06 06:50:33 +01:00
call : & Call ,
2021-10-25 06:01:02 +02:00
_input : PipelineData ,
) -> Result < nu_protocol ::PipelineData , nu_protocol ::ShellError > {
2021-11-30 07:14:05 +01:00
let import_pattern = if let Some ( Expression {
expr : Expr ::ImportPattern ( pat ) ,
..
} ) = call . positional . get ( 0 )
{
pat
} else {
return Err ( ShellError ::InternalError (
" Got something else than import pattern " . into ( ) ,
) ) ;
} ;
let head_name_str = if let Ok ( s ) = String ::from_utf8 ( import_pattern . head . name . clone ( ) ) {
s
} else {
return Err ( ShellError ::NonUtf8 ( import_pattern . head . span ) ) ;
} ;
if let Some ( overlay_id ) = engine_state . find_overlay ( & import_pattern . head . name ) {
// The first word is a module
let overlay = engine_state . get_overlay ( overlay_id ) ;
let env_vars_to_hide = if import_pattern . members . is_empty ( ) {
overlay . env_vars_with_head ( & import_pattern . head . name )
} else {
match & import_pattern . members [ 0 ] {
ImportPatternMember ::Glob { .. } = > {
overlay . env_vars_with_head ( & import_pattern . head . name )
}
ImportPatternMember ::Name { name , span } = > {
let mut output = vec! [ ] ;
if let Some ( ( name , id ) ) =
overlay . env_var_with_head ( name , & import_pattern . head . name )
{
output . push ( ( name , id ) ) ;
} else if ! overlay . has_decl ( name ) {
return Err ( ShellError ::EnvVarNotFoundAtRuntime ( * span ) ) ;
}
output
}
ImportPatternMember ::List { names } = > {
let mut output = vec! [ ] ;
for ( name , span ) in names {
if let Some ( ( name , id ) ) =
overlay . env_var_with_head ( name , & import_pattern . head . name )
{
output . push ( ( name , id ) ) ;
} else if ! overlay . has_decl ( name ) {
return Err ( ShellError ::EnvVarNotFoundAtRuntime ( * span ) ) ;
}
}
output
}
}
} ;
for ( name , _ ) in env_vars_to_hide {
let name = if let Ok ( s ) = String ::from_utf8 ( name . clone ( ) ) {
s
} else {
return Err ( ShellError ::NonUtf8 ( import_pattern . span ( ) ) ) ;
} ;
if stack . remove_env_var ( & name ) . is_none ( ) {
return Err ( ShellError ::NotFound ( call . positional [ 0 ] . span ) ) ;
}
}
} else if ! import_pattern . hidden . contains ( & import_pattern . head . name )
& & stack . remove_env_var ( & head_name_str ) . is_none ( )
{
return Err ( ShellError ::NotFound ( call . positional [ 0 ] . span ) ) ;
}
2021-11-06 06:50:33 +01:00
Ok ( PipelineData ::new ( call . head ) )
2021-09-28 22:32:15 +02:00
}
}