mirror of
https://github.com/nushell/nushell
synced 2025-01-15 22:54:16 +00:00
Extend 'Shell' with open and save capabilities (#2165)
* Extend 'Shell' with open and save capabilities * clippy fix
This commit is contained in:
parent
7a207a673b
commit
07594222c0
7 changed files with 138 additions and 29 deletions
|
@ -1,17 +1,14 @@
|
|||
use crate::commands::classified::maybe_text_codec::{MaybeTextCodec, StringOrBinary};
|
||||
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||
use crate::commands::constants::BAT_LANGUAGES;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use futures_codec::FramedRead;
|
||||
use encoding_rs::{Encoding, UTF_8};
|
||||
use futures_util::StreamExt;
|
||||
use log::debug;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::{AnchorLocation, Span, Tagged};
|
||||
use std::path::PathBuf;
|
||||
extern crate encoding_rs;
|
||||
use crate::commands::constants::BAT_LANGUAGES;
|
||||
use encoding_rs::*;
|
||||
use futures::prelude::*;
|
||||
use log::debug;
|
||||
use std::fs::File;
|
||||
|
||||
pub struct Open;
|
||||
|
||||
|
@ -103,6 +100,7 @@ pub fn get_encoding(opt: Option<Tagged<String>>) -> Result<&'static Encoding, Sh
|
|||
async fn open(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
let cwd = PathBuf::from(args.shell_manager.path());
|
||||
let registry = registry.clone();
|
||||
let shell_manager = args.shell_manager.clone();
|
||||
|
||||
let (
|
||||
OpenArgs {
|
||||
|
@ -159,17 +157,8 @@ async fn open(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
|
|||
} else {
|
||||
Some(get_encoding(encoding)?)
|
||||
};
|
||||
let f = File::open(&path).map_err(|e| {
|
||||
ShellError::labeled_error(
|
||||
format!("Error opening file: {:?}", e),
|
||||
"Error opening file",
|
||||
path.span(),
|
||||
)
|
||||
})?;
|
||||
let async_reader = futures::io::AllowStdIo::new(f);
|
||||
let sob_stream = FramedRead::new(async_reader, MaybeTextCodec::new(with_encoding))
|
||||
.map_err(|e| ShellError::unexpected(format!("AsyncRead failed in open function: {:?}", e)))
|
||||
.into_stream();
|
||||
|
||||
let sob_stream = shell_manager.open(&path.item, path.tag.span, with_encoding)?;
|
||||
|
||||
let final_stream = sob_stream.map(move |x| {
|
||||
// The tag that will used when returning a Value
|
||||
|
|
|
@ -170,7 +170,7 @@ async fn save(
|
|||
let host = raw_args.host.clone();
|
||||
let ctrl_c = raw_args.ctrl_c.clone();
|
||||
let current_errors = raw_args.current_errors.clone();
|
||||
let shell_manager = raw_args.shell_manager.clone();
|
||||
let mut shell_manager = raw_args.shell_manager.clone();
|
||||
|
||||
let head = raw_args.call_info.args.head.clone();
|
||||
let (
|
||||
|
@ -219,7 +219,7 @@ async fn save(
|
|||
host,
|
||||
ctrl_c,
|
||||
current_errors,
|
||||
shell_manager,
|
||||
shell_manager: shell_manager.clone(),
|
||||
call_info: UnevaluatedCallInfo {
|
||||
args: nu_protocol::hir::Call {
|
||||
head,
|
||||
|
@ -252,14 +252,7 @@ async fn save(
|
|||
};
|
||||
|
||||
match content {
|
||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
||||
Ok(_) => Ok(OutputStream::empty()),
|
||||
Err(e) => Err(ShellError::labeled_error(
|
||||
e.to_string(),
|
||||
"IO error while saving",
|
||||
name,
|
||||
)),
|
||||
},
|
||||
Ok(save_data) => shell_manager.save(&full_path, &save_data, name.span),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@ use std::collections::HashMap;
|
|||
use std::io::{Error, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::commands::classified::maybe_text_codec::{MaybeTextCodec, StringOrBinary};
|
||||
use encoding_rs::Encoding;
|
||||
use futures_codec::FramedRead;
|
||||
use futures_util::TryStreamExt;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
|
@ -679,6 +684,45 @@ impl Shell for FilesystemShell {
|
|||
self.path = path.to_string_lossy().to_string();
|
||||
}
|
||||
|
||||
fn open(
|
||||
&self,
|
||||
path: &PathBuf,
|
||||
name: Span,
|
||||
with_encoding: Option<&'static Encoding>,
|
||||
) -> Result<BoxStream<'static, Result<StringOrBinary, ShellError>>, ShellError> {
|
||||
let f = std::fs::File::open(&path).map_err(|e| {
|
||||
ShellError::labeled_error(
|
||||
format!("Error opening file: {:?}", e),
|
||||
"Error opening file",
|
||||
name,
|
||||
)
|
||||
})?;
|
||||
let async_reader = futures::io::AllowStdIo::new(f);
|
||||
let sob_stream = FramedRead::new(async_reader, MaybeTextCodec::new(with_encoding))
|
||||
.map_err(|e| {
|
||||
ShellError::unexpected(format!("AsyncRead failed in open function: {:?}", e))
|
||||
})
|
||||
.into_stream();
|
||||
|
||||
Ok(sob_stream.boxed())
|
||||
}
|
||||
|
||||
fn save(
|
||||
&mut self,
|
||||
full_path: &PathBuf,
|
||||
save_data: &[u8],
|
||||
name: Span,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
match std::fs::write(full_path, save_data) {
|
||||
Ok(_) => Ok(OutputStream::empty()),
|
||||
Err(e) => Err(ShellError::labeled_error(
|
||||
e.to_string(),
|
||||
"IO error while saving",
|
||||
name,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
|
|
|
@ -12,6 +12,8 @@ use crate::shell::shell::Shell;
|
|||
use std::ffi::OsStr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||
use encoding_rs::Encoding;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
Primitive, ReturnSuccess, ShellTypeName, TaggedDictBuilder, UntaggedValue, Value,
|
||||
|
@ -197,6 +199,28 @@ impl Shell for HelpShell {
|
|||
Ok(OutputStream::empty())
|
||||
}
|
||||
|
||||
fn open(
|
||||
&self,
|
||||
_path: &PathBuf,
|
||||
_name: Span,
|
||||
_with_encoding: Option<&'static Encoding>,
|
||||
) -> Result<BoxStream<'static, Result<StringOrBinary, ShellError>>, ShellError> {
|
||||
Err(ShellError::unimplemented(
|
||||
"open on help shell is not supported",
|
||||
))
|
||||
}
|
||||
|
||||
fn save(
|
||||
&mut self,
|
||||
_path: &PathBuf,
|
||||
_contents: &[u8],
|
||||
_name: Span,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
Err(ShellError::unimplemented(
|
||||
"save on help shell is not supported",
|
||||
))
|
||||
}
|
||||
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::commands::cd::CdArgs;
|
||||
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
|
@ -7,6 +8,7 @@ use crate::commands::move_::mv::Arguments as MvArgs;
|
|||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::prelude::*;
|
||||
use crate::stream::OutputStream;
|
||||
use encoding_rs::Encoding;
|
||||
use nu_errors::ShellError;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -28,6 +30,18 @@ pub trait Shell: std::fmt::Debug {
|
|||
fn path(&self) -> String;
|
||||
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
||||
fn set_path(&mut self, path: String);
|
||||
fn open(
|
||||
&self,
|
||||
path: &PathBuf,
|
||||
name: Span,
|
||||
with_encoding: Option<&'static Encoding>,
|
||||
) -> Result<BoxStream<'static, Result<StringOrBinary, ShellError>>, ShellError>;
|
||||
fn save(
|
||||
&mut self,
|
||||
path: &PathBuf,
|
||||
contents: &[u8],
|
||||
name: Span,
|
||||
) -> Result<OutputStream, ShellError>;
|
||||
|
||||
fn complete(
|
||||
&self,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::commands::cd::CdArgs;
|
||||
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::ls::LsArgs;
|
||||
|
@ -9,6 +10,7 @@ use crate::prelude::*;
|
|||
use crate::shell::filesystem_shell::FilesystemShell;
|
||||
use crate::shell::shell::Shell;
|
||||
use crate::stream::OutputStream;
|
||||
use encoding_rs::Encoding;
|
||||
use nu_errors::ShellError;
|
||||
use parking_lot::Mutex;
|
||||
use std::error::Error;
|
||||
|
@ -81,6 +83,25 @@ impl ShellManager {
|
|||
self.shells.lock()[self.current_shell()].set_path(path)
|
||||
}
|
||||
|
||||
pub fn open(
|
||||
&self,
|
||||
full_path: &PathBuf,
|
||||
name: Span,
|
||||
with_encoding: Option<&'static Encoding>,
|
||||
) -> Result<impl Stream<Item = Result<StringOrBinary, ShellError>> + Send + 'static, ShellError>
|
||||
{
|
||||
self.shells.lock()[self.current_shell()].open(full_path, name, with_encoding)
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
&mut self,
|
||||
full_path: &PathBuf,
|
||||
save_data: &[u8],
|
||||
name: Span,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
self.shells.lock()[self.current_shell()].save(full_path, save_data, name)
|
||||
}
|
||||
|
||||
pub fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
|
|
|
@ -9,6 +9,8 @@ use crate::prelude::*;
|
|||
use crate::shell::shell::Shell;
|
||||
use crate::utils::ValueStructure;
|
||||
|
||||
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||
use encoding_rs::Encoding;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
@ -230,6 +232,28 @@ impl Shell for ValueShell {
|
|||
self.path = path;
|
||||
}
|
||||
|
||||
fn open(
|
||||
&self,
|
||||
_path: &PathBuf,
|
||||
_name: Span,
|
||||
_with_encoding: Option<&'static Encoding>,
|
||||
) -> Result<BoxStream<'static, Result<StringOrBinary, ShellError>>, ShellError> {
|
||||
Err(ShellError::unimplemented(
|
||||
"open on help shell is not supported",
|
||||
))
|
||||
}
|
||||
|
||||
fn save(
|
||||
&mut self,
|
||||
_path: &PathBuf,
|
||||
_contents: &[u8],
|
||||
_name: Span,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
Err(ShellError::unimplemented(
|
||||
"save on help shell is not supported",
|
||||
))
|
||||
}
|
||||
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
|
|
Loading…
Reference in a new issue