forked from extern/nushell
Move nu-data out of nu-cli (#2369)
* WIP for moving nu-data out * Refactor nu-data out of nu-cli * Remove unwraps * Remove unwraps
This commit is contained in:
parent
1d5518a214
commit
738541f727
38
Cargo.lock
generated
38
Cargo.lock
generated
@ -593,9 +593,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.13"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
|
||||
checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits 0.2.12",
|
||||
@ -2932,6 +2932,7 @@ dependencies = [
|
||||
"futures 0.3.5",
|
||||
"log 0.4.11",
|
||||
"nu-cli",
|
||||
"nu-data",
|
||||
"nu-errors",
|
||||
"nu-parser",
|
||||
"nu-plugin",
|
||||
@ -3005,6 +3006,7 @@ dependencies = [
|
||||
"log 0.4.11",
|
||||
"meval",
|
||||
"natural",
|
||||
"nu-data",
|
||||
"nu-errors",
|
||||
"nu-parser",
|
||||
"nu-plugin",
|
||||
@ -3058,6 +3060,36 @@ dependencies = [
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-data"
|
||||
version = "0.18.2"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"bigdecimal",
|
||||
"byte-unit",
|
||||
"chrono",
|
||||
"derive-new",
|
||||
"directories 2.0.2",
|
||||
"dirs 2.0.2",
|
||||
"getset",
|
||||
"indexmap",
|
||||
"log 0.4.11",
|
||||
"nu-errors",
|
||||
"nu-protocol",
|
||||
"nu-source",
|
||||
"nu-table",
|
||||
"nu-value-ext",
|
||||
"num-bigint",
|
||||
"num-format",
|
||||
"num-traits 0.2.12",
|
||||
"parking_lot 0.11.0",
|
||||
"query_interface",
|
||||
"serde 1.0.115",
|
||||
"toml 0.5.6",
|
||||
"umask",
|
||||
"users",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-errors"
|
||||
version = "0.18.2"
|
||||
@ -3346,7 +3378,7 @@ version = "0.18.2"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"bat",
|
||||
"nu-cli",
|
||||
"nu-data",
|
||||
"nu-errors",
|
||||
"nu-plugin",
|
||||
"nu-protocol",
|
||||
|
@ -19,6 +19,7 @@ members = ["crates/*/"]
|
||||
|
||||
[dependencies]
|
||||
nu-cli = {version = "0.18.2", path = "./crates/nu-cli"}
|
||||
nu-data = {version = "0.18.2", path = "./crates/nu-data"}
|
||||
nu-errors = {version = "0.18.2", path = "./crates/nu-errors"}
|
||||
nu-parser = {version = "0.18.2", path = "./crates/nu-parser"}
|
||||
nu-plugin = {version = "0.18.2", path = "./crates/nu-plugin"}
|
||||
@ -101,7 +102,7 @@ s3 = ["nu_plugin_s3"]
|
||||
|
||||
clipboard-cli = ["nu-cli/clipboard-cli"]
|
||||
ctrlc-support = ["nu-cli/ctrlc"]
|
||||
directories-support = ["nu-cli/directories", "nu-cli/dirs"]
|
||||
directories-support = ["nu-cli/directories", "nu-cli/dirs", "nu-data/directories", "nu-data/dirs"]
|
||||
git-support = ["nu-cli/git2"]
|
||||
ptree-support = ["nu-cli/ptree"]
|
||||
term-support = ["nu-cli/term"]
|
||||
|
@ -10,6 +10,7 @@ version = "0.18.2"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-data = {version = "0.18.2", path = "../nu-data"}
|
||||
nu-errors = {version = "0.18.2", path = "../nu-errors"}
|
||||
nu-parser = {version = "0.18.2", path = "../nu-parser"}
|
||||
nu-plugin = {version = "0.18.2", path = "../nu-plugin"}
|
||||
|
@ -111,7 +111,7 @@ fn search_paths() -> Vec<std::path::PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(config) = crate::data::config::config(Tag::unknown()) {
|
||||
if let Ok(config) = nu_data::config::config(Tag::unknown()) {
|
||||
if let Some(plugin_dirs) = config.get("plugin_dirs") {
|
||||
if let Value {
|
||||
value: UntaggedValue::Table(pipelines),
|
||||
@ -210,7 +210,7 @@ impl History {
|
||||
})
|
||||
.unwrap_or_else(|_| PathBuf::from(FNAME));
|
||||
|
||||
let cfg = crate::data::config::config(Tag::unknown());
|
||||
let cfg = nu_data::config::config(Tag::unknown());
|
||||
if let Ok(c) = cfg {
|
||||
match &c.get("history-path") {
|
||||
Some(Value {
|
||||
@ -471,7 +471,7 @@ pub async fn run_vec_of_pipelines(
|
||||
}
|
||||
|
||||
// before we start up, let's run our startup commands
|
||||
if let Ok(config) = crate::data::config::config(Tag::unknown()) {
|
||||
if let Ok(config) = nu_data::config::config(Tag::unknown()) {
|
||||
if let Some(commands) = config.get("startup") {
|
||||
match commands {
|
||||
Value {
|
||||
@ -752,7 +752,7 @@ pub async fn cli(
|
||||
let mut ctrlcbreak = false;
|
||||
|
||||
// before we start up, let's run our startup commands
|
||||
if let Ok(config) = crate::data::config::config(Tag::unknown()) {
|
||||
if let Ok(config) = nu_data::config::config(Tag::unknown()) {
|
||||
if let Some(commands) = config.get("startup") {
|
||||
match commands {
|
||||
Value {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::config;
|
||||
use crate::prelude::*;
|
||||
use nu_data::config;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
hir::Block, CommandAction, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
@ -82,7 +82,7 @@ pub async fn alias(
|
||||
let mut processed_args: Vec<String> = vec![];
|
||||
|
||||
if let Some(true) = save {
|
||||
let mut result = crate::data::config::read(name.clone().tag, &None)?;
|
||||
let mut result = nu_data::config::read(name.clone().tag, &None)?;
|
||||
|
||||
// process the alias to remove the --save flag
|
||||
let left_brace = raw_input.find('{').unwrap_or(0);
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::config::table::AutoPivotMode;
|
||||
use crate::data::config::table::HasTableProperties;
|
||||
use crate::data::config::NuConfig as Configuration;
|
||||
use crate::data::value::format_leaf;
|
||||
use crate::prelude::*;
|
||||
use nu_data::config::table::AutoPivotMode;
|
||||
use nu_data::config::table::HasTableProperties;
|
||||
use nu_data::config::NuConfig as Configuration;
|
||||
use nu_data::value::format_leaf;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::{self, Expression, ExternalRedirection, Literal, SpannedExpression};
|
||||
use nu_protocol::{Primitive, Scope, Signature, UntaggedValue, Value};
|
||||
|
@ -2,7 +2,7 @@ use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::value::format_leaf;
|
||||
use nu_data::value::format_leaf;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -425,7 +425,7 @@ fn spawn(
|
||||
};
|
||||
|
||||
if external_failed {
|
||||
let cfg = crate::data::config::config(Tag::unknown());
|
||||
let cfg = nu_data::config::config(Tag::unknown());
|
||||
if let Ok(cfg) = cfg {
|
||||
if cfg.contains_key("nonzero_exit_errors") {
|
||||
let _ = stdout_read_tx.send(Ok(Value {
|
||||
|
@ -45,7 +45,7 @@ pub async fn clear(
|
||||
|
||||
// NOTE: None because we are not loading a new config file, we just want to read from the
|
||||
// existing config
|
||||
let mut result = crate::data::config::read(name_span, &None)?;
|
||||
let mut result = nu_data::config::read(name_span, &None)?;
|
||||
|
||||
result.clear();
|
||||
|
||||
|
@ -27,7 +27,7 @@ impl WholeStreamCommand for Command {
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let name_span = args.call_info.name_tag.clone();
|
||||
let name = args.call_info.name_tag;
|
||||
let result = crate::data::config::read(name_span, &None)?;
|
||||
let result = nu_data::config::read(name_span, &None)?;
|
||||
|
||||
Ok(futures::stream::iter(vec![ReturnSuccess::value(
|
||||
UntaggedValue::Row(result.into()).into_value(name),
|
||||
|
@ -56,7 +56,7 @@ pub async fn get(
|
||||
|
||||
// NOTE: None because we are not loading a new config file, we just want to read from the
|
||||
// existing config
|
||||
let result = crate::data::config::read(name_span, &None)?;
|
||||
let result = nu_data::config::read(name_span, &None)?;
|
||||
|
||||
let key = get.to_string();
|
||||
let value = result
|
||||
|
@ -50,7 +50,7 @@ pub async fn set(
|
||||
|
||||
let configuration = load.item().clone();
|
||||
|
||||
let result = crate::data::config::read(name_span, &Some(configuration))?;
|
||||
let result = nu_data::config::read(name_span, &Some(configuration))?;
|
||||
|
||||
Ok(futures::stream::iter(vec![ReturnSuccess::value(
|
||||
UntaggedValue::Row(result.into()).into_value(name),
|
||||
|
@ -54,7 +54,7 @@ pub async fn remove(
|
||||
let name_span = args.call_info.name_tag.clone();
|
||||
let (RemoveArgs { remove }, _) = args.process(®istry).await?;
|
||||
|
||||
let mut result = crate::data::config::read(name_span, &None)?;
|
||||
let mut result = nu_data::config::read(name_span, &None)?;
|
||||
|
||||
let key = remove.to_string();
|
||||
|
||||
|
@ -55,7 +55,7 @@ pub async fn set(
|
||||
|
||||
// NOTE: None because we are not loading a new config file, we just want to read from the
|
||||
// existing config
|
||||
let mut result = crate::data::config::read(name_span, &None)?;
|
||||
let mut result = nu_data::config::read(name_span, &None)?;
|
||||
|
||||
result.insert(key.to_string(), value.clone());
|
||||
|
||||
|
@ -58,7 +58,7 @@ pub async fn set_into(
|
||||
|
||||
// NOTE: None because we are not loading a new config file, we just want to read from the
|
||||
// existing config
|
||||
let mut result = crate::data::config::read(name_span, &None)?;
|
||||
let mut result = nu_data::config::read(name_span, &None)?;
|
||||
|
||||
// In the original code, this is set to `Some` if the `load flag is set`
|
||||
let configuration = None;
|
||||
|
@ -102,7 +102,7 @@ impl Iterator for RangeIterator {
|
||||
if self.curr != self.end {
|
||||
let output = UntaggedValue::Primitive(self.curr.clone()).into_value(self.tag.clone());
|
||||
|
||||
self.curr = match crate::data::value::compute_values(
|
||||
self.curr = match nu_data::value::compute_values(
|
||||
Operator::Plus,
|
||||
&UntaggedValue::Primitive(self.curr.clone()),
|
||||
&UntaggedValue::int(1),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use crate::TaggedListBuilder;
|
||||
use calamine::*;
|
||||
use nu_data::TaggedListBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, TaggedDictBuilder, UntaggedValue};
|
||||
use std::io::Cursor;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use crate::TaggedListBuilder;
|
||||
use calamine::*;
|
||||
use nu_data::TaggedListBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, TaggedDictBuilder, UntaggedValue};
|
||||
use std::io::Cursor;
|
||||
|
@ -179,7 +179,7 @@ pub async fn group_by(
|
||||
None => as_string(row),
|
||||
});
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
Grouper::ByColumn(column_name) => group(&column_name, &values, name),
|
||||
};
|
||||
@ -234,12 +234,12 @@ pub fn group(
|
||||
}
|
||||
});
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
Grouper::ByColumn(None) => {
|
||||
let block = Box::new(move |_, row: &Value| as_string(row));
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
Grouper::ByBlock => Err(ShellError::unimplemented(
|
||||
"Block not implemented: This should never happen.",
|
||||
@ -250,7 +250,7 @@ pub fn group(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::group;
|
||||
use crate::utils::data::helpers::{committers, date, int, row, string, table};
|
||||
use nu_data::utils::helpers::{committers, date, int, row, string, table};
|
||||
use nu_errors::ShellError;
|
||||
use nu_source::*;
|
||||
|
||||
|
@ -102,7 +102,7 @@ pub async fn group_by_date(
|
||||
(Grouper::ByDate(None), GroupByColumn::Name(None)) => {
|
||||
let block = Box::new(move |_, row: &Value| row.format("%Y-%m-%d"));
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
(Grouper::ByDate(None), GroupByColumn::Name(Some(column_name))) => {
|
||||
let block = Box::new(move |_, row: &Value| {
|
||||
@ -113,12 +113,12 @@ pub async fn group_by_date(
|
||||
group_key?.format("%Y-%m-%d")
|
||||
});
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
(Grouper::ByDate(Some(fmt)), GroupByColumn::Name(None)) => {
|
||||
let block = Box::new(move |_, row: &Value| row.format(&fmt));
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
(Grouper::ByDate(Some(fmt)), GroupByColumn::Name(Some(column_name))) => {
|
||||
let block = Box::new(move |_, row: &Value| {
|
||||
@ -129,7 +129,7 @@ pub async fn group_by_date(
|
||||
group_key?.format(&fmt)
|
||||
});
|
||||
|
||||
crate::utils::data::group(&values, &Some(block), &name)
|
||||
nu_data::utils::group(&values, &Some(block), &name)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::commands::command::Command;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::command_dict;
|
||||
use crate::documentation::{generate_docs, get_documentation, DocumentationConfig};
|
||||
|
||||
use crate::prelude::*;
|
||||
use nu_data::command::signature_dict;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue};
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value};
|
||||
use nu_source::{SpannedItem, Tagged};
|
||||
use nu_value_ext::get_data_by_key;
|
||||
|
||||
@ -38,6 +38,21 @@ impl WholeStreamCommand for Help {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn command_dict(command: Command, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
|
||||
let mut cmd_dict = TaggedDictBuilder::new(&tag);
|
||||
|
||||
cmd_dict.insert_untagged("name", UntaggedValue::string(command.name()));
|
||||
|
||||
cmd_dict.insert_untagged("type", UntaggedValue::string("Command"));
|
||||
|
||||
cmd_dict.insert_value("signature", signature_dict(command.signature(), tag));
|
||||
cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage()));
|
||||
|
||||
cmd_dict.into_value()
|
||||
}
|
||||
|
||||
async fn help(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let name = args.call_info.name_tag.clone();
|
||||
|
@ -107,9 +107,9 @@ pub async fn histogram(
|
||||
"value".to_string().tagged(&name)
|
||||
};
|
||||
|
||||
let results = crate::utils::data::report(
|
||||
let results = nu_data::utils::report(
|
||||
&UntaggedValue::table(&values).into_value(&name),
|
||||
crate::utils::data::Operation {
|
||||
nu_data::utils::Operation {
|
||||
grouper: Some(Box::new(move |_, _| Ok(String::from("frequencies")))),
|
||||
splitter: Some(splitter(column_grouper)),
|
||||
format: None,
|
||||
|
@ -266,7 +266,7 @@ macro_rules! command {
|
||||
|
||||
Extract {
|
||||
$($extract:tt)* {
|
||||
use $crate::data::types::ExtractType;
|
||||
use $nu_data::types::ExtractType;
|
||||
let value = $args.expect_nth($($positional_count)*)?;
|
||||
Block::extract(value)?
|
||||
}
|
||||
@ -321,7 +321,7 @@ macro_rules! command {
|
||||
|
||||
Extract {
|
||||
$($extract:tt)* {
|
||||
use $crate::data::types::ExtractType;
|
||||
use $nu_data::types::ExtractType;
|
||||
let value = $args.expect_nth($($positional_count)*)?;
|
||||
<$param_kind>::extract(&value)?
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ pub fn average(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
|
||||
..
|
||||
} => {
|
||||
let left = UntaggedValue::from(Primitive::Int(num.into()));
|
||||
let result = crate::data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
|
||||
match result {
|
||||
Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) => {
|
||||
@ -142,7 +142,7 @@ pub fn average(values: &[Value], name: &Tag) -> Result<Value, ShellError> {
|
||||
..
|
||||
} => {
|
||||
let left = UntaggedValue::from(other);
|
||||
let result = crate::data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
|
||||
match result {
|
||||
Ok(value) => Ok(value.into_value(name)),
|
||||
|
@ -138,7 +138,7 @@ fn compute_average(values: &[Value], name: impl Into<Tag>) -> Result<Value, Shel
|
||||
..
|
||||
} => {
|
||||
let left = UntaggedValue::from(Primitive::Int(num.into()));
|
||||
let result = crate::data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
|
||||
match result {
|
||||
Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) => {
|
||||
@ -162,7 +162,7 @@ fn compute_average(values: &[Value], name: impl Into<Tag>) -> Result<Value, Shel
|
||||
..
|
||||
} => {
|
||||
let left = UntaggedValue::from(other);
|
||||
let result = crate::data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
let result = nu_data::value::compute_values(Operator::Divide, &left, &total_rows);
|
||||
|
||||
match result {
|
||||
Ok(value) => Ok(value.into_value(name)),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::data::value::{compare_values, compute_values};
|
||||
use nu_data::value::{compare_values, compute_values};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::Operator;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::value::compute_values;
|
||||
use crate::prelude::*;
|
||||
use bigdecimal::FromPrimitive;
|
||||
use nu_data::value::compute_values;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
hir::Operator, Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::classified::block::run_block;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::value::merge_values;
|
||||
use crate::prelude::*;
|
||||
use nu_data::value::merge_values;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::context::CommandRegistry;
|
||||
use crate::data::base::select_fields;
|
||||
use crate::prelude::*;
|
||||
use nu_data::base::select_fields;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, Value};
|
||||
use nu_source::span_for_spanned_list;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{operate, DefaultArguments};
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::files::get_file_type;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::filesystem_shell::get_file_type;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use std::path::Path;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::reject_fields;
|
||||
use crate::prelude::*;
|
||||
use nu_data::base::reject_fields;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::coerce_compare;
|
||||
use crate::prelude::*;
|
||||
use nu_data::base::coerce_compare;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
@ -86,12 +86,12 @@ pub fn split(
|
||||
}
|
||||
});
|
||||
|
||||
crate::utils::data::split(&values, &Some(block), &name)
|
||||
nu_data::utils::split(&values, &Some(block), &name)
|
||||
}
|
||||
Grouper::ByColumn(None) => {
|
||||
let block = Box::new(move |_, row: &Value| as_string(row));
|
||||
|
||||
crate::utils::data::split(&values, &Some(block), &name)
|
||||
nu_data::utils::split(&values, &Some(block), &name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,7 +124,7 @@ pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::split;
|
||||
use crate::utils::data::helpers::{committers_grouped_by_date, date, int, row, string, table};
|
||||
use nu_data::utils::helpers::{committers_grouped_by_date, date, int, row, string, table};
|
||||
use nu_protocol::UntaggedValue;
|
||||
use nu_source::*;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::config::table::HasTableProperties;
|
||||
use crate::data::config::NuConfig as TableConfiguration;
|
||||
use crate::data::value::{format_leaf, style_leaf};
|
||||
use crate::prelude::*;
|
||||
use nu_data::config::table::HasTableProperties;
|
||||
use nu_data::config::NuConfig as TableConfiguration;
|
||||
use nu_data::value::{format_leaf, style_leaf};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_table::{draw_table, Alignment, StyledString, TextStyle};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::value::format_leaf;
|
||||
use crate::prelude::*;
|
||||
use futures::StreamExt;
|
||||
use nu_data::value::format_leaf;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::{AnchorLocation, Tagged};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::value::format_leaf;
|
||||
use crate::prelude::*;
|
||||
use futures::StreamExt;
|
||||
use nu_data::value::format_leaf;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use crate::TaggedListBuilder;
|
||||
use indexmap::IndexMap;
|
||||
use nu_data::TaggedListBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Signature, UntaggedValue};
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
pub(crate) mod base;
|
||||
pub(crate) mod command;
|
||||
pub mod config;
|
||||
pub(crate) mod dict;
|
||||
pub(crate) mod files;
|
||||
pub mod primitive;
|
||||
pub(crate) mod types;
|
||||
pub mod value;
|
||||
|
||||
pub(crate) use command::command_dict;
|
||||
pub(crate) use dict::TaggedListBuilder;
|
||||
pub(crate) use files::dir_entry_dict;
|
@ -1,164 +0,0 @@
|
||||
mod conf;
|
||||
mod nuconfig;
|
||||
pub mod table;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests;
|
||||
|
||||
pub(crate) use conf::Conf;
|
||||
pub(crate) use nuconfig::NuConfig;
|
||||
|
||||
use crate::commands::from_toml::convert_toml_value_to_nu_value;
|
||||
use crate::commands::to_toml::value_to_toml_value;
|
||||
use crate::prelude::*;
|
||||
use indexmap::IndexMap;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, ShellTypeName, UntaggedValue, Value};
|
||||
use nu_source::Tag;
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[cfg(feature = "directories")]
|
||||
pub fn config_path() -> Result<PathBuf, ShellError> {
|
||||
use directories::ProjectDirs;
|
||||
|
||||
let dir = ProjectDirs::from("org", "nushell", "nu")
|
||||
.ok_or_else(|| ShellError::untagged_runtime_error("Couldn't find project directory"))?;
|
||||
let path = ProjectDirs::config_dir(&dir).to_owned();
|
||||
std::fs::create_dir_all(&path).map_err(|err| {
|
||||
ShellError::untagged_runtime_error(&format!("Couldn't create {} path:\n{}", "config", err))
|
||||
})?;
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "directories"))]
|
||||
pub fn config_path() -> Result<PathBuf, ShellError> {
|
||||
// FIXME: unsure if this should be error or a simple default
|
||||
|
||||
Ok(std::path::PathBuf::from("/"))
|
||||
}
|
||||
|
||||
pub fn default_path() -> Result<PathBuf, ShellError> {
|
||||
default_path_for(&None)
|
||||
}
|
||||
|
||||
pub fn default_path_for(file: &Option<PathBuf>) -> Result<PathBuf, ShellError> {
|
||||
let mut filename = config_path()?;
|
||||
let file: &Path = file
|
||||
.as_ref()
|
||||
.map(AsRef::as_ref)
|
||||
.unwrap_or_else(|| "config.toml".as_ref());
|
||||
filename.push(file);
|
||||
|
||||
Ok(filename)
|
||||
}
|
||||
|
||||
#[cfg(feature = "directories")]
|
||||
pub fn user_data() -> Result<PathBuf, ShellError> {
|
||||
use directories::ProjectDirs;
|
||||
|
||||
let dir = ProjectDirs::from("org", "nushell", "nu")
|
||||
.ok_or_else(|| ShellError::untagged_runtime_error("Couldn't find project directory"))?;
|
||||
let path = ProjectDirs::data_local_dir(&dir).to_owned();
|
||||
std::fs::create_dir_all(&path).map_err(|err| {
|
||||
ShellError::untagged_runtime_error(&format!(
|
||||
"Couldn't create {} path:\n{}",
|
||||
"user data", err
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "directories"))]
|
||||
pub fn user_data() -> Result<PathBuf, ShellError> {
|
||||
// FIXME: unsure if this should be error or a simple default
|
||||
|
||||
Ok(std::path::PathBuf::from("/"))
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
tag: impl Into<Tag>,
|
||||
at: &Option<PathBuf>,
|
||||
) -> Result<IndexMap<String, Value>, ShellError> {
|
||||
let filename = default_path()?;
|
||||
|
||||
let filename = match at {
|
||||
None => filename,
|
||||
Some(ref file) => file.clone(),
|
||||
};
|
||||
|
||||
if !filename.exists() && touch(&filename).is_err() {
|
||||
// If we can't create configs, let's just return an empty indexmap instead as we may be in
|
||||
// a readonly environment
|
||||
return Ok(IndexMap::new());
|
||||
}
|
||||
|
||||
trace!("config file = {}", filename.display());
|
||||
|
||||
let tag = tag.into();
|
||||
let contents = fs::read_to_string(filename)
|
||||
.map(|v| v.tagged(&tag))
|
||||
.map_err(|err| {
|
||||
ShellError::labeled_error(
|
||||
&format!("Couldn't read config file:\n{}", err),
|
||||
"file name",
|
||||
&tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
let parsed: toml::Value = toml::from_str(&contents).map_err(|err| {
|
||||
ShellError::labeled_error(
|
||||
&format!("Couldn't parse config file:\n{}", err),
|
||||
"file name",
|
||||
&tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
let value = convert_toml_value_to_nu_value(&parsed, tag);
|
||||
let tag = value.tag();
|
||||
match value.value {
|
||||
UntaggedValue::Row(Dictionary { entries }) => Ok(entries),
|
||||
other => Err(ShellError::type_error(
|
||||
"Dictionary",
|
||||
other.type_name().spanned(tag.span),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config(tag: impl Into<Tag>) -> Result<IndexMap<String, Value>, ShellError> {
|
||||
read(tag, &None)
|
||||
}
|
||||
|
||||
pub fn write(config: &IndexMap<String, Value>, at: &Option<PathBuf>) -> Result<(), ShellError> {
|
||||
let filename = &mut default_path()?;
|
||||
let filename = match at {
|
||||
None => filename,
|
||||
Some(file) => {
|
||||
filename.pop();
|
||||
filename.push(file);
|
||||
filename
|
||||
}
|
||||
};
|
||||
|
||||
let contents = value_to_toml_value(
|
||||
&UntaggedValue::Row(Dictionary::new(config.clone())).into_untagged_value(),
|
||||
)?;
|
||||
|
||||
let contents = toml::to_string(&contents)?;
|
||||
|
||||
fs::write(&filename, &contents)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// A simple implementation of `% touch path` (ignores existing files)
|
||||
fn touch(path: &Path) -> io::Result<()> {
|
||||
match OpenOptions::new().create(true).write(true).open(path) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
use crate::commands::du::{DirBuilder, DirInfo};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
|
||||
pub(crate) fn get_file_type(md: &std::fs::Metadata) -> &str {
|
||||
let ft = md.file_type();
|
||||
let mut file_type = "Unknown";
|
||||
if ft.is_dir() {
|
||||
file_type = "Dir";
|
||||
} else if ft.is_file() {
|
||||
file_type = "File";
|
||||
} else if ft.is_symlink() {
|
||||
file_type = "Symlink";
|
||||
} else {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
if ft.is_block_device() {
|
||||
file_type = "Block device";
|
||||
} else if ft.is_char_device() {
|
||||
file_type = "Char device";
|
||||
} else if ft.is_fifo() {
|
||||
file_type = "Pipe";
|
||||
} else if ft.is_socket() {
|
||||
file_type = "Socket";
|
||||
}
|
||||
}
|
||||
}
|
||||
file_type
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn dir_entry_dict(
|
||||
filename: &std::path::Path,
|
||||
metadata: Option<&std::fs::Metadata>,
|
||||
tag: impl Into<Tag>,
|
||||
long: bool,
|
||||
short_name: bool,
|
||||
du: bool,
|
||||
ctrl_c: Arc<AtomicBool>,
|
||||
) -> Result<Value, ShellError> {
|
||||
let tag = tag.into();
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
// Insert all columns first to maintain proper table alignment if we can't find (or are not allowed to view) any information
|
||||
if long {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
for column in [
|
||||
"name", "type", "target", "readonly", "size", "created", "accessed", "modified",
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
dict.insert_untagged(*column, UntaggedValue::nothing());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
for column in [
|
||||
"name", "type", "target", "readonly", "mode", "uid", "group", "size", "created",
|
||||
"accessed", "modified",
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
dict.insert_untagged(&(*column.to_owned()), UntaggedValue::nothing());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for column in ["name", "type", "target", "size", "modified"].iter() {
|
||||
if *column == "target" {
|
||||
continue;
|
||||
}
|
||||
dict.insert_untagged(*column, UntaggedValue::nothing());
|
||||
}
|
||||
}
|
||||
|
||||
let name = if short_name {
|
||||
filename.file_name().and_then(|s| s.to_str())
|
||||
} else {
|
||||
filename.to_str()
|
||||
}
|
||||
.ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
format!("Invalid file name: {:}", filename.to_string_lossy()),
|
||||
"invalid file name",
|
||||
tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
dict.insert_untagged("name", UntaggedValue::string(name));
|
||||
|
||||
if let Some(md) = metadata {
|
||||
dict.insert_untagged("type", get_file_type(md));
|
||||
}
|
||||
|
||||
if long {
|
||||
if let Some(md) = metadata {
|
||||
if md.file_type().is_symlink() {
|
||||
let symlink_target_untagged_value: UntaggedValue;
|
||||
if let Ok(path_to_link) = filename.read_link() {
|
||||
symlink_target_untagged_value =
|
||||
UntaggedValue::string(path_to_link.to_string_lossy());
|
||||
} else {
|
||||
symlink_target_untagged_value =
|
||||
UntaggedValue::string("Could not obtain target file's path");
|
||||
}
|
||||
dict.insert_untagged("target", symlink_target_untagged_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if long {
|
||||
if let Some(md) = metadata {
|
||||
dict.insert_untagged(
|
||||
"readonly",
|
||||
UntaggedValue::boolean(md.permissions().readonly()),
|
||||
);
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mode = md.permissions().mode();
|
||||
dict.insert_untagged(
|
||||
"mode",
|
||||
UntaggedValue::string(umask::Mode::from(mode).to_string()),
|
||||
);
|
||||
|
||||
if let Some(user) = users::get_user_by_uid(md.uid()) {
|
||||
dict.insert_untagged(
|
||||
"uid",
|
||||
UntaggedValue::string(user.name().to_string_lossy()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(group) = users::get_group_by_gid(md.gid()) {
|
||||
dict.insert_untagged(
|
||||
"group",
|
||||
UntaggedValue::string(group.name().to_string_lossy()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(md) = metadata {
|
||||
let mut size_untagged_value: UntaggedValue = UntaggedValue::nothing();
|
||||
|
||||
if md.is_dir() {
|
||||
let dir_size: u64 = if du {
|
||||
let params = DirBuilder::new(
|
||||
Tag {
|
||||
anchor: None,
|
||||
span: Span::new(0, 2),
|
||||
},
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
||||
DirInfo::new(filename, ¶ms, None, ctrl_c).get_size()
|
||||
} else {
|
||||
md.len()
|
||||
};
|
||||
|
||||
size_untagged_value = UntaggedValue::filesize(dir_size);
|
||||
} else if md.is_file() {
|
||||
size_untagged_value = UntaggedValue::filesize(md.len());
|
||||
} else if md.file_type().is_symlink() {
|
||||
if let Ok(symlink_md) = filename.symlink_metadata() {
|
||||
size_untagged_value = UntaggedValue::filesize(symlink_md.len() as u64);
|
||||
}
|
||||
}
|
||||
|
||||
dict.insert_untagged("size", size_untagged_value);
|
||||
}
|
||||
|
||||
if let Some(md) = metadata {
|
||||
if long {
|
||||
if let Ok(c) = md.created() {
|
||||
dict.insert_untagged("created", UntaggedValue::system_date(c));
|
||||
}
|
||||
|
||||
if let Ok(a) = md.accessed() {
|
||||
dict.insert_untagged("accessed", UntaggedValue::system_date(a));
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(m) = md.modified() {
|
||||
dict.insert_untagged("modified", UntaggedValue::system_date(m));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(dict.into_value())
|
||||
}
|
4
crates/nu-cli/src/env/environment.rs
vendored
4
crates/nu-cli/src/env/environment.rs
vendored
@ -1,6 +1,6 @@
|
||||
use crate::data::config::Conf;
|
||||
use crate::env::directory_specific_environment::*;
|
||||
use indexmap::{indexmap, IndexSet};
|
||||
use nu_data::config::Conf;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
use std::env::*;
|
||||
@ -154,7 +154,7 @@ impl Env for Environment {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Env, Environment};
|
||||
use crate::data::config::{tests::FakeConfig, Conf};
|
||||
use nu_data::config::{tests::FakeConfig, Conf};
|
||||
use nu_protocol::UntaggedValue;
|
||||
use nu_test_support::fs::Stub::FileWithContent;
|
||||
use nu_test_support::playground::Playground;
|
||||
|
4
crates/nu-cli/src/env/environment_syncer.rs
vendored
4
crates/nu-cli/src/env/environment_syncer.rs
vendored
@ -1,5 +1,5 @@
|
||||
use crate::context::Context;
|
||||
use crate::data::config::{Conf, NuConfig};
|
||||
use nu_data::config::{Conf, NuConfig};
|
||||
|
||||
use crate::env::environment::{Env, Environment};
|
||||
use nu_source::Text;
|
||||
@ -128,9 +128,9 @@ impl EnvironmentSyncer {
|
||||
mod tests {
|
||||
use super::EnvironmentSyncer;
|
||||
use crate::context::Context;
|
||||
use crate::data::config::tests::FakeConfig;
|
||||
use crate::env::environment::Env;
|
||||
use indexmap::IndexMap;
|
||||
use nu_data::config::tests::FakeConfig;
|
||||
use nu_errors::ShellError;
|
||||
use nu_test_support::fs::Stub::FileWithContent;
|
||||
use nu_test_support::playground::Playground;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::data::value;
|
||||
use nu_data::value;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::Operator;
|
||||
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
|
||||
|
@ -17,7 +17,7 @@ pub fn nu(env: &IndexMap<String, String>, tag: impl Into<Tag>) -> Result<Value,
|
||||
}
|
||||
nu_dict.insert_value("env", dict.into_value());
|
||||
|
||||
let config = crate::data::config::read(&tag, &None)?;
|
||||
let config = nu_data::config::read(&tag, &None)?;
|
||||
nu_dict.insert_value("config", UntaggedValue::row(config).into_value(&tag));
|
||||
|
||||
let mut table = vec![];
|
||||
@ -39,7 +39,7 @@ pub fn nu(env: &IndexMap<String, String>, tag: impl Into<Tag>) -> Result<Value,
|
||||
let temp = std::env::temp_dir();
|
||||
nu_dict.insert_value("temp-dir", UntaggedValue::path(temp).into_value(&tag));
|
||||
|
||||
let config = crate::data::config::default_path()?;
|
||||
let config = nu_data::config::default_path()?;
|
||||
nu_dict.insert_value("config-path", UntaggedValue::path(config).into_value(&tag));
|
||||
|
||||
let keybinding_path = crate::keybinding::keybinding_path()?;
|
||||
|
@ -406,7 +406,7 @@ pub struct Keybinding {
|
||||
type Keybindings = Vec<Keybinding>;
|
||||
|
||||
pub(crate) fn keybinding_path() -> Result<std::path::PathBuf, nu_errors::ShellError> {
|
||||
crate::data::config::default_path_for(&Some(std::path::PathBuf::from("keybindings.yml")))
|
||||
nu_data::config::default_path_for(&Some(std::path::PathBuf::from("keybindings.yml")))
|
||||
}
|
||||
|
||||
pub(crate) fn load_keybindings(
|
||||
|
@ -17,7 +17,6 @@ mod cli;
|
||||
mod commands;
|
||||
mod completion;
|
||||
mod context;
|
||||
pub mod data;
|
||||
mod deserializer;
|
||||
mod documentation;
|
||||
mod env;
|
||||
@ -43,14 +42,14 @@ pub use crate::commands::command::{
|
||||
};
|
||||
pub use crate::commands::help::get_help;
|
||||
pub use crate::context::{CommandRegistry, Context};
|
||||
pub use crate::data::config;
|
||||
pub use crate::data::dict::TaggedListBuilder;
|
||||
pub use crate::data::primitive;
|
||||
pub use crate::data::value;
|
||||
pub use crate::env::environment_syncer::EnvironmentSyncer;
|
||||
pub use crate::env::host::BasicHost;
|
||||
pub use crate::prelude::ToOutputStream;
|
||||
pub use crate::stream::{InputStream, InterruptibleStream, OutputStream};
|
||||
pub use nu_data::config;
|
||||
pub use nu_data::dict::TaggedListBuilder;
|
||||
pub use nu_data::primitive;
|
||||
pub use nu_data::value;
|
||||
pub use nu_value_ext::ValueExt;
|
||||
pub use num_traits::cast::ToPrimitive;
|
||||
|
||||
|
@ -75,8 +75,8 @@ pub(crate) use crate::commands::command::{CommandArgs, RawCommandArgs, RunnableC
|
||||
pub(crate) use crate::commands::Example;
|
||||
pub(crate) use crate::context::CommandRegistry;
|
||||
pub(crate) use crate::context::Context;
|
||||
pub(crate) use crate::data::config;
|
||||
pub(crate) use crate::data::value;
|
||||
pub(crate) use nu_data::config;
|
||||
pub(crate) use nu_data::value;
|
||||
// pub(crate) use crate::env::host::handle_unexpected;
|
||||
pub(crate) use crate::env::Host;
|
||||
pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
|
||||
@ -87,7 +87,6 @@ pub(crate) use crate::stream::{InputStream, InterruptibleStream, OutputStream};
|
||||
pub(crate) use bigdecimal::BigDecimal;
|
||||
pub(crate) use futures::stream::BoxStream;
|
||||
pub(crate) use futures::{Stream, StreamExt};
|
||||
pub(crate) use nu_protocol::MaybeOwned;
|
||||
pub(crate) use nu_source::{
|
||||
b, AnchorLocation, DebugDocBuilder, PrettyDebug, PrettyDebugWithSource, Span, SpannedItem, Tag,
|
||||
TaggedItem, Text,
|
||||
|
@ -13,8 +13,8 @@ use ichwh::{IchwhError, IchwhResult};
|
||||
|
||||
use crate::completion::{self, Completer};
|
||||
use crate::context;
|
||||
use crate::data::config;
|
||||
use crate::prelude::*;
|
||||
use nu_data::config;
|
||||
|
||||
pub(crate) struct NuCompleter {
|
||||
file_completer: FilenameCompleter,
|
||||
|
@ -1,15 +1,16 @@
|
||||
use crate::commands::cd::CdArgs;
|
||||
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::du::{DirBuilder, DirInfo};
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::data::dir_entry_dict;
|
||||
use crate::path::canonicalize;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::shell::Shell;
|
||||
use crate::utils::FileStructure;
|
||||
use nu_protocol::{TaggedDictBuilder, Value};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Error, ErrorKind};
|
||||
@ -790,3 +791,197 @@ fn is_hidden_dir(dir: impl AsRef<Path>) -> bool {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
|
||||
pub(crate) fn get_file_type(md: &std::fs::Metadata) -> &str {
|
||||
let ft = md.file_type();
|
||||
let mut file_type = "Unknown";
|
||||
if ft.is_dir() {
|
||||
file_type = "Dir";
|
||||
} else if ft.is_file() {
|
||||
file_type = "File";
|
||||
} else if ft.is_symlink() {
|
||||
file_type = "Symlink";
|
||||
} else {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
if ft.is_block_device() {
|
||||
file_type = "Block device";
|
||||
} else if ft.is_char_device() {
|
||||
file_type = "Char device";
|
||||
} else if ft.is_fifo() {
|
||||
file_type = "Pipe";
|
||||
} else if ft.is_socket() {
|
||||
file_type = "Socket";
|
||||
}
|
||||
}
|
||||
}
|
||||
file_type
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn dir_entry_dict(
|
||||
filename: &std::path::Path,
|
||||
metadata: Option<&std::fs::Metadata>,
|
||||
tag: impl Into<Tag>,
|
||||
long: bool,
|
||||
short_name: bool,
|
||||
du: bool,
|
||||
ctrl_c: Arc<AtomicBool>,
|
||||
) -> Result<Value, ShellError> {
|
||||
let tag = tag.into();
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
// Insert all columns first to maintain proper table alignment if we can't find (or are not allowed to view) any information
|
||||
if long {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
for column in [
|
||||
"name", "type", "target", "readonly", "size", "created", "accessed", "modified",
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
dict.insert_untagged(*column, UntaggedValue::nothing());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
for column in [
|
||||
"name", "type", "target", "readonly", "mode", "uid", "group", "size", "created",
|
||||
"accessed", "modified",
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
dict.insert_untagged(&(*column.to_owned()), UntaggedValue::nothing());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for column in ["name", "type", "target", "size", "modified"].iter() {
|
||||
if *column == "target" {
|
||||
continue;
|
||||
}
|
||||
dict.insert_untagged(*column, UntaggedValue::nothing());
|
||||
}
|
||||
}
|
||||
|
||||
let name = if short_name {
|
||||
filename.file_name().and_then(|s| s.to_str())
|
||||
} else {
|
||||
filename.to_str()
|
||||
}
|
||||
.ok_or_else(|| {
|
||||
ShellError::labeled_error(
|
||||
format!("Invalid file name: {:}", filename.to_string_lossy()),
|
||||
"invalid file name",
|
||||
tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
dict.insert_untagged("name", UntaggedValue::string(name));
|
||||
|
||||
if let Some(md) = metadata {
|
||||
dict.insert_untagged("type", get_file_type(md));
|
||||
}
|
||||
|
||||
if long {
|
||||
if let Some(md) = metadata {
|
||||
if md.file_type().is_symlink() {
|
||||
let symlink_target_untagged_value: UntaggedValue;
|
||||
if let Ok(path_to_link) = filename.read_link() {
|
||||
symlink_target_untagged_value =
|
||||
UntaggedValue::string(path_to_link.to_string_lossy());
|
||||
} else {
|
||||
symlink_target_untagged_value =
|
||||
UntaggedValue::string("Could not obtain target file's path");
|
||||
}
|
||||
dict.insert_untagged("target", symlink_target_untagged_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if long {
|
||||
if let Some(md) = metadata {
|
||||
dict.insert_untagged(
|
||||
"readonly",
|
||||
UntaggedValue::boolean(md.permissions().readonly()),
|
||||
);
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
let mode = md.permissions().mode();
|
||||
dict.insert_untagged(
|
||||
"mode",
|
||||
UntaggedValue::string(umask::Mode::from(mode).to_string()),
|
||||
);
|
||||
|
||||
if let Some(user) = users::get_user_by_uid(md.uid()) {
|
||||
dict.insert_untagged(
|
||||
"uid",
|
||||
UntaggedValue::string(user.name().to_string_lossy()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(group) = users::get_group_by_gid(md.gid()) {
|
||||
dict.insert_untagged(
|
||||
"group",
|
||||
UntaggedValue::string(group.name().to_string_lossy()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(md) = metadata {
|
||||
let mut size_untagged_value: UntaggedValue = UntaggedValue::nothing();
|
||||
|
||||
if md.is_dir() {
|
||||
let dir_size: u64 = if du {
|
||||
let params = DirBuilder::new(
|
||||
Tag {
|
||||
anchor: None,
|
||||
span: Span::new(0, 2),
|
||||
},
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
||||
DirInfo::new(filename, ¶ms, None, ctrl_c).get_size()
|
||||
} else {
|
||||
md.len()
|
||||
};
|
||||
|
||||
size_untagged_value = UntaggedValue::filesize(dir_size);
|
||||
} else if md.is_file() {
|
||||
size_untagged_value = UntaggedValue::filesize(md.len());
|
||||
} else if md.file_type().is_symlink() {
|
||||
if let Ok(symlink_md) = filename.symlink_metadata() {
|
||||
size_untagged_value = UntaggedValue::filesize(symlink_md.len() as u64);
|
||||
}
|
||||
}
|
||||
|
||||
dict.insert_untagged("size", size_untagged_value);
|
||||
}
|
||||
|
||||
if let Some(md) = metadata {
|
||||
if long {
|
||||
if let Ok(c) = md.created() {
|
||||
dict.insert_untagged("created", UntaggedValue::system_date(c));
|
||||
}
|
||||
|
||||
if let Ok(a) = md.accessed() {
|
||||
dict.insert_untagged("accessed", UntaggedValue::system_date(a));
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(m) = md.modified() {
|
||||
dict.insert_untagged("modified", UntaggedValue::system_date(m));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(dict.into_value())
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::commands::cd::CdArgs;
|
||||
use crate::commands::command::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::commands::cp::CopyArgs;
|
||||
use crate::commands::help::command_dict;
|
||||
use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::completion;
|
||||
use crate::data::command_dict;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::shell::Shell;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
pub mod data;
|
||||
pub mod test_bins;
|
||||
|
||||
use crate::path::canonicalize;
|
||||
|
40
crates/nu-data/Cargo.toml
Normal file
40
crates/nu-data/Cargo.toml
Normal file
@ -0,0 +1,40 @@
|
||||
[package]
|
||||
authors = ["The Nu Project Contributors"]
|
||||
description = "CLI for nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-data"
|
||||
version = "0.18.2"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.12.1"
|
||||
bigdecimal = "0.1.2"
|
||||
byte-unit = "3.1.3"
|
||||
|
||||
chrono = "0.4.15"
|
||||
derive-new = "0.5.8"
|
||||
directories = {version = "2.0.2", optional = true}
|
||||
dirs = {version = "2.0.2", optional = true}
|
||||
getset = "0.1.1"
|
||||
indexmap = {version = "1.4.0", features = ["serde-1"]}
|
||||
log = "0.4.8"
|
||||
num-bigint = {version = "0.2.6", features = ["serde"]}
|
||||
num-format = {version = "0.4", features = ["with-num-bigint"]}
|
||||
num-traits = "0.2.11"
|
||||
parking_lot = "0.11.0"
|
||||
query_interface = "0.3.5"
|
||||
serde = {version = "1.0.114", features = ["derive"]}
|
||||
toml = "0.5.6"
|
||||
umask = "1.0.0"
|
||||
|
||||
nu-errors = {version = "0.18.2", path = "../nu-errors"}
|
||||
nu-protocol = {version = "0.18.2", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.18.2", path = "../nu-source"}
|
||||
nu-table = {version = "0.18.2", path = "../nu-table"}
|
||||
nu-value-ext = {version = "0.18.2", path = "../nu-value-ext"}
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
users = "0.10.0"
|
@ -49,7 +49,7 @@ impl std::convert::TryFrom<Option<&Value>> for Switch {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Value {
|
||||
pub fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Value {
|
||||
let mut out = TaggedDictBuilder::new(tag);
|
||||
|
||||
let descs = obj.data_descriptors();
|
||||
@ -64,7 +64,7 @@ pub(crate) fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>)
|
||||
out.into_value()
|
||||
}
|
||||
|
||||
pub(crate) fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Value {
|
||||
pub fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Value {
|
||||
let mut out = TaggedDictBuilder::new(tag);
|
||||
|
||||
let descs = obj.data_descriptors();
|
||||
@ -80,7 +80,7 @@ pub(crate) fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>)
|
||||
out.into_value()
|
||||
}
|
||||
|
||||
pub(crate) enum CompareValues {
|
||||
pub enum CompareValues {
|
||||
Ints(BigInt, BigInt),
|
||||
Decimals(BigDecimal, BigDecimal),
|
||||
String(String, String),
|
||||
@ -113,7 +113,7 @@ impl CompareValues {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn coerce_compare(
|
||||
pub fn coerce_compare(
|
||||
left: &UntaggedValue,
|
||||
right: &UntaggedValue,
|
||||
) -> Result<CompareValues, (&'static str, &'static str)> {
|
||||
@ -165,7 +165,7 @@ fn coerce_compare_primitive(
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use indexmap::IndexMap;
|
||||
use indexmap::{indexmap, IndexMap};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ColumnPath as ColumnPathValue, PathMember, UntaggedValue, Value};
|
||||
use nu_source::*;
|
||||
@ -173,19 +173,19 @@ mod tests {
|
||||
use num_bigint::BigInt;
|
||||
|
||||
fn string(input: impl Into<String>) -> Value {
|
||||
crate::utils::data::helpers::string(input)
|
||||
crate::utils::helpers::string(input)
|
||||
}
|
||||
|
||||
fn int(input: impl Into<BigInt>) -> Value {
|
||||
crate::utils::data::helpers::int(input)
|
||||
crate::utils::helpers::int(input)
|
||||
}
|
||||
|
||||
fn row(entries: IndexMap<String, Value>) -> Value {
|
||||
crate::utils::data::helpers::row(entries)
|
||||
crate::utils::helpers::row(entries)
|
||||
}
|
||||
|
||||
fn table(list: &[Value]) -> Value {
|
||||
crate::utils::data::helpers::table(list)
|
||||
crate::utils::helpers::table(list)
|
||||
}
|
||||
|
||||
fn error_callback(
|
@ -1,8 +1,9 @@
|
||||
use crate::prelude::*;
|
||||
use bigdecimal::BigDecimal;
|
||||
use chrono::{DateTime, Utc};
|
||||
use nu_protocol::RangeInclusion;
|
||||
use nu_protocol::{format_primitive, ColumnPath, Dictionary, Primitive, UntaggedValue, Value};
|
||||
use nu_source::{b, PrettyDebug};
|
||||
use nu_source::{b, DebugDocBuilder, PrettyDebug};
|
||||
use num_bigint::BigInt;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
@ -1,23 +1,8 @@
|
||||
use crate::commands::command::Command;
|
||||
use crate::data::TaggedListBuilder;
|
||||
use crate::prelude::*;
|
||||
use crate::TaggedListBuilder;
|
||||
use nu_source::Tag;
|
||||
|
||||
use nu_protocol::{NamedType, PositionalType, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
||||
|
||||
pub(crate) fn command_dict(command: Command, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
|
||||
let mut cmd_dict = TaggedDictBuilder::new(&tag);
|
||||
|
||||
cmd_dict.insert_untagged("name", UntaggedValue::string(command.name()));
|
||||
|
||||
cmd_dict.insert_untagged("type", UntaggedValue::string("Command"));
|
||||
|
||||
cmd_dict.insert_value("signature", signature_dict(command.signature(), tag));
|
||||
cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage()));
|
||||
|
||||
cmd_dict.into_value()
|
||||
}
|
||||
|
||||
fn for_spec(name: &str, ty: &str, required: bool, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
|
||||
@ -33,7 +18,7 @@ fn for_spec(name: &str, ty: &str, required: bool, tag: impl Into<Tag>) -> Value
|
||||
spec.into_value()
|
||||
}
|
||||
|
||||
fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
|
||||
pub fn signature_dict(signature: Signature, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
let mut sig = TaggedListBuilder::new(&tag);
|
||||
|
289
crates/nu-data/src/config.rs
Normal file
289
crates/nu-data/src/config.rs
Normal file
@ -0,0 +1,289 @@
|
||||
mod conf;
|
||||
mod nuconfig;
|
||||
pub mod table;
|
||||
|
||||
pub mod tests;
|
||||
|
||||
pub use conf::Conf;
|
||||
pub use nuconfig::NuConfig;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use log::trace;
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{
|
||||
Dictionary, Primitive, ShellTypeName, TaggedDictBuilder, UnspannedPathMember, UntaggedValue,
|
||||
Value,
|
||||
};
|
||||
use nu_source::{SpannedItem, Tag, TaggedItem};
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
|
||||
match v {
|
||||
toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag),
|
||||
toml::Value::Integer(n) => UntaggedValue::int(*n).into_value(tag),
|
||||
toml::Value::Float(n) => UntaggedValue::decimal(*n).into_value(tag),
|
||||
toml::Value::String(s) => {
|
||||
UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag)
|
||||
}
|
||||
toml::Value::Array(a) => UntaggedValue::Table(
|
||||
a.iter()
|
||||
.map(|x| convert_toml_value_to_nu_value(x, &tag))
|
||||
.collect(),
|
||||
)
|
||||
.into_value(tag),
|
||||
toml::Value::Datetime(dt) => {
|
||||
UntaggedValue::Primitive(Primitive::String(dt.to_string())).into_value(tag)
|
||||
}
|
||||
toml::Value::Table(t) => {
|
||||
let mut collected = TaggedDictBuilder::new(&tag);
|
||||
|
||||
for (k, v) in t.iter() {
|
||||
collected.insert_value(k.clone(), convert_toml_value_to_nu_value(v, &tag));
|
||||
}
|
||||
|
||||
collected.into_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_values(input: &[Value]) -> Result<Vec<toml::Value>, ShellError> {
|
||||
let mut out = vec![];
|
||||
|
||||
for value in input {
|
||||
out.push(helper(value)?);
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
// Helper method to recursively convert nu_protocol::Value -> toml::Value
|
||||
// This shouldn't be called at the top-level
|
||||
fn helper(v: &Value) -> Result<toml::Value, ShellError> {
|
||||
Ok(match &v.value {
|
||||
UntaggedValue::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b),
|
||||
UntaggedValue::Primitive(Primitive::Filesize(b)) => toml::Value::Integer(*b as i64),
|
||||
UntaggedValue::Primitive(Primitive::Duration(i)) => toml::Value::String(i.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::EndOfStream) => {
|
||||
toml::Value::String("<End of Stream>".to_string())
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::BeginningOfStream) => {
|
||||
toml::Value::String("<Beginning of Stream>".to_string())
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Decimal(f)) => {
|
||||
toml::Value::Float(f.tagged(&v.tag).coerce_into("converting to TOML float")?)
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Int(i)) => {
|
||||
toml::Value::Integer(i.tagged(&v.tag).coerce_into("converting to TOML integer")?)
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => {
|
||||
toml::Value::String("<Nothing>".to_string())
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Path(s)) => {
|
||||
toml::Value::String(s.display().to_string())
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => toml::Value::Array(
|
||||
path.iter()
|
||||
.map(|x| match &x.unspanned {
|
||||
UnspannedPathMember::String(string) => Ok(toml::Value::String(string.clone())),
|
||||
UnspannedPathMember::Int(int) => Ok(toml::Value::Integer(
|
||||
int.tagged(&v.tag)
|
||||
.coerce_into("converting to TOML integer")?,
|
||||
)),
|
||||
})
|
||||
.collect::<Result<Vec<toml::Value>, ShellError>>()?,
|
||||
),
|
||||
UntaggedValue::Table(l) => toml::Value::Array(collect_values(l)?),
|
||||
UntaggedValue::Error(e) => return Err(e.clone()),
|
||||
UntaggedValue::Block(_) => toml::Value::String("<Block>".to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Range(_)) => toml::Value::String("<Range>".to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Binary(b)) => {
|
||||
toml::Value::Array(b.iter().map(|x| toml::Value::Integer(*x as i64)).collect())
|
||||
}
|
||||
UntaggedValue::Row(o) => {
|
||||
let mut m = toml::map::Map::new();
|
||||
for (k, v) in o.entries.iter() {
|
||||
m.insert(k.clone(), helper(v)?);
|
||||
}
|
||||
toml::Value::Table(m)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts a nu_protocol::Value into a toml::Value
|
||||
/// Will return a Shell Error, if the Nu Value is not a valid top-level TOML Value
|
||||
pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {
|
||||
match &v.value {
|
||||
UntaggedValue::Row(o) => {
|
||||
let mut m = toml::map::Map::new();
|
||||
for (k, v) in o.entries.iter() {
|
||||
m.insert(k.clone(), helper(v)?);
|
||||
}
|
||||
Ok(toml::Value::Table(m))
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
// Attempt to de-serialize the String
|
||||
toml::de::from_str(s).map_err(|_| {
|
||||
ShellError::labeled_error(
|
||||
format!("{:?} unable to de-serialize string to TOML", s),
|
||||
"invalid TOML",
|
||||
v.tag(),
|
||||
)
|
||||
})
|
||||
}
|
||||
_ => Err(ShellError::labeled_error(
|
||||
format!("{:?} is not a valid top-level TOML", v.value),
|
||||
"invalid TOML",
|
||||
v.tag(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "directories")]
|
||||
pub fn config_path() -> Result<PathBuf, ShellError> {
|
||||
use directories::ProjectDirs;
|
||||
|
||||
let dir = ProjectDirs::from("org", "nushell", "nu")
|
||||
.ok_or_else(|| ShellError::untagged_runtime_error("Couldn't find project directory"))?;
|
||||
let path = ProjectDirs::config_dir(&dir).to_owned();
|
||||
std::fs::create_dir_all(&path).map_err(|err| {
|
||||
ShellError::untagged_runtime_error(&format!("Couldn't create {} path:\n{}", "config", err))
|
||||
})?;
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "directories"))]
|
||||
pub fn config_path() -> Result<PathBuf, ShellError> {
|
||||
// FIXME: unsure if this should be error or a simple default
|
||||
|
||||
Ok(std::path::PathBuf::from("/"))
|
||||
}
|
||||
|
||||
pub fn default_path() -> Result<PathBuf, ShellError> {
|
||||
default_path_for(&None)
|
||||
}
|
||||
|
||||
pub fn default_path_for(file: &Option<PathBuf>) -> Result<PathBuf, ShellError> {
|
||||
let mut filename = config_path()?;
|
||||
let file: &Path = file
|
||||
.as_ref()
|
||||
.map(AsRef::as_ref)
|
||||
.unwrap_or_else(|| "config.toml".as_ref());
|
||||
filename.push(file);
|
||||
|
||||
Ok(filename)
|
||||
}
|
||||
|
||||
#[cfg(feature = "directories")]
|
||||
pub fn user_data() -> Result<PathBuf, ShellError> {
|
||||
use directories::ProjectDirs;
|
||||
|
||||
let dir = ProjectDirs::from("org", "nushell", "nu")
|
||||
.ok_or_else(|| ShellError::untagged_runtime_error("Couldn't find project directory"))?;
|
||||
let path = ProjectDirs::data_local_dir(&dir).to_owned();
|
||||
std::fs::create_dir_all(&path).map_err(|err| {
|
||||
ShellError::untagged_runtime_error(&format!(
|
||||
"Couldn't create {} path:\n{}",
|
||||
"user data", err
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "directories"))]
|
||||
pub fn user_data() -> Result<PathBuf, ShellError> {
|
||||
// FIXME: unsure if this should be error or a simple default
|
||||
|
||||
Ok(std::path::PathBuf::from("/"))
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
tag: impl Into<Tag>,
|
||||
at: &Option<PathBuf>,
|
||||
) -> Result<IndexMap<String, Value>, ShellError> {
|
||||
let filename = default_path()?;
|
||||
|
||||
let filename = match at {
|
||||
None => filename,
|
||||
Some(ref file) => file.clone(),
|
||||
};
|
||||
|
||||
if !filename.exists() && touch(&filename).is_err() {
|
||||
// If we can't create configs, let's just return an empty indexmap instead as we may be in
|
||||
// a readonly environment
|
||||
return Ok(IndexMap::new());
|
||||
}
|
||||
|
||||
trace!("config file = {}", filename.display());
|
||||
|
||||
let tag = tag.into();
|
||||
let contents = fs::read_to_string(filename)
|
||||
.map(|v| v.tagged(&tag))
|
||||
.map_err(|err| {
|
||||
ShellError::labeled_error(
|
||||
&format!("Couldn't read config file:\n{}", err),
|
||||
"file name",
|
||||
&tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
let parsed: toml::Value = toml::from_str(&contents).map_err(|err| {
|
||||
ShellError::labeled_error(
|
||||
&format!("Couldn't parse config file:\n{}", err),
|
||||
"file name",
|
||||
&tag,
|
||||
)
|
||||
})?;
|
||||
|
||||
let value = convert_toml_value_to_nu_value(&parsed, tag);
|
||||
let tag = value.tag();
|
||||
match value.value {
|
||||
UntaggedValue::Row(Dictionary { entries }) => Ok(entries),
|
||||
other => Err(ShellError::type_error(
|
||||
"Dictionary",
|
||||
other.type_name().spanned(tag.span),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config(tag: impl Into<Tag>) -> Result<IndexMap<String, Value>, ShellError> {
|
||||
read(tag, &None)
|
||||
}
|
||||
|
||||
pub fn write(config: &IndexMap<String, Value>, at: &Option<PathBuf>) -> Result<(), ShellError> {
|
||||
let filename = &mut default_path()?;
|
||||
let filename = match at {
|
||||
None => filename,
|
||||
Some(file) => {
|
||||
filename.pop();
|
||||
filename.push(file);
|
||||
filename
|
||||
}
|
||||
};
|
||||
|
||||
let contents = value_to_toml_value(
|
||||
&UntaggedValue::Row(Dictionary::new(config.clone())).into_untagged_value(),
|
||||
)?;
|
||||
|
||||
let contents = toml::to_string(&contents)?;
|
||||
|
||||
fs::write(&filename, &contents)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// A simple implementation of `% touch path` (ignores existing files)
|
||||
fn touch(path: &Path) -> io::Result<()> {
|
||||
match OpenOptions::new().create(true).write(true).open(path) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::data::config::{read, Conf};
|
||||
use crate::config::{read, Conf};
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::Value;
|
||||
use nu_source::Tag;
|
@ -1,4 +1,4 @@
|
||||
use crate::data::config::nuconfig::NuConfig;
|
||||
use crate::config::nuconfig::NuConfig;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
@ -1,4 +1,4 @@
|
||||
use crate::data::config::{read, Conf, NuConfig};
|
||||
use crate::config::{read, Conf, NuConfig};
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::Value;
|
||||
use nu_source::Tag;
|
@ -1,7 +1,6 @@
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use nu_protocol::{Dictionary, Primitive, UntaggedValue, Value};
|
||||
use nu_source::{b, PrettyDebug, Spanned};
|
||||
use nu_protocol::{Dictionary, MaybeOwned, Primitive, UntaggedValue, Value};
|
||||
use nu_source::{b, DebugDocBuilder, PrettyDebug, Spanned, Tag};
|
||||
|
||||
#[derive(Debug, new)]
|
||||
struct DebugEntry<'a> {
|
10
crates/nu-data/src/lib.rs
Normal file
10
crates/nu-data/src/lib.rs
Normal file
@ -0,0 +1,10 @@
|
||||
pub mod base;
|
||||
pub mod command;
|
||||
pub mod config;
|
||||
pub mod dict;
|
||||
pub mod primitive;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
pub mod value;
|
||||
|
||||
pub use dict::TaggedListBuilder;
|
@ -1,4 +1,4 @@
|
||||
use crate::data::{TaggedDictBuilder, Value};
|
||||
use nu_data::{TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
use itertools::join;
|
||||
use sysinfo::ProcessExt;
|
@ -1,8 +1,7 @@
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::{CoerceInto, ShellError};
|
||||
use nu_protocol::{Primitive, SpannedTypeName, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
use nu_source::{Tagged, TaggedItem};
|
||||
|
||||
pub trait ExtractType: Sized {
|
||||
fn extract(value: &Value) -> Result<Self, ShellError>;
|
@ -1,6 +1,6 @@
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use crate::data::value::compute_values;
|
||||
use crate::value::compute_values;
|
||||
use derive_new::new;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::Operator;
|
||||
@ -138,8 +138,7 @@ pub fn sort_columns(
|
||||
if let Some(fmt) = format {
|
||||
for k in values.iter() {
|
||||
let k = k.clone().tagged_unknown();
|
||||
let v =
|
||||
crate::data::value::Date::naive_from_str(k.borrow_tagged())?.into_untagged_value();
|
||||
let v = crate::value::Date::naive_from_str(k.borrow_tagged())?.into_untagged_value();
|
||||
keys.push(fmt(&v, k.to_string())?);
|
||||
}
|
||||
} else {
|
@ -3,10 +3,10 @@ pub mod split;
|
||||
|
||||
mod internal;
|
||||
|
||||
pub use crate::utils::data::group::group;
|
||||
pub use crate::utils::data::split::split;
|
||||
pub use crate::utils::group::group;
|
||||
pub use crate::utils::split::split;
|
||||
|
||||
use crate::utils::data::internal::*;
|
||||
use crate::utils::internal::*;
|
||||
|
||||
use derive_new::new;
|
||||
use getset::Getters;
|
||||
@ -97,9 +97,8 @@ pub fn report(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod helpers {
|
||||
use super::{report, Labels, Model, Operation, Range};
|
||||
use super::Model;
|
||||
use bigdecimal::BigDecimal;
|
||||
use indexmap::indexmap;
|
||||
use nu_errors::ShellError;
|
||||
@ -132,8 +131,8 @@ pub mod helpers {
|
||||
|
||||
pub fn date(input: impl Into<String>) -> Value {
|
||||
let key = input.into().tagged_unknown();
|
||||
crate::data::value::Date::naive_from_str(key.borrow_tagged())
|
||||
.unwrap()
|
||||
crate::value::Date::naive_from_str(key.borrow_tagged())
|
||||
.expect("date from string failed")
|
||||
.into_untagged_value()
|
||||
}
|
||||
|
||||
@ -201,12 +200,15 @@ pub mod helpers {
|
||||
|
||||
let grouper = Box::new(move |_, row: &Value| {
|
||||
let key = String::from("date").tagged_unknown();
|
||||
let group_key = row.get_data_by_key(key.borrow_spanned()).unwrap();
|
||||
let group_key = row
|
||||
.get_data_by_key(key.borrow_spanned())
|
||||
.expect("get key failed");
|
||||
|
||||
group_key.format("%Y-%m-%d")
|
||||
});
|
||||
|
||||
crate::utils::data::group(&sample, &Some(grouper), Tag::unknown()).unwrap()
|
||||
crate::utils::group(&sample, &Some(grouper), Tag::unknown())
|
||||
.expect("failed to create group")
|
||||
}
|
||||
|
||||
pub fn date_formatter(
|
||||
@ -215,13 +217,24 @@ pub mod helpers {
|
||||
Box::new(move |date: &Value, _: String| date.format(&fmt))
|
||||
}
|
||||
|
||||
fn assert_without_checking_percentages(report_a: Model, report_b: Model) {
|
||||
pub fn assert_without_checking_percentages(report_a: Model, report_b: Model) {
|
||||
assert_eq!(report_a.labels.x, report_b.labels.x);
|
||||
assert_eq!(report_a.labels.y, report_b.labels.y);
|
||||
assert_eq!(report_a.ranges, report_b.ranges);
|
||||
assert_eq!(report_a.data, report_b.data);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::helpers::{
|
||||
assert_without_checking_percentages, committers, date_formatter, decimal, int, table,
|
||||
};
|
||||
use super::{report, Labels, Model, Operation, Range};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::Value;
|
||||
use nu_source::{Tag, TaggedItem};
|
||||
use nu_value_ext::ValueExt;
|
||||
#[test]
|
||||
fn prepares_report_using_accumulating_value() {
|
||||
let committers = table(&committers());
|
@ -2,7 +2,7 @@ use nu_errors::ShellError;
|
||||
use nu_protocol::{SpannedTypeName, TaggedDictBuilder, UntaggedValue, Value};
|
||||
use nu_source::Tag;
|
||||
|
||||
use crate::utils::data::group;
|
||||
use crate::utils::group;
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn split(
|
@ -1,6 +1,6 @@
|
||||
use crate::data::base::coerce_compare;
|
||||
use crate::data::base::shape::{Column, InlineShape};
|
||||
use crate::data::primitive::style_primitive;
|
||||
use crate::base::coerce_compare;
|
||||
use crate::base::shape::{Column, InlineShape};
|
||||
use crate::primitive::style_primitive;
|
||||
use chrono::{DateTime, NaiveDate, Utc};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::Operator;
|
@ -10,7 +10,7 @@ version = "0.18.2"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-cli = {path = "../nu-cli", version = "0.18.2"}
|
||||
nu-data = {path = "../nu-data", version = "0.18.2"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.18.2"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.18.2"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.18.2"}
|
||||
|
@ -32,7 +32,7 @@ pub fn view_text_value(value: &Value) {
|
||||
let highlight_range_to: u64 = 0;
|
||||
let mut theme = "OneHalfDark".to_string();
|
||||
|
||||
if let Ok(config) = nu_cli::data::config::config(Tag::unknown()) {
|
||||
if let Ok(config) = nu_data::config::config(Tag::unknown()) {
|
||||
if let Some(batvars) = config.get("textview") {
|
||||
for (idx, value) in batvars.row_entries() {
|
||||
match idx.as_ref() {
|
||||
|
Loading…
Reference in New Issue
Block a user