Add some comments (#1225)

This commit is contained in:
Jonathan Turner 2020-01-14 20:38:56 +13:00 committed by GitHub
parent 3adf52b1c4
commit b32eceffb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 0 deletions

View File

@ -304,6 +304,7 @@ impl serde::de::Error for ShellError {
}
impl ShellError {
/// An error that describes a mismatch between the given type and the expected type
pub fn type_error(
expected: impl Into<String>,
actual: Spanned<impl Into<String>>,

View File

@ -5,6 +5,7 @@ use nu_source::{b, span_for_spanned_list, DebugDocBuilder, HasFallibleSpan, Pret
use num_bigint::BigInt;
use serde::{Deserialize, Serialize};
/// A PathMember that has yet to be spanned so that it can be used in later processing
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum UnspannedPathMember {
String(String),
@ -12,6 +13,7 @@ pub enum UnspannedPathMember {
}
impl UnspannedPathMember {
/// Add the span information and get a full PathMember
pub fn into_path_member(self, span: impl Into<Span>) -> PathMember {
PathMember {
unspanned: self,
@ -20,6 +22,7 @@ impl UnspannedPathMember {
}
}
/// A basic piece of a ColumnPath, which describes the steps to take through a table to arrive a cell, row, or inner table
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub struct PathMember {
pub unspanned: UnspannedPathMember,
@ -27,6 +30,7 @@ pub struct PathMember {
}
impl PrettyDebug for &PathMember {
/// Gets the PathMember ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
match &self.unspanned {
UnspannedPathMember::String(string) => b::primitive(format!("{:?}", string)),
@ -35,6 +39,10 @@ impl PrettyDebug for &PathMember {
}
}
/// The fundamental path primitive to descrive how to navigate through a table to get to a sub-item. A path member can be either a word or a number. Words/strings are taken to mean
/// a column name, and numbers are the row number. Taken together they describe which column or row to narrow to in order to get data.
///
/// Rows must follow column names, they can't come first. eg) `foo.1` is valid where `1.foo` is not.
#[derive(
Debug, Hash, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Getters, Clone, new,
)]
@ -44,16 +52,19 @@ pub struct ColumnPath {
}
impl ColumnPath {
/// Iterate over the members of the column path
pub fn iter(&self) -> impl Iterator<Item = &PathMember> {
self.members.iter()
}
/// Returns the last member and a slice of the remaining members
pub fn split_last(&self) -> Option<(&PathMember, &[PathMember])> {
self.members.split_last()
}
}
impl PrettyDebug for ColumnPath {
/// Gets the ColumnPath ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
let members: Vec<DebugDocBuilder> =
self.members.iter().map(|member| member.pretty()).collect();
@ -68,6 +79,7 @@ impl PrettyDebug for ColumnPath {
}
impl HasFallibleSpan for ColumnPath {
/// Creates a span that will cover the column path, if possible
fn maybe_span(&self) -> Option<Span> {
if self.members.is_empty() {
None
@ -78,15 +90,18 @@ impl HasFallibleSpan for ColumnPath {
}
impl PathMember {
/// Create a string path member
pub fn string(string: impl Into<String>, span: impl Into<Span>) -> PathMember {
UnspannedPathMember::String(string.into()).into_path_member(span)
}
/// Create a numeric path member
pub fn int(int: impl Into<BigInt>, span: impl Into<Span>) -> PathMember {
UnspannedPathMember::Int(int.into()).into_path_member(span)
}
}
/// Prepares a list of "sounds like" matches for the string you're trying to find
pub fn did_you_mean(obj_source: &Value, field_tried: &PathMember) -> Option<Vec<(usize, String)>> {
let field_tried = match &field_tried.unspanned {
UnspannedPathMember::String(string) => string.clone(),

View File

@ -8,6 +8,7 @@ use nu_source::TaggedItem;
impl std::convert::TryFrom<&Value> for i64 {
type Error = ShellError;
/// Convert to an i64 integer, if possible
fn try_from(value: &Value) -> Result<i64, ShellError> {
match &value.value {
UntaggedValue::Primitive(Primitive::Int(int)) => {
@ -21,6 +22,7 @@ impl std::convert::TryFrom<&Value> for i64 {
impl std::convert::TryFrom<&Value> for String {
type Error = ShellError;
/// Convert to a string, if possible
fn try_from(value: &Value) -> Result<String, ShellError> {
match &value.value {
UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()),
@ -32,6 +34,7 @@ impl std::convert::TryFrom<&Value> for String {
impl std::convert::TryFrom<&Value> for Vec<u8> {
type Error = ShellError;
/// Convert to a u8 vec, if possible
fn try_from(value: &Value) -> Result<Vec<u8>, ShellError> {
match &value.value {
UntaggedValue::Primitive(Primitive::Binary(b)) => Ok(b.clone()),
@ -43,6 +46,7 @@ impl std::convert::TryFrom<&Value> for Vec<u8> {
impl<'a> std::convert::TryFrom<&'a Value> for &'a Dictionary {
type Error = ShellError;
/// Convert to a dictionary, if possible
fn try_from(value: &'a Value) -> Result<&'a Dictionary, ShellError> {
match &value.value {
UntaggedValue::Row(d) => Ok(d),

View File

@ -4,12 +4,14 @@ use crate::value::{UntaggedValue, Value};
use nu_source::{b, DebugDocBuilder, PrettyDebug};
impl PrettyDebug for &Value {
/// Get a borrowed Value ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
PrettyDebug::pretty(*self)
}
}
impl PrettyDebug for Value {
/// Get a Value ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
match &self.value {
UntaggedValue::Primitive(p) => p.pretty(),
@ -24,6 +26,7 @@ impl PrettyDebug for Value {
}
impl PrettyType for Primitive {
/// Find the type of the Value and prepare it for pretty-printing
fn pretty_type(&self) -> DebugDocBuilder {
match self {
Primitive::Nothing => ty("nothing"),
@ -47,6 +50,7 @@ impl PrettyType for Primitive {
}
impl PrettyDebug for Primitive {
/// Get a Primitive value ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
match self {
Primitive::Nothing => b::primitive("nothing"),

View File

@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize};
use std::cmp::{Ord, Ordering, PartialOrd};
use std::hash::{Hash, Hasher};
/// A dictionary that can hold a mapping from names to Values
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, Clone, Getters, new)]
pub struct Dictionary {
#[get = "pub"]
@ -17,6 +18,7 @@ pub struct Dictionary {
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for Dictionary {
/// Create the hash function to allow the Hash trait for dictionaries
fn hash<H: Hasher>(&self, state: &mut H) {
let mut entries = self.entries.clone();
entries.sort_keys();
@ -26,6 +28,7 @@ impl Hash for Dictionary {
}
impl PartialOrd for Dictionary {
/// Compare two dictionaries for sort ordering
fn partial_cmp(&self, other: &Dictionary) -> Option<Ordering> {
let this: Vec<&String> = self.entries.keys().collect();
let that: Vec<&String> = other.entries.keys().collect();
@ -42,6 +45,7 @@ impl PartialOrd for Dictionary {
}
impl Ord for Dictionary {
/// Compare two dictionaries for ordering
fn cmp(&self, other: &Dictionary) -> Ordering {
let this: Vec<&String> = self.entries.keys().collect();
let that: Vec<&String> = other.entries.keys().collect();
@ -58,6 +62,7 @@ impl Ord for Dictionary {
}
impl PartialEq<Value> for Dictionary {
/// Test a dictionary against a Value for equality
fn eq(&self, other: &Value) -> bool {
match &other.value {
UntaggedValue::Row(d) => self == d,
@ -66,6 +71,7 @@ impl PartialEq<Value> for Dictionary {
}
}
/// A key-value pair specifically meant to be used in debug and pretty-printing
#[derive(Debug, new)]
struct DebugEntry<'a> {
key: &'a str,
@ -73,12 +79,14 @@ struct DebugEntry<'a> {
}
impl<'a> PrettyDebug for DebugEntry<'a> {
/// Build the the information to pretty-print the DebugEntry
fn pretty(&self) -> DebugDocBuilder {
(b::key(self.key.to_string()) + b::equals() + self.value.pretty().into_value()).group()
}
}
impl PrettyDebug for Dictionary {
/// Get a Dictionary ready to be pretty-printed
fn pretty(&self) -> DebugDocBuilder {
b::delimit(
"(",
@ -94,6 +102,7 @@ impl PrettyDebug for Dictionary {
}
impl From<IndexMap<String, Value>> for Dictionary {
/// Create a dictionary from a map of strings to Values
fn from(input: IndexMap<String, Value>) -> Dictionary {
let mut out = IndexMap::default();
@ -106,6 +115,7 @@ impl From<IndexMap<String, Value>> for Dictionary {
}
impl Dictionary {
/// Find the matching Value for a given key, if possible. If not, return a Primitive::Nothing
pub fn get_data(&self, desc: &str) -> MaybeOwned<'_, Value> {
match self.entries.get(desc) {
Some(v) => MaybeOwned::Borrowed(v),
@ -115,10 +125,12 @@ impl Dictionary {
}
}
/// Iterate the keys in the Dictionary
pub fn keys(&self) -> impl Iterator<Item = &String> {
self.entries.keys()
}
/// Find the matching Value for a key, if possible
pub fn get_data_by_key(&self, name: Spanned<&str>) -> Option<Value> {
let result = self
.entries
@ -134,6 +146,7 @@ impl Dictionary {
)
}
/// Get a mutable entry that matches a key, if possible
pub fn get_mut_data_by_key(&mut self, name: &str) -> Option<&mut Value> {
match self
.entries
@ -145,11 +158,13 @@ impl Dictionary {
}
}
/// Insert a new key/value pair into the dictionary
pub fn insert_data_at_key(&mut self, name: &str, value: Value) {
self.entries.insert(name.to_string(), value);
}
}
/// A helper to help create dictionaries for you. It has the ability to insert values into the dictionary while maintaining the tags that need to be applied to the individual members
#[derive(Debug)]
pub struct TaggedDictBuilder {
tag: Tag,
@ -157,6 +172,7 @@ pub struct TaggedDictBuilder {
}
impl TaggedDictBuilder {
/// Create a new builder
pub fn new(tag: impl Into<Tag>) -> TaggedDictBuilder {
TaggedDictBuilder {
tag: tag.into(),
@ -164,6 +180,7 @@ impl TaggedDictBuilder {
}
}
/// Build the contents of the builder into a Value
pub fn build(tag: impl Into<Tag>, block: impl FnOnce(&mut TaggedDictBuilder)) -> Value {
let mut builder = TaggedDictBuilder::new(tag);
block(&mut builder);

View File

@ -226,6 +226,7 @@ impl History {
}
}
/// The entry point for the CLI. Will register all known internal commands, load experimental commands, load plugins, then prepare the prompt and line reader for input.
pub async fn cli() -> Result<(), Box<dyn Error>> {
let mut context = Context::basic()?;
@ -560,6 +561,7 @@ enum LineResult {
Break,
}
/// Process the line by parsing the text to turn it into commands, classify those commands so that we understand what is being called in the pipeline, and then run this pipeline
async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context) -> LineResult {
match &readline {
Ok(line) if line.trim() == "" => LineResult::Success(line.clone()),