diff --git a/Cargo.lock b/Cargo.lock index a886593ad8..4dd0de6d55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -370,15 +370,6 @@ dependencies = [ "time", ] -[[package]] -name = "chrono-humanize" -version = "0.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2ff48a655fe8d2dae9a39e66af7fd8ff32a879e8c4e27422c25596a8b5e90d" -dependencies = [ - "chrono", -] - [[package]] name = "clap" version = "2.33.0" @@ -2114,7 +2105,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.8.0" +version = "0.8.1" dependencies = [ "ansi_term 0.12.1", "app_dirs", @@ -2128,7 +2119,6 @@ dependencies = [ "calamine", "cfg-if", "chrono", - "chrono-humanize", "clap", "clipboard", "crossterm", @@ -2213,6 +2203,7 @@ dependencies = [ "umask", "unicode-xid", "url", + "users", ] [[package]] @@ -2309,7 +2300,6 @@ dependencies = [ "bigdecimal", "byte-unit", "chrono", - "chrono-humanize", "derive-new", "getset", "indexmap", @@ -3907,6 +3897,15 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "users" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72f4267aea0c3ec6d07eaabea6ead7c5ddacfafc5e22bcf8d186706851fb4cf" +dependencies = [ + "libc", +] + [[package]] name = "utf8parse" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index ae875a9a9e..b0387c8a55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nu" -version = "0.8.0" +version = "0.8.1" authors = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] description = "A shell for the GitHub era" license = "MIT" @@ -71,7 +71,6 @@ ansi_term = "0.12.1" nom = "5.0.1" dunce = "1.0.0" indexmap = { version = "1.3.0", features = ["serde-1"] } -chrono-humanize = "0.0.11" byte-unit = "3.0.3" base64 = "0.11" futures-preview = { version = "=0.3.0-alpha.19", features = ["compat", "io-compat"] } @@ -136,6 +135,9 @@ crossterm = {version = "0.10.2", optional = true} futures-timer = {version = "1.0.2", optional = true} url = {version = "2.1.0", optional = true} +[target.'cfg(unix)'.dependencies] +users = "0.9" + [features] default = ["sys", "ps", "textview", "inc", "str"] stable = ["sys", "ps", "textview", "inc", "str", "starship-prompt", "binaryview", "match", "tree", "average", "sum", "post", "fetch", "clipboard"] diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index 69b4aca8cc..d4f25a1d5a 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -30,7 +30,6 @@ nom-tracable = "0.4.1" typetag = "0.1.4" query_interface = "0.3.5" byte-unit = "3.0.3" -chrono-humanize = "0.0.11" natural = "0.3.0" # implement conversions diff --git a/crates/nu-protocol/src/lib.rs b/crates/nu-protocol/src/lib.rs index 5d55ee498d..ba4dbb0941 100644 --- a/crates/nu-protocol/src/lib.rs +++ b/crates/nu-protocol/src/lib.rs @@ -20,7 +20,7 @@ pub use crate::type_shape::{Row as RowType, Type}; pub use crate::value::column_path::{did_you_mean, ColumnPath, PathMember, UnspannedPathMember}; pub use crate::value::dict::{Dictionary, TaggedDictBuilder}; pub use crate::value::evaluate::{Evaluate, EvaluateTrait, Scope}; -pub use crate::value::primitive::format_primitive; pub use crate::value::primitive::Primitive; +pub use crate::value::primitive::{format_date, format_duration, format_primitive}; pub use crate::value::range::{Range, RangeInclusion}; pub use crate::value::{UntaggedValue, Value}; diff --git a/crates/nu-protocol/src/value/primitive.rs b/crates/nu-protocol/src/value/primitive.rs index 8311ad13cc..dd2d32eae4 100644 --- a/crates/nu-protocol/src/value/primitive.rs +++ b/crates/nu-protocol/src/value/primitive.rs @@ -4,7 +4,6 @@ use crate::value::range::Range; use crate::value::{serde_bigdecimal, serde_bigint}; use bigdecimal::BigDecimal; use chrono::{DateTime, Utc}; -use chrono_humanize::Humanize; use nu_errors::{ExpectedRange, ShellError}; use nu_source::{PrettyDebug, Span, SpannedItem}; use num_bigint::BigInt; @@ -154,7 +153,7 @@ pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> S } .to_owned(), Primitive::Binary(_) => "".to_owned(), - Primitive::Date(d) => d.humanize(), + Primitive::Date(d) => format_date(d), } } @@ -171,3 +170,67 @@ pub fn format_duration(sec: u64) -> String { (d, h, m, s) => format!("{}:{:02}:{:02}:{:02}", d, h, m, s), } } + +pub fn format_date(d: &DateTime) -> String { + let utc: DateTime = Utc::now(); + + let duration = utc.signed_duration_since(*d); + + if duration.num_weeks() >= 52 { + let num_years = duration.num_weeks() / 52; + + format!( + "{} year{} ago", + num_years, + if num_years == 1 { "" } else { "s" } + ) + } else if duration.num_weeks() >= 4 { + let num_months = duration.num_weeks() / 4; + + format!( + "{} month{} ago", + num_months, + if num_months == 1 { "" } else { "s" } + ) + } else if duration.num_weeks() >= 1 { + let num_weeks = duration.num_weeks(); + + format!( + "{} week{} ago", + num_weeks, + if num_weeks == 1 { "" } else { "s" } + ) + } else if duration.num_days() >= 1 { + let num_days = duration.num_days(); + + format!( + "{} day{} ago", + num_days, + if num_days == 1 { "" } else { "s" } + ) + } else if duration.num_hours() >= 1 { + let num_hours = duration.num_hours(); + + format!( + "{} hour{} ago", + num_hours, + if num_hours == 1 { "" } else { "s" } + ) + } else if duration.num_minutes() >= 1 { + let num_minutes = duration.num_minutes(); + + format!( + "{} min{} ago", + num_minutes, + if num_minutes == 1 { "" } else { "s" } + ) + } else { + let num_seconds = duration.num_seconds(); + + format!( + "{} sec{} ago", + num_seconds, + if num_seconds == 1 { "" } else { "s" } + ) + } +} diff --git a/crates/nu-test-support/src/macros.rs b/crates/nu-test-support/src/macros.rs index 7f289f1763..58b56c07b6 100644 --- a/crates/nu-test-support/src/macros.rs +++ b/crates/nu-test-support/src/macros.rs @@ -48,6 +48,7 @@ macro_rules! nu { .expect("couldn't read from stdout"); let out = String::from_utf8_lossy(&output.stdout); + let out = out.lines().skip(1).collect::>().join("\n"); let out = out.replace("\r\n", ""); let out = out.replace("\n", ""); out diff --git a/src/commands/version.rs b/src/commands/version.rs index 75fe60d842..9c74249a60 100644 --- a/src/commands/version.rs +++ b/src/commands/version.rs @@ -24,11 +24,11 @@ impl WholeStreamCommand for Version { args: CommandArgs, registry: &CommandRegistry, ) -> Result { - date(args, registry) + version(args, registry) } } -pub fn date(args: CommandArgs, registry: &CommandRegistry) -> Result { +pub fn version(args: CommandArgs, registry: &CommandRegistry) -> Result { let args = args.evaluate_once(registry)?; let tag = args.call_info.name_tag.clone(); diff --git a/src/data/base/shape.rs b/src/data/base/shape.rs index 5dc34a84f9..67d02bb12e 100644 --- a/src/data/base/shape.rs +++ b/src/data/base/shape.rs @@ -1,6 +1,5 @@ use crate::prelude::*; use chrono::{DateTime, Utc}; -use chrono_humanize::Humanize; use indexmap::IndexMap; use nu_errors::ShellError; use nu_protocol::RangeInclusion; @@ -188,7 +187,7 @@ impl PrettyDebug for FormatInlineShape { } .to_owned(), ), - InlineShape::Date(date) => b::primitive(date.humanize()), + InlineShape::Date(date) => b::primitive(nu_protocol::format_date(date)), InlineShape::Duration(duration) => { b::description(format_primitive(&Primitive::Duration(*duration), None)) } diff --git a/src/data/files.rs b/src/data/files.rs index bb9d74978b..689efa30a5 100644 --- a/src/data/files.rs +++ b/src/data/files.rs @@ -2,13 +2,6 @@ use crate::prelude::*; use nu_errors::ShellError; use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; -#[derive(Debug)] -pub enum FileType { - Directory, - File, - Symlink, -} - pub(crate) fn dir_entry_dict( filename: &std::path::Path, metadata: &std::fs::Metadata, @@ -18,16 +11,14 @@ pub(crate) fn dir_entry_dict( let mut dict = TaggedDictBuilder::new(tag); dict.insert_untagged("name", UntaggedValue::string(filename.to_string_lossy())); - let kind = if metadata.is_dir() { - FileType::Directory + if metadata.is_dir() { + dict.insert_untagged("type", UntaggedValue::string("Dir")); } else if metadata.is_file() { - FileType::File + dict.insert_untagged("type", UntaggedValue::string("File")); } else { - FileType::Symlink + dict.insert_untagged("type", UntaggedValue::string("Symlink")); }; - dict.insert_untagged("type", UntaggedValue::string(format!("{:?}", kind))); - if full { dict.insert_untagged( "readonly", @@ -36,23 +27,37 @@ pub(crate) fn dir_entry_dict( #[cfg(unix)] { + use std::os::unix::fs::MetadataExt; use std::os::unix::fs::PermissionsExt; let mode = metadata.permissions().mode(); dict.insert_untagged( "mode", UntaggedValue::string(umask::Mode::from(mode).to_string()), ); + + if let Some(user) = users::get_user_by_uid(metadata.uid()) { + dict.insert_untagged("uid", UntaggedValue::string(user.name().to_string_lossy())); + } + + if let Some(group) = users::get_group_by_gid(metadata.gid()) { + dict.insert_untagged( + "group", + UntaggedValue::string(group.name().to_string_lossy()), + ); + } } } dict.insert_untagged("size", UntaggedValue::bytes(metadata.len() as u64)); - if let Ok(c) = metadata.created() { - dict.insert_untagged("created", UntaggedValue::system_date(c)); - } + if full { + if let Ok(c) = metadata.created() { + dict.insert_untagged("created", UntaggedValue::system_date(c)); + } - if let Ok(a) = metadata.accessed() { - dict.insert_untagged("accessed", UntaggedValue::system_date(a)); + if let Ok(a) = metadata.accessed() { + dict.insert_untagged("accessed", UntaggedValue::system_date(a)); + } } if let Ok(m) = metadata.modified() { diff --git a/src/main.rs b/src/main.rs index e31c983f60..9b45231406 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,6 +65,10 @@ fn main() -> Result<(), Box> { builder.try_init()?; + println!( + "Welcome to Nushell {} (type 'help' for more info)", + clap::crate_version!() + ); futures::executor::block_on(nu::cli())?; Ok(()) }