mirror of
https://github.com/nushell/nushell.git
synced 2025-04-10 14:08:40 +02: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
@ -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::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
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_errors::ShellError;
|
||||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
use nu_source::{AnchorLocation, Span, Tagged};
|
use nu_source::{AnchorLocation, Span, Tagged};
|
||||||
use std::path::PathBuf;
|
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;
|
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> {
|
async fn open(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let cwd = PathBuf::from(args.shell_manager.path());
|
let cwd = PathBuf::from(args.shell_manager.path());
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
|
let shell_manager = args.shell_manager.clone();
|
||||||
|
|
||||||
let (
|
let (
|
||||||
OpenArgs {
|
OpenArgs {
|
||||||
@ -159,17 +157,8 @@ async fn open(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
|
|||||||
} else {
|
} else {
|
||||||
Some(get_encoding(encoding)?)
|
Some(get_encoding(encoding)?)
|
||||||
};
|
};
|
||||||
let f = File::open(&path).map_err(|e| {
|
|
||||||
ShellError::labeled_error(
|
let sob_stream = shell_manager.open(&path.item, path.tag.span, with_encoding)?;
|
||||||
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 final_stream = sob_stream.map(move |x| {
|
let final_stream = sob_stream.map(move |x| {
|
||||||
// The tag that will used when returning a Value
|
// The tag that will used when returning a Value
|
||||||
|
@ -170,7 +170,7 @@ async fn save(
|
|||||||
let host = raw_args.host.clone();
|
let host = raw_args.host.clone();
|
||||||
let ctrl_c = raw_args.ctrl_c.clone();
|
let ctrl_c = raw_args.ctrl_c.clone();
|
||||||
let current_errors = raw_args.current_errors.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 head = raw_args.call_info.args.head.clone();
|
||||||
let (
|
let (
|
||||||
@ -219,7 +219,7 @@ async fn save(
|
|||||||
host,
|
host,
|
||||||
ctrl_c,
|
ctrl_c,
|
||||||
current_errors,
|
current_errors,
|
||||||
shell_manager,
|
shell_manager: shell_manager.clone(),
|
||||||
call_info: UnevaluatedCallInfo {
|
call_info: UnevaluatedCallInfo {
|
||||||
args: nu_protocol::hir::Call {
|
args: nu_protocol::hir::Call {
|
||||||
head,
|
head,
|
||||||
@ -252,14 +252,7 @@ async fn save(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match content {
|
match content {
|
||||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
Ok(save_data) => shell_manager.save(&full_path, &save_data, name.span),
|
||||||
Ok(_) => Ok(OutputStream::empty()),
|
|
||||||
Err(e) => Err(ShellError::labeled_error(
|
|
||||||
e.to_string(),
|
|
||||||
"IO error while saving",
|
|
||||||
name,
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,11 @@ use std::collections::HashMap;
|
|||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use std::path::{Path, PathBuf};
|
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)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
|
||||||
@ -679,6 +684,45 @@ impl Shell for FilesystemShell {
|
|||||||
self.path = path.to_string_lossy().to_string();
|
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(
|
fn complete(
|
||||||
&self,
|
&self,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
@ -12,6 +12,8 @@ use crate::shell::shell::Shell;
|
|||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||||
|
use encoding_rs::Encoding;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Primitive, ReturnSuccess, ShellTypeName, TaggedDictBuilder, UntaggedValue, Value,
|
Primitive, ReturnSuccess, ShellTypeName, TaggedDictBuilder, UntaggedValue, Value,
|
||||||
@ -197,6 +199,28 @@ impl Shell for HelpShell {
|
|||||||
Ok(OutputStream::empty())
|
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(
|
fn complete(
|
||||||
&self,
|
&self,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::commands::cd::CdArgs;
|
use crate::commands::cd::CdArgs;
|
||||||
|
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||||
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||||
use crate::commands::cp::CopyArgs;
|
use crate::commands::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
@ -7,6 +8,7 @@ use crate::commands::move_::mv::Arguments as MvArgs;
|
|||||||
use crate::commands::rm::RemoveArgs;
|
use crate::commands::rm::RemoveArgs;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::stream::OutputStream;
|
use crate::stream::OutputStream;
|
||||||
|
use encoding_rs::Encoding;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -28,6 +30,18 @@ pub trait Shell: std::fmt::Debug {
|
|||||||
fn path(&self) -> String;
|
fn path(&self) -> String;
|
||||||
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
|
||||||
fn set_path(&mut self, path: String);
|
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(
|
fn complete(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::commands::cd::CdArgs;
|
use crate::commands::cd::CdArgs;
|
||||||
|
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||||
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||||
use crate::commands::cp::CopyArgs;
|
use crate::commands::cp::CopyArgs;
|
||||||
use crate::commands::ls::LsArgs;
|
use crate::commands::ls::LsArgs;
|
||||||
@ -9,6 +10,7 @@ use crate::prelude::*;
|
|||||||
use crate::shell::filesystem_shell::FilesystemShell;
|
use crate::shell::filesystem_shell::FilesystemShell;
|
||||||
use crate::shell::shell::Shell;
|
use crate::shell::shell::Shell;
|
||||||
use crate::stream::OutputStream;
|
use crate::stream::OutputStream;
|
||||||
|
use encoding_rs::Encoding;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@ -81,6 +83,25 @@ impl ShellManager {
|
|||||||
self.shells.lock()[self.current_shell()].set_path(path)
|
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(
|
pub fn complete(
|
||||||
&self,
|
&self,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
@ -9,6 +9,8 @@ use crate::prelude::*;
|
|||||||
use crate::shell::shell::Shell;
|
use crate::shell::shell::Shell;
|
||||||
use crate::utils::ValueStructure;
|
use crate::utils::ValueStructure;
|
||||||
|
|
||||||
|
use crate::commands::classified::maybe_text_codec::StringOrBinary;
|
||||||
|
use encoding_rs::Encoding;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@ -230,6 +232,28 @@ impl Shell for ValueShell {
|
|||||||
self.path = path;
|
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(
|
fn complete(
|
||||||
&self,
|
&self,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
Loading…
Reference in New Issue
Block a user