mirror of
https://github.com/nushell/nushell.git
synced 2025-07-01 07:00:37 +02:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
5183fd25bb | |||
10f5a8ef78 | |||
a30837298d | |||
f377a3a7b4 | |||
83c874666a | |||
e000ed47cd | |||
af2f064f42 | |||
9c7b25134b | |||
2d15df9e6c | |||
d2ab287756 | |||
e73278990c | |||
12bc92df35 | |||
f19a801022 | |||
b193303aa3 |
6
.gitpod.Dockerfile
vendored
6
.gitpod.Dockerfile
vendored
@ -1,5 +1,9 @@
|
||||
FROM gitpod/workspace-full
|
||||
|
||||
# Gitpod will not rebuild Nushell's dev image unless *some* change is made to this Dockerfile.
|
||||
# To force a rebuild, simply increase this counter:
|
||||
ENV TRIGGER_REBUILD 1
|
||||
|
||||
USER gitpod
|
||||
|
||||
RUN sudo apt-get update && \
|
||||
@ -11,4 +15,4 @@ RUN sudo apt-get update && \
|
||||
rust-lldb \
|
||||
&& sudo rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV RUST_LLDB=/usr/bin/lldb-8
|
||||
ENV RUST_LLDB=/usr/bin/lldb-11
|
||||
|
474
Cargo.lock
generated
474
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
56
Cargo.toml
56
Cargo.toml
@ -10,7 +10,7 @@ license = "MIT"
|
||||
name = "nu"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/nushell/nushell"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[workspace]
|
||||
members = ["crates/*/"]
|
||||
@ -18,33 +18,33 @@ members = ["crates/*/"]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
nu-cli = {version = "0.23.0", path = "./crates/nu-cli"}
|
||||
nu-data = {version = "0.23.0", path = "./crates/nu-data"}
|
||||
nu-errors = {version = "0.23.0", path = "./crates/nu-errors"}
|
||||
nu-parser = {version = "0.23.0", path = "./crates/nu-parser"}
|
||||
nu-plugin = {version = "0.23.0", path = "./crates/nu-plugin"}
|
||||
nu-protocol = {version = "0.23.0", path = "./crates/nu-protocol"}
|
||||
nu-source = {version = "0.23.0", path = "./crates/nu-source"}
|
||||
nu-value-ext = {version = "0.23.0", path = "./crates/nu-value-ext"}
|
||||
nu-cli = {version = "0.24.1", path = "./crates/nu-cli"}
|
||||
nu-data = {version = "0.24.1", path = "./crates/nu-data"}
|
||||
nu-errors = {version = "0.24.1", path = "./crates/nu-errors"}
|
||||
nu-parser = {version = "0.24.1", path = "./crates/nu-parser"}
|
||||
nu-plugin = {version = "0.24.1", path = "./crates/nu-plugin"}
|
||||
nu-protocol = {version = "0.24.1", path = "./crates/nu-protocol"}
|
||||
nu-source = {version = "0.24.1", path = "./crates/nu-source"}
|
||||
nu-value-ext = {version = "0.24.1", path = "./crates/nu-value-ext"}
|
||||
|
||||
nu_plugin_binaryview = {version = "0.23.0", path = "./crates/nu_plugin_binaryview", optional = true}
|
||||
nu_plugin_chart = {version = "0.23.0", path = "./crates/nu_plugin_chart", optional = true}
|
||||
nu_plugin_fetch = {version = "0.23.0", path = "./crates/nu_plugin_fetch", optional = true}
|
||||
nu_plugin_from_bson = {version = "0.23.0", path = "./crates/nu_plugin_from_bson", optional = true}
|
||||
nu_plugin_from_sqlite = {version = "0.23.0", path = "./crates/nu_plugin_from_sqlite", optional = true}
|
||||
nu_plugin_inc = {version = "0.23.0", path = "./crates/nu_plugin_inc", optional = true}
|
||||
nu_plugin_match = {version = "0.23.0", path = "./crates/nu_plugin_match", optional = true}
|
||||
nu_plugin_post = {version = "0.23.0", path = "./crates/nu_plugin_post", optional = true}
|
||||
nu_plugin_ps = {version = "0.23.0", path = "./crates/nu_plugin_ps", optional = true}
|
||||
nu_plugin_s3 = {version = "0.23.0", path = "./crates/nu_plugin_s3", optional = true}
|
||||
nu_plugin_start = {version = "0.23.0", path = "./crates/nu_plugin_start", optional = true}
|
||||
nu_plugin_sys = {version = "0.23.0", path = "./crates/nu_plugin_sys", optional = true}
|
||||
nu_plugin_textview = {version = "0.23.0", path = "./crates/nu_plugin_textview", optional = true}
|
||||
nu_plugin_to_bson = {version = "0.23.0", path = "./crates/nu_plugin_to_bson", optional = true}
|
||||
nu_plugin_to_sqlite = {version = "0.23.0", path = "./crates/nu_plugin_to_sqlite", optional = true}
|
||||
nu_plugin_tree = {version = "0.23.0", path = "./crates/nu_plugin_tree", optional = true}
|
||||
nu_plugin_xpath = {version = "0.23.0", path = "./crates/nu_plugin_xpath", optional = true}
|
||||
nu_plugin_selector = {version = "0.23.0", path = "./crates/nu_plugin_selector", optional = true}
|
||||
nu_plugin_binaryview = {version = "0.24.1", path = "./crates/nu_plugin_binaryview", optional = true}
|
||||
nu_plugin_chart = {version = "0.24.1", path = "./crates/nu_plugin_chart", optional = true}
|
||||
nu_plugin_fetch = {version = "0.24.1", path = "./crates/nu_plugin_fetch", optional = true}
|
||||
nu_plugin_from_bson = {version = "0.24.1", path = "./crates/nu_plugin_from_bson", optional = true}
|
||||
nu_plugin_from_sqlite = {version = "0.24.1", path = "./crates/nu_plugin_from_sqlite", optional = true}
|
||||
nu_plugin_inc = {version = "0.24.1", path = "./crates/nu_plugin_inc", optional = true}
|
||||
nu_plugin_match = {version = "0.24.1", path = "./crates/nu_plugin_match", optional = true}
|
||||
nu_plugin_post = {version = "0.24.1", path = "./crates/nu_plugin_post", optional = true}
|
||||
nu_plugin_ps = {version = "0.24.1", path = "./crates/nu_plugin_ps", optional = true}
|
||||
nu_plugin_s3 = {version = "0.24.1", path = "./crates/nu_plugin_s3", optional = true}
|
||||
nu_plugin_start = {version = "0.24.1", path = "./crates/nu_plugin_start", optional = true}
|
||||
nu_plugin_sys = {version = "0.24.1", path = "./crates/nu_plugin_sys", optional = true}
|
||||
nu_plugin_textview = {version = "0.24.1", path = "./crates/nu_plugin_textview", optional = true}
|
||||
nu_plugin_to_bson = {version = "0.24.1", path = "./crates/nu_plugin_to_bson", optional = true}
|
||||
nu_plugin_to_sqlite = {version = "0.24.1", path = "./crates/nu_plugin_to_sqlite", optional = true}
|
||||
nu_plugin_tree = {version = "0.24.1", path = "./crates/nu_plugin_tree", optional = true}
|
||||
nu_plugin_xpath = {version = "0.24.1", path = "./crates/nu_plugin_xpath", optional = true}
|
||||
nu_plugin_selector = {version = "0.24.1", path = "./crates/nu_plugin_selector", optional = true}
|
||||
|
||||
# Required to bootstrap the main binary
|
||||
clap = "2.33.3"
|
||||
@ -56,7 +56,7 @@ itertools = "0.9.0"
|
||||
|
||||
[dev-dependencies]
|
||||
dunce = "1.0.1"
|
||||
nu-test-support = {version = "0.23.0", path = "./crates/nu-test-support"}
|
||||
nu-test-support = {version = "0.24.1", path = "./crates/nu-test-support"}
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
|
@ -4,33 +4,36 @@ description = "CLI for nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-cli"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-data = {version = "0.23.0", path = "../nu-data"}
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-json = {version = "0.23.0", path = "../nu-json"}
|
||||
nu-parser = {version = "0.23.0", path = "../nu-parser"}
|
||||
nu-plugin = {version = "0.23.0", path = "../nu-plugin"}
|
||||
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.23.0", path = "../nu-source"}
|
||||
nu-table = {version = "0.23.0", path = "../nu-table"}
|
||||
nu-test-support = {version = "0.23.0", path = "../nu-test-support"}
|
||||
nu-value-ext = {version = "0.23.0", path = "../nu-value-ext"}
|
||||
nu-data = {version = "0.24.1", path = "../nu-data"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-json = {version = "0.24.1", path = "../nu-json"}
|
||||
nu-parser = {version = "0.24.1", path = "../nu-parser"}
|
||||
nu-plugin = {version = "0.24.1", path = "../nu-plugin"}
|
||||
nu-protocol = {version = "0.24.1", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.24.1", path = "../nu-source"}
|
||||
nu-table = {version = "0.24.1", path = "../nu-table"}
|
||||
nu-test-support = {version = "0.24.1", path = "../nu-test-support"}
|
||||
nu-value-ext = {version = "0.24.1", path = "../nu-value-ext"}
|
||||
|
||||
ansi_term = "0.12.1"
|
||||
async-recursion = "0.3.1"
|
||||
async-trait = "0.1.40"
|
||||
base64 = "0.12.3"
|
||||
base64 = "0.13.0"
|
||||
bigdecimal = {version = "0.2.0", features = ["serde"]}
|
||||
byte-unit = "4.0.9"
|
||||
bytes = "0.5.6"
|
||||
calamine = "0.16.1"
|
||||
chrono = {version = "0.4.15", features = ["serde"]}
|
||||
chrono-tz = "0.5.3"
|
||||
clap = "2.33.3"
|
||||
clipboard = {version = "0.5.0", optional = true}
|
||||
codespan-reporting = "0.9.5"
|
||||
csv = "1.1.3"
|
||||
ctrlc = {version = "3.1.6", optional = true}
|
||||
@ -40,20 +43,23 @@ dirs = {version = "3.0.1", optional = true}
|
||||
dtparse = "1.2.0"
|
||||
dunce = "1.0.1"
|
||||
eml-parser = "0.1.0"
|
||||
encoding_rs = "0.8.24"
|
||||
filesize = "0.2.0"
|
||||
fs_extra = "1.2.0"
|
||||
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
|
||||
futures-util = "0.3.5"
|
||||
futures_codec = "0.4.1"
|
||||
futures-util = "0.3.5"
|
||||
getset = "0.1.1"
|
||||
git2 = {version = "0.13.11", default_features = false, optional = true}
|
||||
glob = "0.3.0"
|
||||
heim = {version = "0.1.0-beta.3", optional = true}
|
||||
heim = {version = "0.1.0-rc.1", optional = true}
|
||||
htmlescape = "0.3.1"
|
||||
ical = "0.6.0"
|
||||
ichwh = {version = "0.3.4", optional = true}
|
||||
indexmap = {version = "1.6.0", features = ["serde-1"]}
|
||||
Inflector = "0.11"
|
||||
itertools = "0.9.0"
|
||||
lazy_static = "1.*"
|
||||
log = "0.4.11"
|
||||
meval = "0.2.0"
|
||||
num-bigint = {version = "0.3.0", features = ["serde"]}
|
||||
@ -66,6 +72,7 @@ ptree = {version = "0.3.0", optional = true}
|
||||
query_interface = "0.3.5"
|
||||
quick-xml = "0.18.1"
|
||||
rand = "0.7.3"
|
||||
rayon = "1.4.0"
|
||||
regex = "1.3.9"
|
||||
roxmltree = "0.13.0"
|
||||
rust-embed = "5.6.0"
|
||||
@ -85,20 +92,15 @@ tempfile = "3.1.0"
|
||||
term = {version = "0.6.1", optional = true}
|
||||
term_size = "0.3.2"
|
||||
termcolor = "1.1.0"
|
||||
titlecase = "1.0"
|
||||
toml = "0.5.6"
|
||||
trash = {version = "1.2.0", optional = true}
|
||||
unicode-segmentation = "1.6.0"
|
||||
uom = {version = "0.28.0", features = ["f64", "try-from"]}
|
||||
uom = {version = "0.30.0", features = ["f64", "try-from"]}
|
||||
url = "2.1.1"
|
||||
uuid_crate = {package = "uuid", version = "0.8.1", features = ["v4"], optional = true}
|
||||
which = {version = "4.0.2", optional = true}
|
||||
zip = {version = "0.5.7", optional = true}
|
||||
lazy_static = "1.*"
|
||||
|
||||
Inflector = "0.11"
|
||||
clipboard = {version = "0.5.0", optional = true}
|
||||
encoding_rs = "0.8.24"
|
||||
rayon = "1.4.0"
|
||||
trash = {version = "1.2.0", optional = true}
|
||||
url = "2.1.1"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
umask = "1.0.0"
|
||||
@ -113,10 +115,10 @@ users = "0.10.0"
|
||||
[dependencies.rusqlite]
|
||||
features = ["bundled", "blob"]
|
||||
optional = true
|
||||
version = "0.24.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[build-dependencies]
|
||||
git2 = {version = "0.13.11", optional = true}
|
||||
shadow-rs = "0.3.20"
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.9.2"
|
||||
|
@ -1,36 +1,6 @@
|
||||
use std::path::Path;
|
||||
use std::{env, fs, io};
|
||||
|
||||
fn main() -> Result<(), io::Error> {
|
||||
let out_dir = env::var_os("OUT_DIR").expect(
|
||||
"\
|
||||
OUT_DIR environment variable not found. \
|
||||
OUT_DIR is guaranteed to exist in a build script by cargo - see \
|
||||
https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts\
|
||||
");
|
||||
|
||||
let latest_commit_hash = latest_commit_hash(env::current_dir()?).unwrap_or_default();
|
||||
|
||||
let commit_hash_path = Path::new(&out_dir).join("git_commit_hash");
|
||||
fs::write(commit_hash_path, latest_commit_hash)?;
|
||||
|
||||
fn main() -> shadow_rs::SdResult<()> {
|
||||
let src_path = std::env::var("CARGO_MANIFEST_DIR")?;
|
||||
let out_path = std::env::var("OUT_DIR")?;
|
||||
shadow_rs::Shadow::build(src_path, out_path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn latest_commit_hash<P: AsRef<Path>>(dir: P) -> Result<String, Box<dyn std::error::Error>> {
|
||||
#[cfg(feature = "git2")]
|
||||
{
|
||||
use git2::Repository;
|
||||
let dir = dir.as_ref();
|
||||
Ok(Repository::discover(dir)?
|
||||
.head()?
|
||||
.peel_to_commit()?
|
||||
.id()
|
||||
.to_string())
|
||||
}
|
||||
#[cfg(not(feature = "git2"))]
|
||||
{
|
||||
Ok(String::new())
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,10 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||
whole_stream_command(Touch),
|
||||
whole_stream_command(Cpy),
|
||||
whole_stream_command(Date),
|
||||
whole_stream_command(DateListTimeZone),
|
||||
whole_stream_command(DateNow),
|
||||
whole_stream_command(DateUTC),
|
||||
whole_stream_command(DateToTable),
|
||||
whole_stream_command(DateToTimeZone),
|
||||
whole_stream_command(DateFormat),
|
||||
whole_stream_command(Cal),
|
||||
whole_stream_command(Mkdir),
|
||||
@ -120,6 +122,8 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||
whole_stream_command(Autoview),
|
||||
whole_stream_command(Table),
|
||||
// Text manipulation
|
||||
whole_stream_command(Hash),
|
||||
whole_stream_command(HashBase64),
|
||||
whole_stream_command(Split),
|
||||
whole_stream_command(SplitColumn),
|
||||
whole_stream_command(SplitRow),
|
||||
@ -213,6 +217,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||
whole_stream_command(AutoenvTrust),
|
||||
whole_stream_command(AutoenvUnTrust),
|
||||
whole_stream_command(Math),
|
||||
whole_stream_command(MathAbs),
|
||||
whole_stream_command(MathAverage),
|
||||
whole_stream_command(MathEval),
|
||||
whole_stream_command(MathMedian),
|
||||
@ -264,6 +269,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||
whole_stream_command(RandomUUID),
|
||||
whole_stream_command(RandomInteger),
|
||||
whole_stream_command(RandomDecimal),
|
||||
whole_stream_command(RandomChars),
|
||||
// Path
|
||||
whole_stream_command(PathBasename),
|
||||
whole_stream_command(PathCommand),
|
||||
|
@ -62,6 +62,7 @@ pub(crate) mod from_yaml;
|
||||
pub(crate) mod get;
|
||||
pub(crate) mod group_by;
|
||||
pub(crate) mod group_by_date;
|
||||
pub(crate) mod hash_;
|
||||
pub(crate) mod headers;
|
||||
pub(crate) mod help;
|
||||
pub(crate) mod histogram;
|
||||
@ -153,7 +154,7 @@ pub(crate) use config::{
|
||||
};
|
||||
pub(crate) use count::Count;
|
||||
pub(crate) use cp::Cpy;
|
||||
pub(crate) use date::{Date, DateFormat, DateNow, DateUTC};
|
||||
pub(crate) use date::{Date, DateFormat, DateListTimeZone, DateNow, DateToTable, DateToTimeZone};
|
||||
pub(crate) use debug::Debug;
|
||||
pub(crate) use default::Default;
|
||||
pub(crate) use describe::Describe;
|
||||
@ -199,6 +200,7 @@ pub(crate) use from_yaml::FromYML;
|
||||
pub(crate) use get::Get;
|
||||
pub(crate) use group_by::Command as GroupBy;
|
||||
pub(crate) use group_by_date::GroupByDate;
|
||||
pub(crate) use hash_::{Hash, HashBase64};
|
||||
pub(crate) use headers::Headers;
|
||||
pub(crate) use help::Help;
|
||||
pub(crate) use histogram::Histogram;
|
||||
@ -210,8 +212,8 @@ pub(crate) use last::Last;
|
||||
pub(crate) use lines::Lines;
|
||||
pub(crate) use ls::Ls;
|
||||
pub(crate) use math::{
|
||||
Math, MathAverage, MathCeil, MathEval, MathFloor, MathMaximum, MathMedian, MathMinimum,
|
||||
MathMode, MathProduct, MathRound, MathStddev, MathSummation, MathVariance,
|
||||
Math, MathAbs, MathAverage, MathCeil, MathEval, MathFloor, MathMaximum, MathMedian,
|
||||
MathMinimum, MathMode, MathProduct, MathRound, MathStddev, MathSummation, MathVariance,
|
||||
};
|
||||
pub(crate) use merge::Merge;
|
||||
pub(crate) use mkdir::Mkdir;
|
||||
@ -230,7 +232,9 @@ pub(crate) use prev::Previous;
|
||||
pub(crate) use pwd::Pwd;
|
||||
#[cfg(feature = "uuid_crate")]
|
||||
pub(crate) use random::RandomUUID;
|
||||
pub(crate) use random::{Random, RandomBool, RandomDecimal, RandomDice, RandomInteger};
|
||||
pub(crate) use random::{
|
||||
Random, RandomBool, RandomChars, RandomDecimal, RandomDice, RandomInteger,
|
||||
};
|
||||
pub(crate) use range::Range;
|
||||
pub(crate) use reduce::Reduce;
|
||||
pub(crate) use reject::Reject;
|
||||
|
@ -9,7 +9,7 @@ use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
|
||||
use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub(crate) async fn run_block(
|
||||
pub async fn run_block(
|
||||
block: &Block,
|
||||
ctx: &mut EvaluationContext,
|
||||
mut input: InputStream,
|
||||
|
@ -1,18 +1,18 @@
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, Local};
|
||||
use nu_errors::ShellError;
|
||||
|
||||
use crate::commands::date::utils::{date_to_value, date_to_value_raw};
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
Dictionary, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::Tagged;
|
||||
use std::fmt::{self, write};
|
||||
|
||||
pub struct Date;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct FormatArgs {
|
||||
format: Tagged<String>,
|
||||
raw: Option<bool>,
|
||||
table: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -24,11 +24,11 @@ impl WholeStreamCommand for Date {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date format")
|
||||
.required("format", SyntaxShape::String, "strftime format")
|
||||
.switch("raw", "print date without tables", Some('r'))
|
||||
.switch("table", "print date in a table", Some('t'))
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"format the current date using the given format string."
|
||||
"Format a given date using the given format string."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
@ -38,6 +38,21 @@ impl WholeStreamCommand for Date {
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
format(args, registry).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Format the current date",
|
||||
example: "date now | date format '%Y.%m.%d_%H %M %S,%z'",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Format the current date and print in a table",
|
||||
example: "date now | date format -t '%Y-%m-%d_%H:%M:%S %z'",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn format(
|
||||
@ -46,20 +61,46 @@ pub async fn format(
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let (FormatArgs { format, raw }, _) = args.process(®istry).await?;
|
||||
let (FormatArgs { format, table }, input) = args.process(®istry).await?;
|
||||
|
||||
let dt_fmt = format.to_string();
|
||||
Ok(input
|
||||
.map(move |value| match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Date(dt)),
|
||||
..
|
||||
} => {
|
||||
let mut output = String::new();
|
||||
if let Err(fmt::Error) =
|
||||
write(&mut output, format_args!("{}", dt.format(&format.item)))
|
||||
{
|
||||
Err(ShellError::labeled_error(
|
||||
"The date format is invalid",
|
||||
"invalid strftime format",
|
||||
&format.tag,
|
||||
))
|
||||
} else {
|
||||
let value = if table {
|
||||
let mut indexmap = IndexMap::new();
|
||||
indexmap.insert(
|
||||
"formatted".to_string(),
|
||||
UntaggedValue::string(&output).into_value(&tag),
|
||||
);
|
||||
|
||||
let value = {
|
||||
let local: DateTime<Local> = Local::now();
|
||||
if let Some(true) = raw {
|
||||
UntaggedValue::string(date_to_value_raw(local, dt_fmt)).into_untagged_value()
|
||||
} else {
|
||||
date_to_value(local, tag, dt_fmt)
|
||||
}
|
||||
};
|
||||
UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)
|
||||
} else {
|
||||
UntaggedValue::string(&output).into_value(&tag)
|
||||
};
|
||||
|
||||
Ok(OutputStream::one(value))
|
||||
ReturnSuccess::value(value)
|
||||
}
|
||||
}
|
||||
_ => Err(ShellError::labeled_error(
|
||||
"Expected a date from pipeline",
|
||||
"requires date input",
|
||||
&tag,
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
82
crates/nu-cli/src/commands/date/list_timezone.rs
Normal file
82
crates/nu-cli/src/commands/date/list_timezone.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use chrono_tz::TZ_VARIANTS;
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, ReturnSuccess, Signature, UntaggedValue};
|
||||
|
||||
pub struct Date;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Date {
|
||||
fn name(&self) -> &str {
|
||||
"date list-timezone"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date list-timezone")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"List supported time zones."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
list_timezone(args, registry).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "List all supported time zones",
|
||||
example: "date list-timezone",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "List all supported European time zones",
|
||||
example: "date list-timezone | where timezone =~ Europe",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_timezone(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let args = args.evaluate_once(®istry).await?;
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
|
||||
let list = TZ_VARIANTS.iter().map(move |tz| {
|
||||
let mut entries = IndexMap::new();
|
||||
|
||||
entries.insert(
|
||||
"timezone".to_string(),
|
||||
UntaggedValue::string(tz.name()).into_value(&tag),
|
||||
);
|
||||
|
||||
Ok(ReturnSuccess::Value(
|
||||
UntaggedValue::Row(Dictionary { entries }).into_value(&tag),
|
||||
))
|
||||
});
|
||||
|
||||
Ok(futures::stream::iter(list).to_output_stream())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Date;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(Date {})?)
|
||||
}
|
||||
}
|
@ -1,11 +1,15 @@
|
||||
pub mod command;
|
||||
pub mod format;
|
||||
pub mod list_timezone;
|
||||
pub mod now;
|
||||
pub mod utc;
|
||||
pub mod to_table;
|
||||
pub mod to_timezone;
|
||||
|
||||
mod utils;
|
||||
mod parser;
|
||||
|
||||
pub use command::Command as Date;
|
||||
pub use format::Date as DateFormat;
|
||||
pub use list_timezone::Date as DateListTimeZone;
|
||||
pub use now::Date as DateNow;
|
||||
pub use utc::Date as DateUTC;
|
||||
pub use to_table::Date as DateToTable;
|
||||
pub use to_timezone::Date as DateToTimeZone;
|
||||
|
@ -1,10 +1,8 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, Local};
|
||||
use nu_errors::ShellError;
|
||||
|
||||
use crate::commands::date::utils::date_to_value;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use nu_protocol::Signature;
|
||||
use nu_protocol::{Signature, UntaggedValue};
|
||||
|
||||
pub struct Date;
|
||||
|
||||
@ -19,7 +17,7 @@ impl WholeStreamCommand for Date {
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"return the current date."
|
||||
"Get the current date."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
@ -35,16 +33,12 @@ pub async fn now(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let args = args.evaluate_once(®istry).await?;
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
|
||||
let no_fmt = "".to_string();
|
||||
let now: DateTime<Local> = Local::now();
|
||||
|
||||
let value = {
|
||||
let local: DateTime<Local> = Local::now();
|
||||
date_to_value(local, tag, no_fmt)
|
||||
};
|
||||
let value = UntaggedValue::date(now.with_timezone(now.offset())).into_value(&tag);
|
||||
|
||||
Ok(OutputStream::one(value))
|
||||
}
|
||||
|
107
crates/nu-cli/src/commands/date/parser.rs
Normal file
107
crates/nu-cli/src/commands/date/parser.rs
Normal file
@ -0,0 +1,107 @@
|
||||
// Modified from chrono::format::scan
|
||||
|
||||
use chrono::{DateTime, FixedOffset, Local, Offset, TimeZone};
|
||||
use chrono_tz::Tz;
|
||||
use titlecase::titlecase;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||
pub enum ParseErrorKind {
|
||||
/// Given field is out of permitted range.
|
||||
OutOfRange,
|
||||
|
||||
/// The input string has some invalid character sequence for given formatting items.
|
||||
Invalid,
|
||||
|
||||
/// The input string has been prematurely ended.
|
||||
TooShort,
|
||||
}
|
||||
|
||||
pub fn datetime_in_timezone(
|
||||
dt: &DateTime<FixedOffset>,
|
||||
s: &str,
|
||||
) -> Result<DateTime<FixedOffset>, ParseErrorKind> {
|
||||
match timezone_offset_internal(s, true, true) {
|
||||
Ok(offset) => match FixedOffset::east_opt(offset) {
|
||||
Some(offset) => Ok(dt.with_timezone(&offset)),
|
||||
None => Err(ParseErrorKind::OutOfRange),
|
||||
},
|
||||
Err(ParseErrorKind::Invalid) => {
|
||||
if s.to_lowercase() == "local" {
|
||||
Ok(dt.with_timezone(Local::now().offset()))
|
||||
} else {
|
||||
let tz: Tz = parse_timezone_internal(s)?;
|
||||
let offset = tz.offset_from_utc_datetime(&dt.naive_utc()).fix();
|
||||
Ok(dt.with_timezone(&offset))
|
||||
}
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_timezone_internal(s: &str) -> Result<Tz, ParseErrorKind> {
|
||||
if let Ok(tz) = s.parse() {
|
||||
Ok(tz)
|
||||
} else if let Ok(tz) = titlecase(s).parse() {
|
||||
Ok(tz)
|
||||
} else if let Ok(tz) = s.to_uppercase().parse() {
|
||||
Ok(tz)
|
||||
} else {
|
||||
Err(ParseErrorKind::Invalid)
|
||||
}
|
||||
}
|
||||
|
||||
fn timezone_offset_internal(
|
||||
mut s: &str,
|
||||
consume_colon: bool,
|
||||
allow_missing_minutes: bool,
|
||||
) -> Result<i32, ParseErrorKind> {
|
||||
fn digits(s: &str) -> Result<(u8, u8), ParseErrorKind> {
|
||||
let b = s.as_bytes();
|
||||
if b.len() < 2 {
|
||||
Err(ParseErrorKind::TooShort)
|
||||
} else {
|
||||
Ok((b[0], b[1]))
|
||||
}
|
||||
}
|
||||
let negative = match s.as_bytes().first() {
|
||||
Some(&b'+') => false,
|
||||
Some(&b'-') => true,
|
||||
Some(_) => return Err(ParseErrorKind::Invalid),
|
||||
None => return Err(ParseErrorKind::TooShort),
|
||||
};
|
||||
s = &s[1..];
|
||||
|
||||
// hours (00--99)
|
||||
let hours = match digits(s)? {
|
||||
(h1 @ b'0'..=b'9', h2 @ b'0'..=b'9') => i32::from((h1 - b'0') * 10 + (h2 - b'0')),
|
||||
_ => return Err(ParseErrorKind::Invalid),
|
||||
};
|
||||
s = &s[2..];
|
||||
|
||||
// colons (and possibly other separators)
|
||||
if consume_colon {
|
||||
s = s.trim_start_matches(|c: char| c == ':' || c.is_whitespace());
|
||||
}
|
||||
|
||||
// minutes (00--59)
|
||||
// if the next two items are digits then we have to add minutes
|
||||
let minutes = if let Ok(ds) = digits(s) {
|
||||
match ds {
|
||||
(m1 @ b'0'..=b'5', m2 @ b'0'..=b'9') => i32::from((m1 - b'0') * 10 + (m2 - b'0')),
|
||||
(b'6'..=b'9', b'0'..=b'9') => return Err(ParseErrorKind::OutOfRange),
|
||||
_ => return Err(ParseErrorKind::Invalid),
|
||||
}
|
||||
} else if allow_missing_minutes {
|
||||
0
|
||||
} else {
|
||||
return Err(ParseErrorKind::TooShort);
|
||||
};
|
||||
match s.len() {
|
||||
len if len >= 2 => &s[2..],
|
||||
len if len == 0 => s,
|
||||
_ => return Err(ParseErrorKind::TooShort),
|
||||
};
|
||||
|
||||
let seconds = hours * 3600 + minutes * 60;
|
||||
Ok(if negative { -seconds } else { seconds })
|
||||
}
|
113
crates/nu-cli/src/commands/date/to_table.rs
Normal file
113
crates/nu-cli/src/commands/date/to_table.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use chrono::{Datelike, Timelike};
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct Date;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Date {
|
||||
fn name(&self) -> &str {
|
||||
"date to-table"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date to-table")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Print the date in a structured table."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
to_table(args, registry).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Print the current date in a table",
|
||||
example: "date now | date to-table",
|
||||
result: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
async fn to_table(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let args = args.evaluate_once(®istry).await?;
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let input = args.input;
|
||||
|
||||
Ok(input
|
||||
.map(move |value| match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Date(dt)),
|
||||
..
|
||||
} => {
|
||||
let mut indexmap = IndexMap::new();
|
||||
|
||||
indexmap.insert(
|
||||
"year".to_string(),
|
||||
UntaggedValue::int(dt.year()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"month".to_string(),
|
||||
UntaggedValue::int(dt.month()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"day".to_string(),
|
||||
UntaggedValue::int(dt.day()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"hour".to_string(),
|
||||
UntaggedValue::int(dt.hour()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"minute".to_string(),
|
||||
UntaggedValue::int(dt.minute()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"second".to_string(),
|
||||
UntaggedValue::int(dt.second()).into_value(&tag),
|
||||
);
|
||||
|
||||
let tz = dt.offset();
|
||||
indexmap.insert(
|
||||
"timezone".to_string(),
|
||||
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
|
||||
);
|
||||
|
||||
let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag);
|
||||
|
||||
ReturnSuccess::value(value)
|
||||
}
|
||||
_ => Err(ShellError::labeled_error(
|
||||
"Expected a date from pipeline",
|
||||
"requires date input",
|
||||
&tag,
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Date;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(Date {})?)
|
||||
}
|
||||
}
|
118
crates/nu-cli/src/commands/date/to_timezone.rs
Normal file
118
crates/nu-cli/src/commands/date/to_timezone.rs
Normal file
@ -0,0 +1,118 @@
|
||||
use crate::commands::date::parser::{datetime_in_timezone, ParseErrorKind};
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct Date;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DateToTimeZoneArgs {
|
||||
timezone: Tagged<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Date {
|
||||
fn name(&self) -> &str {
|
||||
"date to-timezone"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date to-timezone").required(
|
||||
"time zone",
|
||||
SyntaxShape::String,
|
||||
"time zone description",
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Convert a date to a given time zone.
|
||||
|
||||
Use `date list-timezone` to list all supported time zones.
|
||||
"
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
to_timezone(args, registry).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Get the current date in UTC+05:00",
|
||||
example: "date now | date to-timezone +0500",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Get the current local date",
|
||||
example: "date now | date to-timezone local",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Get the current date in Hawaii",
|
||||
example: "date now | date to-timezone US/Hawaii",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
async fn to_timezone(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let (DateToTimeZoneArgs { timezone }, input) = args.process(®istry).await?;
|
||||
|
||||
Ok(input
|
||||
.map(move |value| match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Date(dt)),
|
||||
..
|
||||
} => match datetime_in_timezone(&dt, &timezone.item) {
|
||||
Ok(dt) => {
|
||||
let value = UntaggedValue::date(dt).into_value(&tag);
|
||||
|
||||
ReturnSuccess::value(value)
|
||||
}
|
||||
Err(e) => Err(ShellError::labeled_error(
|
||||
error_message(e),
|
||||
"invalid time zone",
|
||||
&timezone.tag,
|
||||
)),
|
||||
},
|
||||
_ => Err(ShellError::labeled_error(
|
||||
"Expected a date from pipeline",
|
||||
"requires date input",
|
||||
&tag,
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
||||
fn error_message(err: ParseErrorKind) -> &'static str {
|
||||
match err {
|
||||
ParseErrorKind::Invalid => "The time zone description is invalid",
|
||||
ParseErrorKind::OutOfRange => "The time zone offset is out of range",
|
||||
ParseErrorKind::TooShort => "The format of the time zone is invalid",
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Date;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(Date {})?)
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, Utc};
|
||||
use nu_errors::ShellError;
|
||||
|
||||
use crate::commands::date::utils::date_to_value;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use nu_protocol::Signature;
|
||||
|
||||
pub struct Date;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Date {
|
||||
fn name(&self) -> &str {
|
||||
"date utc"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("date utc")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"return the current date in utc."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
utc(args, registry).await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn utc(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let args = args.evaluate_once(®istry).await?;
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
|
||||
let no_fmt = "".to_string();
|
||||
|
||||
let value = {
|
||||
let local: DateTime<Utc> = Utc::now();
|
||||
date_to_value(local, tag, no_fmt)
|
||||
};
|
||||
|
||||
Ok(OutputStream::one(value))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Date;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(Date {})?)
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
use crate::prelude::*;
|
||||
use chrono::DateTime;
|
||||
use nu_protocol::{Dictionary, Value};
|
||||
|
||||
use chrono::{Datelike, TimeZone, Timelike};
|
||||
use core::fmt::Display;
|
||||
use indexmap::IndexMap;
|
||||
use nu_protocol::UntaggedValue;
|
||||
|
||||
pub fn date_to_value_raw<T: TimeZone>(dt: DateTime<T>, dt_format: String) -> String
|
||||
where
|
||||
T::Offset: Display,
|
||||
{
|
||||
let result = dt.format(&dt_format);
|
||||
format!("{}", result)
|
||||
}
|
||||
|
||||
pub fn date_to_value<T: TimeZone>(dt: DateTime<T>, tag: Tag, dt_format: String) -> Value
|
||||
where
|
||||
T::Offset: Display,
|
||||
{
|
||||
let mut indexmap = IndexMap::new();
|
||||
|
||||
if dt_format.is_empty() {
|
||||
indexmap.insert(
|
||||
"year".to_string(),
|
||||
UntaggedValue::int(dt.year()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"month".to_string(),
|
||||
UntaggedValue::int(dt.month()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"day".to_string(),
|
||||
UntaggedValue::int(dt.day()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"hour".to_string(),
|
||||
UntaggedValue::int(dt.hour()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"minute".to_string(),
|
||||
UntaggedValue::int(dt.minute()).into_value(&tag),
|
||||
);
|
||||
indexmap.insert(
|
||||
"second".to_string(),
|
||||
UntaggedValue::int(dt.second()).into_value(&tag),
|
||||
);
|
||||
|
||||
let tz = dt.offset();
|
||||
indexmap.insert(
|
||||
"timezone".to_string(),
|
||||
UntaggedValue::string(format!("{}", tz)).into_value(&tag),
|
||||
);
|
||||
} else {
|
||||
let result = dt.format(&dt_format);
|
||||
indexmap.insert(
|
||||
"formatted".to_string(),
|
||||
UntaggedValue::string(format!("{}", result)).into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag)
|
||||
}
|
@ -54,6 +54,7 @@ pub async fn from_delimited_data(
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let name_tag = name;
|
||||
let concat_string = input.collect_string(name_tag.clone()).await?;
|
||||
let sample_lines = concat_string.item.lines().take(3).collect_vec().join("\n");
|
||||
|
||||
match from_delimited_string_to_value(concat_string.item, headerless, sep, name_tag.clone()) {
|
||||
Ok(x) => match x {
|
||||
@ -65,10 +66,16 @@ pub async fn from_delimited_data(
|
||||
},
|
||||
Err(err) => {
|
||||
let line_one = match pretty_csv_error(err) {
|
||||
Some(pretty) => format!("Could not parse as {} ({})", format_name, pretty),
|
||||
None => format!("Could not parse as {}", format_name),
|
||||
Some(pretty) => format!(
|
||||
"Could not parse as {} split by '{}' ({})",
|
||||
format_name, sep, pretty
|
||||
),
|
||||
None => format!("Could not parse as {} split by '{}'", format_name, sep),
|
||||
};
|
||||
let line_two = format!("input cannot be parsed as {}", format_name);
|
||||
let line_two = format!(
|
||||
"input cannot be parsed as {} split by '{}'. Input's first lines:\n{}",
|
||||
format_name, sep, sample_lines
|
||||
);
|
||||
|
||||
Err(ShellError::labeled_error_with_secondary(
|
||||
line_one,
|
||||
|
314
crates/nu-cli/src/commands/hash_/base64_.rs
Normal file
314
crates/nu-cli/src/commands/hash_/base64_.rs
Normal file
@ -0,0 +1,314 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::ShellTypeName;
|
||||
use nu_protocol::{
|
||||
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
use nu_source::{Tag, Tagged};
|
||||
|
||||
use base64::{decode_config, encode_config};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Arguments {
|
||||
pub rest: Vec<ColumnPath>,
|
||||
pub character_set: Option<Tagged<String>>,
|
||||
pub encode: Tagged<bool>,
|
||||
pub decode: Tagged<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Base64Config {
|
||||
pub character_set: String,
|
||||
pub action_type: ActionType,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum ActionType {
|
||||
Encode,
|
||||
Decode,
|
||||
}
|
||||
pub struct SubCommand;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"hash base64"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("hash base64")
|
||||
.named(
|
||||
"character_set",
|
||||
SyntaxShape::String,
|
||||
"specify the character rules for encoding the input.\n\
|
||||
\tValid values are 'standard', 'standard-no-padding', 'url-safe', 'url-safe-no-padding',\
|
||||
'binhex', 'bcrypt', 'crypt'",
|
||||
Some('c'),
|
||||
)
|
||||
.switch(
|
||||
"encode",
|
||||
"encode the input as base64. This is the default behavior if not specified.",
|
||||
Some('e')
|
||||
)
|
||||
.switch(
|
||||
"decode",
|
||||
"decode the input from base64",
|
||||
Some('d'))
|
||||
.rest(
|
||||
SyntaxShape::ColumnPath,
|
||||
"optionally base64 encode / decode data by column paths",
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"base64 encode or decode a value"
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
operate(args, registry).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Base64 encode a string with default settings",
|
||||
example: "echo 'username:password' | hash base64",
|
||||
result: Some(vec![
|
||||
UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ=").into_untagged_value()
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Base64 encode a string with the binhex character set",
|
||||
example: "echo 'username:password' | hash base64 --character_set binhex --encode",
|
||||
result: Some(vec![
|
||||
UntaggedValue::string("F@0NEPjJD97kE'&bEhFZEP3").into_untagged_value()
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Base64 decode a value",
|
||||
example: "echo 'dXNlcm5hbWU6cGFzc3dvcmQ=' | hash base64 --decode",
|
||||
result: Some(vec![
|
||||
UntaggedValue::string("username:password").into_untagged_value()
|
||||
]),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
async fn operate(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
|
||||
let name_tag = &args.call_info.name_tag.clone();
|
||||
|
||||
let (
|
||||
Arguments {
|
||||
encode,
|
||||
decode,
|
||||
character_set,
|
||||
rest,
|
||||
},
|
||||
input,
|
||||
) = args.process(®istry).await?;
|
||||
|
||||
if encode.item && decode.item {
|
||||
return Ok(OutputStream::one(Err(ShellError::labeled_error(
|
||||
"only one of --decode and --encode flags can be used",
|
||||
"conflicting flags",
|
||||
name_tag,
|
||||
))));
|
||||
}
|
||||
|
||||
// Default the action to be encoding if no flags are specified.
|
||||
let action_type = if *decode.item() {
|
||||
ActionType::Decode
|
||||
} else {
|
||||
ActionType::Encode
|
||||
};
|
||||
|
||||
// Default the character set to standard if the argument is not specified.
|
||||
let character_set = match character_set {
|
||||
Some(inner_tag) => inner_tag.item().to_string(),
|
||||
None => "standard".to_string(),
|
||||
};
|
||||
|
||||
let encoding_config = Base64Config {
|
||||
character_set,
|
||||
action_type,
|
||||
};
|
||||
|
||||
let column_paths: Vec<_> = rest;
|
||||
|
||||
Ok(input
|
||||
.map(move |v| {
|
||||
if column_paths.is_empty() {
|
||||
ReturnSuccess::value(action(&v, &encoding_config, v.tag())?)
|
||||
} else {
|
||||
let mut ret = v;
|
||||
|
||||
for path in &column_paths {
|
||||
let config = encoding_config.clone();
|
||||
ret = ret.swap_data_by_column_path(
|
||||
path,
|
||||
Box::new(move |old| action(old, &config, old.tag())),
|
||||
)?;
|
||||
}
|
||||
|
||||
ReturnSuccess::value(ret)
|
||||
}
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
||||
fn action(
|
||||
input: &Value,
|
||||
base64_config: &Base64Config,
|
||||
tag: impl Into<Tag>,
|
||||
) -> Result<Value, ShellError> {
|
||||
match &input.value {
|
||||
UntaggedValue::Primitive(Primitive::Line(s))
|
||||
| UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
let base64_config_enum: base64::Config = if &base64_config.character_set == "standard" {
|
||||
base64::STANDARD
|
||||
} else if &base64_config.character_set == "standard-no-padding" {
|
||||
base64::STANDARD_NO_PAD
|
||||
} else if &base64_config.character_set == "url-safe" {
|
||||
base64::URL_SAFE
|
||||
} else if &base64_config.character_set == "url-safe-no-padding" {
|
||||
base64::URL_SAFE_NO_PAD
|
||||
} else if &base64_config.character_set == "binhex" {
|
||||
base64::BINHEX
|
||||
} else if &base64_config.character_set == "bcrypt" {
|
||||
base64::BCRYPT
|
||||
} else if &base64_config.character_set == "crypt" {
|
||||
base64::CRYPT
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
"value is not an accepted character set",
|
||||
format!(
|
||||
"{} is not a valid character-set.\nPlease use `help hash base64` to see a list of valid character sets.",
|
||||
&base64_config.character_set
|
||||
),
|
||||
tag.into().span,
|
||||
));
|
||||
};
|
||||
|
||||
match base64_config.action_type {
|
||||
ActionType::Encode => Ok(UntaggedValue::string(encode_config(
|
||||
&s,
|
||||
base64_config_enum,
|
||||
))
|
||||
.into_value(tag)),
|
||||
ActionType::Decode => {
|
||||
let decode_result = decode_config(&s, base64_config_enum);
|
||||
|
||||
match decode_result {
|
||||
Ok(decoded_value) => Ok(UntaggedValue::string(
|
||||
std::string::String::from_utf8_lossy(&decoded_value),
|
||||
)
|
||||
.into_value(tag)),
|
||||
Err(_) => Err(ShellError::labeled_error(
|
||||
"value could not be base64 decoded",
|
||||
format!(
|
||||
"invalid base64 input for character set {}",
|
||||
&base64_config.character_set
|
||||
),
|
||||
tag.into().span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
other => {
|
||||
let got = format!("got {}", other.type_name());
|
||||
Err(ShellError::labeled_error(
|
||||
"value is not string",
|
||||
got,
|
||||
tag.into().span,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{action, ActionType, Base64Config};
|
||||
use nu_protocol::UntaggedValue;
|
||||
use nu_source::Tag;
|
||||
use nu_test_support::value::string;
|
||||
|
||||
#[test]
|
||||
fn base64_encode_standard() {
|
||||
let word = string("username:password");
|
||||
let expected = UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ=").into_untagged_value();
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
&Base64Config {
|
||||
character_set: "standard".to_string(),
|
||||
action_type: ActionType::Encode,
|
||||
},
|
||||
Tag::unknown(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_encode_standard_no_padding() {
|
||||
let word = string("username:password");
|
||||
let expected = UntaggedValue::string("dXNlcm5hbWU6cGFzc3dvcmQ").into_untagged_value();
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
&Base64Config {
|
||||
character_set: "standard-no-padding".to_string(),
|
||||
action_type: ActionType::Encode,
|
||||
},
|
||||
Tag::unknown(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_encode_url_safe() {
|
||||
let word = string("this is for url");
|
||||
let expected = UntaggedValue::string("dGhpcyBpcyBmb3IgdXJs").into_untagged_value();
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
&Base64Config {
|
||||
character_set: "url-safe".to_string(),
|
||||
action_type: ActionType::Encode,
|
||||
},
|
||||
Tag::unknown(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_decode_binhex() {
|
||||
let word = string("A5\"KC9jRB@IIF'8bF!");
|
||||
let expected = UntaggedValue::string("a binhex test").into_untagged_value();
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
&Base64Config {
|
||||
character_set: "binhex".to_string(),
|
||||
action_type: ActionType::Decode,
|
||||
},
|
||||
Tag::unknown(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
50
crates/nu-cli/src/commands/hash_/command.rs
Normal file
50
crates/nu-cli/src/commands/hash_/command.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
|
||||
pub struct Command;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Command {
|
||||
fn name(&self) -> &str {
|
||||
"hash"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("hash").rest(
|
||||
SyntaxShape::ColumnPath,
|
||||
"optionally convert by column paths",
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Apply hash function."
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
_args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
|
||||
Ok(OutputStream::one(ReturnSuccess::value(
|
||||
UntaggedValue::string(crate::commands::help::get_help(&Command, ®istry))
|
||||
.into_value(Tag::unknown()),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Command;
|
||||
use super::ShellError;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(Command {})?)
|
||||
}
|
||||
}
|
5
crates/nu-cli/src/commands/hash_/mod.rs
Normal file
5
crates/nu-cli/src/commands/hash_/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod base64_;
|
||||
mod command;
|
||||
|
||||
pub use base64_::SubCommand as HashBase64;
|
||||
pub use command::Command as Hash;
|
73
crates/nu-cli/src/commands/math/abs.rs
Normal file
73
crates/nu-cli/src/commands/math/abs.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, UntaggedValue, Value};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"math abs"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("math abs")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Returns absolute values of a list of numbers"
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
_: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let mapped = args.input.map(move |val| match val.value {
|
||||
UntaggedValue::Primitive(Primitive::Int(val)) => {
|
||||
UntaggedValue::int(val.magnitude().clone()).into()
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Decimal(val)) => {
|
||||
UntaggedValue::decimal(val.abs()).into()
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Duration(val)) => {
|
||||
UntaggedValue::duration(val.magnitude().clone()).into()
|
||||
}
|
||||
other => abs_default(other),
|
||||
});
|
||||
Ok(OutputStream::from_input(mapped))
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Get absolute of each value in a list of numbers",
|
||||
example: "echo [-50 -100.0 25] | math abs",
|
||||
result: Some(vec![
|
||||
UntaggedValue::int(50).into(),
|
||||
UntaggedValue::decimal_from_float(100.0, Span::default()).into(),
|
||||
UntaggedValue::int(25).into(),
|
||||
]),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
fn abs_default(_: UntaggedValue) -> Value {
|
||||
UntaggedValue::Error(ShellError::unexpected(
|
||||
"Only numerical values are supported",
|
||||
))
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ShellError;
|
||||
use super::SubCommand;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(SubCommand {})?)
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod abs;
|
||||
pub mod avg;
|
||||
pub mod ceil;
|
||||
pub mod command;
|
||||
@ -16,6 +17,7 @@ pub mod variance;
|
||||
mod reducers;
|
||||
mod utils;
|
||||
|
||||
pub use abs::SubCommand as MathAbs;
|
||||
pub use avg::SubCommand as MathAverage;
|
||||
pub use ceil::SubCommand as MathCeil;
|
||||
pub use command::Command as Math;
|
||||
|
89
crates/nu-cli/src/commands/random/chars.rs
Normal file
89
crates/nu-cli/src/commands/random/chars.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_source::Tagged;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::prelude::{thread_rng, Rng};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CharsArgs {
|
||||
length: Option<Tagged<u32>>,
|
||||
}
|
||||
|
||||
const DEFAULT_CHARS_LENGTH: u32 = 25;
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"random chars"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("random chars").named(
|
||||
"length",
|
||||
SyntaxShape::Int,
|
||||
"Number of chars",
|
||||
Some('l'),
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Generate random chars"
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
chars(args, registry).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Generate random chars",
|
||||
example: "random chars",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Generate random chars with specified length",
|
||||
example: "random chars -l 20",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn chars(
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let (CharsArgs { length }, _) = args.process(®istry).await?;
|
||||
|
||||
let chars_length = length.map_or(DEFAULT_CHARS_LENGTH, |l| l.item);
|
||||
|
||||
let random_string: String = thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(chars_length as usize)
|
||||
.collect();
|
||||
|
||||
let result = UntaggedValue::string(random_string);
|
||||
Ok(OutputStream::one(ReturnSuccess::value(result)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ShellError;
|
||||
use super::SubCommand;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
Ok(test_examples(SubCommand {})?)
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
pub mod command;
|
||||
|
||||
pub mod bool;
|
||||
pub mod chars;
|
||||
pub mod decimal;
|
||||
pub mod dice;
|
||||
pub mod integer;
|
||||
@ -10,6 +11,7 @@ pub mod uuid;
|
||||
pub use command::Command as Random;
|
||||
|
||||
pub use self::bool::SubCommand as RandomBool;
|
||||
pub use chars::SubCommand as RandomChars;
|
||||
pub use decimal::SubCommand as RandomDecimal;
|
||||
pub use dice::SubCommand as RandomDice;
|
||||
pub use integer::SubCommand as RandomInteger;
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use indexmap::IndexMap;
|
||||
use nu_data::TaggedListBuilder;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Signature, UntaggedValue};
|
||||
|
||||
const GIT_COMMIT_HASH: &str = include_str!(concat!(env!("OUT_DIR"), "/git_commit_hash"));
|
||||
use nu_protocol::{value::StrExt, value::StringExt, Dictionary, Signature, UntaggedValue};
|
||||
|
||||
pub mod shadow {
|
||||
include!(concat!(env!("OUT_DIR"), "/shadow.rs"));
|
||||
}
|
||||
pub struct Version;
|
||||
|
||||
#[async_trait]
|
||||
@ -50,35 +50,277 @@ pub fn version(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputS
|
||||
UntaggedValue::string(clap::crate_version!()).into_value(&tag),
|
||||
);
|
||||
|
||||
let commit_hash = Some(GIT_COMMIT_HASH.trim()).filter(|x| !x.is_empty());
|
||||
if let Some(commit_hash) = commit_hash {
|
||||
let branch: Option<&str> = Some(shadow::BRANCH).filter(|x| !x.is_empty());
|
||||
if let Some(branch) = branch {
|
||||
indexmap.insert(
|
||||
"commit_hash".to_string(),
|
||||
UntaggedValue::string(commit_hash).into_value(&tag),
|
||||
"branch".to_string(),
|
||||
branch.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
indexmap.insert("features".to_string(), features_enabled(&tag).into_value());
|
||||
let short_commit: Option<&str> = Some(shadow::SHORT_COMMIT).filter(|x| !x.is_empty());
|
||||
if let Some(short_commit) = short_commit {
|
||||
indexmap.insert(
|
||||
"short_commit".to_string(),
|
||||
short_commit.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
let commit_hash: Option<&str> = Some(shadow::COMMIT_HASH).filter(|x| !x.is_empty());
|
||||
if let Some(commit_hash) = commit_hash {
|
||||
indexmap.insert(
|
||||
"commit_hash".to_string(),
|
||||
commit_hash.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
let commit_date: Option<&str> = Some(shadow::COMMIT_DATE).filter(|x| !x.is_empty());
|
||||
if let Some(commit_date) = commit_date {
|
||||
indexmap.insert(
|
||||
"commit_date".to_string(),
|
||||
commit_date.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
// let commit_author: Option<&str> = Some(shadow::COMMIT_AUTHOR).filter(|x| !x.is_empty());
|
||||
// if let Some(commit_author) = commit_author {
|
||||
// indexmap.insert(
|
||||
// "commit_author".to_string(),
|
||||
// commit_author.to_pattern_untagged_value().into_value(&tag),
|
||||
// );
|
||||
// }
|
||||
let _commit_autor = shadow::COMMIT_AUTHOR;
|
||||
|
||||
// let commit_email: Option<&str> = Some(shadow::COMMIT_EMAIL).filter(|x| !x.is_empty());
|
||||
// if let Some(commit_email) = commit_email {
|
||||
// indexmap.insert(
|
||||
// "commit_email".to_string(),
|
||||
// commit_email.to_pattern_untagged_value().into_value(&tag),
|
||||
// );
|
||||
// }
|
||||
let _commit_email = shadow::COMMIT_EMAIL;
|
||||
|
||||
let build_os: Option<&str> = Some(shadow::BUILD_OS).filter(|x| !x.is_empty());
|
||||
if let Some(build_os) = build_os {
|
||||
indexmap.insert(
|
||||
"build_os".to_string(),
|
||||
build_os.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
let rust_version: Option<&str> = Some(shadow::RUST_VERSION).filter(|x| !x.is_empty());
|
||||
if let Some(rust_version) = rust_version {
|
||||
indexmap.insert(
|
||||
"rust_version".to_string(),
|
||||
rust_version.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
let rust_channel: Option<&str> = Some(shadow::RUST_CHANNEL).filter(|x| !x.is_empty());
|
||||
if let Some(rust_channel) = rust_channel {
|
||||
indexmap.insert(
|
||||
"rust_channel".to_string(),
|
||||
rust_channel.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
let cargo_version: Option<&str> = Some(shadow::CARGO_VERSION).filter(|x| !x.is_empty());
|
||||
if let Some(cargo_version) = cargo_version {
|
||||
indexmap.insert(
|
||||
"cargo_version".to_string(),
|
||||
cargo_version.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
let pkg_version: Option<&str> = Some(shadow::PKG_VERSION).filter(|x| !x.is_empty());
|
||||
if let Some(pkg_version) = pkg_version {
|
||||
indexmap.insert(
|
||||
"pkg_version".to_string(),
|
||||
pkg_version.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
// let cargo_tree: Option<&str> = Some(shadow::CARGO_TREE).filter(|x| !x.is_empty());
|
||||
// if let Some(cargo_tree) = cargo_tree {
|
||||
// indexmap.insert(
|
||||
// "cargo_tree".to_string(),
|
||||
// cargo_tree.to_pattern_untagged_value().into_value(&tag),
|
||||
// );
|
||||
// }
|
||||
let _cargo_tree = shadow::CARGO_TREE;
|
||||
|
||||
// let project_name: Option<&str> = Some(shadow::PROJECT_NAME).filter(|x| !x.is_empty());
|
||||
// if let Some(project_name) = project_name {
|
||||
// indexmap.insert(
|
||||
// "project_name".to_string(),
|
||||
// project_name.to_pattern_untagged_value().into_value(&tag),
|
||||
// );
|
||||
// }
|
||||
let _project_name = shadow::PROJECT_NAME;
|
||||
|
||||
let build_time: Option<&str> = Some(shadow::BUILD_TIME).filter(|x| !x.is_empty());
|
||||
if let Some(build_time) = build_time {
|
||||
indexmap.insert(
|
||||
"build_time".to_string(),
|
||||
build_time.to_pattern_untagged_value().into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
let build_rust_channel: Option<&str> =
|
||||
Some(shadow::BUILD_RUST_CHANNEL).filter(|x| !x.is_empty());
|
||||
if let Some(build_rust_channel) = build_rust_channel {
|
||||
indexmap.insert(
|
||||
"build_rust_channel".to_string(),
|
||||
build_rust_channel
|
||||
.to_pattern_untagged_value()
|
||||
.into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
indexmap.insert(
|
||||
"features".to_string(),
|
||||
features_enabled().join(", ").to_string_value_create_tag(),
|
||||
);
|
||||
|
||||
let value = UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag);
|
||||
Ok(OutputStream::one(value))
|
||||
}
|
||||
|
||||
fn features_enabled(tag: impl Into<Tag>) -> TaggedListBuilder {
|
||||
let mut names = TaggedListBuilder::new(tag);
|
||||
fn features_enabled() -> Vec<String> {
|
||||
let mut names = vec![];
|
||||
|
||||
names.push_untagged(UntaggedValue::string("default"));
|
||||
names.push("default".to_string());
|
||||
|
||||
#[cfg(feature = "ctrlc")]
|
||||
{
|
||||
names.push("ctrlc".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "dirs")]
|
||||
{
|
||||
names.push("dirs".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "directories")]
|
||||
{
|
||||
names.push("directories".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "git2")]
|
||||
{
|
||||
names.push("git".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "ptree")]
|
||||
{
|
||||
names.push("ptree".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "rich-benchmark")]
|
||||
{
|
||||
names.push("rich-benchmark".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustyline-support")]
|
||||
{
|
||||
names.push("rustyline".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "term")]
|
||||
{
|
||||
names.push("term".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "uuid_crate")]
|
||||
{
|
||||
names.push("uuid".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "which")]
|
||||
{
|
||||
names.push("which".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "ichwh")]
|
||||
{
|
||||
names.push("ichwh".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "zip")]
|
||||
{
|
||||
names.push("zip".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "clipboard-cli")]
|
||||
{
|
||||
names.push_untagged(UntaggedValue::string("clipboard"));
|
||||
names.push("clipboard-cli".to_string());
|
||||
}
|
||||
|
||||
#[cfg(feature = "trash-support")]
|
||||
{
|
||||
names.push_untagged(UntaggedValue::string("trash"));
|
||||
names.push("trash".to_string());
|
||||
}
|
||||
|
||||
// #[cfg(feature = "binaryview")]
|
||||
// {
|
||||
// names.push("binaryview".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "start")]
|
||||
// {
|
||||
// names.push("start".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "bson")]
|
||||
// {
|
||||
// names.push("bson".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "sqlite")]
|
||||
// {
|
||||
// names.push("sqlite".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "s3")]
|
||||
// {
|
||||
// names.push("s3".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "chart")]
|
||||
// {
|
||||
// names.push("chart".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "xpath")]
|
||||
// {
|
||||
// names.push("xpath".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "selector")]
|
||||
// {
|
||||
// names.push("selector".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "extra")]
|
||||
// {
|
||||
// names.push("extra".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "preserve_order")]
|
||||
// {
|
||||
// names.push("preserve_order".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "wee_alloc")]
|
||||
// {
|
||||
// names.push("wee_alloc".to_string());
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "console_error_panic_hook")]
|
||||
// {
|
||||
// names.push("console_error_panic_hook".to_string());
|
||||
// }
|
||||
|
||||
names.sort();
|
||||
|
||||
names
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ pub struct EvaluationContext {
|
||||
}
|
||||
|
||||
impl EvaluationContext {
|
||||
pub(crate) fn registry(&self) -> &CommandRegistry {
|
||||
pub fn registry(&self) -> &CommandRegistry {
|
||||
&self.registry
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ pub use crate::cli::{
|
||||
run_pipeline_standalone, run_vec_of_pipelines, LineResult,
|
||||
};
|
||||
pub use crate::command_registry::CommandRegistry;
|
||||
pub use crate::commands::classified::block::run_block;
|
||||
pub use crate::commands::command::{
|
||||
whole_stream_command, CommandArgs, EvaluatedWholeStreamCommandArgs, Example, WholeStreamCommand,
|
||||
};
|
||||
|
@ -765,60 +765,59 @@ impl VarSyntaxShapeDeductor {
|
||||
)],
|
||||
)?;
|
||||
}
|
||||
Operator::In | Operator::NotIn => {
|
||||
match var_side {
|
||||
BinarySide::Left => match &expr.expr {
|
||||
Expression::List(list) => {
|
||||
if !list.is_empty() {
|
||||
let shapes_in_list = self
|
||||
.get_shapes_in_list_or_insert_dependency(
|
||||
Operator::In | Operator::NotIn => match var_side {
|
||||
BinarySide::Left => match &expr.expr {
|
||||
Expression::List(list) => {
|
||||
if !list.is_empty() {
|
||||
let shapes_in_list = self.get_shapes_in_list_or_insert_dependency(
|
||||
var,
|
||||
bin_spanned,
|
||||
&list,
|
||||
(pipeline_idx, pipeline),
|
||||
registry,
|
||||
);
|
||||
match shapes_in_list {
|
||||
None => {}
|
||||
Some(shapes_in_list) => {
|
||||
self.checked_insert(
|
||||
var,
|
||||
bin_spanned,
|
||||
&list,
|
||||
(pipeline_idx, pipeline),
|
||||
registry,
|
||||
);
|
||||
match shapes_in_list {
|
||||
None => {}
|
||||
Some(shapes_in_list) => {
|
||||
self.checked_insert(
|
||||
var,
|
||||
VarShapeDeduction::from_usage_with_alternatives(
|
||||
&var.span,
|
||||
&shapes_in_list,
|
||||
),
|
||||
)?;
|
||||
}
|
||||
VarShapeDeduction::from_usage_with_alternatives(
|
||||
&var.span,
|
||||
&shapes_in_list,
|
||||
),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::Table(_, _)
|
||||
| Expression::Literal(_)
|
||||
| Expression::ExternalWord
|
||||
| Expression::Synthetic(_)
|
||||
| Expression::Variable(_, _)
|
||||
| Expression::Binary(_)
|
||||
| Expression::Range(_)
|
||||
| Expression::Block(_)
|
||||
| Expression::Path(_)
|
||||
| Expression::FilePath(_)
|
||||
| Expression::ExternalCommand(_)
|
||||
| Expression::Command
|
||||
| Expression::Invocation(_)
|
||||
| Expression::Boolean(_)
|
||||
| Expression::Garbage => {unreachable!("Parser should have rejected code. In only applicable with rhs of type List")}
|
||||
},
|
||||
BinarySide::Right => {
|
||||
self.checked_insert(
|
||||
var,
|
||||
VarShapeDeduction::from_usage_with_alternatives(
|
||||
&var.span,
|
||||
&[SyntaxShape::Table],
|
||||
),
|
||||
)?;
|
||||
}
|
||||
Expression::Table(_, _)
|
||||
| Expression::Literal(_)
|
||||
| Expression::ExternalWord
|
||||
| Expression::Synthetic(_)
|
||||
| Expression::Variable(_, _)
|
||||
| Expression::Binary(_)
|
||||
| Expression::Range(_)
|
||||
| Expression::Block(_)
|
||||
| Expression::Path(_)
|
||||
| Expression::FilePath(_)
|
||||
| Expression::ExternalCommand(_)
|
||||
| Expression::Command
|
||||
| Expression::Invocation(_)
|
||||
| Expression::Boolean(_)
|
||||
| Expression::Garbage => {
|
||||
unreachable!("Parser should have rejected code. In only applicable with rhs of type List")
|
||||
}
|
||||
},
|
||||
BinarySide::Right => {
|
||||
self.checked_insert(
|
||||
var,
|
||||
VarShapeDeduction::from_usage_with_alternatives(
|
||||
&var.span,
|
||||
&[SyntaxShape::Table],
|
||||
),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
},
|
||||
Operator::Modulo => {
|
||||
self.checked_insert(
|
||||
var,
|
||||
|
85
crates/nu-cli/tests/commands/hash_/mod.rs
Normal file
85
crates/nu-cli/tests/commands/hash_/mod.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn base64_defaults_to_encoding_with_standard_character_type() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo 'username:password' | hash base64
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "dXNlcm5hbWU6cGFzc3dvcmQ=");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_encode_characterset_binhex() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo 'username:password' | hash base64 --character_set binhex --encode
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "F@0NEPjJD97kE\'&bEhFZEP3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_when_invalid_character_set_given() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo 'username:password' | hash base64 --character_set 'this is invalid' --encode
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert!(actual
|
||||
.err
|
||||
.contains("this is invalid is not a valid character-set"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_decode_characterset_binhex() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo "F@0NEPjJD97kE'&bEhFZEP3" | hash base64 --character_set binhex --decode
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "username:password");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_invalid_decode_value() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo "this should not be a valid encoded value" | hash base64 --character_set url-safe --decode
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert!(actual
|
||||
.err
|
||||
.contains("invalid base64 input for character set url-safe"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_use_both_flags() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo 'username:password' | hash base64 --encode --decode
|
||||
"#
|
||||
)
|
||||
);
|
||||
|
||||
assert!(actual
|
||||
.err
|
||||
.contains("only one of --decode and --encode flags can be used"));
|
||||
}
|
@ -20,6 +20,7 @@ mod flatten;
|
||||
mod format;
|
||||
mod get;
|
||||
mod group_by;
|
||||
mod hash_;
|
||||
mod headers;
|
||||
mod histogram;
|
||||
mod insert;
|
||||
|
14
crates/nu-cli/tests/commands/random/chars.rs
Normal file
14
crates/nu-cli/tests/commands/random/chars.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn generates_chars_of_specified_length() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
random chars -l 15 | size | get chars
|
||||
"#
|
||||
));
|
||||
|
||||
let result = actual.out;
|
||||
assert_eq!(result, "15");
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
mod bool;
|
||||
mod chars;
|
||||
mod decimal;
|
||||
mod dice;
|
||||
mod integer;
|
||||
|
@ -4,7 +4,7 @@ description = "CLI for nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-data"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
@ -29,12 +29,12 @@ query_interface = "0.3.5"
|
||||
serde = {version = "1.0.115", features = ["derive"]}
|
||||
toml = "0.5.6"
|
||||
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.23.0", path = "../nu-source"}
|
||||
nu-table = {version = "0.23.0", path = "../nu-table"}
|
||||
nu-test-support = {version = "0.23.0", path = "../nu-test-support"}
|
||||
nu-value-ext = {version = "0.23.0", path = "../nu-value-ext"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-protocol = {version = "0.24.1", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.24.1", path = "../nu-source"}
|
||||
nu-table = {version = "0.24.1", path = "../nu-table"}
|
||||
nu-test-support = {version = "0.24.1", path = "../nu-test-support"}
|
||||
nu-value-ext = {version = "0.24.1", path = "../nu-value-ext"}
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
users = "0.10.0"
|
||||
|
@ -1,7 +1,7 @@
|
||||
pub(crate) mod shape;
|
||||
|
||||
use bigdecimal::BigDecimal;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use derive_new::new;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{
|
||||
@ -75,8 +75,8 @@ pub enum CompareValues {
|
||||
Ints(BigInt, BigInt),
|
||||
Decimals(BigDecimal, BigDecimal),
|
||||
String(String, String),
|
||||
Date(DateTime<Utc>, DateTime<Utc>),
|
||||
DateDuration(DateTime<Utc>, BigInt),
|
||||
Date(DateTime<FixedOffset>, DateTime<FixedOffset>),
|
||||
DateDuration(DateTime<FixedOffset>, BigInt),
|
||||
Booleans(bool, bool),
|
||||
}
|
||||
|
||||
@ -94,9 +94,10 @@ impl CompareValues {
|
||||
Span::unknown(),
|
||||
)
|
||||
.expect("Could not convert nushell Duration into chrono Duration.");
|
||||
let right: DateTime<Utc> = Utc::now()
|
||||
let right: DateTime<FixedOffset> = Utc::now()
|
||||
.checked_sub_signed(duration)
|
||||
.expect("Data overflow");
|
||||
.expect("Data overflow")
|
||||
.into();
|
||||
right.cmp(left)
|
||||
}
|
||||
CompareValues::Booleans(left, right) => left.cmp(right),
|
||||
|
@ -1,6 +1,6 @@
|
||||
// use crate::config::{Conf, NuConfig};
|
||||
use bigdecimal::BigDecimal;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use indexmap::map::IndexMap;
|
||||
use nu_protocol::RangeInclusion;
|
||||
use nu_protocol::{format_primitive, ColumnPath, Dictionary, Primitive, UntaggedValue, Value};
|
||||
@ -31,7 +31,7 @@ pub enum InlineShape {
|
||||
ColumnPath(ColumnPath),
|
||||
Pattern(String),
|
||||
Boolean(bool),
|
||||
Date(DateTime<Utc>),
|
||||
Date(DateTime<FixedOffset>),
|
||||
Duration(BigInt),
|
||||
Path(PathBuf),
|
||||
Binary(usize),
|
||||
|
@ -25,7 +25,7 @@ impl Date {
|
||||
|
||||
let date = date.with_timezone(&chrono::offset::Utc);
|
||||
|
||||
Ok(UntaggedValue::Primitive(Primitive::Date(date)))
|
||||
Ok(UntaggedValue::Primitive(Primitive::Date(date.into())))
|
||||
}
|
||||
|
||||
pub fn naive_from_str(s: Tagged<&str>) -> Result<UntaggedValue, ShellError> {
|
||||
@ -38,7 +38,7 @@ impl Date {
|
||||
})?;
|
||||
|
||||
Ok(UntaggedValue::Primitive(Primitive::Date(
|
||||
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc),
|
||||
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc).into(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ description = "Core error subsystem for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-errors"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
|
||||
ansi_term = "0.12.1"
|
||||
bigdecimal = {version = "0.2.0", features = ["serde"]}
|
||||
|
@ -4,7 +4,7 @@ description = "Fork of serde-hjson"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-json"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -4,7 +4,7 @@ description = "Nushell parser"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-parser"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -19,9 +19,9 @@ num-traits = "0.2.12"
|
||||
serde = "1.0.115"
|
||||
shellexpand = "2.0.0"
|
||||
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.23.0", path = "../nu-source"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-protocol = {version = "0.24.1", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.24.1", path = "../nu-source"}
|
||||
|
||||
[features]
|
||||
stable = []
|
||||
|
@ -4,17 +4,17 @@ description = "Nushell Plugin"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-plugin"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
|
||||
bigdecimal = {version = "0.2.0", features = ["serde"]}
|
||||
indexmap = {version = "1.6.0", features = ["serde-1"]}
|
||||
|
@ -4,7 +4,7 @@ description = "Core values and protocols for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-protocol"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
@ -17,8 +17,8 @@ derive-new = "0.5.8"
|
||||
getset = "0.1.1"
|
||||
indexmap = {version = "1.6.0", features = ["serde-1"]}
|
||||
log = "0.4.11"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
num-bigint = {version = "0.3.0", features = ["serde"]}
|
||||
num-integer = "0.1.43"
|
||||
num-traits = "0.2.12"
|
||||
|
@ -19,7 +19,7 @@ use crate::value::range::{Range, RangeInclusion};
|
||||
use crate::ColumnPath;
|
||||
use bigdecimal::BigDecimal;
|
||||
use bigdecimal::FromPrimitive;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_source::{AnchorLocation, HasSpan, Span, Spanned, SpannedItem, Tag};
|
||||
@ -242,16 +242,17 @@ impl UntaggedValue {
|
||||
}
|
||||
|
||||
/// Helper for creating date duration values
|
||||
pub fn duration(nanos: BigInt) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Duration(nanos))
|
||||
pub fn duration(nanos: impl Into<BigInt>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Duration(nanos.into()))
|
||||
}
|
||||
|
||||
/// Helper for creating datatime values
|
||||
pub fn system_date(s: SystemTime) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Date(s.into()))
|
||||
let utc: DateTime<Utc> = s.into();
|
||||
UntaggedValue::Primitive(Primitive::Date(utc.into()))
|
||||
}
|
||||
|
||||
pub fn date(d: impl Into<DateTime<Utc>>) -> UntaggedValue {
|
||||
pub fn date(d: impl Into<DateTime<FixedOffset>>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Date(d.into()))
|
||||
}
|
||||
|
||||
@ -924,7 +925,7 @@ pub trait DateTimeExt {
|
||||
fn to_value_create_tag(&self) -> Value;
|
||||
}
|
||||
|
||||
impl DateTimeExt for DateTime<Utc> {
|
||||
impl DateTimeExt for DateTime<FixedOffset> {
|
||||
fn to_value(&self, the_tag: Tag) -> Value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Date(*self)),
|
||||
|
@ -3,7 +3,7 @@ use crate::value::column_path::ColumnPath;
|
||||
use crate::value::range::{Range, RangeInclusion};
|
||||
use crate::value::{serde_bigdecimal, serde_bigint};
|
||||
use bigdecimal::BigDecimal;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use nu_errors::{ExpectedRange, ShellError};
|
||||
use nu_source::{PrettyDebug, Span, SpannedItem};
|
||||
use num_bigint::BigInt;
|
||||
@ -42,8 +42,8 @@ pub enum Primitive {
|
||||
Pattern(String),
|
||||
/// A boolean value
|
||||
Boolean(bool),
|
||||
/// A date value, in UTC
|
||||
Date(DateTime<Utc>),
|
||||
/// A date value
|
||||
Date(DateTime<FixedOffset>),
|
||||
/// A count in the number of nanoseconds
|
||||
#[serde(with = "serde_bigint")]
|
||||
Duration(BigInt),
|
||||
@ -385,8 +385,8 @@ pub fn format_duration(duration: &BigInt) -> String {
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
/// Format a UTC date value into a humanized string (eg "1 week ago" instead of a formal date string)
|
||||
pub fn format_date(d: &DateTime<Utc>) -> String {
|
||||
/// Format a date value into a humanized string (eg "1 week ago" instead of a formal date string)
|
||||
pub fn format_date(d: &DateTime<FixedOffset>) -> String {
|
||||
let utc: DateTime<Utc> = Utc::now();
|
||||
|
||||
let duration = utc.signed_duration_since(*d);
|
||||
|
@ -4,7 +4,7 @@ description = "A source string characterizer for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-source"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
@ -4,7 +4,7 @@ description = "Nushell table printing"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-table"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[[bin]]
|
||||
|
@ -4,16 +4,16 @@ description = "Support for writing Nushell tests"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-test-support"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-value-ext = {version = "0.23.0", path = "../nu-value-ext"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-value-ext = {version = "0.24.1", path = "../nu-value-ext"}
|
||||
|
||||
bigdecimal = {version = "0.2.0", features = ["serde"]}
|
||||
chrono = "0.4.15"
|
||||
|
@ -40,10 +40,9 @@ pub fn date(input: impl Into<String>) -> Value {
|
||||
let date = NaiveDate::parse_from_str(key.borrow_tagged().item, "%Y-%m-%d")
|
||||
.expect("date from string failed");
|
||||
|
||||
UntaggedValue::Primitive(Primitive::Date(DateTime::<Utc>::from_utc(
|
||||
date.and_hms(12, 34, 56),
|
||||
Utc,
|
||||
)))
|
||||
UntaggedValue::Primitive(Primitive::Date(
|
||||
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc).into(),
|
||||
))
|
||||
.into_untagged_value()
|
||||
}
|
||||
|
||||
|
@ -4,15 +4,15 @@ description = "Extension traits for values in Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu-value-ext"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
|
||||
indexmap = {version = "1.6.0", features = ["serde-1"]}
|
||||
itertools = "0.9.0"
|
||||
|
@ -4,7 +4,7 @@ description = "A binary viewer plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_binaryview"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
@ -14,10 +14,10 @@ ansi_term = "0.12.1"
|
||||
crossterm = "0.18"
|
||||
image = {version = "0.22.4", default_features = false, features = ["png_codec", "jpeg"]}
|
||||
neso = "0.5.0"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
pretty-hex = "0.2.0"
|
||||
rawkey = "0.1.3"
|
||||
|
||||
|
@ -4,19 +4,19 @@ description = "A plugin to display charts"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_chart"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-cli = {path = "../nu-cli", version = "0.23.0"}
|
||||
nu-data = {path = "../nu-data", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-cli = {path = "../nu-cli", version = "0.24.1"}
|
||||
nu-data = {path = "../nu-data", version = "0.24.1"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
|
||||
crossterm = "0.18"
|
||||
tui = {version = "0.12.0", default-features = false, features = ["crossterm"]}
|
||||
|
@ -4,7 +4,7 @@ description = "A URL fetch plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_fetch"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
@ -12,10 +12,10 @@ doctest = false
|
||||
[dependencies]
|
||||
base64 = "0.12.3"
|
||||
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
surf = "1.0.3"
|
||||
url = "2.1.1"
|
||||
|
||||
|
@ -4,7 +4,7 @@ description = "A converter plugin to the bson format for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_from_bson"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
@ -12,11 +12,11 @@ doctest = false
|
||||
[dependencies]
|
||||
bigdecimal = "0.2.0"
|
||||
bson = {version = "0.14.1", features = ["decimal128"]}
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
num-traits = "0.2.12"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -130,7 +130,9 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Result<Value
|
||||
);
|
||||
collected.into_value()
|
||||
}
|
||||
Bson::UtcDatetime(dt) => UntaggedValue::Primitive(Primitive::Date(*dt)).into_value(&tag),
|
||||
Bson::UtcDatetime(dt) => {
|
||||
UntaggedValue::Primitive(Primitive::Date((*dt).into())).into_value(&tag)
|
||||
}
|
||||
Bson::Symbol(s) => {
|
||||
let mut collected = TaggedDictBuilder::new(tag.clone());
|
||||
collected.insert_value(
|
||||
|
@ -4,23 +4,23 @@ description = "A converter plugin to the bson format for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_from_sqlite"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
bigdecimal = "0.2.0"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
num-traits = "0.2.12"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[dependencies.rusqlite]
|
||||
features = ["bundled", "blob"]
|
||||
version = "0.24.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -4,18 +4,18 @@ description = "A version incrementer plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_inc"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
|
||||
semver = "0.10.0"
|
||||
|
||||
|
@ -4,16 +4,16 @@ description = "A regex match plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_match"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
regex = "1.3.9"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -4,7 +4,7 @@ description = "An HTTP post plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_post"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
@ -12,10 +12,10 @@ doctest = false
|
||||
[dependencies]
|
||||
base64 = "0.12.3"
|
||||
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
num-traits = "0.2.12"
|
||||
serde_json = "1.0.57"
|
||||
surf = "1.0.3"
|
||||
|
@ -4,16 +4,16 @@ description = "A process list plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_ps"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
|
||||
num-bigint = "0.3.0"
|
||||
|
||||
@ -23,6 +23,6 @@ futures-timer = "3.0.2"
|
||||
[dependencies.heim]
|
||||
default-features = false
|
||||
features = ["process"]
|
||||
version = "0.1.0-beta.3"
|
||||
version = "0.1.0-rc.1"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -4,17 +4,17 @@ description = "An S3 plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_s3"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
s3handler = "0.5.0"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -4,17 +4,17 @@ description = "web scraping using css selector"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_selector"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-plugin = {version = "0.23.0", path = "../nu-plugin"}
|
||||
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.23.0", path = "../nu-source"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-plugin = {version = "0.24.1", path = "../nu-plugin"}
|
||||
nu-protocol = {version = "0.24.1", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.24.1", path = "../nu-source"}
|
||||
nipper = "0.1.8"
|
||||
|
||||
[dev-dependencies]
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.24.1"}
|
||||
|
@ -4,20 +4,20 @@ description = "A plugin to open files/URLs directly from Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_start"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
glob = "0.3.0"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
open = "1.4.0"
|
||||
url = "2.1.1"
|
||||
|
||||
[build-dependencies]
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-source = {version = "0.23.0", path = "../nu-source"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-source = {version = "0.24.1", path = "../nu-source"}
|
||||
|
@ -4,16 +4,16 @@ description = "A system info plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_sys"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
|
||||
battery = "0.7.6"
|
||||
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
|
||||
|
@ -4,17 +4,17 @@ description = "Text viewer plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_textview"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-data = {path = "../nu-data", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-data = {path = "../nu-data", version = "0.24.1"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
|
||||
ansi_term = "0.12.1"
|
||||
bat = {version = "0.15.4", features = ["regex-fancy", "paging"]}
|
||||
|
@ -4,18 +4,18 @@ description = "A converter plugin to the bson format for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_to_bson"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
bson = "0.14.1"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
num-traits = "0.2.12"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -29,7 +29,7 @@ pub fn value_to_bson_value(v: &Value) -> Result<Bson, ShellError> {
|
||||
.expect("Unimplemented BUG: What about big decimals?"),
|
||||
),
|
||||
UntaggedValue::Primitive(Primitive::Duration(i)) => Bson::String(i.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::Date(d)) => Bson::UtcDatetime(*d),
|
||||
UntaggedValue::Primitive(Primitive::Date(d)) => Bson::UtcDatetime((*d).into()),
|
||||
UntaggedValue::Primitive(Primitive::EndOfStream) => Bson::Null,
|
||||
UntaggedValue::Primitive(Primitive::BeginningOfStream) => Bson::Null,
|
||||
UntaggedValue::Primitive(Primitive::Decimal(d)) => {
|
||||
|
@ -4,23 +4,23 @@ description = "A converter plugin to the bson format for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_to_sqlite"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
hex = "0.4.2"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
nu-value-ext = {path = "../nu-value-ext", version = "0.24.1"}
|
||||
num-traits = "0.2.12"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[dependencies.rusqlite]
|
||||
features = ["bundled", "blob"]
|
||||
version = "0.24.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -4,17 +4,17 @@ description = "Tree viewer plugin for Nushell"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_tree"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
derive-new = "0.5.8"
|
||||
nu-errors = {path = "../nu-errors", version = "0.23.0"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.23.0"}
|
||||
nu-source = {path = "../nu-source", version = "0.23.0"}
|
||||
nu-errors = {path = "../nu-errors", version = "0.24.1"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {path = "../nu-protocol", version = "0.24.1"}
|
||||
nu-source = {path = "../nu-source", version = "0.24.1"}
|
||||
ptree = "0.3.0"
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -4,16 +4,16 @@ description = "Traverses xml"
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
name = "nu_plugin_xpath"
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-errors = {version = "0.23.0", path = "../nu-errors"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.23.0"}
|
||||
nu-protocol = {version = "0.23.0", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.23.0", path = "../nu-source"}
|
||||
nu-errors = {version = "0.24.1", path = "../nu-errors"}
|
||||
nu-plugin = {path = "../nu-plugin", version = "0.24.1"}
|
||||
nu-protocol = {version = "0.24.1", path = "../nu-protocol"}
|
||||
nu-source = {version = "0.24.1", path = "../nu-source"}
|
||||
|
||||
bigdecimal = {version = "0.2.0", features = ["serde"]}
|
||||
indexmap = {version = "1.6.0", features = ["serde-1"]}
|
||||
@ -21,4 +21,4 @@ sxd-document = "0.3.2"
|
||||
sxd-xpath = "0.4.2"
|
||||
|
||||
[dev-dependencies]
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.23.0"}
|
||||
nu-test-support = {path = "../nu-test-support", version = "0.24.1"}
|
||||
|
@ -3,6 +3,7 @@
|
||||
Mathematical functions that generally only operate on a list of numbers (integers, decimals, bytes) and tables.
|
||||
Currently the following functions are implemented:
|
||||
|
||||
* `math abs`: Returns absolute values of a list of numbers
|
||||
* `math avg`: Finds the average of a list of numbers or tables
|
||||
* `math ceil`: Applies the ceil function to a list of numbers
|
||||
* [`math eval`](math-eval.md): Evaluates a list of math expressions into numbers
|
||||
@ -147,6 +148,15 @@ To get the average of the file sizes in a directory, simply pipe the size column
|
||||
───┴────
|
||||
```
|
||||
|
||||
```shell
|
||||
> echo [1 -2 -3.0] | math abs
|
||||
───┬────────
|
||||
0 │ 1
|
||||
1 │ 2
|
||||
2 │ 3.0000
|
||||
───┴────────
|
||||
```
|
||||
|
||||
### Dates
|
||||
|
||||
```shell
|
||||
|
@ -119,3 +119,10 @@ true
|
||||
> random integer 100000..200000
|
||||
173400
|
||||
```
|
||||
|
||||
### chars Examples
|
||||
Generate a random password of length 15
|
||||
```shell
|
||||
> random chars -l 15
|
||||
fWBSbE7QtaoJGeo
|
||||
```
|
@ -88,7 +88,7 @@ version = "0.4.6"
|
||||
[dependencies.cursive]
|
||||
default-features = false
|
||||
features = ["pancurses-backend"]
|
||||
version = "0.23.0"
|
||||
version = "0.24.1"
|
||||
|
||||
[dependencies.futures-preview]
|
||||
features = ["compat", "io-compat"]
|
||||
|
Reference in New Issue
Block a user