forked from extern/nushell
commit
58e09e2295
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -1702,6 +1702,7 @@ dependencies = [
|
|||||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syntect 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sys-info 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sys-info 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sysinfo 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sysinfo 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1709,6 +1710,7 @@ dependencies = [
|
|||||||
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"toml-query 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml-query 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3202,6 +3204,7 @@ version = "0.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -76,6 +76,8 @@ crossterm = "0.9.6"
|
|||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
image = "0.21.2"
|
image = "0.21.2"
|
||||||
semver = "0.9.0"
|
semver = "0.9.0"
|
||||||
|
uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
|
||||||
|
syntect = "3.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6.1"
|
pretty_assertions = "0.6.1"
|
||||||
|
BIN
assets/themes.bin
Normal file
BIN
assets/themes.bin
Normal file
Binary file not shown.
@ -495,6 +495,7 @@ fn classify_command(
|
|||||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||||
command,
|
command,
|
||||||
name_span: Some(head.span().clone()),
|
name_span: Some(head.span().clone()),
|
||||||
|
source_map: context.source_map.clone(),
|
||||||
args,
|
args,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::commands::command::SinkCommandArgs;
|
use crate::commands::command::SinkCommandArgs;
|
||||||
|
use crate::context::{SourceMap, SpanSource};
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::format::GenericView;
|
use crate::format::GenericView;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
if args.input.len() > 0 {
|
if args.input.len() > 0 {
|
||||||
@ -11,6 +13,8 @@ pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
|||||||
} = args.input[0]
|
} = args.input[0]
|
||||||
{
|
{
|
||||||
args.ctx.get_sink("binaryview").run(args)?;
|
args.ctx.get_sink("binaryview").run(args)?;
|
||||||
|
} else if is_single_text_value(&args.input) {
|
||||||
|
view_text_value(&args.input[0], &args.call_info.source_map);
|
||||||
} else if equal_shapes(&args.input) {
|
} else if equal_shapes(&args.input) {
|
||||||
args.ctx.get_sink("table").run(args)?;
|
args.ctx.get_sink("table").run(args)?;
|
||||||
} else {
|
} else {
|
||||||
@ -44,3 +48,76 @@ fn equal_shapes(input: &Vec<Spanned<Value>>) -> bool {
|
|||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_single_text_value(input: &Vec<Spanned<Value>>) -> bool {
|
||||||
|
if input.len() != 1 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Spanned {
|
||||||
|
item: Value::Primitive(Primitive::String(_)),
|
||||||
|
..
|
||||||
|
} = input[0]
|
||||||
|
{
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view_text_value(value: &Spanned<Value>, source_map: &SourceMap) {
|
||||||
|
match value {
|
||||||
|
Spanned {
|
||||||
|
item: Value::Primitive(Primitive::String(s)),
|
||||||
|
span,
|
||||||
|
} => {
|
||||||
|
let source = span.source.map(|x| source_map.get(&x)).flatten();
|
||||||
|
|
||||||
|
if let Some(source) = source {
|
||||||
|
match source {
|
||||||
|
SpanSource::File(file) => {
|
||||||
|
let path = Path::new(file);
|
||||||
|
match path.extension() {
|
||||||
|
Some(extension) => {
|
||||||
|
use syntect::easy::HighlightLines;
|
||||||
|
use syntect::highlighting::{Style, ThemeSet};
|
||||||
|
use syntect::parsing::SyntaxSet;
|
||||||
|
use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
|
||||||
|
|
||||||
|
// Load these once at the start of your program
|
||||||
|
let ps = SyntaxSet::load_defaults_newlines();
|
||||||
|
|
||||||
|
if let Some(syntax) =
|
||||||
|
ps.find_syntax_by_extension(extension.to_str().unwrap())
|
||||||
|
{
|
||||||
|
let ts: ThemeSet = syntect::dumps::from_binary(include_bytes!(
|
||||||
|
"../../assets/themes.bin"
|
||||||
|
));
|
||||||
|
let mut h =
|
||||||
|
HighlightLines::new(syntax, &ts.themes["OneHalfDark"]);
|
||||||
|
|
||||||
|
for line in LinesWithEndings::from(s) {
|
||||||
|
let ranges: Vec<(Style, &str)> = h.highlight(line, &ps);
|
||||||
|
let escaped =
|
||||||
|
as_24_bit_terminal_escaped(&ranges[..], false);
|
||||||
|
print!("{}", escaped);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Can not change to home directory",
|
"Can not change to home directory",
|
||||||
"can not go to home",
|
"can not go to home",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::commands::command::Sink;
|
use crate::commands::command::Sink;
|
||||||
|
use crate::context::SourceMap;
|
||||||
use crate::parser::{registry::Args, Span, Spanned, TokenNode};
|
use crate::parser::{registry::Args, Span, Spanned, TokenNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
@ -116,6 +117,7 @@ impl SinkCommand {
|
|||||||
crate struct InternalCommand {
|
crate struct InternalCommand {
|
||||||
crate command: Arc<dyn Command>,
|
crate command: Arc<dyn Command>,
|
||||||
crate name_span: Option<Span>,
|
crate name_span: Option<Span>,
|
||||||
|
crate source_map: SourceMap,
|
||||||
crate args: Args,
|
crate args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,8 +136,13 @@ impl InternalCommand {
|
|||||||
let objects: InputStream =
|
let objects: InputStream =
|
||||||
trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects);
|
trace_stream!(target: "nu::trace_stream::internal", "input" = input.objects);
|
||||||
|
|
||||||
let result =
|
let result = context.run_command(
|
||||||
context.run_command(self.command, self.name_span.clone(), self.args, objects)?;
|
self.command,
|
||||||
|
self.name_span.clone(),
|
||||||
|
self.source_map,
|
||||||
|
self.args,
|
||||||
|
objects,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut result = result.values;
|
let mut result = result.values;
|
||||||
|
|
||||||
@ -146,6 +153,9 @@ impl InternalCommand {
|
|||||||
CommandAction::ChangePath(path) => {
|
CommandAction::ChangePath(path) => {
|
||||||
context.env.lock().unwrap().path = path;
|
context.env.lock().unwrap().path = path;
|
||||||
}
|
}
|
||||||
|
CommandAction::AddSpanSource(uuid, span_source) => {
|
||||||
|
context.add_span_source(uuid, span_source);
|
||||||
|
}
|
||||||
CommandAction::Exit => std::process::exit(0),
|
CommandAction::Exit => std::process::exit(0),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ pub fn clip(args: SinkCommandArgs) -> Result<(), ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let string = i.as_string().map_err(labelled(
|
let string = i.as_string().map_err(labelled(
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
"Given non-string data",
|
"Given non-string data",
|
||||||
"expected strings from pipeline",
|
"expected strings from pipeline",
|
||||||
))?;
|
))?;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::context::SourceMap;
|
||||||
|
use crate::context::SpanSource;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
@ -8,54 +10,61 @@ use crate::prelude::*;
|
|||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct CallInfo {
|
||||||
|
pub args: Args,
|
||||||
|
pub source_map: SourceMap,
|
||||||
|
pub name_span: Option<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Getters)]
|
#[derive(Getters)]
|
||||||
#[get = "crate"]
|
#[get = "crate"]
|
||||||
pub struct CommandArgs {
|
pub struct CommandArgs {
|
||||||
pub host: Arc<Mutex<dyn Host + Send>>,
|
pub host: Arc<Mutex<dyn Host + Send>>,
|
||||||
pub env: Arc<Mutex<Environment>>,
|
pub env: Arc<Mutex<Environment>>,
|
||||||
pub name_span: Option<Span>,
|
pub call_info: CallInfo,
|
||||||
pub args: Args,
|
|
||||||
pub input: InputStream,
|
pub input: InputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandArgs {
|
impl CommandArgs {
|
||||||
pub fn nth(&self, pos: usize) -> Option<&Spanned<Value>> {
|
pub fn nth(&self, pos: usize) -> Option<&Spanned<Value>> {
|
||||||
self.args.nth(pos)
|
self.call_info.args.nth(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn positional_iter(&self) -> impl Iterator<Item = &Spanned<Value>> {
|
pub fn positional_iter(&self) -> impl Iterator<Item = &Spanned<Value>> {
|
||||||
self.args.positional_iter()
|
self.call_info.args.positional_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_nth(&self, pos: usize) -> Result<&Spanned<Value>, ShellError> {
|
pub fn expect_nth(&self, pos: usize) -> Result<&Spanned<Value>, ShellError> {
|
||||||
self.args.expect_nth(pos)
|
self.call_info.args.expect_nth(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.args.len()
|
self.call_info.args.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, name: &str) -> Option<&Spanned<Value>> {
|
pub fn get(&self, name: &str) -> Option<&Spanned<Value>> {
|
||||||
self.args.get(name)
|
self.call_info.args.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn has(&self, name: &str) -> bool {
|
pub fn has(&self, name: &str) -> bool {
|
||||||
self.args.has(name)
|
self.call_info.args.has(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SinkCommandArgs {
|
pub struct SinkCommandArgs {
|
||||||
pub ctx: Context,
|
pub ctx: Context,
|
||||||
pub name_span: Option<Span>,
|
pub call_info: CallInfo,
|
||||||
pub args: Args,
|
|
||||||
pub input: Vec<Spanned<Value>>,
|
pub input: Vec<Spanned<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum CommandAction {
|
pub enum CommandAction {
|
||||||
ChangePath(PathBuf),
|
ChangePath(PathBuf),
|
||||||
|
AddSpanSource(Uuid, SpanSource),
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +91,10 @@ impl ReturnSuccess {
|
|||||||
Ok(ReturnSuccess::Value(input.into()))
|
Ok(ReturnSuccess::Value(input.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn action(input: CommandAction) -> ReturnValue {
|
||||||
|
Ok(ReturnSuccess::Action(input))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
|
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
|
||||||
Ok(ReturnSuccess::Value(Spanned::from_item(input, span)))
|
Ok(ReturnSuccess::Value(Spanned::from_item(input, span)))
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,10 @@ impl Command for Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut result = crate::object::config::config(args.name_span)?;
|
let mut result = crate::object::config::config(args.call_info.name_span)?;
|
||||||
|
|
||||||
trace!("{:#?}", args.args.positional);
|
trace!("{:#?}", args.call_info.args.positional);
|
||||||
trace!("{:#?}", args.args.named);
|
trace!("{:#?}", args.call_info.args.named);
|
||||||
|
|
||||||
if let Some(v) = args.get("get") {
|
if let Some(v) = args.get("get") {
|
||||||
let key = v.as_string()?;
|
let key = v.as_string()?;
|
||||||
@ -95,7 +95,7 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Ok(vec![Value::Object(result.into()).spanned(args.name_span)].into());
|
return Ok(vec![Value::Object(result.into()).spanned(args.call_info.name_span)].into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ShellError::string(format!("Unimplemented")))
|
Err(ShellError::string(format!("Unimplemented")))
|
||||||
|
@ -8,7 +8,7 @@ pub fn first(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"First requires an amount",
|
"First requires an amount",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@ pub fn from_csv_string_to_value(
|
|||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
span: impl Into<Span>,
|
||||||
) -> Result<Spanned<Value>, Box<dyn std::error::Error>> {
|
) -> Result<Spanned<Value>, Box<dyn std::error::Error>> {
|
||||||
|
let mut reader = ReaderBuilder::new()
|
||||||
let mut reader = ReaderBuilder::new().has_headers(false).from_reader(s.as_bytes());
|
.has_headers(false)
|
||||||
|
.from_reader(s.as_bytes());
|
||||||
let span = span.into();
|
let span = span.into();
|
||||||
|
|
||||||
let mut fields: VecDeque<String> = VecDeque::new();
|
let mut fields: VecDeque<String> = VecDeque::new();
|
||||||
@ -28,9 +29,12 @@ pub fn from_csv_string_to_value(
|
|||||||
let row_values = row_values?;
|
let row_values = row_values?;
|
||||||
|
|
||||||
let mut row = SpannedDictBuilder::new(span);
|
let mut row = SpannedDictBuilder::new(span);
|
||||||
|
|
||||||
for (idx, entry) in row_values.iter().enumerate() {
|
for (idx, entry) in row_values.iter().enumerate() {
|
||||||
row.insert_spanned(fields.get(idx).unwrap(), Value::Primitive(Primitive::String(String::from(entry))).spanned(span));
|
row.insert_spanned(
|
||||||
|
fields.get(idx).unwrap(),
|
||||||
|
Value::Primitive(Primitive::String(String::from(entry))).spanned(span),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
rows.insert_spanned(row.into_spanned_value());
|
rows.insert_spanned(row.into_spanned_value());
|
||||||
@ -45,7 +49,7 @@ pub fn from_csv_string_to_value(
|
|||||||
|
|
||||||
pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
|
@ -39,7 +39,7 @@ pub fn from_ini_string_to_value(
|
|||||||
|
|
||||||
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
|
@ -45,7 +45,7 @@ pub fn from_json_string_to_value(
|
|||||||
|
|
||||||
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
|
@ -43,7 +43,7 @@ pub fn from_toml_string_to_value(
|
|||||||
|
|
||||||
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
|
@ -61,7 +61,7 @@ pub fn from_xml_string_to_value(
|
|||||||
|
|
||||||
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
|
@ -50,7 +50,7 @@ pub fn from_yaml_string_to_value(
|
|||||||
|
|
||||||
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| match a.item {
|
||||||
|
@ -26,7 +26,7 @@ pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Get requires a field or field path",
|
"Get requires a field or field path",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use log::trace;
|
|||||||
|
|
||||||
pub fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
let stream = input
|
let stream = input
|
||||||
.values
|
.values
|
||||||
|
@ -30,7 +30,7 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let mut shell_entries = VecDeque::new();
|
let mut shell_entries = VecDeque::new();
|
||||||
|
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let value = dir_entry_dict(&entry?, args.name_span)?;
|
let value = dir_entry_dict(&entry?, args.call_info.name_span)?;
|
||||||
shell_entries.push_back(ReturnSuccess::value(value))
|
shell_entries.push_back(ReturnSuccess::value(value))
|
||||||
}
|
}
|
||||||
Ok(shell_entries.to_output_stream())
|
Ok(shell_entries.to_output_stream())
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::context::SpanSource;
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::{Primitive, Switch, Value};
|
use crate::object::{Primitive, Switch, Value};
|
||||||
use crate::parser::parse::span::Span;
|
use crate::parser::parse::span::Span;
|
||||||
@ -5,10 +6,11 @@ use crate::prelude::*;
|
|||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
command! {
|
command! {
|
||||||
Open as open(args, path: Spanned<PathBuf>, --raw: Switch,) {
|
Open as open(args, path: Spanned<PathBuf>, --raw: Switch,) {
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
let cwd = args
|
let cwd = args
|
||||||
.env
|
.env
|
||||||
@ -21,19 +23,7 @@ command! {
|
|||||||
|
|
||||||
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".spanned(path.span)))?;
|
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".spanned(path.span)))?;
|
||||||
|
|
||||||
let (file_extension, contents, contents_span) = fetch(&full_path, path_str, path.span)?;
|
let (file_extension, contents, contents_span, span_source) = fetch(&full_path, path_str, path.span)?;
|
||||||
// let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
|
|
||||||
// Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
|
|
||||||
// _ => {
|
|
||||||
// return Err(ShellError::labeled_error(
|
|
||||||
// "Expected string value for filename",
|
|
||||||
// "expected filename",
|
|
||||||
// args.expect_nth(0)?.span,
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
let mut stream = VecDeque::new();
|
|
||||||
|
|
||||||
let file_extension = if raw.is_present() {
|
let file_extension = if raw.is_present() {
|
||||||
None
|
None
|
||||||
@ -41,6 +31,13 @@ command! {
|
|||||||
file_extension
|
file_extension
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut stream = VecDeque::new();
|
||||||
|
|
||||||
|
if let Some(uuid) = contents_span.source {
|
||||||
|
// If we have loaded something, track its source
|
||||||
|
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(uuid, span_source)))
|
||||||
|
}
|
||||||
|
|
||||||
match contents {
|
match contents {
|
||||||
Value::Primitive(Primitive::String(string)) =>
|
Value::Primitive(Primitive::String(string)) =>
|
||||||
stream.push_back(ReturnSuccess::value(parse_as_value(
|
stream.push_back(ReturnSuccess::value(parse_as_value(
|
||||||
@ -51,7 +48,7 @@ command! {
|
|||||||
)?)
|
)?)
|
||||||
),
|
),
|
||||||
|
|
||||||
other => stream.push_back(ReturnSuccess::value(other.spanned(span))),
|
other => stream.push_back(ReturnSuccess::value(other.spanned(contents_span))),
|
||||||
};
|
};
|
||||||
|
|
||||||
stream
|
stream
|
||||||
@ -62,7 +59,7 @@ pub fn fetch(
|
|||||||
cwd: &PathBuf,
|
cwd: &PathBuf,
|
||||||
location: &str,
|
location: &str,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(Option<String>, Value, Span), ShellError> {
|
) -> Result<(Option<String>, Value, Span, SpanSource), ShellError> {
|
||||||
let mut cwd = cwd.clone();
|
let mut cwd = cwd.clone();
|
||||||
if location.starts_with("http:") || location.starts_with("https:") {
|
if location.starts_with("http:") || location.starts_with("https:") {
|
||||||
let response = reqwest::get(location);
|
let response = reqwest::get(location);
|
||||||
@ -74,12 +71,14 @@ pub fn fetch(
|
|||||||
(mime::APPLICATION, mime::XML) => Ok((
|
(mime::APPLICATION, mime::XML) => Ok((
|
||||||
Some("xml".to_string()),
|
Some("xml".to_string()),
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
span,
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::JSON) => Ok((
|
(mime::APPLICATION, mime::JSON) => Ok((
|
||||||
Some("json".to_string()),
|
Some("json".to_string()),
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
span,
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
@ -90,7 +89,12 @@ pub fn fetch(
|
|||||||
span,
|
span,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((None, Value::Binary(buf), span))
|
Ok((
|
||||||
|
None,
|
||||||
|
Value::Binary(buf),
|
||||||
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
(mime::IMAGE, image_ty) => {
|
(mime::IMAGE, image_ty) => {
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
@ -101,12 +105,18 @@ pub fn fetch(
|
|||||||
span,
|
span,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((Some(image_ty.to_string()), Value::Binary(buf), span))
|
Ok((
|
||||||
|
Some(image_ty.to_string()),
|
||||||
|
Value::Binary(buf),
|
||||||
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
(mime::TEXT, mime::HTML) => Ok((
|
(mime::TEXT, mime::HTML) => Ok((
|
||||||
Some("html".to_string()),
|
Some("html".to_string()),
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
span,
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::TEXT, mime::PLAIN) => {
|
(mime::TEXT, mime::PLAIN) => {
|
||||||
let path_extension = r
|
let path_extension = r
|
||||||
@ -120,16 +130,27 @@ pub fn fetch(
|
|||||||
.map(|name| name.to_string_lossy().to_string())
|
.map(|name| name.to_string_lossy().to_string())
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok((path_extension, Value::string(r.text().unwrap()), span))
|
Ok((
|
||||||
|
path_extension,
|
||||||
|
Value::string(r.text().unwrap()),
|
||||||
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
(ty, sub_ty) => Ok((
|
(ty, sub_ty) => Ok((
|
||||||
None,
|
None,
|
||||||
Value::string(format!("Not yet support MIME type: {} {}", ty, sub_ty)),
|
Value::string(format!("Not yet support MIME type: {} {}", ty, sub_ty)),
|
||||||
span,
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Ok((None, Value::string(format!("No content type found")), span)),
|
None => Ok((
|
||||||
|
None,
|
||||||
|
Value::string(format!("No content type found")),
|
||||||
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::Url(r.url().to_string()),
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
@ -147,9 +168,15 @@ pub fn fetch(
|
|||||||
cwd.extension()
|
cwd.extension()
|
||||||
.map(|name| name.to_string_lossy().to_string()),
|
.map(|name| name.to_string_lossy().to_string()),
|
||||||
Value::string(s),
|
Value::string(s),
|
||||||
span,
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
|
)),
|
||||||
|
Err(_) => Ok((
|
||||||
|
None,
|
||||||
|
Value::Binary(bytes),
|
||||||
|
Span::unknown_with_uuid(Uuid::new_v4()),
|
||||||
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
Err(_) => Ok((None, Value::Binary(bytes), span)),
|
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
|
@ -7,7 +7,7 @@ pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Pick requires fields",
|
"Pick requires fields",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ pub fn filter_plugin(path: String, args: CommandArgs) -> Result<OutputStream, Sh
|
|||||||
|
|
||||||
let mut reader = BufReader::new(stdout);
|
let mut reader = BufReader::new(stdout);
|
||||||
|
|
||||||
let request = JsonRpc::new("begin_filter", args.args);
|
let request = JsonRpc::new("begin_filter", args.call_info);
|
||||||
let request_raw = serde_json::to_string(&request).unwrap();
|
let request_raw = serde_json::to_string(&request).unwrap();
|
||||||
stdin.write(format!("{}\n", request_raw).as_bytes())?;
|
stdin.write(format!("{}\n", request_raw).as_bytes())?;
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
@ -183,7 +183,7 @@ pub fn filter_plugin(path: String, args: CommandArgs) -> Result<OutputStream, Sh
|
|||||||
|
|
||||||
pub fn sink_plugin(path: String, args: SinkCommandArgs) -> Result<(), ShellError> {
|
pub fn sink_plugin(path: String, args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
//use subprocess::Exec;
|
//use subprocess::Exec;
|
||||||
let request = JsonRpc::new("sink", (args.args, args.input));
|
let request = JsonRpc::new("sink", (args.call_info, args.input));
|
||||||
let request_raw = serde_json::to_string(&request).unwrap();
|
let request_raw = serde_json::to_string(&request).unwrap();
|
||||||
let mut tmpfile = tempfile::NamedTempFile::new()?;
|
let mut tmpfile = tempfile::NamedTempFile::new()?;
|
||||||
let _ = writeln!(tmpfile, "{}", request_raw);
|
let _ = writeln!(tmpfile, "{}", request_raw);
|
||||||
|
@ -10,7 +10,7 @@ pub fn ps(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
|
|
||||||
let list = list
|
let list = list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, process)| process_dict(process, args.name_span))
|
.map(|(_, process)| process_dict(process, args.call_info.name_span))
|
||||||
.collect::<VecDeque<_>>();
|
.collect::<VecDeque<_>>();
|
||||||
|
|
||||||
Ok(list.from_input_stream())
|
Ok(list.from_input_stream())
|
||||||
|
@ -3,13 +3,13 @@ use crate::object::base::reject_fields;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = args.name_span;
|
let name_span = args.call_info.name_span;
|
||||||
|
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Reject requires fields",
|
"Reject requires fields",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::parser::registry::{CommandConfig, NamedType, PositionalType};
|
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxType;
|
||||||
|
use crate::parser::registry::{CommandConfig, NamedType, PositionalType};
|
||||||
|
use crate::prelude::*;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
pub struct Remove;
|
pub struct Remove;
|
||||||
@ -31,28 +31,25 @@ impl Command for Remove {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut full_path = args.env
|
let mut full_path = args.env.lock().unwrap().path().to_path_buf();
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.path()
|
|
||||||
.to_path_buf();
|
|
||||||
|
|
||||||
|
match args
|
||||||
match args.nth(0)
|
.nth(0)
|
||||||
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
|
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
|
||||||
.as_string()?
|
.as_string()?
|
||||||
.as_str() {
|
.as_str()
|
||||||
"." | ".." => return Err(ShellError::string("\".\" and \"..\" may not be removed")),
|
{
|
||||||
file => full_path.push(file),
|
"." | ".." => return Err(ShellError::string("\".\" and \"..\" may not be removed")),
|
||||||
|
file => full_path.push(file),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if full_path.is_dir() {
|
if full_path.is_dir() {
|
||||||
if !args.has("recursive") {
|
if !args.has("recursive") {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"is a directory",
|
"is a directory",
|
||||||
"",
|
"",
|
||||||
args.name_span.unwrap()));
|
args.call_info.name_span.unwrap(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
std::fs::remove_dir_all(&full_path).expect("can not remove directory");
|
std::fs::remove_dir_all(&full_path).expect("can not remove directory");
|
||||||
} else if full_path.is_file() {
|
} else if full_path.is_file() {
|
||||||
|
@ -8,15 +8,15 @@ use crate::parser::Spanned;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
if args.args.positional.is_none() {
|
if args.call_info.args.positional.is_none() {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let positional = match args.args.positional {
|
let positional = match args.call_info.args.positional {
|
||||||
None => return Err(ShellError::string("save requires a filepath")),
|
None => return Err(ShellError::string("save requires a filepath")),
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ pub fn skip_while(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Where requires a condition",
|
"Where requires a condition",
|
||||||
"needs condition",
|
"needs condition",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,13 @@ use log::trace;
|
|||||||
|
|
||||||
pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let positional: Vec<_> = args.positional_iter().cloned().collect();
|
let positional: Vec<_> = args.positional_iter().cloned().collect();
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
if positional.len() == 0 {
|
if positional.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Split-column needs more information",
|
"Split-column needs more information",
|
||||||
"needs parameter (eg split-column \",\")",
|
"needs parameter (eg split-column \",\")",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ use log::trace;
|
|||||||
|
|
||||||
pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let positional: Vec<Spanned<Value>> = args.positional_iter().cloned().collect();
|
let positional: Vec<Spanned<Value>> = args.positional_iter().cloned().collect();
|
||||||
let span = args.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
if positional.len() == 0 {
|
if positional.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::maybe_labeled_error(
|
||||||
"Split-row needs more information",
|
"Split-row needs more information",
|
||||||
"needs parameter (eg split-row \"\\n\")",
|
"needs parameter (eg split-row \"\\n\")",
|
||||||
args.name_span,
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,11 @@ use sys_info::*;
|
|||||||
use sysinfo::{ComponentExt, DiskExt, NetworkExt, RefreshKind, SystemExt};
|
use sysinfo::{ComponentExt, DiskExt, NetworkExt, RefreshKind, SystemExt};
|
||||||
|
|
||||||
pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut idx = SpannedDictBuilder::new(args.name_span);
|
let name_span = args.call_info.name_span;
|
||||||
|
let mut idx = SpannedDictBuilder::new(name_span);
|
||||||
|
|
||||||
if let (Ok(name), Ok(version)) = (os_type(), os_release()) {
|
if let (Ok(name), Ok(version)) = (os_type(), os_release()) {
|
||||||
let mut os_idx = SpannedDictBuilder::new(args.name_span);
|
let mut os_idx = SpannedDictBuilder::new(name_span);
|
||||||
os_idx.insert("name", Primitive::String(name));
|
os_idx.insert("name", Primitive::String(name));
|
||||||
os_idx.insert("version", Primitive::String(version));
|
os_idx.insert("version", Primitive::String(version));
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let (Ok(num_cpu), Ok(cpu_speed)) = (cpu_num(), cpu_speed()) {
|
if let (Ok(num_cpu), Ok(cpu_speed)) = (cpu_num(), cpu_speed()) {
|
||||||
let mut cpu_idx = SpannedDictBuilder::new(args.name_span);
|
let mut cpu_idx = SpannedDictBuilder::new(name_span);
|
||||||
cpu_idx.insert("num", Primitive::Int(num_cpu as i64));
|
cpu_idx.insert("num", Primitive::Int(num_cpu as i64));
|
||||||
cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64));
|
cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64));
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(x) = loadavg() {
|
if let Ok(x) = loadavg() {
|
||||||
let mut load_idx = SpannedDictBuilder::new(args.name_span);
|
let mut load_idx = SpannedDictBuilder::new(name_span);
|
||||||
|
|
||||||
load_idx.insert("1min", Primitive::Float(OF64::from(x.one)));
|
load_idx.insert("1min", Primitive::Float(OF64::from(x.one)));
|
||||||
load_idx.insert("5min", Primitive::Float(OF64::from(x.five)));
|
load_idx.insert("5min", Primitive::Float(OF64::from(x.five)));
|
||||||
@ -36,7 +37,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(x) = mem_info() {
|
if let Ok(x) = mem_info() {
|
||||||
let mut mem_idx = SpannedDictBuilder::new(args.name_span);
|
let mut mem_idx = SpannedDictBuilder::new(name_span);
|
||||||
|
|
||||||
mem_idx.insert("total", Primitive::Bytes(x.total as u64 * 1024));
|
mem_idx.insert("total", Primitive::Bytes(x.total as u64 * 1024));
|
||||||
mem_idx.insert("free", Primitive::Bytes(x.free as u64 * 1024));
|
mem_idx.insert("free", Primitive::Bytes(x.free as u64 * 1024));
|
||||||
@ -70,7 +71,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
if let Ok(x) = boottime() {
|
if let Ok(x) = boottime() {
|
||||||
let mut boottime_idx = SpannedDictBuilder::new(args.name_span);
|
let mut boottime_idx = SpannedDictBuilder::new(name_span);
|
||||||
boottime_idx.insert("days", Primitive::Int(x.tv_sec / (24 * 3600)));
|
boottime_idx.insert("days", Primitive::Int(x.tv_sec / (24 * 3600)));
|
||||||
boottime_idx.insert("hours", Primitive::Int((x.tv_sec / 3600) % 24));
|
boottime_idx.insert("hours", Primitive::Int((x.tv_sec / 3600) % 24));
|
||||||
boottime_idx.insert("mins", Primitive::Int((x.tv_sec / 60) % 60));
|
boottime_idx.insert("mins", Primitive::Int((x.tv_sec / 60) % 60));
|
||||||
@ -84,7 +85,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
if components_list.len() > 0 {
|
if components_list.len() > 0 {
|
||||||
let mut v: Vec<Spanned<Value>> = vec![];
|
let mut v: Vec<Spanned<Value>> = vec![];
|
||||||
for component in components_list {
|
for component in components_list {
|
||||||
let mut component_idx = SpannedDictBuilder::new(args.name_span);
|
let mut component_idx = SpannedDictBuilder::new(name_span);
|
||||||
component_idx.insert("name", Primitive::String(component.get_label().to_string()));
|
component_idx.insert("name", Primitive::String(component.get_label().to_string()));
|
||||||
component_idx.insert(
|
component_idx.insert(
|
||||||
"temp",
|
"temp",
|
||||||
@ -107,7 +108,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
|
|
||||||
for disk in disks {
|
for disk in disks {
|
||||||
let mut disk_idx = SpannedDictBuilder::new(args.name_span);
|
let mut disk_idx = SpannedDictBuilder::new(name_span);
|
||||||
disk_idx.insert("name", Value::string(disk.get_name().to_string_lossy()));
|
disk_idx.insert("name", Value::string(disk.get_name().to_string_lossy()));
|
||||||
disk_idx.insert("available", Value::bytes(disk.get_available_space()));
|
disk_idx.insert("available", Value::bytes(disk.get_available_space()));
|
||||||
disk_idx.insert("total", Value::bytes(disk.get_total_space()));
|
disk_idx.insert("total", Value::bytes(disk.get_total_space()));
|
||||||
@ -121,7 +122,7 @@ pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
let incoming = network.get_income();
|
let incoming = network.get_income();
|
||||||
let outgoing = network.get_outcome();
|
let outgoing = network.get_outcome();
|
||||||
|
|
||||||
let mut network_idx = SpannedDictBuilder::new(args.name_span);
|
let mut network_idx = SpannedDictBuilder::new(name_span);
|
||||||
network_idx.insert("incoming", Value::bytes(incoming));
|
network_idx.insert("incoming", Value::bytes(incoming));
|
||||||
network_idx.insert("outgoing", Value::bytes(outgoing));
|
network_idx.insert("outgoing", Value::bytes(outgoing));
|
||||||
idx.insert_spanned("network", network_idx);
|
idx.insert_spanned("network", network_idx);
|
||||||
|
@ -42,7 +42,7 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
|||||||
|
|
||||||
pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let name_span = args.name_span;
|
let name_span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
|
@ -32,7 +32,7 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
|||||||
|
|
||||||
pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let name_span = args.name_span;
|
let name_span = args.call_info.name_span;
|
||||||
|
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
|
@ -40,7 +40,7 @@ pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {
|
|||||||
|
|
||||||
pub fn to_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn to_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let out = args.input;
|
let out = args.input;
|
||||||
let name_span = args.name_span;
|
let name_span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
|
@ -2,8 +2,6 @@ use crate::errors::ShellError;
|
|||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
// TODO: "Amount remaining" wrapper
|
|
||||||
|
|
||||||
pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
|
@ -1,18 +1,45 @@
|
|||||||
use crate::commands::command::{Sink, SinkCommandArgs};
|
use crate::commands::command::{CallInfo, Sink, SinkCommandArgs};
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
registry::{Args, CommandConfig, CommandRegistry},
|
registry::{Args, CommandConfig, CommandRegistry},
|
||||||
Span,
|
Span,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum SpanSource {
|
||||||
|
Url(String),
|
||||||
|
File(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct SourceMap(HashMap<Uuid, SpanSource>);
|
||||||
|
|
||||||
|
impl SourceMap {
|
||||||
|
pub fn insert(&mut self, uuid: Uuid, span_source: SpanSource) {
|
||||||
|
self.0.insert(uuid, span_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, uuid: &Uuid) -> Option<&SpanSource> {
|
||||||
|
self.0.get(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> SourceMap {
|
||||||
|
SourceMap(HashMap::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
commands: IndexMap<String, Arc<dyn Command>>,
|
commands: IndexMap<String, Arc<dyn Command>>,
|
||||||
sinks: IndexMap<String, Arc<dyn Sink>>,
|
sinks: IndexMap<String, Arc<dyn Sink>>,
|
||||||
|
crate source_map: SourceMap,
|
||||||
crate host: Arc<Mutex<dyn Host + Send>>,
|
crate host: Arc<Mutex<dyn Host + Send>>,
|
||||||
crate env: Arc<Mutex<Environment>>,
|
crate env: Arc<Mutex<Environment>>,
|
||||||
}
|
}
|
||||||
@ -22,6 +49,7 @@ impl Context {
|
|||||||
Ok(Context {
|
Ok(Context {
|
||||||
commands: indexmap::IndexMap::new(),
|
commands: indexmap::IndexMap::new(),
|
||||||
sinks: indexmap::IndexMap::new(),
|
sinks: indexmap::IndexMap::new(),
|
||||||
|
source_map: SourceMap::new(),
|
||||||
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
|
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
|
||||||
env: Arc::new(Mutex::new(Environment::basic()?)),
|
env: Arc::new(Mutex::new(Environment::basic()?)),
|
||||||
})
|
})
|
||||||
@ -39,6 +67,10 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_span_source(&mut self, uuid: Uuid, span_source: SpanSource) {
|
||||||
|
self.source_map.insert(uuid, span_source);
|
||||||
|
}
|
||||||
|
|
||||||
crate fn has_sink(&self, name: &str) -> bool {
|
crate fn has_sink(&self, name: &str) -> bool {
|
||||||
self.sinks.contains_key(name)
|
self.sinks.contains_key(name)
|
||||||
}
|
}
|
||||||
@ -56,8 +88,11 @@ impl Context {
|
|||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
let command_args = SinkCommandArgs {
|
let command_args = SinkCommandArgs {
|
||||||
ctx: self.clone(),
|
ctx: self.clone(),
|
||||||
name_span,
|
call_info: CallInfo {
|
||||||
args,
|
name_span,
|
||||||
|
source_map: self.source_map.clone(),
|
||||||
|
args,
|
||||||
|
},
|
||||||
input,
|
input,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,14 +115,18 @@ impl Context {
|
|||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<dyn Command>,
|
command: Arc<dyn Command>,
|
||||||
name_span: Option<Span>,
|
name_span: Option<Span>,
|
||||||
|
source_map: SourceMap,
|
||||||
args: Args,
|
args: Args,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let command_args = CommandArgs {
|
let command_args = CommandArgs {
|
||||||
host: self.host.clone(),
|
host: self.host.clone(),
|
||||||
env: self.env.clone(),
|
env: self.env.clone(),
|
||||||
name_span,
|
call_info: CallInfo {
|
||||||
args,
|
name_span,
|
||||||
|
source_map,
|
||||||
|
args,
|
||||||
|
},
|
||||||
input,
|
input,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,7 +17,12 @@ impl Description {
|
|||||||
pub fn from(item: Spanned<impl Into<String>>) -> Description {
|
pub fn from(item: Spanned<impl Into<String>>) -> Description {
|
||||||
match item {
|
match item {
|
||||||
Spanned {
|
Spanned {
|
||||||
span: Span { start: 0, end: 0 },
|
span:
|
||||||
|
Span {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
source: None,
|
||||||
|
},
|
||||||
item,
|
item,
|
||||||
} => Description::Synthetic(item.into()),
|
} => Description::Synthetic(item.into()),
|
||||||
Spanned { span, item } => Description::Source(Spanned::from_item(item.into(), span)),
|
Spanned { span, item } => Description::Source(Spanned::from_item(item.into(), span)),
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#![feature(bind_by_move_pattern_guards)]
|
#![feature(bind_by_move_pattern_guards)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(type_ascription)]
|
#![feature(type_ascription)]
|
||||||
|
#![feature(option_flattening)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod prelude;
|
mod prelude;
|
||||||
@ -23,7 +24,8 @@ mod plugin;
|
|||||||
mod shell;
|
mod shell;
|
||||||
mod stream;
|
mod stream;
|
||||||
|
|
||||||
pub use crate::commands::command::{ReturnSuccess, ReturnValue};
|
pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue};
|
||||||
|
pub use crate::context::SpanSource;
|
||||||
pub use crate::env::host::BasicHost;
|
pub use crate::env::host::BasicHost;
|
||||||
pub use crate::parser::parse::span::SpannedItem;
|
pub use crate::parser::parse::span::SpannedItem;
|
||||||
pub use crate::parser::Spanned;
|
pub use crate::parser::Spanned;
|
||||||
|
@ -9,8 +9,8 @@ use log::LevelFilter;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let matches = App::new("nu shell")
|
let matches = App::new("nushell")
|
||||||
.version("0.5")
|
.version("0.1.3")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("loglevel")
|
Arg::with_name("loglevel")
|
||||||
.short("l")
|
.short("l")
|
||||||
|
@ -3,6 +3,7 @@ use derive_new::new;
|
|||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
|
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
|
||||||
@ -75,13 +76,17 @@ impl<T> Spanned<T> {
|
|||||||
pub struct Span {
|
pub struct Span {
|
||||||
crate start: usize,
|
crate start: usize,
|
||||||
crate end: usize,
|
crate end: usize,
|
||||||
// source: &'source str,
|
pub source: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<Span>> for Span {
|
impl From<Option<Span>> for Span {
|
||||||
fn from(input: Option<Span>) -> Span {
|
fn from(input: Option<Span>) -> Span {
|
||||||
match input {
|
match input {
|
||||||
None => Span { start: 0, end: 0 },
|
None => Span {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
source: None,
|
||||||
|
},
|
||||||
Some(span) => span,
|
Some(span) => span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,6 +109,7 @@ impl From<nom5_locate::LocatedSpan<&str>> for Span {
|
|||||||
Span {
|
Span {
|
||||||
start: input.offset,
|
start: input.offset,
|
||||||
end: input.offset + input.fragment.len(),
|
end: input.offset + input.fragment.len(),
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,6 +119,7 @@ impl<T> From<(nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)> for Spa
|
|||||||
Span {
|
Span {
|
||||||
start: input.0.offset,
|
start: input.0.offset,
|
||||||
end: input.1.offset,
|
end: input.1.offset,
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,6 +129,7 @@ impl From<(usize, usize)> for Span {
|
|||||||
Span {
|
Span {
|
||||||
start: input.0,
|
start: input.0,
|
||||||
end: input.1,
|
end: input.1,
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,13 +139,26 @@ impl From<&std::ops::Range<usize>> for Span {
|
|||||||
Span {
|
Span {
|
||||||
start: input.start,
|
start: input.start,
|
||||||
end: input.end,
|
end: input.end,
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn unknown() -> Span {
|
pub fn unknown() -> Span {
|
||||||
Span { start: 0, end: 0 }
|
Span {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
source: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unknown_with_uuid(uuid: Uuid) -> Span {
|
||||||
|
Span {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
source: Some(uuid),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unknown(&self) -> bool {
|
pub fn is_unknown(&self) -> bool {
|
||||||
@ -154,6 +175,7 @@ impl language_reporting::ReportingSpan for Span {
|
|||||||
Span {
|
Span {
|
||||||
start,
|
start,
|
||||||
end: self.end,
|
end: self.end,
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,6 +183,7 @@ impl language_reporting::ReportingSpan for Span {
|
|||||||
Span {
|
Span {
|
||||||
start: self.start,
|
start: self.start,
|
||||||
end,
|
end,
|
||||||
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::{Args, CommandConfig, ReturnValue, ShellError, Spanned, Value};
|
use crate::{CallInfo, CommandConfig, ReturnValue, ShellError, Spanned, Value};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
pub trait Plugin {
|
pub trait Plugin {
|
||||||
fn config(&mut self) -> Result<CommandConfig, ShellError>;
|
fn config(&mut self) -> Result<CommandConfig, ShellError>;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> {
|
||||||
Err(ShellError::string(
|
Err(ShellError::string(
|
||||||
"`begin_filter` not implemented in plugin",
|
"`begin_filter` not implemented in plugin",
|
||||||
))
|
))
|
||||||
@ -15,7 +15,7 @@ pub trait Plugin {
|
|||||||
Err(ShellError::string("`filter` not implemented in plugin"))
|
Err(ShellError::string("`filter` not implemented in plugin"))
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn sink(&mut self, args: Args, input: Vec<Spanned<Value>>) {}
|
fn sink(&mut self, call_info: CallInfo, input: Vec<Spanned<Value>>) {}
|
||||||
|
|
||||||
fn quit(&mut self) {
|
fn quit(&mut self) {
|
||||||
return;
|
return;
|
||||||
@ -134,8 +134,14 @@ fn send_response<T: Serialize>(result: T) {
|
|||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub enum NuCommand {
|
pub enum NuCommand {
|
||||||
config,
|
config,
|
||||||
begin_filter { params: Args },
|
begin_filter {
|
||||||
filter { params: Spanned<Value> },
|
params: CallInfo,
|
||||||
sink { params: (Args, Vec<Spanned<Value>>) },
|
},
|
||||||
|
filter {
|
||||||
|
params: Spanned<Value>,
|
||||||
|
},
|
||||||
|
sink {
|
||||||
|
params: (CallInfo, Vec<Spanned<Value>>),
|
||||||
|
},
|
||||||
quit,
|
quit,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
#![feature(option_flattening)]
|
||||||
use crossterm::{cursor, terminal, Attribute, RawScreen};
|
use crossterm::{cursor, terminal, Attribute, RawScreen};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{serve_plugin, Args, CommandConfig, NamedType, Plugin, ShellError, Spanned, Value};
|
use nu::{
|
||||||
|
serve_plugin, CallInfo, CommandConfig, NamedType, Plugin, ShellError, SpanSource, Spanned,
|
||||||
|
Value,
|
||||||
|
};
|
||||||
use pretty_hex::*;
|
use pretty_hex::*;
|
||||||
|
|
||||||
struct BinaryView;
|
struct BinaryView;
|
||||||
@ -25,14 +29,15 @@ impl Plugin for BinaryView {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sink(&mut self, args: Args, input: Vec<Spanned<Value>>) {
|
fn sink(&mut self, call_info: CallInfo, input: Vec<Spanned<Value>>) {
|
||||||
for v in input {
|
for v in input {
|
||||||
match v {
|
match v {
|
||||||
Spanned {
|
Spanned {
|
||||||
item: Value::Binary(b),
|
item: Value::Binary(b),
|
||||||
..
|
span,
|
||||||
} => {
|
} => {
|
||||||
let _ = view_binary(&b, args.has("lores"));
|
let source = span.source.map(|x| call_info.source_map.get(&x)).flatten();
|
||||||
|
let _ = view_binary(&b, source, call_info.args.has("lores"));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -40,17 +45,21 @@ impl Plugin for BinaryView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_binary(b: &[u8], lores_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
fn view_binary(
|
||||||
|
b: &[u8],
|
||||||
|
source: Option<&SpanSource>,
|
||||||
|
lores_mode: bool,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if b.len() > 3 {
|
if b.len() > 3 {
|
||||||
match (b[0], b[1], b[2]) {
|
match (b[0], b[1], b[2]) {
|
||||||
(0x4e, 0x45, 0x53) => {
|
(0x4e, 0x45, 0x53) => {
|
||||||
view_contents_interactive(b, lores_mode)?;
|
view_contents_interactive(b, source, lores_mode)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view_contents(b, lores_mode)?;
|
view_contents(b, source, lores_mode)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +256,11 @@ fn load_from_jpg_buffer(buffer: &[u8]) -> Option<(RawImageBuffer)> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_contents(buffer: &[u8], lores_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn view_contents(
|
||||||
|
buffer: &[u8],
|
||||||
|
_source: Option<&SpanSource>,
|
||||||
|
lores_mode: bool,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut raw_image_buffer = load_from_png_buffer(buffer);
|
let mut raw_image_buffer = load_from_png_buffer(buffer);
|
||||||
|
|
||||||
if raw_image_buffer.is_none() {
|
if raw_image_buffer.is_none() {
|
||||||
@ -332,14 +345,29 @@ pub fn view_contents(buffer: &[u8], lores_mode: bool) -> Result<(), Box<dyn std:
|
|||||||
|
|
||||||
pub fn view_contents_interactive(
|
pub fn view_contents_interactive(
|
||||||
buffer: &[u8],
|
buffer: &[u8],
|
||||||
|
source: Option<&SpanSource>,
|
||||||
lores_mode: bool,
|
lores_mode: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
use rawkey::{KeyCode, RawKey};
|
use rawkey::{KeyCode, RawKey};
|
||||||
|
|
||||||
|
let sav_path = if let Some(SpanSource::File(f)) = source {
|
||||||
|
let mut path = std::path::PathBuf::from(f);
|
||||||
|
path.set_extension("sav");
|
||||||
|
Some(path)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let mut nes = neso::Nes::new(48000.0);
|
let mut nes = neso::Nes::new(48000.0);
|
||||||
let rawkey = RawKey::new();
|
let rawkey = RawKey::new();
|
||||||
nes.load_rom(&buffer);
|
nes.load_rom(&buffer);
|
||||||
|
|
||||||
|
if let Some(ref sav_path) = sav_path {
|
||||||
|
if let Ok(contents) = std::fs::read(sav_path) {
|
||||||
|
let _ = nes.load_state(&contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nes.reset();
|
nes.reset();
|
||||||
|
|
||||||
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
if let Ok(_raw) = RawScreen::into_raw_mode() {
|
||||||
@ -403,6 +431,13 @@ pub fn view_contents_interactive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref sav_path) = sav_path {
|
||||||
|
let buffer = nes.save_state();
|
||||||
|
if let Ok(buffer) = buffer {
|
||||||
|
let _ = std::fs::write(sav_path, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let cursor = cursor();
|
let cursor = cursor();
|
||||||
let _ = cursor.show();
|
let _ = cursor.show();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, Args, CommandConfig, NamedType, Plugin, PositionalType, Primitive, ReturnSuccess,
|
serve_plugin, CallInfo, CommandConfig, NamedType, Plugin, PositionalType, Primitive,
|
||||||
ReturnValue, ShellError, Spanned, SpannedItem, Value,
|
ReturnSuccess, ReturnValue, ShellError, Spanned, SpannedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Inc {
|
struct Inc {
|
||||||
@ -99,18 +99,18 @@ impl Plugin for Inc {
|
|||||||
rest_positional: true,
|
rest_positional: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> {
|
||||||
if args.has("major") {
|
if call_info.args.has("major") {
|
||||||
self.major = true;
|
self.major = true;
|
||||||
}
|
}
|
||||||
if args.has("minor") {
|
if call_info.args.has("minor") {
|
||||||
self.minor = true;
|
self.minor = true;
|
||||||
}
|
}
|
||||||
if args.has("patch") {
|
if call_info.args.has("patch") {
|
||||||
self.patch = true;
|
self.patch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(args) = args.positional {
|
if let Some(args) = call_info.args.positional {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
match arg {
|
||||||
Spanned {
|
Spanned {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, Args, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue,
|
||||||
Spanned, Value,
|
ShellError, Spanned, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NewSkip {
|
struct NewSkip {
|
||||||
@ -24,8 +24,8 @@ impl Plugin for NewSkip {
|
|||||||
rest_positional: true,
|
rest_positional: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> {
|
||||||
if let Some(args) = args.positional {
|
if let Some(args) = call_info.args.positional {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
match arg {
|
||||||
Spanned {
|
Spanned {
|
||||||
@ -34,7 +34,13 @@ impl Plugin for NewSkip {
|
|||||||
} => {
|
} => {
|
||||||
self.skip_amount = i;
|
self.skip_amount = i;
|
||||||
}
|
}
|
||||||
_ => return Err(ShellError::labeled_error("Unrecognized type in params", "expected an integer", arg.span)),
|
_ => {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"Unrecognized type in params",
|
||||||
|
"expected an integer",
|
||||||
|
arg.span,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Spanned, Value};
|
use nu::{serve_plugin, CallInfo, CommandConfig, Plugin, ShellError, Spanned, Value};
|
||||||
use ptree::item::StringItem;
|
use ptree::item::StringItem;
|
||||||
use ptree::output::print_tree_with;
|
use ptree::output::print_tree_with;
|
||||||
use ptree::print_config::PrintConfig;
|
use ptree::print_config::PrintConfig;
|
||||||
@ -91,7 +91,7 @@ impl Plugin for TreeViewer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sink(&mut self, _args: Args, input: Vec<Spanned<Value>>) {
|
fn sink(&mut self, _call_info: CallInfo, input: Vec<Spanned<Value>>) {
|
||||||
if input.len() > 0 {
|
if input.len() > 0 {
|
||||||
for i in input.iter() {
|
for i in input.iter() {
|
||||||
let view = TreeView::from_value(&i);
|
let view = TreeView::from_value(&i);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use helpers as h;
|
|
||||||
use h::in_directory as cwd;
|
use h::in_directory as cwd;
|
||||||
|
use helpers as h;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lines() {
|
fn lines() {
|
||||||
@ -14,18 +14,22 @@ fn lines() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_csv() {
|
fn open_csv() {
|
||||||
nu!(output,
|
nu!(
|
||||||
|
output,
|
||||||
cwd("tests/fixtures/formats"),
|
cwd("tests/fixtures/formats"),
|
||||||
"open caco3_plastics.csv | get root | first 1 | get origin | echo $it");
|
"open caco3_plastics.csv | get root | first 1 | get origin | echo $it"
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(output, "SPAIN");
|
assert_eq!(output, "SPAIN");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_toml() {
|
fn open_toml() {
|
||||||
nu!(output,
|
nu!(
|
||||||
cwd("tests/fixtures/formats"),
|
output,
|
||||||
"open cargo_sample.toml | get package.edition | echo $it");
|
cwd("tests/fixtures/formats"),
|
||||||
|
"open cargo_sample.toml | get package.edition | echo $it"
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(output, "2018");
|
assert_eq!(output, "2018");
|
||||||
}
|
}
|
||||||
@ -41,32 +45,40 @@ fn open_json() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_xml() {
|
fn open_xml() {
|
||||||
nu!(output,
|
nu!(
|
||||||
|
output,
|
||||||
cwd("tests/fixtures/formats"),
|
cwd("tests/fixtures/formats"),
|
||||||
"open jonathan.xml | get rss.channel.item.link | echo $it");
|
"open jonathan.xml | get rss.channel.item.link | echo $it"
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(output, "http://www.jonathanturner.org/2015/10/off-to-new-adventures.html")
|
assert_eq!(
|
||||||
|
output,
|
||||||
|
"http://www.jonathanturner.org/2015/10/off-to-new-adventures.html"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_ini() {
|
fn open_ini() {
|
||||||
nu!(output,
|
nu!(
|
||||||
|
output,
|
||||||
cwd("tests/fixtures/formats"),
|
cwd("tests/fixtures/formats"),
|
||||||
"open sample.ini | get SectionOne.integer | echo $it");
|
"open sample.ini | get SectionOne.integer | echo $it"
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(output, "1234")
|
assert_eq!(output, "1234")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_error_if_file_not_found() {
|
fn open_error_if_file_not_found() {
|
||||||
nu_error!(output,
|
nu_error!(
|
||||||
|
output,
|
||||||
cwd("tests/fixtures/formats"),
|
cwd("tests/fixtures/formats"),
|
||||||
"open i_dont_exist.txt | echo $it");
|
"open i_dont_exist.txt | echo $it"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(output.contains("File cound not be opened"));
|
assert!(output.contains("File cound not be opened"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rm() {
|
fn rm() {
|
||||||
let directory = "tests/fixtures/nuplayground";
|
let directory = "tests/fixtures/nuplayground";
|
||||||
@ -74,9 +86,7 @@ fn rm() {
|
|||||||
|
|
||||||
h::create_file_at(&file);
|
h::create_file_at(&file);
|
||||||
|
|
||||||
nu!(_output,
|
nu!(_output, cwd(directory), "rm rm_test.txt");
|
||||||
cwd(directory),
|
|
||||||
"rm rm_test.txt");
|
|
||||||
|
|
||||||
assert!(!h::file_exists_at(&file));
|
assert!(!h::file_exists_at(&file));
|
||||||
}
|
}
|
||||||
@ -85,30 +95,34 @@ fn rm() {
|
|||||||
fn can_remove_directory_contents_with_recursive_flag() {
|
fn can_remove_directory_contents_with_recursive_flag() {
|
||||||
let path = "tests/fixtures/nuplayground/rm_test";
|
let path = "tests/fixtures/nuplayground/rm_test";
|
||||||
|
|
||||||
if h::file_exists_at(&path) { h::delete_directory_at(path) }
|
if h::file_exists_at(&path) {
|
||||||
|
h::delete_directory_at(path)
|
||||||
|
}
|
||||||
h::create_directory_at(path);
|
h::create_directory_at(path);
|
||||||
|
|
||||||
for f in ["yehuda.txt", "jonathan.txt", "andres.txt"].iter() {
|
for f in ["yehuda.txt", "jonathan.txt", "andres.txt"].iter() {
|
||||||
h::create_file_at(&format!("{}/{}", path, f));
|
h::create_file_at(&format!("{}/{}", path, f));
|
||||||
};
|
}
|
||||||
|
|
||||||
nu!(_output,
|
nu!(
|
||||||
|
_output,
|
||||||
cwd("tests/fixtures/nuplayground"),
|
cwd("tests/fixtures/nuplayground"),
|
||||||
"rm rm_test --recursive");
|
"rm rm_test --recursive"
|
||||||
|
);
|
||||||
|
|
||||||
assert!(!h::file_exists_at(&path));
|
assert!(!h::file_exists_at(&path));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rm_error_if_attempting_to_delete_a_directory_without_recursive_flag() {
|
fn rm_error_if_attempting_to_delete_a_directory_without_recursive_flag() {
|
||||||
let path = "tests/fixtures/nuplayground/rm_test";
|
let path = "tests/fixtures/nuplayground/rm_test_2";
|
||||||
|
|
||||||
if h::file_exists_at(&path) { h::delete_directory_at(path) }
|
if h::file_exists_at(&path) {
|
||||||
|
h::delete_directory_at(path)
|
||||||
|
}
|
||||||
h::create_directory_at(path);
|
h::create_directory_at(path);
|
||||||
|
|
||||||
nu_error!(output,
|
nu_error!(output, cwd("tests/fixtures/nuplayground"), "rm rm_test_2");
|
||||||
cwd("tests/fixtures/nuplayground"),
|
|
||||||
"rm rm_test");
|
|
||||||
|
|
||||||
assert!(h::file_exists_at(&path));
|
assert!(h::file_exists_at(&path));
|
||||||
assert!(output.contains("is a directory"));
|
assert!(output.contains("is a directory"));
|
||||||
@ -117,18 +131,14 @@ fn rm_error_if_attempting_to_delete_a_directory_without_recursive_flag() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rm_error_if_attempting_to_delete_single_dot_as_argument() {
|
fn rm_error_if_attempting_to_delete_single_dot_as_argument() {
|
||||||
nu_error!(output,
|
nu_error!(output, cwd("tests/fixtures/nuplayground"), "rm .");
|
||||||
cwd("tests/fixtures/nuplayground"),
|
|
||||||
"rm .");
|
|
||||||
|
|
||||||
assert!(output.contains("may not be removed"));
|
assert!(output.contains("may not be removed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rm_error_if_attempting_to_delete_two_dot_as_argument() {
|
fn rm_error_if_attempting_to_delete_two_dot_as_argument() {
|
||||||
nu_error!(output,
|
nu_error!(output, cwd("tests/fixtures/nuplayground"), "rm ..");
|
||||||
cwd("tests/fixtures/nuplayground"),
|
|
||||||
"rm ..");
|
|
||||||
|
|
||||||
assert!(output.contains("may not be removed"));
|
assert!(output.contains("may not be removed"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user