Add more comments (#1228)

* Add some more docs

* More docs

* More docs
This commit is contained in:
Jonathan Turner 2020-01-16 05:28:31 +13:00 committed by GitHub
parent b32eceffb3
commit 2956b0b087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 90 additions and 2 deletions

View File

@ -5,12 +5,16 @@ use nu_errors::ShellError;
use nu_source::Tag;
use serde::{Deserialize, Serialize};
/// Associated information for the call of a command, including the args passed to the command and a tag that spans the name of the command being called
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct CallInfo {
pub args: EvaluatedArgs,
pub name_tag: Tag,
}
/// The set of positional and named arguments, after their values have been evaluated.
/// Positional arguments are those who are given as values, without any associated flag. For example, in `foo arg1 arg2`, both `arg1` and `arg2` are positional arguments
/// Named arguments are those associated with a flag. For example, `foo --given bar` the named argument would be name `given` and the value `bar`.
#[derive(Debug, Default, new, Serialize, Deserialize, Clone)]
pub struct EvaluatedArgs {
pub positional: Option<Vec<Value>>,
@ -18,6 +22,7 @@ pub struct EvaluatedArgs {
}
impl EvaluatedArgs {
/// Retrieve a subset of positional arguments starting at a given position
pub fn slice_from(&self, from: usize) -> Vec<Value> {
let positional = &self.positional;
@ -27,6 +32,7 @@ impl EvaluatedArgs {
}
}
/// Get the nth positional argument, if possible
pub fn nth(&self, pos: usize) -> Option<&Value> {
match &self.positional {
None => None,
@ -34,6 +40,7 @@ impl EvaluatedArgs {
}
}
/// Get the nth positional argument, error if not possible
pub fn expect_nth(&self, pos: usize) -> Result<&Value, ShellError> {
match &self.positional {
None => Err(ShellError::unimplemented("Better error: expect_nth")),
@ -44,6 +51,7 @@ impl EvaluatedArgs {
}
}
/// Get the number of positional arguments available
pub fn len(&self) -> usize {
match &self.positional {
None => 0,
@ -51,10 +59,12 @@ impl EvaluatedArgs {
}
}
/// Return if there are no positional arguments
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Return true if the set of named arguments contains the name provided
pub fn has(&self, name: &str) -> bool {
match &self.named {
None => false,
@ -62,6 +72,7 @@ impl EvaluatedArgs {
}
}
/// Gets the corresponding Value for the named argument given, if possible
pub fn get(&self, name: &str) -> Option<&Value> {
match &self.named {
None => None,
@ -69,6 +80,7 @@ impl EvaluatedArgs {
}
}
/// Iterates over the positional arguments
pub fn positional_iter(&self) -> PositionalIter<'_> {
match &self.positional {
None => PositionalIter::Empty,
@ -80,6 +92,7 @@ impl EvaluatedArgs {
}
}
/// An iterator to help iterate over positional arguments
pub enum PositionalIter<'a> {
Empty,
Array(std::slice::Iter<'a, Value>),
@ -88,6 +101,7 @@ pub enum PositionalIter<'a> {
impl<'a> Iterator for PositionalIter<'a> {
type Item = &'a Value;
/// The required `next` function to implement the Iterator trait
fn next(&mut self) -> Option<Self::Item> {
match self {
PositionalIter::Empty => None,

View File

@ -1,5 +1,6 @@
#![allow(clippy::should_implement_trait)]
/// Helper type to allow passing something that may potentially be owned, but could also be borrowed
#[derive(Debug)]
pub enum MaybeOwned<'a, T> {
Owned(T),
@ -7,6 +8,7 @@ pub enum MaybeOwned<'a, T> {
}
impl<T> MaybeOwned<'_, T> {
/// Allows the borrowing of an owned value or passes out the borrowed value
pub fn borrow(&self) -> &T {
match self {
MaybeOwned::Owned(v) => v,

View File

@ -3,21 +3,33 @@ use nu_errors::ShellError;
use nu_source::{b, DebugDocBuilder, PrettyDebug};
use serde::{Deserialize, Serialize};
/// The inner set of actions for the command processor. Each denotes a way to change state in the processor without changing it directly from the command itself.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CommandAction {
/// Change to a new directory or path (in non-filesystem situations)
ChangePath(String),
/// Exit out of Nu
Exit,
/// Display an error
Error(ShellError),
/// Enter a new shell at the given path
EnterShell(String),
/// Convert the value given from one type to another
AutoConvert(Value, String),
/// Enter a value shell, one that allows exploring inside of a Value
EnterValueShell(Value),
/// Enter the help shell, which allows exploring the help system
EnterHelpShell(Value),
/// Go to the previous shell in the shell ring buffer
PreviousShell,
/// Go to the next shell in the shell ring buffer
NextShell,
/// Leave the current shell. If it's the last shell, exit out of Nu
LeaveShell,
}
impl PrettyDebug for CommandAction {
/// Get a command action ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
match self {
CommandAction::ChangePath(path) => b::typed("change path", b::description(path)),
@ -36,14 +48,19 @@ impl PrettyDebug for CommandAction {
}
}
/// The fundamental success type in the pipeline. Commands return these values as their main responsibility
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ReturnSuccess {
/// A value to be used or shown to the user
Value(Value),
/// A debug-enabled value to be used or shown to the user
DebugValue(Value),
/// An action to be performed as values pass out of the command. These are performed rather than passed to the next command in the pipeline
Action(CommandAction),
}
impl PrettyDebug for ReturnSuccess {
/// Get a return success ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
match self {
ReturnSuccess::Value(value) => b::typed("value", value.pretty()),
@ -53,15 +70,18 @@ impl PrettyDebug for ReturnSuccess {
}
}
/// The core Result type for pipelines
pub type ReturnValue = Result<ReturnSuccess, ShellError>;
impl Into<ReturnValue> for Value {
/// Lift a Value into a ReturnValue
fn into(self) -> ReturnValue {
Ok(ReturnSuccess::Value(self))
}
}
impl ReturnSuccess {
/// Get to the contained Value, if possible
pub fn raw_value(&self) -> Option<Value> {
match self {
ReturnSuccess::Value(raw) => Some(raw.clone()),
@ -70,18 +90,22 @@ impl ReturnSuccess {
}
}
/// Helper function for an action to change the the path
pub fn change_cwd(path: String) -> ReturnValue {
Ok(ReturnSuccess::Action(CommandAction::ChangePath(path)))
}
/// Helper function to create simple values for returning
pub fn value(input: impl Into<Value>) -> ReturnValue {
Ok(ReturnSuccess::Value(input.into()))
}
/// Helper function to create simple debug-enabled values for returning
pub fn debug_value(input: impl Into<Value>) -> ReturnValue {
Ok(ReturnSuccess::DebugValue(input.into()))
}
/// Helper function for creating actions
pub fn action(input: CommandAction) -> ReturnValue {
Ok(ReturnSuccess::Action(input))
}

View File

@ -187,6 +187,7 @@ impl TaggedDictBuilder {
builder.into_value()
}
/// Create a new builder with a pre-defined capacity
pub fn with_capacity(tag: impl Into<Tag>, n: usize) -> TaggedDictBuilder {
TaggedDictBuilder {
tag: tag.into(),
@ -194,30 +195,36 @@ impl TaggedDictBuilder {
}
}
/// Insert an untagged key/value pair into the dictionary, to later be tagged when built
pub fn insert_untagged(&mut self, key: impl Into<String>, value: impl Into<UntaggedValue>) {
self.dict
.insert(key.into(), value.into().into_value(&self.tag));
}
/// Insert a key/value pair into the dictionary
pub fn insert_value(&mut self, key: impl Into<String>, value: impl Into<Value>) {
self.dict.insert(key.into(), value.into());
}
/// Convert the dictionary into a tagged Value using the original tag
pub fn into_value(self) -> Value {
let tag = self.tag.clone();
self.into_untagged_value().into_value(tag)
}
/// Convert the dictionary into an UntaggedValue
pub fn into_untagged_value(self) -> UntaggedValue {
UntaggedValue::Row(Dictionary { entries: self.dict })
}
/// Returns true if the dictionary is empty, false otherwise
pub fn is_empty(&self) -> bool {
self.dict.is_empty()
}
}
impl From<TaggedDictBuilder> for Value {
/// Convert a builder into a tagged Value
fn from(input: TaggedDictBuilder) -> Value {
input.into_value()
}

View File

@ -6,6 +6,9 @@ use serde::{Deserialize, Serialize};
use std::cmp::{Ord, Ordering, PartialOrd};
use std::fmt::Debug;
/// An evaluation scope. Scopes map variable names to Values and aid in evaluating blocks and expressions.
/// Additionally, holds the value for the special $it variable, a variable used to refer to the value passing
/// through the pipeline at that moment
#[derive(Debug)]
pub struct Scope {
pub it: Value,
@ -13,6 +16,7 @@ pub struct Scope {
}
impl Scope {
/// Create a new scope
pub fn new(it: Value) -> Scope {
Scope {
it,
@ -22,6 +26,7 @@ impl Scope {
}
impl Scope {
/// Create an empty scope
pub fn empty() -> Scope {
Scope {
it: UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(),
@ -29,6 +34,7 @@ impl Scope {
}
}
/// Create an empty scope, setting $it to a known Value
pub fn it_value(value: Value) -> Scope {
Scope {
it: value,

View File

@ -11,32 +11,52 @@ use num_traits::cast::{FromPrimitive, ToPrimitive};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
/// 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
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub enum Primitive {
/// An empty value
Nothing,
/// A "big int", an integer with arbitrarily large size (aka not limited to 64-bit)
#[serde(with = "serde_bigint")]
Int(BigInt),
/// A "big decimal", an decimal number with arbitrarily large size (aka not limited to 64-bit)
#[serde(with = "serde_bigdecimal")]
Decimal(BigDecimal),
/// A count in the number of bytes, used as a filesize
Bytes(u64),
/// A string value
String(String),
/// A string value with an implied carriage return (or cr/lf) ending
Line(String),
/// A path to travel to reach a value in a table
ColumnPath(ColumnPath),
/// A glob pattern, eg foo*
Pattern(String),
/// A boolean value
Boolean(bool),
/// A date value, in UTC
Date(DateTime<Utc>),
Duration(u64), // Duration in seconds
/// A count in the number of seconds
Duration(u64),
/// A range of values
Range(Box<Range>),
/// A file path
Path(PathBuf),
/// A vector of raw binary data
#[serde(with = "serde_bytes")]
Binary(Vec<u8>),
// Stream markers (used as bookend markers rather than actual values)
/// Beginning of stream marker, a pseudo-value not intended for tables
BeginningOfStream,
/// End of stream marker, a pseudo-value not intended for tables
EndOfStream,
}
impl Primitive {
/// Converts a primitive value to a u64, if possible. Uses a span to build an error if the conversion isn't possible.
pub fn as_u64(&self, span: Span) -> Result<u64, ShellError> {
match self {
Primitive::Int(int) => match int.to_u64() {
@ -56,12 +76,14 @@ impl Primitive {
}
impl From<BigDecimal> for Primitive {
/// Helper to convert from decimals to a Primitive value
fn from(decimal: BigDecimal) -> Primitive {
Primitive::Decimal(decimal)
}
}
impl From<f64> for Primitive {
/// Helper to convert from 64-bit float to a Primitive value
fn from(float: f64) -> Primitive {
if let Some(f) = BigDecimal::from_f64(float) {
Primitive::Decimal(f)
@ -72,6 +94,7 @@ impl From<f64> for Primitive {
}
impl ShellTypeName for Primitive {
/// Get the name of the type of a Primitive value
fn type_name(&self) -> &'static str {
match self {
Primitive::Nothing => "nothing",
@ -94,6 +117,7 @@ impl ShellTypeName for Primitive {
}
}
/// Format a Primitive value into a string
pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> String {
match primitive {
Primitive::Nothing => String::new(),
@ -157,6 +181,7 @@ pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> S
}
}
/// Format a duration in seconds into a string
pub fn format_duration(sec: u64) -> String {
let (minutes, seconds) = (sec / 60, sec % 60);
let (hours, minutes) = (minutes / 60, minutes % 60);
@ -171,6 +196,7 @@ pub fn format_duration(sec: u64) -> String {
}
}
/// 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 {
let utc: DateTime<Utc> = Utc::now();

View File

@ -3,6 +3,8 @@ use derive_new::new;
use nu_source::{b, DebugDocBuilder, Spanned};
use serde::{Deserialize, Serialize};
/// The two types of ways to include a range end. Inclusive means to include the value (eg 1..3 inclusive would include the 3 value).
/// Exclusive excludes the value (eg 1..3 exclusive does not include 3 value)
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub enum RangeInclusion {
Inclusive,
@ -10,6 +12,7 @@ pub enum RangeInclusion {
}
impl RangeInclusion {
/// Get a RangeInclusion left bracket ready for pretty printing
pub fn debug_left_bracket(self) -> DebugDocBuilder {
b::delimiter(match self {
RangeInclusion::Exclusive => "(",
@ -17,6 +20,7 @@ impl RangeInclusion {
})
}
/// Get a RangeInclusion right bracket ready for pretty printing
pub fn debug_right_bracket(self) -> DebugDocBuilder {
b::delimiter(match self {
RangeInclusion::Exclusive => ")",
@ -25,6 +29,7 @@ impl RangeInclusion {
}
}
/// The range definition, holding the starting and end point of the range
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize, new)]
pub struct Range {
pub from: (Spanned<Primitive>, RangeInclusion),

View File

@ -2,6 +2,7 @@ use bigdecimal::BigDecimal;
use num_traits::cast::FromPrimitive;
use num_traits::cast::ToPrimitive;
/// Enable big decimal serialization by providing a `serialize` function
pub fn serialize<S>(big_decimal: &BigDecimal, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
@ -14,6 +15,7 @@ where
)
}
/// Enable big decimal deserialization by providing a `deserialize` function
pub fn deserialize<'de, D>(deserializer: D) -> Result<BigDecimal, D::Error>
where
D: serde::Deserializer<'de>,

View File

@ -2,6 +2,7 @@ use num_bigint::BigInt;
use num_traits::cast::FromPrimitive;
use num_traits::cast::ToPrimitive;
/// Enable big int serialization by providing a `serialize` function
pub fn serialize<S>(big_int: &BigInt, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
@ -14,6 +15,7 @@ where
)
}
/// Enable big int deserialization by providing a `deserialize` function
pub fn deserialize<'de, D>(deserializer: D) -> Result<BigInt, D::Error>
where
D: serde::Deserializer<'de>,