mirror of
https://github.com/nushell/nushell.git
synced 2025-08-14 04:18:31 +02:00
Merge master
This commit is contained in:
19
src/cli.rs
19
src/cli.rs
@ -7,7 +7,7 @@ use crate::commands::plugin::JsonRpc;
|
||||
use crate::commands::plugin::{PluginCommand, PluginSink};
|
||||
use crate::commands::whole_stream_command;
|
||||
use crate::context::Context;
|
||||
crate use crate::errors::ShellError;
|
||||
pub(crate) use crate::errors::ShellError;
|
||||
use crate::git::current_branch;
|
||||
use crate::object::Value;
|
||||
use crate::parser::registry::Signature;
|
||||
@ -17,7 +17,7 @@ use crate::prelude::*;
|
||||
use log::{debug, trace};
|
||||
use regex::Regex;
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::{self, ColorMode, Config, Editor};
|
||||
use rustyline::{self, ColorMode, Config, Editor, config::Configurer, config::EditMode};
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
@ -30,7 +30,7 @@ pub enum MaybeOwned<'a, T> {
|
||||
Borrowed(&'a T),
|
||||
}
|
||||
|
||||
impl<T> MaybeOwned<'a, T> {
|
||||
impl<T> MaybeOwned<'_, T> {
|
||||
pub fn borrow(&self) -> &T {
|
||||
match self {
|
||||
MaybeOwned::Owned(v) => v,
|
||||
@ -180,6 +180,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
whole_stream_command(ToCSV),
|
||||
whole_stream_command(ToJSON),
|
||||
whole_stream_command(ToTOML),
|
||||
whole_stream_command(ToTSV),
|
||||
whole_stream_command(ToYAML),
|
||||
whole_stream_command(SortBy),
|
||||
whole_stream_command(Tags),
|
||||
@ -188,6 +189,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
whole_stream_command(FromArray),
|
||||
whole_stream_command(FromArray),
|
||||
whole_stream_command(FromCSV),
|
||||
whole_stream_command(FromTSV),
|
||||
whole_stream_command(FromINI),
|
||||
whole_stream_command(FromBSON),
|
||||
whole_stream_command(FromJSON),
|
||||
@ -255,6 +257,17 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
context.shell_manager.clone(),
|
||||
)));
|
||||
|
||||
let edit_mode = crate::object::config::config(Span::unknown())?
|
||||
.get("edit_mode")
|
||||
.map(|s| match s.as_string().unwrap().as_ref() {
|
||||
"vi" => EditMode::Vi,
|
||||
"emacs" => EditMode::Emacs,
|
||||
_ => EditMode::Emacs,
|
||||
})
|
||||
.unwrap_or(EditMode::Emacs);
|
||||
|
||||
rl.set_edit_mode(edit_mode);
|
||||
|
||||
let readline = rl.readline(&format!(
|
||||
"{}{}> ",
|
||||
cwd,
|
||||
|
228
src/commands.rs
228
src/commands.rs
@ -1,118 +1,122 @@
|
||||
#[macro_use]
|
||||
crate mod macros;
|
||||
pub(crate) mod macros;
|
||||
|
||||
crate mod args;
|
||||
crate mod autoview;
|
||||
crate mod cd;
|
||||
crate mod classified;
|
||||
crate mod clip;
|
||||
crate mod command;
|
||||
crate mod config;
|
||||
crate mod cp;
|
||||
crate mod date;
|
||||
crate mod debug;
|
||||
crate mod enter;
|
||||
crate mod exit;
|
||||
crate mod first;
|
||||
crate mod from_array;
|
||||
crate mod from_bson;
|
||||
crate mod from_csv;
|
||||
crate mod from_ini;
|
||||
crate mod from_json;
|
||||
crate mod from_toml;
|
||||
crate mod from_xml;
|
||||
crate mod from_yaml;
|
||||
crate mod get;
|
||||
crate mod last;
|
||||
crate mod lines;
|
||||
crate mod ls;
|
||||
crate mod mkdir;
|
||||
crate mod mv;
|
||||
crate mod next;
|
||||
crate mod nth;
|
||||
crate mod open;
|
||||
crate mod pick;
|
||||
crate mod plugin;
|
||||
crate mod prev;
|
||||
crate mod ps;
|
||||
crate mod reject;
|
||||
crate mod reverse;
|
||||
crate mod rm;
|
||||
crate mod save;
|
||||
crate mod shells;
|
||||
crate mod size;
|
||||
crate mod skip_while;
|
||||
crate mod sort_by;
|
||||
crate mod split_column;
|
||||
crate mod split_row;
|
||||
crate mod table;
|
||||
crate mod tags;
|
||||
crate mod to_array;
|
||||
crate mod to_bson;
|
||||
crate mod to_csv;
|
||||
crate mod to_json;
|
||||
crate mod to_toml;
|
||||
crate mod to_yaml;
|
||||
crate mod trim;
|
||||
crate mod version;
|
||||
crate mod vtable;
|
||||
crate mod where_;
|
||||
crate mod which_;
|
||||
pub(crate) mod args;
|
||||
pub(crate) mod autoview;
|
||||
pub(crate) mod cd;
|
||||
pub(crate) mod classified;
|
||||
pub(crate) mod clip;
|
||||
pub(crate) mod command;
|
||||
pub(crate) mod config;
|
||||
pub(crate) mod cp;
|
||||
pub(crate) mod date;
|
||||
pub(crate) mod debug;
|
||||
pub(crate) mod enter;
|
||||
pub(crate) mod exit;
|
||||
pub(crate) mod first;
|
||||
pub(crate) mod from_array;
|
||||
pub(crate) mod from_bson;
|
||||
pub(crate) mod from_csv;
|
||||
pub(crate) mod from_ini;
|
||||
pub(crate) mod from_json;
|
||||
pub(crate) mod from_toml;
|
||||
pub(crate) mod from_tsv;
|
||||
pub(crate) mod from_xml;
|
||||
pub(crate) mod from_yaml;
|
||||
pub(crate) mod get;
|
||||
pub(crate) mod last;
|
||||
pub(crate) mod lines;
|
||||
pub(crate) mod ls;
|
||||
pub(crate) mod mkdir;
|
||||
pub(crate) mod mv;
|
||||
pub(crate) mod next;
|
||||
pub(crate) mod nth;
|
||||
pub(crate) mod open;
|
||||
pub(crate) mod pick;
|
||||
pub(crate) mod plugin;
|
||||
pub(crate) mod prev;
|
||||
pub(crate) mod ps;
|
||||
pub(crate) mod reject;
|
||||
pub(crate) mod reverse;
|
||||
pub(crate) mod rm;
|
||||
pub(crate) mod save;
|
||||
pub(crate) mod shells;
|
||||
pub(crate) mod size;
|
||||
pub(crate) mod skip_while;
|
||||
pub(crate) mod sort_by;
|
||||
pub(crate) mod split_column;
|
||||
pub(crate) mod split_row;
|
||||
pub(crate) mod table;
|
||||
pub(crate) mod tags;
|
||||
pub(crate) mod to_array;
|
||||
pub(crate) mod to_bson;
|
||||
pub(crate) mod to_csv;
|
||||
pub(crate) mod to_json;
|
||||
pub(crate) mod to_toml;
|
||||
pub(crate) mod to_tsv;
|
||||
pub(crate) mod to_yaml;
|
||||
pub(crate) mod trim;
|
||||
pub(crate) mod version;
|
||||
pub(crate) mod vtable;
|
||||
pub(crate) mod where_;
|
||||
pub(crate) mod which_;
|
||||
|
||||
crate use autoview::Autoview;
|
||||
crate use cd::CD;
|
||||
crate use command::{
|
||||
pub(crate) use autoview::Autoview;
|
||||
pub(crate) use cd::CD;
|
||||
pub(crate) use command::{
|
||||
per_item_command, whole_stream_command, Command, PerItemCommand, RawCommandArgs,
|
||||
UnevaluatedCallInfo, WholeStreamCommand,
|
||||
};
|
||||
crate use config::Config;
|
||||
crate use cp::Cpy;
|
||||
crate use date::Date;
|
||||
crate use debug::Debug;
|
||||
crate use enter::Enter;
|
||||
crate use exit::Exit;
|
||||
crate use first::First;
|
||||
crate use from_array::FromArray;
|
||||
crate use from_bson::FromBSON;
|
||||
crate use from_csv::FromCSV;
|
||||
crate use from_ini::FromINI;
|
||||
crate use from_json::FromJSON;
|
||||
crate use from_toml::FromTOML;
|
||||
crate use from_xml::FromXML;
|
||||
crate use from_yaml::FromYAML;
|
||||
crate use from_yaml::FromYML;
|
||||
crate use get::Get;
|
||||
crate use last::Last;
|
||||
crate use lines::Lines;
|
||||
crate use ls::LS;
|
||||
crate use mkdir::Mkdir;
|
||||
crate use mv::Move;
|
||||
crate use next::Next;
|
||||
crate use nth::Nth;
|
||||
crate use open::Open;
|
||||
crate use pick::Pick;
|
||||
crate use prev::Previous;
|
||||
crate use ps::PS;
|
||||
crate use reject::Reject;
|
||||
crate use reverse::Reverse;
|
||||
crate use rm::Remove;
|
||||
crate use save::Save;
|
||||
crate use shells::Shells;
|
||||
crate use size::Size;
|
||||
crate use skip_while::SkipWhile;
|
||||
crate use sort_by::SortBy;
|
||||
crate use split_column::SplitColumn;
|
||||
crate use split_row::SplitRow;
|
||||
crate use table::Table;
|
||||
crate use tags::Tags;
|
||||
crate use to_array::ToArray;
|
||||
crate use to_bson::ToBSON;
|
||||
crate use to_csv::ToCSV;
|
||||
crate use to_json::ToJSON;
|
||||
crate use to_toml::ToTOML;
|
||||
crate use to_yaml::ToYAML;
|
||||
crate use trim::Trim;
|
||||
crate use version::Version;
|
||||
crate use vtable::VTable;
|
||||
crate use where_::Where;
|
||||
crate use which_::Which;
|
||||
pub(crate) use config::Config;
|
||||
pub(crate) use cp::Cpy;
|
||||
pub(crate) use date::Date;
|
||||
pub(crate) use debug::Debug;
|
||||
pub(crate) use enter::Enter;
|
||||
pub(crate) use exit::Exit;
|
||||
pub(crate) use first::First;
|
||||
pub(crate) use from_array::FromArray;
|
||||
pub(crate) use from_bson::FromBSON;
|
||||
pub(crate) use from_csv::FromCSV;
|
||||
pub(crate) use from_ini::FromINI;
|
||||
pub(crate) use from_json::FromJSON;
|
||||
pub(crate) use from_toml::FromTOML;
|
||||
pub(crate) use from_tsv::FromTSV;
|
||||
pub(crate) use from_xml::FromXML;
|
||||
pub(crate) use from_yaml::FromYAML;
|
||||
pub(crate) use from_yaml::FromYML;
|
||||
pub(crate) use get::Get;
|
||||
pub(crate) use last::Last;
|
||||
pub(crate) use lines::Lines;
|
||||
pub(crate) use ls::LS;
|
||||
pub(crate) use mkdir::Mkdir;
|
||||
pub(crate) use mv::Move;
|
||||
pub(crate) use next::Next;
|
||||
pub(crate) use nth::Nth;
|
||||
pub(crate) use open::Open;
|
||||
pub(crate) use pick::Pick;
|
||||
pub(crate) use prev::Previous;
|
||||
pub(crate) use ps::PS;
|
||||
pub(crate) use reject::Reject;
|
||||
pub(crate) use reverse::Reverse;
|
||||
pub(crate) use rm::Remove;
|
||||
pub(crate) use save::Save;
|
||||
pub(crate) use shells::Shells;
|
||||
pub(crate) use size::Size;
|
||||
pub(crate) use skip_while::SkipWhile;
|
||||
pub(crate) use sort_by::SortBy;
|
||||
pub(crate) use split_column::SplitColumn;
|
||||
pub(crate) use split_row::SplitRow;
|
||||
pub(crate) use table::Table;
|
||||
pub(crate) use tags::Tags;
|
||||
pub(crate) use to_array::ToArray;
|
||||
pub(crate) use to_bson::ToBSON;
|
||||
pub(crate) use to_csv::ToCSV;
|
||||
pub(crate) use to_json::ToJSON;
|
||||
pub(crate) use to_toml::ToTOML;
|
||||
pub(crate) use to_tsv::ToTSV;
|
||||
pub(crate) use to_yaml::ToYAML;
|
||||
pub(crate) use trim::Trim;
|
||||
pub(crate) use version::Version;
|
||||
pub(crate) use vtable::VTable;
|
||||
pub(crate) use where_::Where;
|
||||
pub(crate) use which_::Which;
|
||||
|
@ -45,27 +45,27 @@ impl Decoder for LinesCodec {
|
||||
}
|
||||
}
|
||||
|
||||
crate struct ClassifiedInputStream {
|
||||
crate objects: InputStream,
|
||||
crate stdin: Option<std::fs::File>,
|
||||
pub(crate) struct ClassifiedInputStream {
|
||||
pub(crate) objects: InputStream,
|
||||
pub(crate) stdin: Option<std::fs::File>,
|
||||
}
|
||||
|
||||
impl ClassifiedInputStream {
|
||||
crate fn new() -> ClassifiedInputStream {
|
||||
pub(crate) fn new() -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: VecDeque::new().into(),
|
||||
stdin: None,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn from_input_stream(stream: impl Into<InputStream>) -> ClassifiedInputStream {
|
||||
pub(crate) fn from_input_stream(stream: impl Into<InputStream>) -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: stream.into(),
|
||||
stdin: None,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn from_stdout(stdout: std::fs::File) -> ClassifiedInputStream {
|
||||
pub(crate) fn from_stdout(stdout: std::fs::File) -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: VecDeque::new().into(),
|
||||
stdin: Some(stdout),
|
||||
@ -73,11 +73,11 @@ impl ClassifiedInputStream {
|
||||
}
|
||||
}
|
||||
|
||||
crate struct ClassifiedPipeline {
|
||||
crate commands: Vec<ClassifiedCommand>,
|
||||
pub(crate) struct ClassifiedPipeline {
|
||||
pub(crate) commands: Vec<ClassifiedCommand>,
|
||||
}
|
||||
|
||||
crate enum ClassifiedCommand {
|
||||
pub(crate) enum ClassifiedCommand {
|
||||
#[allow(unused)]
|
||||
Expr(TokenNode),
|
||||
Internal(InternalCommand),
|
||||
@ -95,14 +95,14 @@ impl ClassifiedCommand {
|
||||
}
|
||||
}
|
||||
|
||||
crate struct InternalCommand {
|
||||
crate command: Arc<Command>,
|
||||
crate name_span: Span,
|
||||
crate args: hir::Call,
|
||||
pub(crate) struct InternalCommand {
|
||||
pub(crate) command: Arc<Command>,
|
||||
pub(crate) name_span: Span,
|
||||
pub(crate) args: hir::Call,
|
||||
}
|
||||
|
||||
impl InternalCommand {
|
||||
crate async fn run(
|
||||
pub(crate) async fn run(
|
||||
self,
|
||||
context: &mut Context,
|
||||
input: ClassifiedInputStream,
|
||||
@ -206,21 +206,21 @@ impl InternalCommand {
|
||||
}
|
||||
}
|
||||
|
||||
crate struct ExternalCommand {
|
||||
crate name: String,
|
||||
pub(crate) struct ExternalCommand {
|
||||
pub(crate) name: String,
|
||||
#[allow(unused)]
|
||||
crate name_span: Span,
|
||||
crate args: Vec<Tagged<String>>,
|
||||
pub(crate) name_span: Span,
|
||||
pub(crate) args: Vec<Tagged<String>>,
|
||||
}
|
||||
|
||||
crate enum StreamNext {
|
||||
pub(crate) enum StreamNext {
|
||||
Last,
|
||||
External,
|
||||
Internal,
|
||||
}
|
||||
|
||||
impl ExternalCommand {
|
||||
crate async fn run(
|
||||
pub(crate) async fn run(
|
||||
self,
|
||||
context: &mut Context,
|
||||
input: ClassifiedInputStream,
|
||||
|
@ -111,6 +111,7 @@ pub fn config(
|
||||
|
||||
if result.contains_key(&key) {
|
||||
result.remove(&key);
|
||||
config::write_config(&result)?;
|
||||
} else {
|
||||
return Err(ShellError::string(&format!(
|
||||
"{} does not exist in config",
|
||||
|
@ -3,7 +3,7 @@ use crate::{EntriesListView, GenericView, TreeView};
|
||||
use futures::stream::{self, StreamExt};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
crate fn format(input: Vec<Value>, host: &mut dyn Host) {
|
||||
pub(crate) fn format(input: Vec<Value>, host: &mut dyn Host) {
|
||||
let last = input.len() - 1;
|
||||
for (i, item) in input.iter().enumerate() {
|
||||
let view = GenericView::new(item);
|
||||
|
135
src/commands/from_tsv.rs
Normal file
135
src/commands/from_tsv.rs
Normal file
@ -0,0 +1,135 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
use csv::ReaderBuilder;
|
||||
|
||||
pub struct FromTSV;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct FromTSVArgs {
|
||||
headerless: bool,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for FromTSV {
|
||||
fn name(&self) -> &str {
|
||||
"from-tsv"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("from-tsv").switch("headerless")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, from_tsv)?.run()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_tsv_string_to_value(
|
||||
s: String,
|
||||
headerless: bool,
|
||||
tag: impl Into<Tag>,
|
||||
) -> Result<Tagged<Value>, csv::Error> {
|
||||
let mut reader = ReaderBuilder::new()
|
||||
.has_headers(false)
|
||||
.delimiter(b'\t')
|
||||
.from_reader(s.as_bytes());
|
||||
let tag = tag.into();
|
||||
|
||||
let mut fields: VecDeque<String> = VecDeque::new();
|
||||
let mut iter = reader.records();
|
||||
let mut rows = vec![];
|
||||
|
||||
if let Some(result) = iter.next() {
|
||||
let line = result?;
|
||||
|
||||
for (idx, item) in line.iter().enumerate() {
|
||||
if headerless {
|
||||
fields.push_back(format!("Column{}", idx + 1));
|
||||
} else {
|
||||
fields.push_back(item.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
if let Some(row_values) = iter.next() {
|
||||
let row_values = row_values?;
|
||||
|
||||
let mut row = TaggedDictBuilder::new(tag);
|
||||
|
||||
for (idx, entry) in row_values.iter().enumerate() {
|
||||
row.insert_tagged(
|
||||
fields.get(idx).unwrap(),
|
||||
Value::Primitive(Primitive::String(String::from(entry))).tagged(tag),
|
||||
);
|
||||
}
|
||||
|
||||
rows.push(row.into_tagged_value());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Tagged::from_item(Value::List(rows), tag))
|
||||
}
|
||||
|
||||
fn from_tsv(
|
||||
FromTSVArgs {
|
||||
headerless: skip_headers,
|
||||
}: FromTSVArgs,
|
||||
RunnableContext { input, name, .. }: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let name_span = name;
|
||||
|
||||
let stream = async_stream_block! {
|
||||
let values: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
|
||||
let mut concat_string = String::new();
|
||||
let mut latest_tag: Option<Tag> = None;
|
||||
|
||||
for value in values {
|
||||
let value_tag = value.tag();
|
||||
latest_tag = Some(value_tag);
|
||||
match value.item {
|
||||
Value::Primitive(Primitive::String(s)) => {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_tag.span,
|
||||
)),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
match from_tsv_string_to_value(concat_string, skip_headers, name_span) {
|
||||
Ok(x) => match x {
|
||||
Tagged { item: Value::List(list), .. } => {
|
||||
for l in list {
|
||||
yield ReturnSuccess::value(l);
|
||||
}
|
||||
}
|
||||
x => yield ReturnSuccess::value(x),
|
||||
},
|
||||
Err(_) => if let Some(last_tag) = latest_tag {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Could not parse as TSV",
|
||||
"input cannot be parsed as TSV",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
last_tag.span,
|
||||
))
|
||||
} ,
|
||||
}
|
||||
};
|
||||
|
||||
Ok(stream.to_output_stream())
|
||||
}
|
@ -1,8 +1,13 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::process::process_dict;
|
||||
use crate::object::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use sysinfo::SystemExt;
|
||||
use std::time::Duration;
|
||||
use std::usize;
|
||||
|
||||
use futures::stream::{StreamExt, TryStreamExt};
|
||||
use heim::process::{self as process, Process, ProcessResult};
|
||||
use heim::units::{ratio, Ratio};
|
||||
|
||||
pub struct PS;
|
||||
|
||||
@ -24,28 +29,44 @@ impl WholeStreamCommand for PS {
|
||||
}
|
||||
}
|
||||
|
||||
fn ps(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
let system;
|
||||
async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio)> {
|
||||
let usage_1 = process.cpu_usage().await?;
|
||||
futures_timer::Delay::new(Duration::from_millis(100)).await?;
|
||||
let usage_2 = process.cpu_usage().await?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
system = sysinfo::System::new();
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
use sysinfo::RefreshKind;
|
||||
let mut sy = sysinfo::System::new_with_specifics(RefreshKind::new().with_processes());
|
||||
sy.refresh_processes();
|
||||
|
||||
system = sy;
|
||||
}
|
||||
let list = system.get_process_list();
|
||||
|
||||
let list = list
|
||||
.into_iter()
|
||||
.map(|(_, process)| process_dict(process, Tag::unknown_origin(args.call_info.name_span)))
|
||||
.collect::<VecDeque<_>>();
|
||||
|
||||
Ok(list.from_input_stream())
|
||||
Ok((process, usage_2 - usage_1))
|
||||
}
|
||||
|
||||
fn ps(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
let args = args.evaluate_once(registry)?;
|
||||
let span = args.name_span();
|
||||
|
||||
let stream = async_stream_block! {
|
||||
let processes = process::processes()
|
||||
.map_ok(|process| {
|
||||
// Note that there is no `.await` here,
|
||||
// as we want to pass the returned future
|
||||
// into the `.try_buffer_unordered`.
|
||||
usage(process)
|
||||
})
|
||||
.try_buffer_unordered(usize::MAX);
|
||||
pin_utils::pin_mut!(processes);
|
||||
|
||||
while let Some(res) = processes.next().await {
|
||||
if let Ok((process, usage)) = res {
|
||||
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span));
|
||||
dict.insert("pid", Value::int(process.pid()));
|
||||
if let Ok(name) = process.name().await {
|
||||
dict.insert("name", Value::string(name));
|
||||
}
|
||||
if let Ok(status) = process.status().await {
|
||||
dict.insert("status", Value::string(format!("{:?}", status)));
|
||||
}
|
||||
dict.insert("cpu", Value::float(usage.get::<ratio::percent>() as f64));
|
||||
yield ReturnSuccess::value(dict.into_tagged_value());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(stream.to_output_stream())
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::commands::to_csv::{to_string as to_csv_to_string, value_to_csv_value};
|
||||
use crate::commands::to_tsv::{to_string as to_tsv_to_string, value_to_tsv_value};
|
||||
use crate::commands::to_json::value_to_json_value;
|
||||
use crate::commands::to_toml::value_to_toml_value;
|
||||
use crate::commands::to_yaml::value_to_yaml_value;
|
||||
@ -166,6 +167,14 @@ async fn to_string_for(
|
||||
}
|
||||
to_csv_to_string(&value_to_csv_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "tsv" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to tsv requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
to_tsv_to_string(&value_to_tsv_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "toml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
|
108
src/commands/to_tsv.rs
Normal file
108
src/commands/to_tsv.rs
Normal file
@ -0,0 +1,108 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::object::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use csv::WriterBuilder;
|
||||
|
||||
pub struct ToTSV;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ToTSVArgs {
|
||||
headerless: bool,
|
||||
}
|
||||
|
||||
impl WholeStreamCommand for ToTSV {
|
||||
fn name(&self) -> &str {
|
||||
"to-tsv"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("to-tsv").switch("headerless")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, to_tsv)?.run()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_to_tsv_value(v: &Value) -> Value {
|
||||
match v {
|
||||
Value::Primitive(Primitive::String(s)) => Value::Primitive(Primitive::String(s.clone())),
|
||||
Value::Primitive(Primitive::Nothing) => Value::Primitive(Primitive::Nothing),
|
||||
Value::Primitive(Primitive::Boolean(b)) => Value::Primitive(Primitive::Boolean(b.clone())),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Value::Primitive(Primitive::Bytes(b.clone())),
|
||||
Value::Primitive(Primitive::Date(d)) => Value::Primitive(Primitive::Date(d.clone())),
|
||||
Value::Object(o) => Value::Object(o.clone()),
|
||||
Value::List(l) => Value::List(l.clone()),
|
||||
Value::Block(_) => Value::Primitive(Primitive::Nothing),
|
||||
_ => Value::Primitive(Primitive::Nothing),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string_helper(v: &Value) -> Result<String, Box<dyn std::error::Error>> {
|
||||
match v {
|
||||
Value::Primitive(Primitive::Date(d)) => Ok(d.to_string()),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Ok(format!("{}", *b as u64)),
|
||||
Value::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?),
|
||||
Value::List(_) => return Ok(String::from("[list list]")),
|
||||
Value::Object(_) => return Ok(String::from("[object]")),
|
||||
Value::Primitive(Primitive::String(s)) => return Ok(s.to_string()),
|
||||
_ => return Err("Bad input".into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(v: &Value) -> Result<String, Box<dyn std::error::Error>> {
|
||||
match v {
|
||||
Value::Object(o) => {
|
||||
let mut wtr = WriterBuilder::new().delimiter(b'\t').from_writer(vec![]);
|
||||
let mut fields: VecDeque<String> = VecDeque::new();
|
||||
let mut values: VecDeque<String> = VecDeque::new();
|
||||
|
||||
for (k, v) in o.entries.iter() {
|
||||
fields.push_back(k.clone());
|
||||
values.push_back(to_string_helper(&v)?);
|
||||
}
|
||||
|
||||
wtr.write_record(fields).expect("can not write.");
|
||||
wtr.write_record(values).expect("can not write.");
|
||||
|
||||
return Ok(String::from_utf8(wtr.into_inner()?)?);
|
||||
}
|
||||
_ => return to_string_helper(&v),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_tsv(
|
||||
ToTSVArgs { headerless }: ToTSVArgs,
|
||||
RunnableContext { input, name, .. }: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let name_span = name;
|
||||
let out = input;
|
||||
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match to_string(&value_to_tsv_value(&a.item)) {
|
||||
Ok(x) => {
|
||||
let converted = if headerless {
|
||||
x.lines().skip(1).collect()
|
||||
} else {
|
||||
x
|
||||
};
|
||||
|
||||
ReturnSuccess::value(
|
||||
Value::Primitive(Primitive::String(converted)).simple_spanned(name_span),
|
||||
)
|
||||
}
|
||||
_ => Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected an object with TSV-compatible structure from pipeline",
|
||||
"requires TSV-compatible input",
|
||||
name_span,
|
||||
format!("{} originates from here", a.item.type_name()),
|
||||
a.span(),
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
@ -41,13 +41,13 @@ pub struct CommandRegistry {
|
||||
}
|
||||
|
||||
impl CommandRegistry {
|
||||
crate fn empty() -> CommandRegistry {
|
||||
pub(crate) fn empty() -> CommandRegistry {
|
||||
CommandRegistry {
|
||||
registry: Arc::new(Mutex::new(IndexMap::default())),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_command(&self, name: &str) -> Option<Arc<Command>> {
|
||||
pub(crate) fn get_command(&self, name: &str) -> Option<Arc<Command>> {
|
||||
let registry = self.registry.lock().unwrap();
|
||||
|
||||
registry.get(name).map(|c| c.clone())
|
||||
@ -64,7 +64,7 @@ impl CommandRegistry {
|
||||
registry.insert(name.into(), command);
|
||||
}
|
||||
|
||||
crate fn names(&self) -> Vec<String> {
|
||||
pub(crate) fn names(&self) -> Vec<String> {
|
||||
let registry = self.registry.lock().unwrap();
|
||||
registry.keys().cloned().collect()
|
||||
}
|
||||
@ -73,17 +73,17 @@ impl CommandRegistry {
|
||||
#[derive(Clone)]
|
||||
pub struct Context {
|
||||
registry: CommandRegistry,
|
||||
crate source_map: SourceMap,
|
||||
pub(crate) source_map: SourceMap,
|
||||
host: Arc<Mutex<dyn Host + Send>>,
|
||||
crate shell_manager: ShellManager,
|
||||
pub(crate) shell_manager: ShellManager,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
crate fn registry(&self) -> &CommandRegistry {
|
||||
pub(crate) fn registry(&self) -> &CommandRegistry {
|
||||
&self.registry
|
||||
}
|
||||
|
||||
crate fn basic() -> Result<Context, Box<dyn Error>> {
|
||||
pub(crate) fn basic() -> Result<Context, Box<dyn Error>> {
|
||||
let registry = CommandRegistry::new();
|
||||
Ok(Context {
|
||||
registry: registry.clone(),
|
||||
@ -93,7 +93,7 @@ impl Context {
|
||||
})
|
||||
}
|
||||
|
||||
crate fn with_host(&mut self, block: impl FnOnce(&mut dyn Host)) {
|
||||
pub(crate) fn with_host(&mut self, block: impl FnOnce(&mut dyn Host)) {
|
||||
let mut host = self.host.lock().unwrap();
|
||||
|
||||
block(&mut *host)
|
||||
@ -109,15 +109,15 @@ impl Context {
|
||||
self.source_map.insert(uuid, span_source);
|
||||
}
|
||||
|
||||
crate fn has_command(&self, name: &str) -> bool {
|
||||
pub(crate) fn has_command(&self, name: &str) -> bool {
|
||||
self.registry.has(name)
|
||||
}
|
||||
|
||||
crate fn get_command(&self, name: &str) -> Arc<Command> {
|
||||
pub(crate) fn get_command(&self, name: &str) -> Arc<Command> {
|
||||
self.registry.get_command(name).unwrap()
|
||||
}
|
||||
|
||||
crate fn run_command<'a>(
|
||||
pub(crate) fn run_command<'a>(
|
||||
&mut self,
|
||||
command: Arc<Command>,
|
||||
name_span: Span,
|
||||
|
@ -1,3 +1,3 @@
|
||||
crate mod host;
|
||||
pub(crate) mod host;
|
||||
|
||||
crate use self::host::Host;
|
||||
pub(crate) use self::host::Host;
|
||||
|
2
src/env/host.rs
vendored
2
src/env/host.rs
vendored
@ -73,7 +73,7 @@ impl Host for BasicHost {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn handle_unexpected<T>(
|
||||
pub(crate) fn handle_unexpected<T>(
|
||||
host: &mut dyn Host,
|
||||
func: impl FnOnce(&mut dyn Host) -> Result<T, ShellError>,
|
||||
) {
|
||||
|
@ -73,7 +73,7 @@ impl serde::de::Error for ShellError {
|
||||
}
|
||||
|
||||
impl ShellError {
|
||||
crate fn type_error(
|
||||
pub(crate) fn type_error(
|
||||
expected: impl Into<String>,
|
||||
actual: Tagged<impl Into<String>>,
|
||||
) -> ShellError {
|
||||
@ -84,21 +84,21 @@ impl ShellError {
|
||||
.start()
|
||||
}
|
||||
|
||||
crate fn syntax_error(problem: Tagged<impl Into<String>>) -> ShellError {
|
||||
pub(crate) fn syntax_error(problem: Tagged<impl Into<String>>) -> ShellError {
|
||||
ProximateShellError::SyntaxError {
|
||||
problem: problem.map(|p| p.into()),
|
||||
}
|
||||
.start()
|
||||
}
|
||||
|
||||
crate fn invalid_command(problem: impl Into<Tag>) -> ShellError {
|
||||
pub(crate) fn invalid_command(problem: impl Into<Tag>) -> ShellError {
|
||||
ProximateShellError::InvalidCommand {
|
||||
command: problem.into(),
|
||||
}
|
||||
.start()
|
||||
}
|
||||
|
||||
crate fn coerce_error(
|
||||
pub(crate) fn coerce_error(
|
||||
left: Tagged<impl Into<String>>,
|
||||
right: Tagged<impl Into<String>>,
|
||||
) -> ShellError {
|
||||
@ -109,11 +109,11 @@ impl ShellError {
|
||||
.start()
|
||||
}
|
||||
|
||||
crate fn missing_property(subpath: Description, expr: Description) -> ShellError {
|
||||
pub(crate) fn missing_property(subpath: Description, expr: Description) -> ShellError {
|
||||
ProximateShellError::MissingProperty { subpath, expr }.start()
|
||||
}
|
||||
|
||||
crate fn missing_value(span: Option<Span>, reason: impl Into<String>) -> ShellError {
|
||||
pub(crate) fn missing_value(span: Option<Span>, reason: impl Into<String>) -> ShellError {
|
||||
ProximateShellError::MissingValue {
|
||||
span,
|
||||
reason: reason.into(),
|
||||
@ -121,7 +121,7 @@ impl ShellError {
|
||||
.start()
|
||||
}
|
||||
|
||||
crate fn argument_error(
|
||||
pub(crate) fn argument_error(
|
||||
command: impl Into<String>,
|
||||
kind: ArgumentError,
|
||||
span: Span,
|
||||
@ -134,7 +134,7 @@ impl ShellError {
|
||||
.start()
|
||||
}
|
||||
|
||||
crate fn parse_error(
|
||||
pub(crate) fn parse_error(
|
||||
error: nom::Err<(nom5_locate::LocatedSpan<&str>, nom::error::ErrorKind)>,
|
||||
) -> ShellError {
|
||||
use language_reporting::*;
|
||||
@ -158,11 +158,11 @@ impl ShellError {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
||||
pub(crate) fn diagnostic(diagnostic: Diagnostic<Span>) -> ShellError {
|
||||
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
|
||||
}
|
||||
|
||||
crate fn to_diagnostic(self) -> Diagnostic<Span> {
|
||||
pub(crate) fn to_diagnostic(self) -> Diagnostic<Span> {
|
||||
match self.error {
|
||||
ProximateShellError::String(StringError { title, .. }) => {
|
||||
Diagnostic::new(Severity::Error, title)
|
||||
@ -309,11 +309,11 @@ impl ShellError {
|
||||
ProximateShellError::String(StringError::new(title.into(), Value::nothing())).start()
|
||||
}
|
||||
|
||||
crate fn unimplemented(title: impl Into<String>) -> ShellError {
|
||||
pub(crate) fn unimplemented(title: impl Into<String>) -> ShellError {
|
||||
ShellError::string(&format!("Unimplemented: {}", title.into()))
|
||||
}
|
||||
|
||||
crate fn unexpected(title: impl Into<String>) -> ShellError {
|
||||
pub(crate) fn unexpected(title: impl Into<String>) -> ShellError {
|
||||
ShellError::string(&format!("Unexpected: {}", title.into()))
|
||||
}
|
||||
}
|
||||
@ -369,12 +369,12 @@ impl ToDebug for ProximateShellError {
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ShellDiagnostic {
|
||||
crate diagnostic: Diagnostic<Span>,
|
||||
pub(crate) diagnostic: Diagnostic<Span>,
|
||||
}
|
||||
|
||||
impl ShellDiagnostic {
|
||||
#[allow(unused)]
|
||||
crate fn simple_diagnostic(
|
||||
pub(crate) fn simple_diagnostic(
|
||||
span: impl Into<Span>,
|
||||
source: impl Into<String>,
|
||||
) -> ShellDiagnostic {
|
||||
|
@ -16,14 +16,14 @@ pub struct Scope {
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
crate fn empty() -> Scope {
|
||||
pub(crate) fn empty() -> Scope {
|
||||
Scope {
|
||||
it: Value::nothing().tagged_unknown(),
|
||||
vars: IndexMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn it_value(value: Tagged<Value>) -> Scope {
|
||||
pub(crate) fn it_value(value: Tagged<Value>) -> Scope {
|
||||
Scope {
|
||||
it: value,
|
||||
vars: IndexMap::new(),
|
||||
@ -31,7 +31,7 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn evaluate_baseline_expr(
|
||||
pub(crate) fn evaluate_baseline_expr(
|
||||
expr: &Expression,
|
||||
registry: &CommandRegistry,
|
||||
scope: &Scope,
|
||||
|
@ -1,3 +1,3 @@
|
||||
crate mod evaluator;
|
||||
pub(crate) mod evaluator;
|
||||
|
||||
crate use evaluator::{evaluate_baseline_expr, Scope};
|
||||
pub(crate) use evaluator::{evaluate_baseline_expr, Scope};
|
||||
|
@ -1,21 +1,21 @@
|
||||
crate mod entries;
|
||||
crate mod generic;
|
||||
crate mod list;
|
||||
crate mod table;
|
||||
crate mod vtable;
|
||||
pub(crate) mod entries;
|
||||
pub(crate) mod generic;
|
||||
pub(crate) mod list;
|
||||
pub(crate) mod table;
|
||||
pub(crate) mod vtable;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
crate use entries::EntriesView;
|
||||
pub(crate) use entries::EntriesView;
|
||||
#[allow(unused)]
|
||||
crate use generic::GenericView;
|
||||
crate use table::TableView;
|
||||
crate use vtable::VTableView;
|
||||
pub(crate) use generic::GenericView;
|
||||
pub(crate) use table::TableView;
|
||||
pub(crate) use vtable::VTableView;
|
||||
|
||||
crate trait RenderView {
|
||||
pub(crate) trait RenderView {
|
||||
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError>;
|
||||
}
|
||||
|
||||
crate fn print_view(view: &impl RenderView, host: &mut dyn Host) -> Result<(), ShellError> {
|
||||
pub(crate) fn print_view(view: &impl RenderView, host: &mut dyn Host) -> Result<(), ShellError> {
|
||||
view.render_view(host)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ pub struct EntriesView {
|
||||
}
|
||||
|
||||
impl EntriesView {
|
||||
crate fn from_value(value: &Value) -> EntriesView {
|
||||
pub(crate) fn from_value(value: &Value) -> EntriesView {
|
||||
let descs = value.data_descriptors();
|
||||
let mut entries = vec![];
|
||||
|
||||
|
@ -9,7 +9,7 @@ pub struct GenericView<'value> {
|
||||
value: &'value Value,
|
||||
}
|
||||
|
||||
impl RenderView for GenericView<'value> {
|
||||
impl RenderView for GenericView<'_> {
|
||||
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
|
||||
match self.value {
|
||||
Value::Primitive(p) => Ok(host.stdout(&p.format(None))),
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(generators)]
|
||||
#![feature(specialization)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
|
@ -1,13 +1,12 @@
|
||||
crate mod base;
|
||||
crate mod config;
|
||||
crate mod dict;
|
||||
crate mod files;
|
||||
crate mod into;
|
||||
crate mod meta;
|
||||
crate mod process;
|
||||
crate mod types;
|
||||
pub(crate) mod base;
|
||||
pub(crate) mod config;
|
||||
pub(crate) mod dict;
|
||||
pub(crate) mod files;
|
||||
pub(crate) mod into;
|
||||
pub(crate) mod meta;
|
||||
pub(crate) mod types;
|
||||
|
||||
#[allow(unused)]
|
||||
crate use base::{Block, Primitive, Switch, Value};
|
||||
crate use dict::{Dictionary, TaggedDictBuilder};
|
||||
crate use files::dir_entry_dict;
|
||||
pub(crate) use base::{Block, Primitive, Switch, Value};
|
||||
pub(crate) use dict::{Dictionary, TaggedDictBuilder};
|
||||
pub(crate) use files::dir_entry_dict;
|
||||
|
@ -16,11 +16,11 @@ use std::time::SystemTime;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, new, Serialize, Deserialize)]
|
||||
pub struct OF64 {
|
||||
crate inner: OrderedFloat<f64>,
|
||||
pub(crate) inner: OrderedFloat<f64>,
|
||||
}
|
||||
|
||||
impl OF64 {
|
||||
crate fn into_inner(&self) -> f64 {
|
||||
pub(crate) fn into_inner(&self) -> f64 {
|
||||
self.inner.into_inner()
|
||||
}
|
||||
}
|
||||
@ -49,7 +49,7 @@ pub enum Primitive {
|
||||
}
|
||||
|
||||
impl Primitive {
|
||||
crate fn type_name(&self) -> String {
|
||||
pub(crate) fn type_name(&self) -> String {
|
||||
use Primitive::*;
|
||||
|
||||
match self {
|
||||
@ -67,7 +67,7 @@ impl Primitive {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
crate fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Primitive::*;
|
||||
|
||||
match self {
|
||||
@ -130,16 +130,16 @@ impl Primitive {
|
||||
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)]
|
||||
pub struct Operation {
|
||||
crate left: Value,
|
||||
crate operator: Operator,
|
||||
crate right: Value,
|
||||
pub(crate) left: Value,
|
||||
pub(crate) operator: Operator,
|
||||
pub(crate) right: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Serialize, Deserialize, new)]
|
||||
pub struct Block {
|
||||
crate expressions: Vec<hir::Expression>,
|
||||
crate source: Text,
|
||||
crate span: Span,
|
||||
pub(crate) expressions: Vec<hir::Expression>,
|
||||
pub(crate) source: Text,
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
@ -176,7 +176,7 @@ pub enum Value {
|
||||
Block(Block),
|
||||
}
|
||||
|
||||
pub fn debug_list(values: &'a Vec<Tagged<Value>>) -> ValuesDebug<'a> {
|
||||
pub fn debug_list(values: &Vec<Tagged<Value>>) -> ValuesDebug<'_> {
|
||||
ValuesDebug { values }
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ pub struct ValuesDebug<'a> {
|
||||
values: &'a Vec<Tagged<Value>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ValuesDebug<'a> {
|
||||
impl fmt::Debug for ValuesDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.values.iter().map(|i| i.debug()))
|
||||
@ -196,7 +196,7 @@ pub struct ValueDebug<'a> {
|
||||
value: &'a Tagged<Value>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ValueDebug<'a> {
|
||||
impl fmt::Debug for ValueDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.value.item() {
|
||||
Value::Primitive(p) => p.debug(f),
|
||||
@ -209,16 +209,16 @@ impl fmt::Debug for ValueDebug<'a> {
|
||||
}
|
||||
|
||||
impl Tagged<Value> {
|
||||
crate fn tagged_type_name(&self) -> Tagged<String> {
|
||||
pub(crate) fn tagged_type_name(&self) -> Tagged<String> {
|
||||
let name = self.type_name();
|
||||
Tagged::from_item(name, self.tag())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&'a Tagged<Value>> for Block {
|
||||
impl std::convert::TryFrom<&Tagged<Value>> for Block {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &'a Tagged<Value>) -> Result<Block, ShellError> {
|
||||
fn try_from(value: &Tagged<Value>) -> Result<Block, ShellError> {
|
||||
match value.item() {
|
||||
Value::Block(block) => Ok(block.clone()),
|
||||
v => Err(ShellError::type_error(
|
||||
@ -229,10 +229,10 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&'a Tagged<Value>> for i64 {
|
||||
impl std::convert::TryFrom<&Tagged<Value>> for i64 {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &'a Tagged<Value>) -> Result<i64, ShellError> {
|
||||
fn try_from(value: &Tagged<Value>) -> Result<i64, ShellError> {
|
||||
match value.item() {
|
||||
Value::Primitive(Primitive::Int(int)) => Ok(*int),
|
||||
v => Err(ShellError::type_error(
|
||||
@ -243,10 +243,10 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for i64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&'a Tagged<Value>> for String {
|
||||
impl std::convert::TryFrom<&Tagged<Value>> for String {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &'a Tagged<Value>) -> Result<String, ShellError> {
|
||||
fn try_from(value: &Tagged<Value>) -> Result<String, ShellError> {
|
||||
match value.item() {
|
||||
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||
v => Err(ShellError::type_error(
|
||||
@ -257,10 +257,10 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&'a Tagged<Value>> for Vec<u8> {
|
||||
impl std::convert::TryFrom<&Tagged<Value>> for Vec<u8> {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &'a Tagged<Value>) -> Result<Vec<u8>, ShellError> {
|
||||
fn try_from(value: &Tagged<Value>) -> Result<Vec<u8>, ShellError> {
|
||||
match value.item() {
|
||||
Value::Binary(b) => Ok(b.clone()),
|
||||
v => Err(ShellError::type_error(
|
||||
@ -271,7 +271,7 @@ impl std::convert::TryFrom<&'a Tagged<Value>> for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&'a Tagged<Value>> for &'a crate::object::Dictionary {
|
||||
impl<'a> std::convert::TryFrom<&'a Tagged<Value>> for &'a crate::object::Dictionary {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: &'a Tagged<Value>) -> Result<&'a crate::object::Dictionary, ShellError> {
|
||||
@ -301,10 +301,10 @@ impl Switch {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<Option<&'a Tagged<Value>>> for Switch {
|
||||
impl std::convert::TryFrom<Option<&Tagged<Value>>> for Switch {
|
||||
type Error = ShellError;
|
||||
|
||||
fn try_from(value: Option<&'a Tagged<Value>>) -> Result<Switch, ShellError> {
|
||||
fn try_from(value: Option<&Tagged<Value>>) -> Result<Switch, ShellError> {
|
||||
match value {
|
||||
None => Ok(Switch::Absent),
|
||||
Some(value) => match value.item() {
|
||||
@ -319,13 +319,13 @@ impl std::convert::TryFrom<Option<&'a Tagged<Value>>> for Switch {
|
||||
}
|
||||
|
||||
impl Tagged<Value> {
|
||||
crate fn debug(&'a self) -> ValueDebug<'a> {
|
||||
pub(crate) fn debug(&self) -> ValueDebug<'_> {
|
||||
ValueDebug { value: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
crate fn type_name(&self) -> String {
|
||||
pub(crate) fn type_name(&self) -> String {
|
||||
match self {
|
||||
Value::Primitive(p) => p.type_name(),
|
||||
Value::Object(_) => format!("object"),
|
||||
@ -351,7 +351,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data_by_key(&'a self, name: &str) -> Option<&Tagged<Value>> {
|
||||
pub(crate) fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
||||
match self {
|
||||
Value::Object(o) => o.get_data_by_key(name),
|
||||
Value::List(l) => {
|
||||
@ -374,14 +374,14 @@ impl Value {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn get_data_by_index(&'a self, idx: usize) -> Option<&Tagged<Value>> {
|
||||
pub(crate) fn get_data_by_index(&self, idx: usize) -> Option<&Tagged<Value>> {
|
||||
match self {
|
||||
Value::List(l) => l.iter().nth(idx),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_data_by_path(&'a self, tag: Tag, path: &str) -> Option<Tagged<&Value>> {
|
||||
pub fn get_data_by_path(&self, tag: Tag, path: &str) -> Option<Tagged<&Value>> {
|
||||
let mut current = self;
|
||||
for p in path.split(".") {
|
||||
match current.get_data_by_key(p) {
|
||||
@ -394,7 +394,7 @@ impl Value {
|
||||
}
|
||||
|
||||
pub fn insert_data_at_path(
|
||||
&'a self,
|
||||
&self,
|
||||
tag: Tag,
|
||||
path: &str,
|
||||
new_value: Value,
|
||||
@ -447,7 +447,7 @@ impl Value {
|
||||
}
|
||||
|
||||
pub fn replace_data_at_path(
|
||||
&'a self,
|
||||
&self,
|
||||
tag: Tag,
|
||||
path: &str,
|
||||
replaced_value: Value,
|
||||
@ -481,7 +481,7 @@ impl Value {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
|
||||
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||
match self {
|
||||
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
||||
Value::Object(o) => o.get_data(desc),
|
||||
@ -491,7 +491,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn format_leaf(&self, desc: Option<&String>) -> String {
|
||||
pub(crate) fn format_leaf(&self, desc: Option<&String>) -> String {
|
||||
match self {
|
||||
Value::Primitive(p) => p.format(desc),
|
||||
Value::Block(b) => itertools::join(
|
||||
@ -510,7 +510,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn style_leaf(&self) -> &'static str {
|
||||
pub(crate) fn style_leaf(&self) -> &'static str {
|
||||
match self {
|
||||
Value::Primitive(p) => p.style(),
|
||||
_ => "",
|
||||
@ -518,7 +518,7 @@ impl Value {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn compare(&self, operator: &Operator, other: &Value) -> Result<bool, (String, String)> {
|
||||
pub(crate) fn compare(&self, operator: &Operator, other: &Value) -> Result<bool, (String, String)> {
|
||||
match operator {
|
||||
_ => {
|
||||
let coerced = coerce_compare(self, other)?;
|
||||
@ -545,14 +545,14 @@ impl Value {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn is_string(&self, expected: &str) -> bool {
|
||||
pub(crate) fn is_string(&self, expected: &str) -> bool {
|
||||
match self {
|
||||
Value::Primitive(Primitive::String(s)) if s == expected => true,
|
||||
other => false,
|
||||
}
|
||||
}
|
||||
|
||||
// crate fn as_pair(&self) -> Result<(Tagged<Value>, Tagged<Value>), ShellError> {
|
||||
// pub(crate) fn as_pair(&self) -> Result<(Tagged<Value>, Tagged<Value>), ShellError> {
|
||||
// match self {
|
||||
// Value::List(list) if list.len() == 2 => Ok((list[0].clone(), list[1].clone())),
|
||||
// other => Err(ShellError::string(format!(
|
||||
@ -562,7 +562,7 @@ impl Value {
|
||||
// }
|
||||
// }
|
||||
|
||||
crate fn as_string(&self) -> Result<String, ShellError> {
|
||||
pub(crate) fn as_string(&self) -> Result<String, ShellError> {
|
||||
match self {
|
||||
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||
Value::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
|
||||
@ -577,7 +577,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn as_i64(&self) -> Result<i64, ShellError> {
|
||||
pub(crate) fn as_i64(&self) -> Result<i64, ShellError> {
|
||||
match self {
|
||||
Value::Primitive(Primitive::Int(i)) => Ok(*i),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Ok(*b as i64),
|
||||
@ -589,7 +589,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn is_true(&self) -> bool {
|
||||
pub(crate) fn is_true(&self) -> bool {
|
||||
match self {
|
||||
Value::Primitive(Primitive::Boolean(true)) => true,
|
||||
_ => false,
|
||||
@ -640,7 +640,7 @@ impl Value {
|
||||
}
|
||||
|
||||
impl Tagged<Value> {
|
||||
crate fn as_path(&self) -> Result<PathBuf, ShellError> {
|
||||
pub(crate) fn as_path(&self) -> Result<PathBuf, ShellError> {
|
||||
match self.item() {
|
||||
Value::Primitive(Primitive::Path(path)) => Ok(path.clone()),
|
||||
other => Err(ShellError::type_error(
|
||||
@ -651,7 +651,7 @@ impl Tagged<Value> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||
pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||
let mut out = TaggedDictBuilder::new(tag);
|
||||
|
||||
let descs = obj.data_descriptors();
|
||||
@ -666,7 +666,7 @@ crate fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> T
|
||||
out.into_tagged_value()
|
||||
}
|
||||
|
||||
crate fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||
pub(crate) fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||
let mut out = TaggedDictBuilder::new(tag);
|
||||
|
||||
let descs = obj.data_descriptors();
|
||||
@ -683,7 +683,7 @@ crate fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> T
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
||||
pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
||||
let descs = obj.data_descriptors();
|
||||
match descs.iter().find(|d| *d == field) {
|
||||
None => false,
|
||||
|
@ -22,14 +22,14 @@ struct Config {
|
||||
extra: IndexMap<String, Tagged<Value>>,
|
||||
}
|
||||
|
||||
crate fn config_path() -> Result<PathBuf, ShellError> {
|
||||
pub(crate) fn config_path() -> Result<PathBuf, ShellError> {
|
||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
||||
|
||||
Ok(location.join("config.toml"))
|
||||
}
|
||||
|
||||
crate fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(), ShellError> {
|
||||
pub(crate) fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(), ShellError> {
|
||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
||||
|
||||
@ -45,7 +45,7 @@ crate fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(), Sh
|
||||
Ok(())
|
||||
}
|
||||
|
||||
crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
||||
pub(crate) fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>, ShellError> {
|
||||
let span = span.into();
|
||||
|
||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||
|
@ -72,14 +72,14 @@ impl PartialEq<Value> for Dictionary {
|
||||
}
|
||||
|
||||
impl Dictionary {
|
||||
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
|
||||
pub fn get_data(&self, desc: &String) -> MaybeOwned<'_, Value> {
|
||||
match self.entries.get(desc) {
|
||||
Some(v) => MaybeOwned::Borrowed(v),
|
||||
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
||||
pub(crate) fn get_data_by_key(&self, name: &str) -> Option<&Tagged<Value>> {
|
||||
match self
|
||||
.entries
|
||||
.iter()
|
||||
@ -90,7 +90,7 @@ impl Dictionary {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut debug = f.debug_struct("Dictionary");
|
||||
|
||||
for (desc, value) in self.entries.iter() {
|
||||
@ -146,6 +146,13 @@ impl TaggedDictBuilder {
|
||||
dict: IndexMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_capacity(tag: impl Into<Tag>, n: usize) -> TaggedDictBuilder {
|
||||
TaggedDictBuilder {
|
||||
tag: tag.into(),
|
||||
dict: IndexMap::with_capacity(n),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
||||
self.dict.insert(key.into(), value.into().tagged(self.tag));
|
||||
|
@ -9,7 +9,7 @@ pub enum FileType {
|
||||
Symlink,
|
||||
}
|
||||
|
||||
crate fn dir_entry_dict(
|
||||
pub(crate) fn dir_entry_dict(
|
||||
filename: &std::path::Path,
|
||||
metadata: &std::fs::Metadata,
|
||||
tag: impl Into<Tag>,
|
||||
|
@ -87,7 +87,7 @@ impl<T> Tagged<T> {
|
||||
Tagged::from_item(mapped, tag.clone())
|
||||
}
|
||||
|
||||
crate fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
||||
pub(crate) fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
||||
let span = self.span();
|
||||
|
||||
Tagged::from_simple_spanned_item(output, span)
|
||||
@ -224,8 +224,8 @@ impl Tag {
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||
pub struct Span {
|
||||
crate start: usize,
|
||||
crate end: usize,
|
||||
pub(crate) start: usize,
|
||||
pub(crate) end: usize,
|
||||
}
|
||||
|
||||
impl From<Option<Span>> for Span {
|
||||
@ -256,7 +256,7 @@ impl Span {
|
||||
self.start == 0 && self.end == 0
|
||||
}
|
||||
|
||||
pub fn slice(&self, source: &'a str) -> &'a str {
|
||||
pub fn slice<'a>(&self, source: &'a str) -> &'a str {
|
||||
&source[self.start..self.end]
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
use crate::object::{TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
use itertools::join;
|
||||
use sysinfo::ProcessExt;
|
||||
|
||||
crate fn process_dict(proc: &sysinfo::Process, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
|
||||
let cmd = proc.cmd();
|
||||
|
||||
let cmd_value = if cmd.len() == 0 {
|
||||
Value::nothing()
|
||||
} else {
|
||||
Value::string(join(cmd, ""))
|
||||
};
|
||||
|
||||
dict.insert("pid", Value::int(proc.pid() as i64));
|
||||
dict.insert("status", Value::string(proc.status().to_string()));
|
||||
dict.insert("cpu", Value::float(proc.cpu_usage() as f64));
|
||||
//dict.insert("name", Value::string(proc.name()));
|
||||
match cmd_value {
|
||||
Value::Primitive(Primitive::Nothing) => {
|
||||
dict.insert("name", Value::string(proc.name()));
|
||||
}
|
||||
_ => dict.insert("name", cmd_value),
|
||||
}
|
||||
|
||||
dict.into_tagged_value()
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
use crate::object::base as value;
|
||||
use crate::parser::hir;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
|
||||
pub trait ExtractType: Sized {
|
||||
fn extract(value: &Tagged<Value>) -> Result<Self, ShellError>;
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError>;
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
hir::SyntaxType::Any
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ExtractType for T {
|
||||
@ -19,14 +14,6 @@ impl<T> ExtractType for T {
|
||||
name
|
||||
)))
|
||||
}
|
||||
|
||||
default fn check(_value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
Err(ShellError::unimplemented("ExtractType for T"))
|
||||
}
|
||||
|
||||
default fn syntax_type() -> hir::SyntaxType {
|
||||
hir::SyntaxType::Any
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ExtractType> ExtractType for Vec<Tagged<T>> {
|
||||
@ -50,20 +37,6 @@ impl<T: ExtractType> ExtractType for Vec<Tagged<T>> {
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
match value.item() {
|
||||
Value::List(_) => Ok(value),
|
||||
other => Err(ShellError::type_error(
|
||||
"Vec",
|
||||
other.type_name().tagged(value.tag()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
hir::SyntaxType::List
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ExtractType, U: ExtractType> ExtractType for (T, U) {
|
||||
@ -107,17 +80,6 @@ impl<T: ExtractType> ExtractType for Option<T> {
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
match value.item() {
|
||||
Value::Primitive(Primitive::Nothing) => Ok(value),
|
||||
_ => T::check(value),
|
||||
}
|
||||
}
|
||||
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
T::syntax_type()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ExtractType> ExtractType for Tagged<T> {
|
||||
@ -127,14 +89,6 @@ impl<T: ExtractType> ExtractType for Tagged<T> {
|
||||
|
||||
Ok(T::extract(value)?.tagged(value.tag()))
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
T::check(value)
|
||||
}
|
||||
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
T::syntax_type()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for Value {
|
||||
@ -143,22 +97,10 @@ impl ExtractType for Value {
|
||||
|
||||
Ok(value.item().clone())
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
SyntaxType::Any
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for bool {
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
hir::SyntaxType::Boolean
|
||||
}
|
||||
|
||||
fn extract(value: &'a Tagged<Value>) -> Result<bool, ShellError> {
|
||||
fn extract(value: &Tagged<Value>) -> Result<bool, ShellError> {
|
||||
trace!("Extracting {:?} for bool", value);
|
||||
|
||||
match &value {
|
||||
@ -173,24 +115,10 @@ impl ExtractType for bool {
|
||||
other => Err(ShellError::type_error("Boolean", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
match &value {
|
||||
value @ Tagged {
|
||||
item: Value::Primitive(Primitive::Boolean(_)),
|
||||
..
|
||||
} => Ok(value),
|
||||
other => Err(ShellError::type_error("Boolean", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for std::path::PathBuf {
|
||||
fn syntax_type() -> hir::SyntaxType {
|
||||
hir::SyntaxType::Path
|
||||
}
|
||||
|
||||
fn extract(value: &'a Tagged<Value>) -> Result<std::path::PathBuf, ShellError> {
|
||||
fn extract(value: &Tagged<Value>) -> Result<std::path::PathBuf, ShellError> {
|
||||
trace!("Extracting {:?} for PathBuf", value);
|
||||
|
||||
match &value {
|
||||
@ -201,16 +129,6 @@ impl ExtractType for std::path::PathBuf {
|
||||
other => Err(ShellError::type_error("Path", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
match &value {
|
||||
v @ Tagged {
|
||||
item: Value::Primitive(Primitive::Path(_)),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Path", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for i64 {
|
||||
@ -225,16 +143,6 @@ impl ExtractType for i64 {
|
||||
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Tagged {
|
||||
item: Value::Primitive(Primitive::Int(_)),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for String {
|
||||
@ -249,31 +157,9 @@ impl ExtractType for String {
|
||||
other => Err(ShellError::type_error("String", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Tagged {
|
||||
item: Value::Primitive(Primitive::String(_)),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("String", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for value::Block {
|
||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||
trace!("Extracting {:?} for Block", value);
|
||||
|
||||
match value {
|
||||
v @ Tagged {
|
||||
item: Value::Block(_),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Block", other.tagged_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn extract(value: &Tagged<Value>) -> Result<value::Block, ShellError> {
|
||||
match value {
|
||||
Tagged {
|
||||
|
@ -1,25 +1,25 @@
|
||||
crate mod deserializer;
|
||||
crate mod hir;
|
||||
crate mod parse;
|
||||
crate mod parse_command;
|
||||
crate mod registry;
|
||||
pub(crate) mod deserializer;
|
||||
pub(crate) mod hir;
|
||||
pub(crate) mod parse;
|
||||
pub(crate) mod parse_command;
|
||||
pub(crate) mod registry;
|
||||
|
||||
use crate::errors::ShellError;
|
||||
|
||||
crate use deserializer::ConfigDeserializer;
|
||||
crate use hir::baseline_parse_tokens::baseline_parse_tokens;
|
||||
crate use parse::call_node::CallNode;
|
||||
crate use parse::files::Files;
|
||||
crate use parse::flag::Flag;
|
||||
crate use parse::operator::Operator;
|
||||
crate use parse::parser::{nom_input, pipeline};
|
||||
crate use parse::pipeline::{Pipeline, PipelineElement};
|
||||
crate use parse::text::Text;
|
||||
crate use parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||
crate use parse::tokens::{RawToken, Token};
|
||||
crate use parse::unit::Unit;
|
||||
crate use parse_command::parse_command;
|
||||
crate use registry::CommandRegistry;
|
||||
pub(crate) use deserializer::ConfigDeserializer;
|
||||
pub(crate) use hir::baseline_parse_tokens::baseline_parse_tokens;
|
||||
pub(crate) use parse::call_node::CallNode;
|
||||
pub(crate) use parse::files::Files;
|
||||
pub(crate) use parse::flag::Flag;
|
||||
pub(crate) use parse::operator::Operator;
|
||||
pub(crate) use parse::parser::{nom_input, pipeline};
|
||||
pub(crate) use parse::pipeline::{Pipeline, PipelineElement};
|
||||
pub(crate) use parse::text::Text;
|
||||
pub(crate) use parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||
pub(crate) use parse::tokens::{RawToken, Token};
|
||||
pub(crate) use parse::unit::Unit;
|
||||
pub(crate) use parse_command::parse_command;
|
||||
pub(crate) use registry::CommandRegistry;
|
||||
|
||||
pub fn parse(input: &str) -> Result<TokenNode, ShellError> {
|
||||
let _ = pretty_env_logger::try_init();
|
||||
|
@ -16,7 +16,7 @@ pub struct ConfigDeserializer<'de> {
|
||||
position: usize,
|
||||
}
|
||||
|
||||
impl ConfigDeserializer<'de> {
|
||||
impl<'de> ConfigDeserializer<'de> {
|
||||
pub fn from_call_info(call: CallInfo) -> ConfigDeserializer<'de> {
|
||||
ConfigDeserializer {
|
||||
call,
|
||||
|
@ -1,9 +1,9 @@
|
||||
crate mod baseline_parse;
|
||||
crate mod baseline_parse_tokens;
|
||||
crate mod binary;
|
||||
crate mod external_command;
|
||||
crate mod named;
|
||||
crate mod path;
|
||||
pub(crate) mod baseline_parse;
|
||||
pub(crate) mod baseline_parse_tokens;
|
||||
pub(crate) mod binary;
|
||||
pub(crate) mod external_command;
|
||||
pub(crate) mod named;
|
||||
pub(crate) mod path;
|
||||
|
||||
use crate::parser::{registry, Unit};
|
||||
use crate::prelude::*;
|
||||
@ -15,15 +15,15 @@ use std::path::PathBuf;
|
||||
|
||||
use crate::evaluate::Scope;
|
||||
|
||||
crate use self::baseline_parse::{
|
||||
pub(crate) use self::baseline_parse::{
|
||||
baseline_parse_single_token, baseline_parse_token_as_number, baseline_parse_token_as_path,
|
||||
baseline_parse_token_as_string,
|
||||
};
|
||||
crate use self::baseline_parse_tokens::{baseline_parse_next_expr, TokensIterator};
|
||||
crate use self::binary::Binary;
|
||||
crate use self::external_command::ExternalCommand;
|
||||
crate use self::named::NamedArguments;
|
||||
crate use self::path::Path;
|
||||
pub(crate) use self::baseline_parse_tokens::{baseline_parse_next_expr, TokensIterator};
|
||||
pub(crate) use self::binary::Binary;
|
||||
pub(crate) use self::external_command::ExternalCommand;
|
||||
pub(crate) use self::named::NamedArguments;
|
||||
pub(crate) use self::path::Path;
|
||||
|
||||
pub use self::baseline_parse_tokens::SyntaxType;
|
||||
|
||||
@ -129,51 +129,51 @@ impl RawExpression {
|
||||
pub type Expression = Tagged<RawExpression>;
|
||||
|
||||
impl Expression {
|
||||
crate fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Integer(i.into())), span)
|
||||
}
|
||||
|
||||
crate fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(
|
||||
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
||||
span,
|
||||
)
|
||||
}
|
||||
|
||||
crate fn synthetic_string(s: impl Into<String>) -> Expression {
|
||||
pub(crate) fn synthetic_string(s: impl Into<String>) -> Expression {
|
||||
RawExpression::Synthetic(Synthetic::String(s.into())).tagged_unknown()
|
||||
}
|
||||
|
||||
crate fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(
|
||||
RawExpression::Literal(Literal::String(inner.into())),
|
||||
outer.into(),
|
||||
)
|
||||
}
|
||||
|
||||
crate fn file_path(path: impl Into<PathBuf>, outer: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn file_path(path: impl Into<PathBuf>, outer: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(RawExpression::FilePath(path.into()), outer.into())
|
||||
}
|
||||
|
||||
crate fn bare(span: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn bare(span: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into())
|
||||
}
|
||||
|
||||
crate fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(
|
||||
RawExpression::Variable(Variable::Other(inner.into())),
|
||||
outer.into(),
|
||||
)
|
||||
}
|
||||
|
||||
crate fn external_command(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn external_command(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(
|
||||
RawExpression::ExternalCommand(ExternalCommand::new(inner.into())),
|
||||
outer.into(),
|
||||
)
|
||||
}
|
||||
|
||||
crate fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(
|
||||
RawExpression::Variable(Variable::It(inner.into())),
|
||||
outer.into(),
|
||||
|
@ -331,7 +331,7 @@ pub struct TokensIterator<'a> {
|
||||
seen: indexmap::IndexSet<usize>,
|
||||
}
|
||||
|
||||
impl TokensIterator<'a> {
|
||||
impl TokensIterator<'_> {
|
||||
pub fn remove(&mut self, position: usize) {
|
||||
self.seen.insert(position);
|
||||
}
|
||||
@ -404,7 +404,7 @@ impl TokensIterator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for TokensIterator<'a> {
|
||||
impl<'a> Iterator for TokensIterator<'a> {
|
||||
type Item = &'a TokenNode;
|
||||
|
||||
fn next(&mut self) -> Option<&'a TokenNode> {
|
||||
|
@ -19,7 +19,7 @@ pub enum NamedValue {
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, new)]
|
||||
pub struct NamedArguments {
|
||||
#[new(default)]
|
||||
crate named: IndexMap<String, NamedValue>,
|
||||
pub(crate) named: IndexMap<String, NamedValue>,
|
||||
}
|
||||
|
||||
impl ToDebug for NamedArguments {
|
||||
|
@ -1,12 +1,12 @@
|
||||
crate mod call_node;
|
||||
crate mod files;
|
||||
crate mod flag;
|
||||
crate mod operator;
|
||||
crate mod parser;
|
||||
crate mod pipeline;
|
||||
crate mod text;
|
||||
crate mod token_tree;
|
||||
crate mod token_tree_builder;
|
||||
crate mod tokens;
|
||||
crate mod unit;
|
||||
crate mod util;
|
||||
pub(crate) mod call_node;
|
||||
pub(crate) mod files;
|
||||
pub(crate) mod flag;
|
||||
pub(crate) mod operator;
|
||||
pub(crate) mod parser;
|
||||
pub(crate) mod pipeline;
|
||||
pub(crate) mod text;
|
||||
pub(crate) mod token_tree;
|
||||
pub(crate) mod token_tree_builder;
|
||||
pub(crate) mod tokens;
|
||||
pub(crate) mod unit;
|
||||
pub(crate) mod util;
|
||||
|
@ -23,7 +23,7 @@ use std::str::FromStr;
|
||||
|
||||
pub type NomSpan<'a> = LocatedSpan<&'a str>;
|
||||
|
||||
pub fn nom_input(s: &'a str) -> NomSpan<'a> {
|
||||
pub fn nom_input(s: &str) -> NomSpan<'_> {
|
||||
LocatedSpan::new(s)
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ use getset::Getters;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, new)]
|
||||
pub struct Pipeline {
|
||||
crate parts: Vec<PipelineElement>,
|
||||
crate post_ws: Option<Span>,
|
||||
pub(crate) parts: Vec<PipelineElement>,
|
||||
pub(crate) post_ws: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
||||
|
@ -213,7 +213,7 @@ impl Serialize for Text {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize<'de> for Text {
|
||||
impl<'de> Deserialize<'de> for Text {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
|
@ -27,7 +27,7 @@ pub struct DebugTokenNode<'a> {
|
||||
source: &'a Text,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugTokenNode<'a> {
|
||||
impl fmt::Debug for DebugTokenNode<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.node {
|
||||
TokenNode::Token(t) => write!(f, "{:?}", t.debug(self.source)),
|
||||
@ -115,7 +115,7 @@ impl TokenNode {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn debug(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
||||
pub fn debug<'a>(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
||||
DebugTokenNode { node: self, source }
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ impl TokenNode {
|
||||
self.span().slice(source).to_string()
|
||||
}
|
||||
|
||||
pub fn source(&self, source: &'a Text) -> &'a str {
|
||||
pub fn source<'a>(&self, source: &'a Text) -> &'a str {
|
||||
self.span().slice(source)
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ impl TokenNode {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn as_flag(&self, value: &str, source: &Text) -> Option<Tagged<Flag>> {
|
||||
pub(crate) fn as_flag(&self, value: &str, source: &Text) -> Option<Tagged<Flag>> {
|
||||
match self {
|
||||
TokenNode::Flag(
|
||||
flag @ Tagged {
|
||||
|
@ -28,7 +28,7 @@ impl RawToken {
|
||||
pub type Token = Tagged<RawToken>;
|
||||
|
||||
impl Token {
|
||||
pub fn debug(&self, source: &'a Text) -> DebugToken<'a> {
|
||||
pub fn debug<'a>(&self, source: &'a Text) -> DebugToken<'a> {
|
||||
DebugToken {
|
||||
node: *self,
|
||||
source,
|
||||
@ -41,7 +41,7 @@ pub struct DebugToken<'a> {
|
||||
source: &'a Text,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugToken<'a> {
|
||||
impl fmt::Debug for DebugToken<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.node.span().slice(self.source))
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ impl Unit {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn compute(&self, size: i64) -> Value {
|
||||
pub(crate) fn compute(&self, size: i64) -> Value {
|
||||
Value::int(match self {
|
||||
Unit::B => size,
|
||||
Unit::KB => size * 1024,
|
||||
|
@ -205,7 +205,7 @@ fn extract_switch(name: &str, tokens: &mut hir::TokensIterator<'_>, source: &Tex
|
||||
fn extract_mandatory(
|
||||
config: &Signature,
|
||||
name: &str,
|
||||
tokens: &mut hir::TokensIterator<'a>,
|
||||
tokens: &mut hir::TokensIterator<'_>,
|
||||
source: &Text,
|
||||
span: Span,
|
||||
) -> Result<(usize, Tagged<Flag>), ShellError> {
|
||||
@ -227,7 +227,7 @@ fn extract_mandatory(
|
||||
|
||||
fn extract_optional(
|
||||
name: &str,
|
||||
tokens: &mut hir::TokensIterator<'a>,
|
||||
tokens: &mut hir::TokensIterator<'_>,
|
||||
source: &Text,
|
||||
) -> Result<(Option<(usize, Tagged<Flag>)>), ShellError> {
|
||||
let flag = tokens.extract(|t| t.as_flag(name, source));
|
||||
@ -241,7 +241,7 @@ fn extract_optional(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trace_remaining(desc: &'static str, tail: hir::TokensIterator<'a>, source: &Text) {
|
||||
pub fn trace_remaining(desc: &'static str, tail: hir::TokensIterator<'_>, source: &Text) {
|
||||
trace!(
|
||||
"{} = {:?}",
|
||||
desc,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// TODO: Temporary redirect
|
||||
crate use crate::context::CommandRegistry;
|
||||
pub(crate) use crate::context::CommandRegistry;
|
||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||
use crate::parser::{hir, hir::SyntaxType, parse_command, CallNode};
|
||||
use crate::prelude::*;
|
||||
@ -46,7 +46,7 @@ impl PositionalType {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn to_coerce_hint(&self) -> Option<SyntaxType> {
|
||||
pub(crate) fn to_coerce_hint(&self) -> Option<SyntaxType> {
|
||||
match self {
|
||||
PositionalType::Mandatory(_, SyntaxType::Block)
|
||||
| PositionalType::Optional(_, SyntaxType::Block) => Some(SyntaxType::Block),
|
||||
@ -54,14 +54,14 @@ impl PositionalType {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn name(&self) -> &str {
|
||||
pub(crate) fn name(&self) -> &str {
|
||||
match self {
|
||||
PositionalType::Mandatory(s, _) => s,
|
||||
PositionalType::Optional(s, _) => s,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn syntax_type(&self) -> SyntaxType {
|
||||
pub(crate) fn syntax_type(&self) -> SyntaxType {
|
||||
match *self {
|
||||
PositionalType::Mandatory(_, t) => t,
|
||||
PositionalType::Optional(_, t) => t,
|
||||
@ -158,7 +158,7 @@ pub struct DebugEvaluatedPositional<'a> {
|
||||
positional: &'a Option<Vec<Tagged<Value>>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugEvaluatedPositional<'a> {
|
||||
impl fmt::Debug for DebugEvaluatedPositional<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self.positional {
|
||||
None => write!(f, "None"),
|
||||
@ -175,7 +175,7 @@ pub struct DebugEvaluatedNamed<'a> {
|
||||
named: &'a Option<IndexMap<String, Tagged<Value>>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugEvaluatedNamed<'a> {
|
||||
impl fmt::Debug for DebugEvaluatedNamed<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self.named {
|
||||
None => write!(f, "None"),
|
||||
@ -191,7 +191,7 @@ pub struct DebugEvaluatedArgs<'a> {
|
||||
args: &'a EvaluatedArgs,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugEvaluatedArgs<'a> {
|
||||
impl fmt::Debug for DebugEvaluatedArgs<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut s = f.debug_struct("Args");
|
||||
|
||||
@ -206,7 +206,7 @@ impl fmt::Debug for DebugEvaluatedArgs<'a> {
|
||||
}
|
||||
|
||||
impl EvaluatedArgs {
|
||||
pub fn debug(&'a self) -> DebugEvaluatedArgs<'a> {
|
||||
pub fn debug(&self) -> DebugEvaluatedArgs<'_> {
|
||||
DebugEvaluatedArgs { args: self }
|
||||
}
|
||||
|
||||
@ -248,7 +248,7 @@ impl EvaluatedArgs {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn positional_iter(&'a self) -> PositionalIter<'a> {
|
||||
pub fn positional_iter(&self) -> PositionalIter<'_> {
|
||||
match &self.positional {
|
||||
None => PositionalIter::Empty,
|
||||
Some(v) => {
|
||||
@ -264,7 +264,7 @@ pub enum PositionalIter<'a> {
|
||||
Array(std::slice::Iter<'a, Tagged<Value>>),
|
||||
}
|
||||
|
||||
impl Iterator for PositionalIter<'a> {
|
||||
impl<'a> Iterator for PositionalIter<'a> {
|
||||
type Item = &'a Tagged<Value>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -276,7 +276,7 @@ impl Iterator for PositionalIter<'a> {
|
||||
}
|
||||
|
||||
impl Signature {
|
||||
crate fn parse_args(
|
||||
pub(crate) fn parse_args(
|
||||
&self,
|
||||
call: &Tagged<CallNode>,
|
||||
context: &Context,
|
||||
@ -290,12 +290,12 @@ impl Signature {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn signature(&self) -> String {
|
||||
pub(crate) fn signature(&self) -> String {
|
||||
format!("TODO")
|
||||
}
|
||||
}
|
||||
|
||||
crate fn evaluate_args(
|
||||
pub(crate) fn evaluate_args(
|
||||
call: &hir::Call,
|
||||
registry: &CommandRegistry,
|
||||
scope: &Scope,
|
||||
|
@ -1,11 +1,13 @@
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use futures::executor::block_on;
|
||||
use futures::stream::StreamExt;
|
||||
use heim::{disk, memory, net};
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
Tag, Tagged, TaggedDictBuilder, Value,
|
||||
};
|
||||
use std::ffi::OsStr;
|
||||
use heim::{disk, memory, net, sensors, host};
|
||||
use heim::units::{frequency, information, time, thermodynamic_temperature};
|
||||
|
||||
struct Sys;
|
||||
impl Sys {
|
||||
@ -15,52 +17,65 @@ impl Sys {
|
||||
}
|
||||
|
||||
async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
||||
if let (Ok(num_cpu), Ok(cpu_speed)) = (
|
||||
heim::cpu::logical_count().await,
|
||||
heim::cpu::frequency().await,
|
||||
) {
|
||||
let mut cpu_idx = TaggedDictBuilder::new(tag);
|
||||
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
||||
match futures::future::try_join(
|
||||
heim::cpu::logical_count(),
|
||||
heim::cpu::frequency(),
|
||||
).await {
|
||||
Ok((num_cpu, cpu_speed)) => {
|
||||
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
|
||||
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
||||
|
||||
let current_speed =
|
||||
(cpu_speed.current().get() as f64 / 1000000000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("current ghz", Primitive::Float(current_speed.into()));
|
||||
let current_speed =
|
||||
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("current ghz", Primitive::Float(current_speed.into()));
|
||||
|
||||
if let Some(min_speed) = cpu_speed.min() {
|
||||
let min_speed = (min_speed.get() as f64 / 1000000000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("min ghz", Primitive::Float(min_speed.into()));
|
||||
}
|
||||
if let Some(min_speed) = cpu_speed.min() {
|
||||
let min_speed = (min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("min ghz", Primitive::Float(min_speed.into()));
|
||||
}
|
||||
|
||||
if let Some(max_speed) = cpu_speed.max() {
|
||||
let max_speed = (max_speed.get() as f64 / 1000000000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("max ghz", Primitive::Float(max_speed.into()));
|
||||
}
|
||||
Some(cpu_idx.into_tagged_value())
|
||||
} else {
|
||||
None
|
||||
if let Some(max_speed) = cpu_speed.max() {
|
||||
let max_speed = (max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("max ghz", Primitive::Float(max_speed.into()));
|
||||
}
|
||||
|
||||
Some(cpu_idx.into_tagged_value())
|
||||
},
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn mem(tag: Tag) -> Tagged<Value> {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
let mut dict = TaggedDictBuilder::with_capacity(tag, 4);
|
||||
|
||||
if let Ok(memory) = memory::memory().await {
|
||||
dict.insert("total", Value::bytes(memory.total().get()));
|
||||
dict.insert("free", Value::bytes(memory.free().get()));
|
||||
let (memory_result, swap_result) = futures::future::join(
|
||||
memory::memory(),
|
||||
memory::swap()
|
||||
).await;
|
||||
|
||||
if let Ok(memory) = memory_result {
|
||||
dict.insert("total", Value::bytes(memory.total().get::<information::byte>()));
|
||||
dict.insert("free", Value::bytes(memory.free().get::<information::byte>()));
|
||||
}
|
||||
if let Ok(swap) = memory::swap().await {
|
||||
dict.insert("swap total", Value::bytes(swap.total().get()));
|
||||
dict.insert("swap free", Value::bytes(swap.free().get()));
|
||||
|
||||
if let Ok(swap) = swap_result {
|
||||
dict.insert("swap total", Value::bytes(swap.total().get::<information::byte>()));
|
||||
dict.insert("swap free", Value::bytes(swap.free().get::<information::byte>()));
|
||||
}
|
||||
|
||||
dict.into_tagged_value()
|
||||
}
|
||||
|
||||
async fn host(tag: Tag) -> Tagged<Value> {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
let mut dict = TaggedDictBuilder::with_capacity(tag, 6);
|
||||
|
||||
let (platform_result, uptime_result) = futures::future::join(
|
||||
host::platform(),
|
||||
host::uptime(),
|
||||
).await;
|
||||
|
||||
// OS
|
||||
if let Ok(platform) = heim::host::platform().await {
|
||||
if let Ok(platform) = platform_result {
|
||||
dict.insert("name", Value::string(platform.system()));
|
||||
dict.insert("release", Value::string(platform.release()));
|
||||
dict.insert("hostname", Value::string(platform.hostname()));
|
||||
@ -68,10 +83,10 @@ async fn host(tag: Tag) -> Tagged<Value> {
|
||||
}
|
||||
|
||||
// Uptime
|
||||
if let Ok(uptime) = heim::host::uptime().await {
|
||||
let mut uptime_dict = TaggedDictBuilder::new(tag);
|
||||
if let Ok(uptime) = uptime_result {
|
||||
let mut uptime_dict = TaggedDictBuilder::with_capacity(tag, 4);
|
||||
|
||||
let uptime = uptime.get().round() as i64;
|
||||
let uptime = uptime.get::<time::second>().round() as i64;
|
||||
let days = uptime / (60 * 60 * 24);
|
||||
let hours = (uptime - days * 60 * 60 * 24) / (60 * 60);
|
||||
let minutes = (uptime - days * 60 * 60 * 24 - hours * 60 * 60) / 60;
|
||||
@ -82,11 +97,11 @@ async fn host(tag: Tag) -> Tagged<Value> {
|
||||
uptime_dict.insert("mins", Value::int(minutes));
|
||||
uptime_dict.insert("secs", Value::int(seconds));
|
||||
|
||||
dict.insert_tagged("uptime", uptime_dict.into_tagged_value());
|
||||
dict.insert_tagged("uptime", uptime_dict);
|
||||
}
|
||||
|
||||
// Users
|
||||
let mut users = heim::host::users();
|
||||
let mut users = host::users();
|
||||
let mut user_vec = vec![];
|
||||
while let Some(user) = users.next().await {
|
||||
if let Ok(user) = user {
|
||||
@ -104,7 +119,7 @@ async fn disks(tag: Tag) -> Option<Value> {
|
||||
let mut partitions = disk::partitions_physical();
|
||||
while let Some(part) = partitions.next().await {
|
||||
if let Ok(part) = part {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
let mut dict = TaggedDictBuilder::with_capacity(tag, 6);
|
||||
dict.insert(
|
||||
"device",
|
||||
Value::string(
|
||||
@ -116,16 +131,18 @@ async fn disks(tag: Tag) -> Option<Value> {
|
||||
|
||||
dict.insert("type", Value::string(part.file_system().as_str()));
|
||||
dict.insert("mount", Value::string(part.mount_point().to_string_lossy()));
|
||||
|
||||
if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await {
|
||||
dict.insert("total", Value::bytes(usage.total().get()));
|
||||
dict.insert("used", Value::bytes(usage.used().get()));
|
||||
dict.insert("free", Value::bytes(usage.free().get()));
|
||||
dict.insert("total", Value::bytes(usage.total().get::<information::byte>()));
|
||||
dict.insert("used", Value::bytes(usage.used().get::<information::byte>()));
|
||||
dict.insert("free", Value::bytes(usage.free().get::<information::byte>()));
|
||||
}
|
||||
|
||||
output.push(dict.into_tagged_value());
|
||||
}
|
||||
}
|
||||
|
||||
if output.len() > 0 {
|
||||
if !output.is_empty() {
|
||||
Some(Value::List(output))
|
||||
} else {
|
||||
None
|
||||
@ -167,57 +184,56 @@ async fn battery(tag: Tag) -> Option<Value> {
|
||||
}
|
||||
}
|
||||
|
||||
if output.len() > 0 {
|
||||
if !output.is_empty() {
|
||||
Some(Value::List(output))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: add back when heim releases new version
|
||||
// async fn temp(tag: Tag) -> Option<Value> {
|
||||
// let mut output = vec![];
|
||||
async fn temp(tag: Tag) -> Option<Value> {
|
||||
let mut output = vec![];
|
||||
|
||||
// let mut sensors = sensors::temperatures();
|
||||
// while let Some(sensor) = sensors.next().await {
|
||||
// if let Ok(sensor) = sensor {
|
||||
// let mut dict = TaggedDictBuilder::new(tag);
|
||||
// dict.insert("unit", Value::string(sensor.unit()));
|
||||
// if let Some(label) = sensor.label() {
|
||||
// dict.insert("label", Value::string(label));
|
||||
// }
|
||||
// dict.insert("temp", Value::float(sensor.current().get()));
|
||||
// if let Some(high) = sensor.high() {
|
||||
// dict.insert("high", Value::float(high.get()));
|
||||
// }
|
||||
// if let Some(critical) = sensor.critical() {
|
||||
// dict.insert("critical", Value::float(critical.get()));
|
||||
// }
|
||||
let mut sensors = sensors::temperatures();
|
||||
while let Some(sensor) = sensors.next().await {
|
||||
if let Ok(sensor) = sensor {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
dict.insert("unit", Value::string(sensor.unit()));
|
||||
if let Some(label) = sensor.label() {
|
||||
dict.insert("label", Value::string(label));
|
||||
}
|
||||
dict.insert("temp", Value::float(sensor.current().get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||
if let Some(high) = sensor.high() {
|
||||
dict.insert("high", Value::float(high.get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||
}
|
||||
if let Some(critical) = sensor.critical() {
|
||||
dict.insert("critical", Value::float(critical.get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||
}
|
||||
|
||||
// output.push(dict.into_tagged_value());
|
||||
// }
|
||||
// }
|
||||
output.push(dict.into_tagged_value());
|
||||
}
|
||||
}
|
||||
|
||||
// if output.len() > 0 {
|
||||
// Some(Value::List(output))
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
if !output.is_empty() {
|
||||
Some(Value::List(output))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
async fn net(tag: Tag) -> Option<Value> {
|
||||
let mut output = vec![];
|
||||
let mut io_counters = net::io_counters();
|
||||
while let Some(nic) = io_counters.next().await {
|
||||
if let Ok(nic) = nic {
|
||||
let mut network_idx = TaggedDictBuilder::new(tag);
|
||||
let mut network_idx = TaggedDictBuilder::with_capacity(tag, 3);
|
||||
network_idx.insert("name", Value::string(nic.interface()));
|
||||
network_idx.insert("sent", Value::bytes(nic.bytes_sent().get()));
|
||||
network_idx.insert("recv", Value::bytes(nic.bytes_recv().get()));
|
||||
network_idx.insert("sent", Value::bytes(nic.bytes_sent().get::<information::byte>()));
|
||||
network_idx.insert("recv", Value::bytes(nic.bytes_recv().get::<information::byte>()));
|
||||
output.push(network_idx.into_tagged_value());
|
||||
}
|
||||
}
|
||||
if output.len() > 0 {
|
||||
if !output.is_empty() {
|
||||
Some(Value::List(output))
|
||||
} else {
|
||||
None
|
||||
@ -225,23 +241,35 @@ async fn net(tag: Tag) -> Option<Value> {
|
||||
}
|
||||
|
||||
async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
|
||||
let mut sysinfo = TaggedDictBuilder::new(tag);
|
||||
let mut sysinfo = TaggedDictBuilder::with_capacity(tag, 7);
|
||||
|
||||
let (host, cpu, disks, memory, temp) = futures::future::join5(
|
||||
host(tag),
|
||||
cpu(tag),
|
||||
disks(tag),
|
||||
mem(tag),
|
||||
temp(tag),
|
||||
).await;
|
||||
let (net, battery) = futures::future::join(
|
||||
net(tag),
|
||||
battery(tag),
|
||||
).await;
|
||||
|
||||
sysinfo.insert_tagged("host", host(tag).await);
|
||||
if let Some(cpu) = cpu(tag).await {
|
||||
sysinfo.insert_tagged("host", host);
|
||||
if let Some(cpu) = cpu {
|
||||
sysinfo.insert_tagged("cpu", cpu);
|
||||
}
|
||||
if let Some(disks) = disks(tag).await {
|
||||
if let Some(disks) = disks {
|
||||
sysinfo.insert("disks", disks);
|
||||
}
|
||||
sysinfo.insert_tagged("mem", mem(tag).await);
|
||||
// if let Some(temp) = temp(tag).await {
|
||||
// sysinfo.insert("temp", temp);
|
||||
// }
|
||||
if let Some(net) = net(tag).await {
|
||||
sysinfo.insert_tagged("mem", memory);
|
||||
if let Some(temp) = temp {
|
||||
sysinfo.insert("temp", temp);
|
||||
}
|
||||
if let Some(net) = net {
|
||||
sysinfo.insert("net", net);
|
||||
}
|
||||
if let Some(battery) = battery(tag).await {
|
||||
if let Some(battery) = battery {
|
||||
sysinfo.insert("battery", battery);
|
||||
}
|
||||
|
||||
@ -256,7 +284,7 @@ impl Plugin for Sys {
|
||||
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span)))
|
||||
.into_iter()
|
||||
.map(|x| ReturnSuccess::value(x))
|
||||
.map(ReturnSuccess::value)
|
||||
.collect())
|
||||
}
|
||||
|
||||
|
@ -54,13 +54,25 @@ fn paint_textview(
|
||||
match command {
|
||||
DrawCommand::DrawString(style, string) => {
|
||||
for chr in string.chars() {
|
||||
frame_buffer.push((
|
||||
chr,
|
||||
style.foreground.r,
|
||||
style.foreground.g,
|
||||
style.foreground.b,
|
||||
));
|
||||
pos += 1;
|
||||
if chr == '\t' {
|
||||
for _ in 0..8 {
|
||||
frame_buffer.push((
|
||||
' ',
|
||||
style.foreground.r,
|
||||
style.foreground.g,
|
||||
style.foreground.b,
|
||||
));
|
||||
}
|
||||
pos += 8;
|
||||
} else {
|
||||
frame_buffer.push((
|
||||
chr,
|
||||
style.foreground.r,
|
||||
style.foreground.g,
|
||||
style.foreground.b,
|
||||
));
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
DrawCommand::NextLine => {
|
||||
|
@ -47,37 +47,38 @@ macro_rules! trace_out_stream {
|
||||
}};
|
||||
}
|
||||
|
||||
crate use crate::cli::MaybeOwned;
|
||||
crate use crate::commands::command::{
|
||||
pub(crate) use crate::cli::MaybeOwned;
|
||||
pub(crate) use crate::commands::command::{
|
||||
CallInfo, CommandAction, CommandArgs, ReturnSuccess, ReturnValue, RunnableContext,
|
||||
};
|
||||
crate use crate::commands::{PerItemCommand, RawCommandArgs};
|
||||
crate use crate::context::CommandRegistry;
|
||||
crate use crate::context::{Context, SpanSource};
|
||||
crate use crate::env::host::handle_unexpected;
|
||||
crate use crate::env::Host;
|
||||
crate use crate::errors::ShellError;
|
||||
crate use crate::object::base as value;
|
||||
crate use crate::object::meta::{Tag, Tagged, TaggedItem};
|
||||
crate use crate::object::types::ExtractType;
|
||||
crate use crate::object::{Primitive, Value};
|
||||
crate use crate::parser::hir::SyntaxType;
|
||||
crate use crate::parser::registry::Signature;
|
||||
crate use crate::shell::filesystem_shell::FilesystemShell;
|
||||
crate use crate::shell::shell_manager::ShellManager;
|
||||
crate use crate::shell::value_shell::ValueShell;
|
||||
crate use crate::stream::{InputStream, OutputStream};
|
||||
crate use crate::traits::{HasSpan, ToDebug};
|
||||
crate use crate::Span;
|
||||
crate use crate::Text;
|
||||
crate use futures::stream::BoxStream;
|
||||
crate use futures::{FutureExt, Stream, StreamExt};
|
||||
crate use futures_async_stream::async_stream_block;
|
||||
pub(crate) use crate::commands::PerItemCommand;
|
||||
pub(crate) use crate::commands::RawCommandArgs;
|
||||
pub(crate) use crate::context::CommandRegistry;
|
||||
pub(crate) use crate::context::{Context, SpanSource};
|
||||
pub(crate) use crate::env::host::handle_unexpected;
|
||||
pub(crate) use crate::env::Host;
|
||||
pub(crate) use crate::errors::ShellError;
|
||||
pub(crate) use crate::object::base as value;
|
||||
pub(crate) use crate::object::meta::{Tag, Tagged, TaggedItem};
|
||||
pub(crate) use crate::object::types::ExtractType;
|
||||
pub(crate) use crate::object::{Primitive, Value};
|
||||
pub(crate) use crate::parser::hir::SyntaxType;
|
||||
pub(crate) use crate::parser::registry::Signature;
|
||||
pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
|
||||
pub(crate) use crate::shell::shell_manager::ShellManager;
|
||||
pub(crate) use crate::shell::value_shell::ValueShell;
|
||||
pub(crate) use crate::stream::{InputStream, OutputStream};
|
||||
pub(crate) use crate::traits::{HasSpan, ToDebug};
|
||||
pub(crate) use crate::Span;
|
||||
pub(crate) use crate::Text;
|
||||
pub(crate) use futures::stream::BoxStream;
|
||||
pub(crate) use futures::{FutureExt, Stream, StreamExt};
|
||||
pub(crate) use futures_async_stream::async_stream_block;
|
||||
#[allow(unused)]
|
||||
crate use serde::{Deserialize, Serialize};
|
||||
crate use std::collections::VecDeque;
|
||||
crate use std::future::Future;
|
||||
crate use std::sync::{Arc, Mutex};
|
||||
pub(crate) use serde::{Deserialize, Serialize};
|
||||
pub(crate) use std::collections::VecDeque;
|
||||
pub(crate) use std::future::Future;
|
||||
pub(crate) use std::sync::{Arc, Mutex};
|
||||
|
||||
pub trait FromInputStream {
|
||||
fn from_input_stream(self) -> OutputStream;
|
||||
|
14
src/shell.rs
14
src/shell.rs
@ -1,8 +1,8 @@
|
||||
crate mod completer;
|
||||
crate mod filesystem_shell;
|
||||
crate mod helper;
|
||||
crate mod shell;
|
||||
crate mod shell_manager;
|
||||
crate mod value_shell;
|
||||
pub(crate) mod completer;
|
||||
pub(crate) mod filesystem_shell;
|
||||
pub(crate) mod helper;
|
||||
pub(crate) mod shell;
|
||||
pub(crate) mod shell_manager;
|
||||
pub(crate) mod value_shell;
|
||||
|
||||
crate use helper::Helper;
|
||||
pub(crate) use helper::Helper;
|
||||
|
@ -3,7 +3,7 @@ use derive_new::new;
|
||||
use rustyline::completion::{Completer, FilenameCompleter};
|
||||
|
||||
#[derive(new)]
|
||||
crate struct NuCompleter {
|
||||
pub(crate) struct NuCompleter {
|
||||
pub file_completer: FilenameCompleter,
|
||||
pub commands: CommandRegistry,
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use rustyline::hint::{Hinter, HistoryHinter};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub struct FilesystemShell {
|
||||
crate path: String,
|
||||
pub(crate) path: String,
|
||||
completer: NuCompleter,
|
||||
hinter: HistoryHinter,
|
||||
}
|
||||
|
@ -11,12 +11,12 @@ use rustyline::highlight::Highlighter;
|
||||
use rustyline::hint::Hinter;
|
||||
use std::borrow::Cow::{self, Owned};
|
||||
|
||||
crate struct Helper {
|
||||
pub(crate) struct Helper {
|
||||
helper: ShellManager,
|
||||
}
|
||||
|
||||
impl Helper {
|
||||
crate fn new(helper: ShellManager) -> Helper {
|
||||
pub(crate) fn new(helper: ShellManager) -> Helper {
|
||||
Helper { helper }
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShellManager {
|
||||
crate current_shell: usize,
|
||||
crate shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>,
|
||||
pub(crate) current_shell: usize,
|
||||
pub(crate) shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>,
|
||||
}
|
||||
|
||||
impl ShellManager {
|
||||
|
@ -11,8 +11,8 @@ use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ValueShell {
|
||||
crate path: String,
|
||||
crate value: Tagged<Value>,
|
||||
pub(crate) path: String,
|
||||
pub(crate) value: Tagged<Value>,
|
||||
}
|
||||
|
||||
impl ValueShell {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct InputStream {
|
||||
crate values: BoxStream<'static, Tagged<Value>>,
|
||||
pub(crate) values: BoxStream<'static, Tagged<Value>>,
|
||||
}
|
||||
|
||||
impl InputStream {
|
||||
@ -49,7 +49,7 @@ impl From<Vec<Tagged<Value>>> for InputStream {
|
||||
}
|
||||
|
||||
pub struct OutputStream {
|
||||
crate values: BoxStream<'static, ReturnValue>,
|
||||
pub(crate) values: BoxStream<'static, ReturnValue>,
|
||||
}
|
||||
|
||||
impl OutputStream {
|
||||
|
@ -6,7 +6,7 @@ pub struct Debuggable<'a, T: ToDebug> {
|
||||
source: &'a str,
|
||||
}
|
||||
|
||||
impl<T: ToDebug> fmt::Display for Debuggable<'a, T> {
|
||||
impl<T: ToDebug> fmt::Display for Debuggable<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.inner.fmt_debug(f, self.source)
|
||||
}
|
||||
@ -17,7 +17,7 @@ pub trait HasSpan {
|
||||
}
|
||||
|
||||
pub trait ToDebug: Sized {
|
||||
fn debug(&'a self, source: &'a str) -> Debuggable<'a, Self> {
|
||||
fn debug<'a>(&'a self, source: &'a str) -> Debuggable<'a, Self> {
|
||||
Debuggable {
|
||||
inner: self,
|
||||
source,
|
||||
|
@ -185,7 +185,7 @@ impl FileStructure {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build(&mut self, src: &'a Path, lvl: usize) -> Result<(), ShellError> {
|
||||
fn build(&mut self, src: &Path, lvl: usize) -> Result<(), ShellError> {
|
||||
let source = dunce::canonicalize(src)?;
|
||||
|
||||
if source.is_dir() {
|
||||
@ -250,6 +250,10 @@ mod tests {
|
||||
loc: fixtures().join("caco3_plastics.csv"),
|
||||
at: 0
|
||||
},
|
||||
Res {
|
||||
loc: fixtures().join("caco3_plastics.tsv"),
|
||||
at: 0
|
||||
},
|
||||
Res {
|
||||
loc: fixtures().join("cargo_sample.toml"),
|
||||
at: 0
|
||||
|
Reference in New Issue
Block a user