add mkdir command

This commit is contained in:
xiuxiu62 2021-10-07 15:20:23 -07:00
parent 8550f50522
commit bdfe8c0888
5 changed files with 94 additions and 17 deletions

View file

@ -35,6 +35,7 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
working_set.add_decl(Box::new(LetEnv));
working_set.add_decl(Box::new(Lines));
working_set.add_decl(Box::new(Ls));
working_set.add_decl(Box::new(Mkdir));
working_set.add_decl(Box::new(Module));
working_set.add_decl(Box::new(Mv));
working_set.add_decl(Box::new(Ps));

View file

@ -0,0 +1,74 @@
use std::collections::VecDeque;
use std::env::current_dir;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EvaluationContext};
use nu_protocol::{ShellError, Signature, SyntaxShape, Value, ValueStream};
pub struct Mkdir;
impl Command for Mkdir {
fn name(&self) -> &str {
"mkdir"
}
fn signature(&self) -> Signature {
Signature::build("mkdir")
.rest(
"rest",
SyntaxShape::Filepath,
"the name(s) of the path(s) to create",
)
.switch("show-created-paths", "show the path(s) created.", Some('s'))
}
fn usage(&self) -> &str {
"Make directories, creates intermediary directories as required."
}
fn run(
&self,
context: &EvaluationContext,
call: &Call,
_input: Value,
) -> Result<Value, ShellError> {
let path = current_dir()?;
let mut directories = call
.rest::<String>(context, 0)?
.into_iter()
.map(|dir| path.join(dir))
.peekable();
let show_created_paths = call.has_flag("show-created-paths");
let mut stream: VecDeque<Value> = VecDeque::new();
if directories.peek().is_none() {
return Err(ShellError::MissingParameter(
"requires directory paths".to_string(),
call.head,
));
}
for (i, dir) in directories.enumerate() {
let span = call.positional[i].span;
let dir_res = std::fs::create_dir_all(&dir);
if let Err(reason) = dir_res {
return Err(ShellError::CreateNotPossible(
format!("failed to create directory: {}", reason),
call.positional[i].span,
));
}
if show_created_paths {
let val = format!("{:}", dir.to_string_lossy());
stream.push_back(Value::String { val, span });
}
}
let stream = ValueStream::from_stream(stream.into_iter());
let span = call.head;
Ok(Value::Stream { stream, span })
}
}

View file

@ -1,6 +1,7 @@
mod cd;
mod cp;
mod ls;
mod mkdir;
mod mv;
mod touch;
mod util;
@ -8,5 +9,6 @@ mod util;
pub use cd::Cd;
pub use cp::Cp;
pub use ls::Ls;
pub use mkdir::Mkdir;
pub use mv::Mv;
pub use touch::Touch;

View file

@ -32,25 +32,21 @@ impl Command for Touch {
call: &Call,
_input: Value,
) -> Result<Value, ShellError> {
touch(context, call)
}
}
let target: String = call.req(context, 0)?;
let rest: Vec<String> = call.rest(context, 1)?;
fn touch(context: &EvaluationContext, call: &Call) -> Result<Value, ShellError> {
let target: String = call.req(context, 0)?;
let rest: Vec<String> = call.rest(context, 1)?;
for (index, item) in vec![target].into_iter().chain(rest).enumerate() {
match OpenOptions::new().write(true).create(true).open(&item) {
Ok(_) => continue,
Err(err) => {
return Err(ShellError::CreateNotPossible(
format!("Failed to create file: {}", err),
call.positional[index].span,
));
for (index, item) in vec![target].into_iter().chain(rest).enumerate() {
match OpenOptions::new().write(true).create(true).open(&item) {
Ok(_) => continue,
Err(err) => {
return Err(ShellError::CreateNotPossible(
format!("Failed to create file: {}", err),
call.positional[index].span,
));
}
}
}
}
Ok(Value::Nothing { span: call.head })
Ok(Value::Nothing { span: call.head })
}
}

View file

@ -27,6 +27,10 @@ pub enum ShellError {
#[diagnostic(code(nu::shell::unknown_operator), url(docsrs))]
UnknownOperator(String, #[label = "unsupported operator"] Span),
#[error("Missing parameter: {0}.")]
#[diagnostic(code(nu::shell::missing_parameter), url(docsrs))]
MissingParameter(String, #[label = "missing parameter: {0}"] Span),
#[error("External commands not yet supported")]
#[diagnostic(code(nu::shell::external_commands), url(docsrs))]
ExternalNotSupported(#[label = "external not supported"] Span),