Merge master

This commit is contained in:
Jonathan Turner
2019-11-17 06:17:05 +13:00
195 changed files with 19791 additions and 5402 deletions

View File

@ -3,7 +3,6 @@ use crate::commands::cp::CopyArgs;
use crate::commands::mkdir::MkdirArgs;
use crate::commands::mv::MoveArgs;
use crate::commands::rm::RemoveArgs;
use crate::context::SourceMap;
use crate::data::dir_entry_dict;
use crate::prelude::*;
use crate::shell::completer::NuCompleter;
@ -12,6 +11,8 @@ use crate::utils::FileStructure;
use rustyline::completion::FilenameCompleter;
use rustyline::hint::{Hinter, HistoryHinter};
use std::path::{Path, PathBuf};
use std::sync::atomic::Ordering;
use trash as SendToTrash;
pub struct FilesystemShell {
pub(crate) path: String,
@ -73,7 +74,7 @@ impl FilesystemShell {
}
impl Shell for FilesystemShell {
fn name(&self, _source_map: &SourceMap) -> String {
fn name(&self) -> String {
"filesystem".to_string()
}
@ -84,7 +85,7 @@ impl Shell for FilesystemShell {
fn ls(
&self,
pattern: Option<Tagged<PathBuf>>,
command_tag: Tag,
context: &RunnableContext,
) -> Result<OutputStream, ShellError> {
let cwd = self.path();
let mut full_path = PathBuf::from(self.path());
@ -94,7 +95,8 @@ impl Shell for FilesystemShell {
_ => {}
}
let mut shell_entries = VecDeque::new();
let ctrl_c = context.ctrl_c.clone();
let name_tag = context.name.clone();
//If it's not a glob, try to display the contents of the entry if it's a directory
let lossy_path = full_path.to_string_lossy();
@ -114,24 +116,33 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error(
e.to_string(),
e.to_string(),
command_tag,
name_tag,
));
}
}
Ok(o) => o,
};
for entry in entries {
let entry = entry?;
let filepath = entry.path();
let filename = if let Ok(fname) = filepath.strip_prefix(&cwd) {
fname
} else {
Path::new(&filepath)
};
let value = dir_entry_dict(filename, &entry.metadata()?, command_tag)?;
shell_entries.push_back(ReturnSuccess::value(value))
}
return Ok(shell_entries.to_output_stream());
let stream = async_stream! {
for entry in entries {
if ctrl_c.load(Ordering::SeqCst) {
break;
}
if let Ok(entry) = entry {
let filepath = entry.path();
if let Ok(metadata) = std::fs::symlink_metadata(&filepath) {
let filename = if let Ok(fname) = filepath.strip_prefix(&cwd) {
fname
} else {
Path::new(&filepath)
};
let value = dir_entry_dict(filename, &metadata, &name_tag)?;
yield ReturnSuccess::value(value);
}
}
}
};
return Ok(stream.to_output_stream());
}
}
@ -145,26 +156,33 @@ impl Shell for FilesystemShell {
source.tag(),
));
} else {
return Err(ShellError::string("Invalid pattern."));
return Err(ShellError::untagged_runtime_error("Invalid pattern."));
}
}
};
// Enumerate the entries from the glob and add each
for entry in entries {
if let Ok(entry) = entry {
let filename = if let Ok(fname) = entry.strip_prefix(&cwd) {
fname
} else {
Path::new(&entry)
};
let metadata = std::fs::metadata(&entry)?;
let value = dir_entry_dict(filename, &metadata, command_tag)?;
shell_entries.push_back(ReturnSuccess::value(value))
}
}
let stream = async_stream! {
for entry in entries {
if ctrl_c.load(Ordering::SeqCst) {
break;
}
if let Ok(entry) = entry {
if let Ok(metadata) = std::fs::symlink_metadata(&entry) {
let filename = if let Ok(fname) = entry.strip_prefix(&cwd) {
fname
} else {
Path::new(&entry)
};
Ok(shell_entries.to_output_stream())
if let Ok(value) = dir_entry_dict(filename, &metadata, &name_tag) {
yield ReturnSuccess::value(value);
}
}
}
}
};
Ok(stream.to_output_stream())
}
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
@ -175,7 +193,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error(
"Can not change to home directory",
"can not go to home",
args.call_info.name_tag,
&args.call_info.name_tag,
))
}
},
@ -605,26 +623,71 @@ impl Shell for FilesystemShell {
}
if entry.is_file() {
match std::fs::rename(&entry, &destination) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
};
#[cfg(not(windows))]
{
match std::fs::rename(&entry, &destination) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
};
}
#[cfg(windows)]
{
match std::fs::copy(&entry, &destination) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(_) => match std::fs::remove_file(&entry) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
},
};
}
}
if entry.is_dir() {
@ -727,26 +790,45 @@ impl Shell for FilesystemShell {
}
if src.is_file() {
match std::fs::rename(src, dst) {
match std::fs::copy(&src, &dst) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
src,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
src,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
}
Ok(_) => match std::fs::remove_file(&src) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
},
};
}
}
@ -806,26 +888,71 @@ impl Shell for FilesystemShell {
to.push(entry_file_name);
if entry.is_file() {
match std::fs::rename(&entry, &to) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
};
#[cfg(not(windows))]
{
match std::fs::rename(&entry, &to) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
};
}
#[cfg(windows)]
{
match std::fs::copy(&entry, &to) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(_) => match std::fs::remove_file(&entry) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Remove {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Remove {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_tag,
));
}
Ok(o) => o,
},
};
}
}
}
}
@ -843,7 +970,11 @@ impl Shell for FilesystemShell {
fn rm(
&self,
RemoveArgs { target, recursive }: RemoveArgs,
RemoveArgs {
target,
recursive,
trash,
}: RemoveArgs,
name: Tag,
path: &str,
) -> Result<OutputStream, ShellError> {
@ -926,7 +1057,9 @@ impl Shell for FilesystemShell {
));
}
if path.is_dir() {
if trash.item {
SendToTrash::remove(path).unwrap();
} else if path.is_dir() {
std::fs::remove_dir_all(&path)?;
} else if path.is_file() {
std::fs::remove_file(&path)?;
@ -957,7 +1090,7 @@ impl Shell for FilesystemShell {
return Err(ShellError::labeled_error(
"unable to show current directory",
"pwd command failed",
args.call_info.name_tag,
&args.call_info.name_tag,
));
}
};
@ -965,7 +1098,7 @@ impl Shell for FilesystemShell {
let mut stream = VecDeque::new();
stream.push_back(ReturnSuccess::value(
Value::Primitive(Primitive::String(p.to_string_lossy().to_string()))
.tagged(args.call_info.name_tag),
.tagged(&args.call_info.name_tag),
));
Ok(stream.into())

View File

@ -3,7 +3,6 @@ use crate::commands::cp::CopyArgs;
use crate::commands::mkdir::MkdirArgs;
use crate::commands::mv::MoveArgs;
use crate::commands::rm::RemoveArgs;
use crate::context::SourceMap;
use crate::data::{command_dict, TaggedDictBuilder};
use crate::prelude::*;
use crate::shell::shell::Shell;
@ -98,8 +97,8 @@ impl HelpShell {
}
impl Shell for HelpShell {
fn name(&self, source_map: &SourceMap) -> String {
let anchor_name = self.value.anchor_name(source_map);
fn name(&self) -> String {
let anchor_name = self.value.anchor_name();
format!(
"{}",
match anchor_name {
@ -129,7 +128,7 @@ impl Shell for HelpShell {
fn ls(
&self,
_pattern: Option<Tagged<PathBuf>>,
_command_tag: Tag,
_context: &RunnableContext,
) -> Result<OutputStream, ShellError> {
Ok(self
.commands()

View File

@ -1,10 +1,11 @@
use crate::context::Context;
use crate::parser::hir::syntax_shape::{color_fallible_syntax, FlatShape, PipelineShape};
use crate::parser::hir::TokensIterator;
use crate::parser::nom_input;
use crate::parser::parse::token_tree::TokenNode;
use crate::parser::parse::tokens::RawToken;
use crate::parser::{Pipeline, PipelineElement};
use crate::shell::shell_manager::ShellManager;
use crate::Tagged;
use crate::{HasSpan, Spanned, SpannedItem, Tag, Tagged, Text};
use ansi_term::Color;
use log::{log_enabled, trace};
use rustyline::completion::Completer;
use rustyline::error::ReadlineError;
use rustyline::highlight::Highlighter;
@ -12,12 +13,12 @@ use rustyline::hint::Hinter;
use std::borrow::Cow::{self, Owned};
pub(crate) struct Helper {
helper: ShellManager,
context: Context,
}
impl Helper {
pub(crate) fn new(helper: ShellManager) -> Helper {
Helper { helper }
pub(crate) fn new(context: Context) -> Helper {
Helper { context }
}
}
@ -29,30 +30,13 @@ impl Completer for Helper {
pos: usize,
ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<rustyline::completion::Pair>), ReadlineError> {
self.helper.complete(line, pos, ctx)
self.context.shell_manager.complete(line, pos, ctx)
}
}
/*
impl Completer for Helper {
type Candidate = rustyline::completion::Pair;
fn complete(
&self,
line: &str,
pos: usize,
ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<rustyline::completion::Pair>), ReadlineError> {
let result = self.helper.complete(line, pos, ctx);
result.map(|(x, y)| (x, y.iter().map(|z| z.into()).collect()))
}
}
*/
impl Hinter for Helper {
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.helper.hint(line, pos, ctx)
self.context.shell_manager.hint(line, pos, ctx)
}
}
@ -66,7 +50,7 @@ impl Highlighter for Helper {
}
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
let tokens = crate::parser::pipeline(nom_input(line, uuid::Uuid::nil()));
let tokens = crate::parser::pipeline(nom_input(line));
match tokens {
Err(_) => Cow::Borrowed(line),
@ -77,24 +61,49 @@ impl Highlighter for Helper {
Ok(v) => v,
};
let Pipeline { parts, post_ws } = pipeline;
let mut iter = parts.into_iter();
let tokens = vec![TokenNode::Pipeline(pipeline.clone().spanned(v.span()))];
let mut tokens = TokensIterator::all(&tokens[..], v.span());
loop {
match iter.next() {
None => {
if let Some(ws) = post_ws {
out.push_str(ws.slice(line));
}
let text = Text::from(line);
let expand_context = self.context.expand_context(&text);
return Cow::Owned(out);
}
Some(token) => {
let styled = paint_pipeline_element(&token, line);
out.push_str(&styled.to_string());
}
}
#[cfg(not(coloring_in_tokens))]
let shapes = {
let mut shapes = vec![];
color_fallible_syntax(
&PipelineShape,
&mut tokens,
&expand_context,
&mut shapes,
)
.unwrap();
shapes
};
#[cfg(coloring_in_tokens)]
let shapes = {
// We just constructed a token list that only contains a pipeline, so it can't fail
color_fallible_syntax(&PipelineShape, &mut tokens, &expand_context).unwrap();
tokens.with_color_tracer(|_, tracer| tracer.finish());
tokens.state().shapes()
};
trace!(target: "nu::color_syntax", "{:#?}", tokens.color_tracer());
if log_enabled!(target: "nu::color_syntax", log::Level::Debug) {
println!("");
ptree::print_tree(&tokens.color_tracer().clone().print(Text::from(line)))
.unwrap();
println!("");
}
for shape in shapes {
let styled = paint_flat_shape(&shape, line);
out.push_str(&styled);
}
Cow::Owned(out)
}
}
}
@ -104,83 +113,55 @@ impl Highlighter for Helper {
}
}
fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
let styled = match token_node {
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.tag().slice(line)),
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.tag().slice(line)),
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.tag().slice(line)),
TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.tag().slice(line)),
TokenNode::Path(..) => Color::Green.bold().paint(token_node.tag().slice(line)),
TokenNode::Error(..) => Color::Red.bold().paint(token_node.tag().slice(line)),
TokenNode::Delimited(..) => Color::White.paint(token_node.tag().slice(line)),
TokenNode::Operator(..) => Color::White.normal().paint(token_node.tag().slice(line)),
TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::Number(..),
..
}) => Color::Purple.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::Size(..),
..
}) => Color::Purple.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::GlobPattern,
..
}) => Color::Cyan.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::String(..),
..
}) => Color::Green.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::Variable(..),
..
}) => Color::Yellow.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::Bare,
..
}) => Color::Green.normal().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::ExternalCommand(..),
..
}) => Color::Cyan.bold().paint(token_node.tag().slice(line)),
TokenNode::Token(Tagged {
item: RawToken::ExternalWord,
..
}) => Color::Black.bold().paint(token_node.tag().slice(line)),
};
#[allow(unused)]
fn vec_tag<T>(input: Vec<Tagged<T>>) -> Option<Tag> {
let mut iter = input.iter();
let first = iter.next()?.tag.clone();
let last = iter.last();
styled.to_string()
Some(match last {
None => first,
Some(last) => first.until(&last.tag),
})
}
fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> String {
let mut styled = String::new();
if let Some(_) = pipeline_element.pipe {
styled.push_str(&Color::Purple.paint("|"));
}
if let Some(ws) = pipeline_element.pre_ws {
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
}
styled.push_str(
&Color::Cyan
.bold()
.paint(pipeline_element.call().head().tag().slice(line))
.to_string(),
);
if let Some(children) = pipeline_element.call().children() {
for child in children {
styled.push_str(&paint_token_node(child, line));
fn paint_flat_shape(flat_shape: &Spanned<FlatShape>, line: &str) -> String {
let style = match &flat_shape.item {
FlatShape::OpenDelimiter(_) => Color::White.normal(),
FlatShape::CloseDelimiter(_) => Color::White.normal(),
FlatShape::ItVariable => Color::Purple.bold(),
FlatShape::Variable => Color::Purple.normal(),
FlatShape::Operator => Color::Yellow.normal(),
FlatShape::Dot => Color::White.normal(),
FlatShape::InternalCommand => Color::Cyan.bold(),
FlatShape::ExternalCommand => Color::Cyan.normal(),
FlatShape::ExternalWord => Color::Black.bold(),
FlatShape::BareMember => Color::Yellow.bold(),
FlatShape::StringMember => Color::Yellow.bold(),
FlatShape::String => Color::Green.normal(),
FlatShape::Path => Color::Cyan.normal(),
FlatShape::GlobPattern => Color::Cyan.bold(),
FlatShape::Word => Color::Green.normal(),
FlatShape::Pipe => Color::Purple.bold(),
FlatShape::Flag => Color::Black.bold(),
FlatShape::ShorthandFlag => Color::Black.bold(),
FlatShape::Int => Color::Purple.bold(),
FlatShape::Decimal => Color::Purple.bold(),
FlatShape::Whitespace => Color::White.normal(),
FlatShape::Error => Color::Red.bold(),
FlatShape::Size { number, unit } => {
let number = number.slice(line);
let unit = unit.slice(line);
return format!(
"{}{}",
Color::Purple.bold().paint(number),
Color::Cyan.bold().paint(unit)
);
}
}
};
if let Some(ws) = pipeline_element.post_ws {
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
}
styled.to_string()
let body = flat_shape.span.slice(line);
style.paint(body).to_string()
}
impl rustyline::Helper for Helper {}

View File

@ -3,20 +3,19 @@ use crate::commands::cp::CopyArgs;
use crate::commands::mkdir::MkdirArgs;
use crate::commands::mv::MoveArgs;
use crate::commands::rm::RemoveArgs;
use crate::context::SourceMap;
use crate::errors::ShellError;
use crate::prelude::*;
use crate::stream::OutputStream;
use std::path::PathBuf;
pub trait Shell: std::fmt::Debug {
fn name(&self, source_map: &SourceMap) -> String;
fn name(&self) -> String;
fn homedir(&self) -> Option<PathBuf>;
fn ls(
&self,
pattern: Option<Tagged<PathBuf>>,
command_tag: Tag,
context: &RunnableContext,
) -> Result<OutputStream, ShellError>;
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn cp(&self, args: CopyArgs, name: Tag, path: &str) -> Result<OutputStream, ShellError>;

View File

@ -10,18 +10,19 @@ use crate::shell::shell::Shell;
use crate::stream::OutputStream;
use std::error::Error;
use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug)]
pub struct ShellManager {
pub(crate) current_shell: usize,
pub(crate) current_shell: Arc<AtomicUsize>,
pub(crate) shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>,
}
impl ShellManager {
pub fn basic(commands: CommandRegistry) -> Result<ShellManager, Box<dyn Error>> {
Ok(ShellManager {
current_shell: 0,
current_shell: Arc::new(AtomicUsize::new(0)),
shells: Arc::new(Mutex::new(vec![Box::new(FilesystemShell::basic(
commands,
)?)])),
@ -30,24 +31,29 @@ impl ShellManager {
pub fn insert_at_current(&mut self, shell: Box<dyn Shell + Send>) {
self.shells.lock().unwrap().push(shell);
self.current_shell = self.shells.lock().unwrap().len() - 1;
self.current_shell
.store(self.shells.lock().unwrap().len() - 1, Ordering::SeqCst);
self.set_path(self.path());
}
pub fn current_shell(&self) -> usize {
self.current_shell.load(Ordering::SeqCst)
}
pub fn remove_at_current(&mut self) {
{
let mut shells = self.shells.lock().unwrap();
if shells.len() > 0 {
if self.current_shell == shells.len() - 1 {
if self.current_shell() == shells.len() - 1 {
shells.pop();
let new_len = shells.len();
if new_len > 0 {
self.current_shell = new_len - 1;
self.current_shell.store(new_len - 1, Ordering::SeqCst);
} else {
return;
}
} else {
shells.remove(self.current_shell);
shells.remove(self.current_shell());
}
}
}
@ -59,17 +65,17 @@ impl ShellManager {
}
pub fn path(&self) -> String {
self.shells.lock().unwrap()[self.current_shell].path()
self.shells.lock().unwrap()[self.current_shell()].path()
}
pub fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap();
env[self.current_shell].pwd(args)
env[self.current_shell()].pwd(args)
}
pub fn set_path(&mut self, path: String) {
self.shells.lock().unwrap()[self.current_shell].set_path(path)
self.shells.lock().unwrap()[self.current_shell()].set_path(path)
}
pub fn complete(
@ -78,20 +84,21 @@ impl ShellManager {
pos: usize,
ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<rustyline::completion::Pair>), rustyline::error::ReadlineError> {
self.shells.lock().unwrap()[self.current_shell].complete(line, pos, ctx)
self.shells.lock().unwrap()[self.current_shell()].complete(line, pos, ctx)
}
pub fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.shells.lock().unwrap()[self.current_shell].hint(line, pos, ctx)
self.shells.lock().unwrap()[self.current_shell()].hint(line, pos, ctx)
}
pub fn next(&mut self) {
{
let shell_len = self.shells.lock().unwrap().len();
if self.current_shell == (shell_len - 1) {
self.current_shell = 0;
if self.current_shell() == (shell_len - 1) {
self.current_shell.store(0, Ordering::SeqCst);
} else {
self.current_shell += 1;
self.current_shell
.store(self.current_shell() + 1, Ordering::SeqCst);
}
}
self.set_path(self.path());
@ -100,10 +107,11 @@ impl ShellManager {
pub fn prev(&mut self) {
{
let shell_len = self.shells.lock().unwrap().len();
if self.current_shell == 0 {
self.current_shell = shell_len - 1;
if self.current_shell() == 0 {
self.current_shell.store(shell_len - 1, Ordering::SeqCst);
} else {
self.current_shell -= 1;
self.current_shell
.store(self.current_shell() - 1, Ordering::SeqCst);
}
}
self.set_path(self.path());
@ -112,23 +120,23 @@ impl ShellManager {
pub fn homedir(&self) -> Option<PathBuf> {
let env = self.shells.lock().unwrap();
env[self.current_shell].homedir()
env[self.current_shell()].homedir()
}
pub fn ls(
&self,
path: Option<Tagged<PathBuf>>,
command_tag: Tag,
context: &RunnableContext,
) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap();
env[self.current_shell].ls(path, command_tag)
env[self.current_shell()].ls(path, context)
}
pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap();
env[self.current_shell].cd(args)
env[self.current_shell()].cd(args)
}
pub fn cp(
@ -140,13 +148,13 @@ impl ShellManager {
match env {
Ok(x) => {
let path = x[self.current_shell].path();
x[self.current_shell].cp(args, context.name, &path)
let path = x[self.current_shell()].path();
x[self.current_shell()].cp(args, context.name.clone(), &path)
}
Err(e) => Err(ShellError::labeled_error(
format!("Internal error: could not lock {}", e),
"Internal error: could not lock",
context.name,
&context.name,
)),
}
}
@ -160,13 +168,13 @@ impl ShellManager {
match env {
Ok(x) => {
let path = x[self.current_shell].path();
x[self.current_shell].rm(args, context.name, &path)
let path = x[self.current_shell()].path();
x[self.current_shell()].rm(args, context.name.clone(), &path)
}
Err(e) => Err(ShellError::labeled_error(
format!("Internal error: could not lock {}", e),
"Internal error: could not lock",
context.name,
&context.name,
)),
}
}
@ -180,13 +188,13 @@ impl ShellManager {
match env {
Ok(x) => {
let path = x[self.current_shell].path();
x[self.current_shell].mkdir(args, context.name, &path)
let path = x[self.current_shell()].path();
x[self.current_shell()].mkdir(args, context.name.clone(), &path)
}
Err(e) => Err(ShellError::labeled_error(
format!("Internal error: could not lock {}", e),
"Internal error: could not lock",
context.name,
&context.name,
)),
}
}
@ -200,13 +208,13 @@ impl ShellManager {
match env {
Ok(x) => {
let path = x[self.current_shell].path();
x[self.current_shell].mv(args, context.name, &path)
let path = x[self.current_shell()].path();
x[self.current_shell()].mv(args, context.name.clone(), &path)
}
Err(e) => Err(ShellError::labeled_error(
format!("Internal error: could not lock {}", e),
"Internal error: could not lock",
context.name,
&context.name,
)),
}
}

View File

@ -3,7 +3,6 @@ use crate::commands::cp::CopyArgs;
use crate::commands::mkdir::MkdirArgs;
use crate::commands::mv::MoveArgs;
use crate::commands::rm::RemoveArgs;
use crate::context::SourceMap;
use crate::prelude::*;
use crate::shell::shell::Shell;
use crate::utils::ValueStructure;
@ -72,8 +71,8 @@ impl ValueShell {
}
impl Shell for ValueShell {
fn name(&self, source_map: &SourceMap) -> String {
let anchor_name = self.value.anchor_name(source_map);
fn name(&self) -> String {
let anchor_name = self.value.anchor_name();
format!(
"{}",
match anchor_name {
@ -90,9 +89,10 @@ impl Shell for ValueShell {
fn ls(
&self,
target: Option<Tagged<PathBuf>>,
command_name: Tag,
context: &RunnableContext,
) -> Result<OutputStream, ShellError> {
let mut full_path = PathBuf::from(self.path());
let name_tag = context.name.clone();
match &target {
Some(value) => full_path.push(value.as_ref()),
@ -114,7 +114,7 @@ impl Shell for ValueShell {
return Err(ShellError::labeled_error(
"Can not list entries inside",
"No such path exists",
command_name,
name_tag,
));
}
@ -166,7 +166,7 @@ impl Shell for ValueShell {
return Err(ShellError::labeled_error(
"Can not change to path inside",
"No such path exists",
args.call_info.name_tag,
&args.call_info.name_tag,
));
}
@ -213,10 +213,9 @@ impl Shell for ValueShell {
fn pwd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
let mut stream = VecDeque::new();
stream.push_back(ReturnSuccess::value(Tagged::from_item(
Value::string(self.path()),
args.call_info.name_tag,
)));
stream.push_back(ReturnSuccess::value(
Value::string(self.path()).tagged(&args.call_info.name_tag),
));
Ok(stream.into())
}