mirror of
https://github.com/nushell/nushell.git
synced 2025-08-26 01:15:25 +02:00
feat(overlay): add active column to overlay list
(#16125)
# Description This adds a column to overlay list which indicates whether given overlay is active or not ```nu overlay new spam overlay hide spam overlay list 0 spam ``` # User-Facing Changes ## Release notes summary `overlay list` now returns table instead of list of overlays. Before, only active overlays were included in `overlay list`. Now, hidden overlays will be included as well, and there is a column indicating whether a given overlay is hidden or not. > TODO(release-notes): make sure this call out is formatted correctly for the blog > [!TIP] > The ordering of `overlay list` is still preserved. If you run `overlay list | last`, you will still get the most recently activated overlay. > > For migrating to the new behavior, you can update any usages of `overlay list | last` to `overlay list | last | get name`. # Tests + Formatting # After Submitting
This commit is contained in:
@@ -16,7 +16,7 @@ impl Command for Hide {
|
||||
.optional(
|
||||
"members",
|
||||
SyntaxShape::Any,
|
||||
"Which members of the module to import.",
|
||||
"Which members of the module to hide.",
|
||||
)
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
@@ -9,42 +9,96 @@ impl Command for OverlayList {
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"List all active overlays."
|
||||
"List all overlays with their active status."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("overlay list")
|
||||
.category(Category::Core)
|
||||
.input_output_types(vec![(Type::Nothing, Type::List(Box::new(Type::String)))])
|
||||
.input_output_types(vec![(
|
||||
Type::Nothing,
|
||||
Type::Table(
|
||||
vec![
|
||||
("name".to_string(), Type::String),
|
||||
("active".to_string(), Type::Bool),
|
||||
]
|
||||
.into(),
|
||||
),
|
||||
)])
|
||||
}
|
||||
|
||||
fn extra_description(&self) -> &str {
|
||||
"The overlays are listed in the order they were activated."
|
||||
"The overlays are listed in the order they were activated. Hidden overlays are listed first, followed by active overlays listed in the order that they were activated. `last` command will always give the top active overlay"
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_engine_state: &EngineState,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let active_overlays_engine: Vec<Value> = stack
|
||||
// get active overlay iterator
|
||||
let active_overlays = stack
|
||||
.active_overlays
|
||||
.iter()
|
||||
.map(|s| Value::string(s, call.head))
|
||||
.map(|overlay| (overlay.clone(), true));
|
||||
|
||||
// Get all overlay names from engine state
|
||||
let output_rows: Vec<Value> = engine_state
|
||||
.scope
|
||||
.overlays
|
||||
.iter()
|
||||
.filter_map(|(name, _)| {
|
||||
let name = String::from_utf8_lossy(name).to_string();
|
||||
if stack
|
||||
.active_overlays
|
||||
.iter()
|
||||
.any(|active_name| active_name == &name)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some((name, false))
|
||||
}
|
||||
})
|
||||
.chain(active_overlays)
|
||||
.map(|(name, active)| {
|
||||
Value::record(
|
||||
record! {
|
||||
"name" => Value::string(name.to_owned(), call.head),
|
||||
"active" => Value::bool(active, call.head),
|
||||
},
|
||||
call.head,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(Value::list(active_overlays_engine, call.head).into_pipeline_data())
|
||||
Ok(Value::list(output_rows, call.head).into_pipeline_data())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Get the last activated overlay",
|
||||
example: r#"module spam { export def foo [] { "foo" } }
|
||||
vec![
|
||||
Example {
|
||||
description: "List all overlays with their active status",
|
||||
example: r#"module spam { export def foo [] { "foo" } }
|
||||
overlay use spam
|
||||
overlay list | last"#,
|
||||
result: Some(Value::test_string("spam")),
|
||||
}]
|
||||
overlay list"#,
|
||||
result: Some(Value::test_list(vec![Value::test_record(record! {
|
||||
"name" => Value::test_string("spam"),
|
||||
"active" => Value::test_bool(true),
|
||||
})])),
|
||||
},
|
||||
Example {
|
||||
description: "Get overlay status after hiding",
|
||||
example: r#"module spam { export def foo [] { "foo" } }
|
||||
overlay use spam
|
||||
overlay hide spam
|
||||
overlay list | where name == "spam""#,
|
||||
result: Some(Value::test_list(vec![Value::test_record(record! {
|
||||
"name" => Value::test_string("spam"),
|
||||
"active" => Value::test_bool(false),
|
||||
})])),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -66,8 +66,8 @@ impl Command for OverlayUse {
|
||||
return Ok(PipelineData::empty());
|
||||
}
|
||||
|
||||
let mut name_arg: Spanned<String> = call.req(engine_state, caller_stack, 0)?;
|
||||
name_arg.item = trim_quotes_str(&name_arg.item).to_string();
|
||||
let name_arg: Spanned<String> = call.req(engine_state, caller_stack, 0)?;
|
||||
let name_arg_item = trim_quotes_str(&name_arg.item);
|
||||
|
||||
let maybe_origin_module_id: Option<ModuleId> =
|
||||
if let Some(overlay_expr) = call.get_parser_info(caller_stack, "overlay_expr") {
|
||||
@@ -91,11 +91,11 @@ impl Command for OverlayUse {
|
||||
let overlay_name = if let Some(name) = call.opt(engine_state, caller_stack, 1)? {
|
||||
name
|
||||
} else if engine_state
|
||||
.find_overlay(name_arg.item.as_bytes())
|
||||
.find_overlay(name_arg_item.as_bytes())
|
||||
.is_some()
|
||||
{
|
||||
name_arg.item.clone()
|
||||
} else if let Some(os_str) = Path::new(&name_arg.item).file_stem() {
|
||||
name_arg_item.to_string()
|
||||
} else if let Some(os_str) = Path::new(name_arg_item).file_stem() {
|
||||
if let Some(name) = os_str.to_str() {
|
||||
name.to_string()
|
||||
} else {
|
||||
@@ -105,7 +105,7 @@ impl Command for OverlayUse {
|
||||
}
|
||||
} else {
|
||||
return Err(ShellError::OverlayNotFoundAtRuntime {
|
||||
overlay_name: name_arg.item,
|
||||
overlay_name: (name_arg_item.to_string()),
|
||||
span: name_arg.span,
|
||||
});
|
||||
};
|
||||
@@ -122,7 +122,7 @@ impl Command for OverlayUse {
|
||||
// Evaluate the export-env block (if any) and keep its environment
|
||||
if let Some(block_id) = module.env_block {
|
||||
let maybe_file_path_or_dir = find_in_dirs_env(
|
||||
&name_arg.item,
|
||||
name_arg_item,
|
||||
engine_state,
|
||||
caller_stack,
|
||||
get_dirs_var_from_call(caller_stack, call),
|
||||
|
@@ -198,7 +198,7 @@ fn new_overlay_from_const_name() {
|
||||
let inp = &[
|
||||
"const mod = 'spam'",
|
||||
"overlay new $mod",
|
||||
"overlay list | last",
|
||||
"overlay list | last | get name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -212,7 +212,7 @@ fn hide_overlay_from_const_name() {
|
||||
"const mod = 'spam'",
|
||||
"overlay new $mod",
|
||||
"overlay hide $mod",
|
||||
"overlay list | str join ' '",
|
||||
"overlay list | where active == true | get name | str join ' '",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -410,7 +410,7 @@ fn hide_overlay_scoped_env() {
|
||||
|
||||
#[test]
|
||||
fn list_default_overlay() {
|
||||
let inp = &["overlay list | last"];
|
||||
let inp = &["overlay list | last | get name"];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
let actual_repl = nu!(nu_repl_code(inp));
|
||||
@@ -424,7 +424,7 @@ fn list_last_overlay() {
|
||||
let inp = &[
|
||||
r#"module spam { export def foo [] { "foo" } }"#,
|
||||
"overlay use spam",
|
||||
"overlay list | last",
|
||||
"overlay list | last | get name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -439,7 +439,7 @@ fn list_overlay_scoped() {
|
||||
let inp = &[
|
||||
r#"module spam { export def foo [] { "foo" } }"#,
|
||||
"overlay use spam",
|
||||
"do { overlay list | last }",
|
||||
"do { overlay list | last | get name }",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -695,7 +695,7 @@ fn reset_overrides() {
|
||||
|
||||
#[test]
|
||||
fn overlay_new() {
|
||||
let inp = &["overlay new spam", "overlay list | last"];
|
||||
let inp = &["overlay new spam", "overlay list | last | get name"];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
let actual_repl = nu!(nu_repl_code(inp));
|
||||
@@ -1080,7 +1080,7 @@ fn overlay_use_find_scoped_module() {
|
||||
module spam { }
|
||||
|
||||
overlay use spam
|
||||
overlay list | last
|
||||
overlay list | last | get name
|
||||
}
|
||||
";
|
||||
|
||||
@@ -1196,7 +1196,7 @@ fn overlay_trim_single_quote() {
|
||||
let inp = &[
|
||||
r#"module spam { export def foo [] { "foo" } }"#,
|
||||
"overlay use 'spam'",
|
||||
"overlay list | last ",
|
||||
"overlay list | last | get name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -1227,7 +1227,7 @@ fn overlay_trim_double_quote() {
|
||||
let inp = &[
|
||||
r#"module spam { export def foo [] { "foo" } }"#,
|
||||
r#"overlay use "spam" "#,
|
||||
"overlay list | last ",
|
||||
"overlay list | last | get name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -1428,7 +1428,7 @@ fn alias_overlay_use_2() {
|
||||
"module spam { export alias b = overlay use inner }",
|
||||
"use spam",
|
||||
"spam b",
|
||||
"overlay list | get 1",
|
||||
"overlay list | get 1.name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -1447,7 +1447,7 @@ fn alias_overlay_use_3() {
|
||||
"module spam { export alias b = overlay use inner }",
|
||||
"use spam b",
|
||||
"b",
|
||||
"overlay list | get 1",
|
||||
"overlay list | get 1.name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
@@ -1465,7 +1465,7 @@ fn alias_overlay_new() {
|
||||
"alias on = overlay new",
|
||||
"on spam",
|
||||
"on eggs",
|
||||
"overlay list | last",
|
||||
"overlay list | last | get name",
|
||||
];
|
||||
|
||||
let actual = nu!(&inp.join("; "));
|
||||
|
Reference in New Issue
Block a user