mirror of
https://github.com/nushell/nushell.git
synced 2024-12-23 07:30:13 +01:00
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 command;
|
||||
mod list;
|
||||
mod new;
|
||||
mod remove;
|
||||
|
||||
pub use add::OverlayAdd;
|
||||
pub use command::Overlay;
|
||||
pub use list::OverlayList;
|
||||
pub use new::OverlayNew;
|
||||
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,
|
||||
OverlayAdd,
|
||||
OverlayList,
|
||||
OverlayNew,
|
||||
OverlayRemove,
|
||||
Let,
|
||||
Metadata,
|
||||
|
@ -1745,6 +1745,9 @@ pub fn parse_overlay(
|
||||
None,
|
||||
);
|
||||
}
|
||||
b"new" => {
|
||||
return parse_overlay_new(working_set, spans, expand_aliases_denylist);
|
||||
}
|
||||
b"remove" => {
|
||||
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(
|
||||
working_set: &mut StateWorkingSet,
|
||||
spans: &[Span],
|
||||
|
@ -496,3 +496,14 @@ fn reset_overrides() {
|
||||
assert_eq!(actual.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