Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use crate ::type_name ::ShellTypeName ;
use crate ::value ::column_path ::ColumnPath ;
2019-12-04 22:14:52 +01:00
use crate ::value ::range ::Range ;
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use crate ::value ::{ serde_bigdecimal , serde_bigint } ;
use bigdecimal ::BigDecimal ;
use chrono ::{ DateTime , Utc } ;
2019-12-04 22:14:52 +01:00
use nu_errors ::{ ExpectedRange , ShellError } ;
use nu_source ::{ PrettyDebug , Span , SpannedItem } ;
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use num_bigint ::BigInt ;
2020-07-10 19:48:11 +02:00
use num_integer ::Integer ;
2019-12-04 22:14:52 +01:00
use num_traits ::cast ::{ FromPrimitive , ToPrimitive } ;
2020-03-19 00:46:00 +01:00
use num_traits ::identities ::Zero ;
2020-07-10 19:48:11 +02:00
use num_traits ::sign ::Signed ;
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use serde ::{ Deserialize , Serialize } ;
use std ::path ::PathBuf ;
2020-07-10 19:48:11 +02:00
const NANOS_PER_SEC : u32 = 1000000000 ;
2020-01-15 17:28:31 +01:00
/// The most fundamental of structured values in Nu are the Primitive values. These values represent types like integers, strings, booleans, dates, etc that are then used
/// as the buildig blocks to build up more complex structures.
///
/// Primitives also include marker values BeginningOfStream and EndOfStream which denote a change of condition in the stream
2019-12-31 05:05:02 +01:00
#[ derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize) ]
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
pub enum Primitive {
2020-01-15 17:28:31 +01:00
/// An empty value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Nothing ,
2020-01-15 17:28:31 +01:00
/// A "big int", an integer with arbitrarily large size (aka not limited to 64-bit)
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
#[ serde(with = " serde_bigint " ) ]
Int ( BigInt ) ,
2020-01-15 17:28:31 +01:00
/// A "big decimal", an decimal number with arbitrarily large size (aka not limited to 64-bit)
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
#[ serde(with = " serde_bigdecimal " ) ]
Decimal ( BigDecimal ) ,
2020-01-15 17:28:31 +01:00
/// A count in the number of bytes, used as a filesize
2020-07-11 04:17:37 +02:00
Filesize ( u64 ) ,
2020-01-15 17:28:31 +01:00
/// A string value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
String ( String ) ,
2020-01-15 17:28:31 +01:00
/// A string value with an implied carriage return (or cr/lf) ending
2019-12-03 07:44:59 +01:00
Line ( String ) ,
2020-01-15 17:28:31 +01:00
/// A path to travel to reach a value in a table
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
ColumnPath ( ColumnPath ) ,
2020-01-15 17:28:31 +01:00
/// A glob pattern, eg foo*
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Pattern ( String ) ,
2020-01-15 17:28:31 +01:00
/// A boolean value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Boolean ( bool ) ,
2020-01-15 17:28:31 +01:00
/// A date value, in UTC
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Date ( DateTime < Utc > ) ,
2020-07-10 19:48:11 +02:00
/// A count in the number of nanoseconds
#[ serde(with = " serde_bigint " ) ]
Duration ( BigInt ) ,
2020-01-15 17:28:31 +01:00
/// A range of values
2019-12-04 22:14:52 +01:00
Range ( Box < Range > ) ,
2020-01-15 17:28:31 +01:00
/// A file path
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Path ( PathBuf ) ,
2020-01-15 17:28:31 +01:00
/// A vector of raw binary data
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
#[ serde(with = " serde_bytes " ) ]
Binary ( Vec < u8 > ) ,
2020-01-15 17:28:31 +01:00
/// Beginning of stream marker, a pseudo-value not intended for tables
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
BeginningOfStream ,
2020-01-15 17:28:31 +01:00
/// End of stream marker, a pseudo-value not intended for tables
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
EndOfStream ,
}
2019-12-04 22:14:52 +01:00
impl Primitive {
2020-01-15 17:28:31 +01:00
/// Converts a primitive value to a u64, if possible. Uses a span to build an error if the conversion isn't possible.
2019-12-04 22:14:52 +01:00
pub fn as_u64 ( & self , span : Span ) -> Result < u64 , ShellError > {
match self {
2020-08-03 00:34:33 +02:00
Primitive ::Int ( int ) = > int . to_u64 ( ) . ok_or_else ( | | {
ShellError ::range_error (
2019-12-04 22:14:52 +01:00
ExpectedRange ::U64 ,
& format! ( " {} " , int ) . spanned ( span ) ,
" converting an integer into a 64-bit integer " ,
2020-08-03 00:34:33 +02:00
)
} ) ,
2020-08-04 00:47:19 +02:00
Primitive ::Decimal ( decimal ) = > decimal . to_u64 ( ) . ok_or_else ( | | {
ShellError ::range_error (
ExpectedRange ::U64 ,
& format! ( " {} " , decimal ) . spanned ( span ) ,
" converting a decimal into a 64-bit integer " ,
)
} ) ,
2019-12-04 22:14:52 +01:00
other = > Err ( ShellError ::type_error (
2020-08-04 00:47:19 +02:00
" number " ,
2019-12-04 22:14:52 +01:00
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
2020-03-31 01:19:48 +02:00
2020-07-10 19:48:11 +02:00
// FIXME: This is a bad name, but no other way to differentiate with our own Duration.
pub fn into_chrono_duration ( self , span : Span ) -> Result < chrono ::Duration , ShellError > {
match self {
Primitive ::Duration ( duration ) = > {
let ( secs , nanos ) = duration . div_rem ( & BigInt ::from ( NANOS_PER_SEC ) ) ;
let secs = match secs . to_i64 ( ) {
Some ( secs ) = > secs ,
None = > {
return Err ( ShellError ::labeled_error (
" Internal duration conversion overflow. " ,
" duration overflow " ,
span ,
) )
}
} ;
// This should never fail since nanos < 10^9.
let nanos = match nanos . to_i64 ( ) {
Some ( nanos ) = > nanos ,
None = > return Err ( ShellError ::unexpected ( " Unexpected i64 overflow " ) ) ,
} ;
let nanos = chrono ::Duration ::nanoseconds ( nanos ) ;
// This should also never fail since we are adding less than NANOS_PER_SEC.
2020-08-03 00:34:33 +02:00
chrono ::Duration ::seconds ( secs )
. checked_add ( & nanos )
. ok_or_else ( | | ShellError ::unexpected ( " Unexpected duration overflow " ) )
2020-07-10 19:48:11 +02:00
}
other = > Err ( ShellError ::type_error (
" duration " ,
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
2020-03-31 01:19:48 +02:00
pub fn into_string ( self , span : Span ) -> Result < String , ShellError > {
match self {
Primitive ::String ( s ) = > Ok ( s ) ,
other = > Err ( ShellError ::type_error (
" string " ,
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
2020-04-26 19:30:52 +02:00
/// Returns true if the value is empty
pub fn is_empty ( & self ) -> bool {
match self {
Primitive ::Nothing = > true ,
Primitive ::String ( s ) = > s . is_empty ( ) ,
_ = > false ,
}
}
2019-12-04 22:14:52 +01:00
}
2020-05-18 14:56:01 +02:00
impl From < & str > for Primitive {
/// Helper to convert from string slices to a primitive
fn from ( s : & str ) -> Primitive {
Primitive ::String ( s . to_string ( ) )
}
}
impl From < String > for Primitive {
/// Helper to convert from Strings to a primitive
fn from ( s : String ) -> Primitive {
Primitive ::String ( s )
}
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
impl From < BigDecimal > for Primitive {
2020-01-15 17:28:31 +01:00
/// Helper to convert from decimals to a Primitive value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
fn from ( decimal : BigDecimal ) -> Primitive {
Primitive ::Decimal ( decimal )
}
}
2020-03-19 00:46:00 +01:00
impl From < BigInt > for Primitive {
/// Helper to convert from integers to a Primitive value
fn from ( int : BigInt ) -> Primitive {
Primitive ::Int ( int )
}
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
impl From < f64 > for Primitive {
2020-01-15 17:28:31 +01:00
/// Helper to convert from 64-bit float to a Primitive value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
fn from ( float : f64 ) -> Primitive {
2020-01-04 07:44:17 +01:00
if let Some ( f ) = BigDecimal ::from_f64 ( float ) {
Primitive ::Decimal ( f )
} else {
unreachable! ( " Internal error: protocol did not use f64-compatible decimal " )
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
}
}
2020-07-10 19:48:11 +02:00
impl From < chrono ::Duration > for Primitive {
fn from ( duration : chrono ::Duration ) -> Primitive {
// FIXME: This is a hack since chrono::Duration does not give access to its 'nanos' field.
let secs : i64 = duration . num_seconds ( ) ;
// This will never fail.
let nanos : u32 = duration
. checked_sub ( & chrono ::Duration ::seconds ( secs ) )
. expect ( " Unexpected overflow " )
. num_nanoseconds ( )
. expect ( " Unexpected overflow " ) as u32 ;
Primitive ::Duration ( BigInt ::from ( secs ) * NANOS_PER_SEC + nanos )
}
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
impl ShellTypeName for Primitive {
2020-01-15 17:28:31 +01:00
/// Get the name of the type of a Primitive value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
fn type_name ( & self ) -> & 'static str {
match self {
Primitive ::Nothing = > " nothing " ,
Primitive ::Int ( _ ) = > " integer " ,
2019-12-04 22:14:52 +01:00
Primitive ::Range ( _ ) = > " range " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::Decimal ( _ ) = > " decimal " ,
2020-07-11 04:17:37 +02:00
Primitive ::Filesize ( _ ) = > " filesize(in bytes) " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::String ( _ ) = > " string " ,
2019-12-03 07:44:59 +01:00
Primitive ::Line ( _ ) = > " line " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::ColumnPath ( _ ) = > " column path " ,
Primitive ::Pattern ( _ ) = > " pattern " ,
Primitive ::Boolean ( _ ) = > " boolean " ,
Primitive ::Date ( _ ) = > " date " ,
Primitive ::Duration ( _ ) = > " duration " ,
Primitive ::Path ( _ ) = > " file path " ,
Primitive ::Binary ( _ ) = > " binary " ,
Primitive ::BeginningOfStream = > " marker<beginning of stream> " ,
Primitive ::EndOfStream = > " marker<end of stream> " ,
}
}
}
2019-12-09 19:39:51 +01:00
2020-01-15 17:28:31 +01:00
/// Format a Primitive value into a string
2019-12-09 19:39:51 +01:00
pub fn format_primitive ( primitive : & Primitive , field_name : Option < & String > ) -> String {
match primitive {
Primitive ::Nothing = > String ::new ( ) ,
Primitive ::BeginningOfStream = > String ::new ( ) ,
Primitive ::EndOfStream = > String ::new ( ) ,
Primitive ::Path ( p ) = > format! ( " {} " , p . display ( ) ) ,
2020-07-11 04:17:37 +02:00
Primitive ::Filesize ( num_bytes ) = > {
let byte = byte_unit ::Byte ::from_bytes ( * num_bytes as u128 ) ;
2019-12-09 19:39:51 +01:00
if byte . get_bytes ( ) = = 0 u128 {
return " — " . to_string ( ) ;
}
let byte = byte . get_appropriate_unit ( false ) ;
match byte . get_unit ( ) {
byte_unit ::ByteUnit ::B = > format! ( " {} B " , byte . get_value ( ) ) ,
2019-12-31 08:36:08 +01:00
_ = > byte . format ( 1 ) ,
2019-12-09 19:39:51 +01:00
}
}
2020-07-10 19:48:11 +02:00
Primitive ::Duration ( duration ) = > format_duration ( duration ) ,
2019-12-09 19:39:51 +01:00
Primitive ::Int ( i ) = > i . to_string ( ) ,
2019-12-24 02:26:47 +01:00
Primitive ::Decimal ( decimal ) = > format! ( " {:.4} " , decimal ) ,
2019-12-04 22:14:52 +01:00
Primitive ::Range ( range ) = > format! (
" {}..{} " ,
format_primitive ( & range . from . 0. item , None ) ,
format_primitive ( & range . to . 0. item , None )
) ,
2019-12-09 19:39:51 +01:00
Primitive ::Pattern ( s ) = > s . to_string ( ) ,
Primitive ::String ( s ) = > s . to_owned ( ) ,
Primitive ::Line ( s ) = > s . to_owned ( ) ,
Primitive ::ColumnPath ( p ) = > {
let mut members = p . iter ( ) ;
let mut f = String ::new ( ) ;
f . push_str (
& members
. next ( )
. expect ( " BUG: column path with zero members " )
. display ( ) ,
) ;
for member in members {
f . push_str ( " . " ) ;
f . push_str ( & member . display ( ) )
}
f
}
Primitive ::Boolean ( b ) = > match ( b , field_name ) {
( true , None ) = > " Yes " ,
( false , None ) = > " No " ,
( true , Some ( s ) ) if ! s . is_empty ( ) = > s ,
( false , Some ( s ) ) if ! s . is_empty ( ) = > " " ,
( true , Some ( _ ) ) = > " Yes " ,
( false , Some ( _ ) ) = > " No " ,
}
. to_owned ( ) ,
Primitive ::Binary ( _ ) = > " <binary> " . to_owned ( ) ,
2020-01-11 21:49:20 +01:00
Primitive ::Date ( d ) = > format_date ( d ) ,
2019-12-09 19:39:51 +01:00
}
}
2019-12-04 22:14:52 +01:00
2020-07-10 19:48:11 +02:00
/// Format a duration in nanoseconds into a string
pub fn format_duration ( duration : & BigInt ) -> String {
// FIXME: This involves a lot of allocation, but it seems inevitable with BigInt.
let big_int_1000 = BigInt ::from ( 1000 ) ;
let big_int_60 = BigInt ::from ( 60 ) ;
let big_int_24 = BigInt ::from ( 24 ) ;
// We only want the biggest subvidision to have the negative sign.
let ( sign , duration ) = if duration . is_zero ( ) | | duration . is_positive ( ) {
( 1 , duration . clone ( ) )
} else {
( - 1 , - duration )
} ;
let ( micros , nanos ) : ( BigInt , BigInt ) = duration . div_rem ( & big_int_1000 ) ;
let ( millis , micros ) : ( BigInt , BigInt ) = micros . div_rem ( & big_int_1000 ) ;
let ( secs , millis ) : ( BigInt , BigInt ) = millis . div_rem ( & big_int_1000 ) ;
let ( mins , secs ) : ( BigInt , BigInt ) = secs . div_rem ( & big_int_60 ) ;
let ( hours , mins ) : ( BigInt , BigInt ) = mins . div_rem ( & big_int_60 ) ;
let ( days , hours ) : ( BigInt , BigInt ) = hours . div_rem ( & big_int_24 ) ;
2020-07-10 23:06:52 +02:00
let mut output_prep = vec! [ ] ;
if ! days . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} day " , days ) ) ;
2020-07-10 23:06:52 +02:00
}
if ! hours . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} hr " , hours ) ) ;
2020-07-10 23:06:52 +02:00
}
if ! mins . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} min " , mins ) ) ;
2019-12-09 19:39:51 +01:00
}
2020-07-10 23:06:52 +02:00
if ! secs . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} sec " , secs ) ) ;
2020-07-10 23:06:52 +02:00
}
if ! millis . is_zero ( ) {
output_prep . push ( format! ( " {} ms " , millis ) ) ;
}
if ! micros . is_zero ( ) {
output_prep . push ( format! ( " {} us " , micros ) ) ;
}
if ! nanos . is_zero ( ) {
output_prep . push ( format! ( " {} ns " , nanos ) ) ;
}
format! (
" {}{} " ,
if sign = = - 1 { " - " } else { " " } ,
output_prep . join ( " " )
)
2019-12-09 19:39:51 +01:00
}
2020-01-11 21:49:20 +01:00
2020-04-18 03:50:58 +02:00
#[ allow(clippy::cognitive_complexity) ]
2020-01-15 17:28:31 +01:00
/// Format a UTC date value into a humanized string (eg "1 week ago" instead of a formal date string)
2020-01-11 21:49:20 +01:00
pub fn format_date ( d : & DateTime < Utc > ) -> String {
let utc : DateTime < Utc > = Utc ::now ( ) ;
let duration = utc . signed_duration_since ( * d ) ;
2020-04-18 03:50:58 +02:00
if duration . num_seconds ( ) < 0 {
// Our duration is negative, so we need to speak about the future
if - duration . num_weeks ( ) > = 52 {
let num_years = - duration . num_weeks ( ) / 52 ;
format! (
" {} year{} from now " ,
num_years ,
if num_years = = 1 { " " } else { " s " }
)
} else if - duration . num_weeks ( ) > = 4 {
let num_months = - duration . num_weeks ( ) / 4 ;
format! (
" {} month{} from now " ,
num_months ,
if num_months = = 1 { " " } else { " s " }
)
} else if - duration . num_weeks ( ) > = 1 {
let num_weeks = - duration . num_weeks ( ) ;
format! (
" {} week{} from now " ,
num_weeks ,
if num_weeks = = 1 { " " } else { " s " }
)
} else if - duration . num_days ( ) > = 1 {
let num_days = - duration . num_days ( ) ;
format! (
" {} day{} from now " ,
num_days ,
if num_days = = 1 { " " } else { " s " }
)
} else if - duration . num_hours ( ) > = 1 {
let num_hours = - duration . num_hours ( ) ;
format! (
" {} hour{} from now " ,
num_hours ,
if num_hours = = 1 { " " } else { " s " }
)
} else if - duration . num_minutes ( ) > = 1 {
let num_minutes = - duration . num_minutes ( ) ;
format! (
" {} min{} from now " ,
num_minutes ,
if num_minutes = = 1 { " " } else { " s " }
)
} else {
let num_seconds = - duration . num_seconds ( ) ;
format! (
" {} sec{} from now " ,
num_seconds ,
if num_seconds = = 1 { " " } else { " s " }
)
}
} else if duration . num_weeks ( ) > = 52 {
2020-01-11 21:49:20 +01:00
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 " }
)
}
}