forked from extern/nushell
Begin directory contrib docs and split commands (#3650)
* Begin directory contrib docs and split commands * Fix unused import warning
This commit is contained in:
61
crates/nu-command/src/commands/shells/command.rs
Normal file
61
crates/nu-command/src/commands/shells/command.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, TaggedDictBuilder};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub struct Shells;
|
||||
|
||||
impl WholeStreamCommand for Shells {
|
||||
fn name(&self) -> &str {
|
||||
"shells"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("shells")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Display the list of current shells."
|
||||
}
|
||||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
Ok(shells(args))
|
||||
}
|
||||
}
|
||||
|
||||
fn shells(args: CommandArgs) -> ActionStream {
|
||||
let mut shells_out = VecDeque::new();
|
||||
let shell_manager = args.shell_manager();
|
||||
let tag = args.call_info.name_tag;
|
||||
let active_index = shell_manager.current_shell.load(Ordering::SeqCst);
|
||||
|
||||
for (index, shell) in shell_manager.shells.lock().iter().enumerate() {
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
|
||||
if index == active_index {
|
||||
dict.insert_untagged("active", true);
|
||||
} else {
|
||||
dict.insert_untagged("active", false);
|
||||
}
|
||||
dict.insert_untagged("name", shell.name());
|
||||
dict.insert_untagged("path", shell.path());
|
||||
|
||||
shells_out.push_back(dict.into_value());
|
||||
}
|
||||
|
||||
shells_out.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ShellError;
|
||||
use super::Shells;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Shells {})
|
||||
}
|
||||
}
|
163
crates/nu-command/src/commands/shells/enter.rs
Normal file
163
crates/nu-command/src/commands/shells/enter.rs
Normal file
@ -0,0 +1,163 @@
|
||||
use crate::prelude::*;
|
||||
use nu_engine::UnevaluatedCallInfo;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::ExternalRedirection;
|
||||
use nu_protocol::{
|
||||
CommandAction, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::Tagged;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Enter;
|
||||
|
||||
impl WholeStreamCommand for Enter {
|
||||
fn name(&self) -> &str {
|
||||
"enter"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("enter")
|
||||
.required(
|
||||
"location",
|
||||
SyntaxShape::FilePath,
|
||||
"the location to create a new shell from",
|
||||
)
|
||||
.named(
|
||||
"encoding",
|
||||
SyntaxShape::String,
|
||||
"encoding to use to open file",
|
||||
Some('e'),
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Create a new shell and begin at this path."
|
||||
}
|
||||
|
||||
fn extra_usage(&self) -> &str {
|
||||
r#"Multiple encodings are supported for reading text files by using
|
||||
the '--encoding <encoding>' parameter. Here is an example of a few:
|
||||
big5, euc-jp, euc-kr, gbk, iso-8859-1, utf-16, cp1252, latin5
|
||||
|
||||
For a more complete list of encodings please refer to the encoding_rs
|
||||
documentation link at https://docs.rs/encoding_rs/0.8.28/encoding_rs/#statics"#
|
||||
}
|
||||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
enter(args)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Enter a path as a new shell",
|
||||
example: "enter ../projectB",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Enter a file as a new shell",
|
||||
example: "enter package.json",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Enters file with iso-8859-1 encoding",
|
||||
example: "enter file.csv --encoding iso-8859-1",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn enter(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let head = args.call_info.args.head.clone();
|
||||
let context = args.context.clone();
|
||||
let scope = args.scope().clone();
|
||||
let path = args.context.shell_manager().path();
|
||||
|
||||
let location: Tagged<PathBuf> = args.req(0)?;
|
||||
let encoding: Option<Tagged<String>> = args.get_flag("encoding")?;
|
||||
let location_string = location.display().to_string();
|
||||
|
||||
if location.is_dir() {
|
||||
Ok(ActionStream::one(ReturnSuccess::action(
|
||||
CommandAction::EnterShell(location_string),
|
||||
)))
|
||||
} else {
|
||||
// If it's a file, attempt to open the file as a value and enter it
|
||||
let cwd = path;
|
||||
|
||||
let full_path = std::path::PathBuf::from(cwd);
|
||||
let span = location.span();
|
||||
|
||||
let (file_extension, tagged_contents) = crate::commands::filesystem::open::fetch(
|
||||
&full_path,
|
||||
&PathBuf::from(location_string),
|
||||
span,
|
||||
encoding,
|
||||
)?;
|
||||
|
||||
match tagged_contents.value {
|
||||
UntaggedValue::Primitive(Primitive::String(_)) => {
|
||||
if let Some(extension) = file_extension {
|
||||
let command_name = format!("from {}", extension);
|
||||
if let Some(converter) = scope.get_command(&command_name) {
|
||||
let tag = tagged_contents.tag.clone();
|
||||
let new_args = CommandArgs {
|
||||
context,
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: nu_protocol::hir::Call {
|
||||
head,
|
||||
positional: None,
|
||||
named: None,
|
||||
span: Span::unknown(),
|
||||
external_redirection: ExternalRedirection::Stdout,
|
||||
},
|
||||
name_tag: tag.clone(),
|
||||
},
|
||||
input: InputStream::one(tagged_contents),
|
||||
};
|
||||
let mut result = converter.run(new_args)?;
|
||||
let result_vec: Vec<Value> = result.drain_vec();
|
||||
Ok(result_vec
|
||||
.into_iter()
|
||||
.map(move |res| {
|
||||
let Value { value, .. } = res;
|
||||
Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(
|
||||
Value {
|
||||
value,
|
||||
tag: tag.clone(),
|
||||
},
|
||||
)))
|
||||
})
|
||||
.into_action_stream())
|
||||
} else {
|
||||
Ok(ActionStream::one(ReturnSuccess::action(
|
||||
CommandAction::EnterValueShell(tagged_contents),
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
Ok(ActionStream::one(ReturnSuccess::action(
|
||||
CommandAction::EnterValueShell(tagged_contents),
|
||||
)))
|
||||
}
|
||||
}
|
||||
_ => Ok(ActionStream::one(ReturnSuccess::action(
|
||||
CommandAction::EnterValueShell(tagged_contents),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Enter;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Enter {})
|
||||
}
|
||||
}
|
73
crates/nu-command/src/commands/shells/exit.rs
Normal file
73
crates/nu-command/src/commands/shells/exit.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape};
|
||||
|
||||
pub struct Exit;
|
||||
|
||||
impl WholeStreamCommand for Exit {
|
||||
fn name(&self) -> &str {
|
||||
"exit"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("exit")
|
||||
.optional(
|
||||
"code",
|
||||
SyntaxShape::Number,
|
||||
"Status code to return if this was the last shell or --now was specified",
|
||||
)
|
||||
.switch("now", "Exit out of the shell immediately", Some('n'))
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Exit the current shell (or all shells)."
|
||||
}
|
||||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
exit(args)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Exit the current shell",
|
||||
example: "exit",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Exit all shells (exiting Nu)",
|
||||
example: "exit --now",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
let code = if let Some(value) = args.opt::<i64>(0)? {
|
||||
value as i32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let command_action = if args.has_flag("now") {
|
||||
CommandAction::Exit(code)
|
||||
} else {
|
||||
CommandAction::LeaveShell(code)
|
||||
};
|
||||
|
||||
Ok(ActionStream::one(ReturnSuccess::action(command_action)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Exit;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Exit {})
|
||||
}
|
||||
}
|
11
crates/nu-command/src/commands/shells/mod.rs
Normal file
11
crates/nu-command/src/commands/shells/mod.rs
Normal file
@ -0,0 +1,11 @@
|
||||
mod command;
|
||||
mod enter;
|
||||
mod exit;
|
||||
mod next;
|
||||
mod prev;
|
||||
|
||||
pub use command::Shells;
|
||||
pub use enter::Enter;
|
||||
pub use exit::Exit;
|
||||
pub use next::Next;
|
||||
pub use prev::Previous;
|
41
crates/nu-command/src/commands/shells/next.rs
Normal file
41
crates/nu-command/src/commands/shells/next.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature};
|
||||
|
||||
pub struct Next;
|
||||
|
||||
impl WholeStreamCommand for Next {
|
||||
fn name(&self) -> &str {
|
||||
"n"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("n")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Go to next shell."
|
||||
}
|
||||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
Ok(next(args))
|
||||
}
|
||||
}
|
||||
|
||||
fn next(_args: CommandArgs) -> ActionStream {
|
||||
vec![Ok(ReturnSuccess::Action(CommandAction::NextShell))].into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Next;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Next {})
|
||||
}
|
||||
}
|
42
crates/nu-command/src/commands/shells/prev.rs
Normal file
42
crates/nu-command/src/commands/shells/prev.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature};
|
||||
|
||||
use nu_engine::WholeStreamCommand;
|
||||
|
||||
pub struct Previous;
|
||||
|
||||
impl WholeStreamCommand for Previous {
|
||||
fn name(&self) -> &str {
|
||||
"p"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("p")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Go to previous shell."
|
||||
}
|
||||
|
||||
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
||||
Ok(previous(args))
|
||||
}
|
||||
}
|
||||
|
||||
fn previous(_args: CommandArgs) -> ActionStream {
|
||||
vec![Ok(ReturnSuccess::Action(CommandAction::PreviousShell))].into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Previous;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Previous {})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user