forked from extern/nushell
Add 'overlay new' command (#5647)
* Add 'overlay new' command * Add missing file
This commit is contained in:
parent
0594f9e7aa
commit
2042f7f769
@ -1,9 +1,11 @@
|
|||||||
mod add;
|
mod add;
|
||||||
mod command;
|
mod command;
|
||||||
mod list;
|
mod list;
|
||||||
|
mod new;
|
||||||
mod remove;
|
mod remove;
|
||||||
|
|
||||||
pub use add::OverlayAdd;
|
pub use add::OverlayAdd;
|
||||||
pub use command::Overlay;
|
pub use command::Overlay;
|
||||||
pub use list::OverlayList;
|
pub use list::OverlayList;
|
||||||
|
pub use new::OverlayNew;
|
||||||
pub use remove::OverlayRemove;
|
pub use remove::OverlayRemove;
|
||||||
|
74
crates/nu-command/src/core_commands/overlay/new.rs
Normal file
74
crates/nu-command/src/core_commands/overlay/new.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
use nu_engine::CallExt;
|
||||||
|
use nu_protocol::ast::Call;
|
||||||
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
|
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct OverlayNew;
|
||||||
|
|
||||||
|
impl Command for OverlayNew {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"overlay new"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Create an empty overlay"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> nu_protocol::Signature {
|
||||||
|
Signature::build("overlay new")
|
||||||
|
.required("name", SyntaxShape::String, "Name of the overlay")
|
||||||
|
// TODO:
|
||||||
|
// .switch(
|
||||||
|
// "prefix",
|
||||||
|
// "Prepend module name to the imported symbols",
|
||||||
|
// Some('p'),
|
||||||
|
// )
|
||||||
|
.category(Category::Core)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extra_usage(&self) -> &str {
|
||||||
|
r#"The command will first create an empty module, then add it as an overlay.
|
||||||
|
|
||||||
|
This command is a parser keyword. For details, check:
|
||||||
|
https://www.nushell.sh/book/thinking_in_nushell.html"#
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_parser_keyword(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
_input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let name_arg: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
|
stack.add_overlay(name_arg.item);
|
||||||
|
|
||||||
|
Ok(PipelineData::new(call.head))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Create an empty overlay",
|
||||||
|
example: r#"overlay new spam"#,
|
||||||
|
result: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
use crate::test_examples;
|
||||||
|
|
||||||
|
test_examples(OverlayNew {})
|
||||||
|
}
|
||||||
|
}
|
@ -55,6 +55,7 @@ pub fn create_default_context(cwd: impl AsRef<Path>) -> EngineState {
|
|||||||
Overlay,
|
Overlay,
|
||||||
OverlayAdd,
|
OverlayAdd,
|
||||||
OverlayList,
|
OverlayList,
|
||||||
|
OverlayNew,
|
||||||
OverlayRemove,
|
OverlayRemove,
|
||||||
Let,
|
Let,
|
||||||
Metadata,
|
Metadata,
|
||||||
|
@ -1745,6 +1745,9 @@ pub fn parse_overlay(
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
b"new" => {
|
||||||
|
return parse_overlay_new(working_set, spans, expand_aliases_denylist);
|
||||||
|
}
|
||||||
b"remove" => {
|
b"remove" => {
|
||||||
return parse_overlay_remove(working_set, spans, expand_aliases_denylist);
|
return parse_overlay_remove(working_set, spans, expand_aliases_denylist);
|
||||||
}
|
}
|
||||||
@ -1802,6 +1805,96 @@ pub fn parse_overlay(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_overlay_new(
|
||||||
|
working_set: &mut StateWorkingSet,
|
||||||
|
spans: &[Span],
|
||||||
|
expand_aliases_denylist: &[usize],
|
||||||
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
|
if spans.len() > 1 && working_set.get_span_contents(span(&spans[0..2])) != b"overlay new" {
|
||||||
|
return (
|
||||||
|
garbage_pipeline(spans),
|
||||||
|
Some(ParseError::UnknownState(
|
||||||
|
"internal error: Wrong call name for 'overlay new' command".into(),
|
||||||
|
span(spans),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (call, call_span) = match working_set.find_decl(b"overlay new") {
|
||||||
|
Some(decl_id) => {
|
||||||
|
let (call, mut err) = parse_internal_call(
|
||||||
|
working_set,
|
||||||
|
span(&spans[0..2]),
|
||||||
|
&spans[2..],
|
||||||
|
decl_id,
|
||||||
|
expand_aliases_denylist,
|
||||||
|
);
|
||||||
|
let decl = working_set.get_decl(decl_id);
|
||||||
|
|
||||||
|
let call_span = span(spans);
|
||||||
|
|
||||||
|
err = check_call(call_span, &decl.signature(), &call).or(err);
|
||||||
|
if err.is_some() || call.has_flag("help") {
|
||||||
|
return (
|
||||||
|
Pipeline::from_vec(vec![Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
span: call_span,
|
||||||
|
ty: Type::Any,
|
||||||
|
custom_completion: None,
|
||||||
|
}]),
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(call, call_span)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return (
|
||||||
|
garbage_pipeline(spans),
|
||||||
|
Some(ParseError::UnknownState(
|
||||||
|
"internal error: 'overlay new' declaration not found".into(),
|
||||||
|
span(spans),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (overlay_name, _) = if let Some(expr) = call.positional_nth(0) {
|
||||||
|
if let Some(s) = expr.as_string() {
|
||||||
|
(s, expr.span)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
garbage_pipeline(spans),
|
||||||
|
Some(ParseError::UnknownState(
|
||||||
|
"internal error: Module name not a string".into(),
|
||||||
|
expr.span,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
garbage_pipeline(spans),
|
||||||
|
Some(ParseError::UnknownState(
|
||||||
|
"internal error: Missing required positional after call parsing".into(),
|
||||||
|
call_span,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
span: span(spans),
|
||||||
|
ty: Type::Any,
|
||||||
|
custom_completion: None,
|
||||||
|
}]);
|
||||||
|
|
||||||
|
let module_id = working_set.add_module(&overlay_name, Module::new());
|
||||||
|
|
||||||
|
working_set.add_overlay(overlay_name.as_bytes().to_vec(), module_id, vec![], vec![]);
|
||||||
|
|
||||||
|
(pipeline, None)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_overlay_add(
|
pub fn parse_overlay_add(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
|
@ -496,3 +496,14 @@ fn reset_overrides() {
|
|||||||
assert_eq!(actual.out, "foo");
|
assert_eq!(actual.out, "foo");
|
||||||
assert_eq!(actual_repl.out, "foo");
|
assert_eq!(actual_repl.out, "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn overlay_new() {
|
||||||
|
let inp = &[r#"overlay new spam"#, r#"overlay list | last"#];
|
||||||
|
|
||||||
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
||||||
|
let actual_repl = nu_repl("tests/overlays", inp);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "spam");
|
||||||
|
assert_eq!(actual_repl.out, "spam");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user