mirror of
https://github.com/nushell/nushell.git
synced 2024-11-25 18:03:51 +01:00
Remove Record::from_raw_cols_vals_unchecked
(#11810)
# Description Follows from #11718 and replaces all usages of `Record::from_raw_cols_vals_unchecked` with iterator or `record!` equivalents.
This commit is contained in:
parent
28f0f32ae7
commit
fb4251aba7
@ -5,7 +5,7 @@ use nu_engine::CallExt;
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, Record, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
record, Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
use polars::prelude::*;
|
use polars::prelude::*;
|
||||||
|
|
||||||
@ -52,13 +52,10 @@ impl Command for CastDF {
|
|||||||
description: "Cast a column in a dataframe to a different dtype",
|
description: "Cast a column in a dataframe to a different dtype",
|
||||||
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr cast u8 a | dfr schema",
|
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr cast u8 a | dfr schema",
|
||||||
result: Some(Value::record(
|
result: Some(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(
|
record! {
|
||||||
vec!["a".to_string(), "b".to_string()],
|
"a" => Value::string("u8", Span::test_data()),
|
||||||
vec![
|
"b" => Value::string("i64", Span::test_data()),
|
||||||
Value::string("u8", Span::test_data()),
|
},
|
||||||
Value::string("i64", Span::test_data()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Span::test_data(),
|
Span::test_data(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
@ -66,13 +63,10 @@ impl Command for CastDF {
|
|||||||
description: "Cast a column in a lazy dataframe to a different dtype",
|
description: "Cast a column in a lazy dataframe to a different dtype",
|
||||||
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr into-lazy | dfr cast u8 a | dfr schema",
|
example: "[[a b]; [1 2] [3 4]] | dfr into-df | dfr into-lazy | dfr cast u8 a | dfr schema",
|
||||||
result: Some(Value::record(
|
result: Some(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(
|
record! {
|
||||||
vec!["a".to_string(), "b".to_string()],
|
"a" => Value::string("u8", Span::test_data()),
|
||||||
vec![
|
"b" => Value::string("i64", Span::test_data()),
|
||||||
Value::string("u8", Span::test_data()),
|
},
|
||||||
Value::string("i64", Span::test_data()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Span::test_data(),
|
Span::test_data(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@ use nu_engine::CallExt;
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, Record, ShellError, Signature, Span, Type, Value,
|
record, Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -33,13 +33,10 @@ impl Command for SchemaDF {
|
|||||||
description: "Dataframe schema",
|
description: "Dataframe schema",
|
||||||
example: r#"[[a b]; [1 "foo"] [3 "bar"]] | dfr into-df | dfr schema"#,
|
example: r#"[[a b]; [1 "foo"] [3 "bar"]] | dfr into-df | dfr schema"#,
|
||||||
result: Some(Value::record(
|
result: Some(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(
|
record! {
|
||||||
vec!["a".to_string(), "b".to_string()],
|
"a" => Value::string("i64", Span::test_data()),
|
||||||
vec![
|
"b" => Value::string("str", Span::test_data()),
|
||||||
Value::string("i64", Span::test_data()),
|
},
|
||||||
Value::string("str", Span::test_data()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Span::test_data(),
|
Span::test_data(),
|
||||||
)),
|
)),
|
||||||
}]
|
}]
|
||||||
@ -98,10 +95,11 @@ fn datatype_list(span: Span) -> Value {
|
|||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(dtype, note)| {
|
.map(|(dtype, note)| {
|
||||||
Value::record(Record::from_raw_cols_vals_unchecked(
|
Value::record(record! {
|
||||||
vec!["dtype".to_string(), "note".to_string()],
|
"dtype" => Value::string(*dtype, span),
|
||||||
vec![Value::string(*dtype, span), Value::string(*note, span)],
|
"note" => Value::string(*note, span),
|
||||||
),span)
|
},
|
||||||
|
span)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Value::list(types, span)
|
Value::list(types, span)
|
||||||
|
@ -1033,15 +1033,14 @@ fn series_to_values(
|
|||||||
Either::Right(it)
|
Either::Right(it)
|
||||||
}
|
}
|
||||||
.map(|any_values| {
|
.map(|any_values| {
|
||||||
let vals: Result<Vec<Value>, ShellError> = any_values
|
let record = polar_fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| any_value_to_value(v, span))
|
.zip(any_values)
|
||||||
.collect();
|
.map(|(field, val)| {
|
||||||
let cols: Vec<String> = polar_fields
|
any_value_to_value(val, span).map(|val| (field.name.to_string(), val))
|
||||||
.iter()
|
})
|
||||||
.map(|field| field.name.to_string())
|
.collect::<Result<_, _>>()?;
|
||||||
.collect();
|
|
||||||
let record = Record::from_raw_cols_vals_unchecked(cols, vals?);
|
|
||||||
Ok(Value::record(record, span))
|
Ok(Value::record(record, span))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -1138,20 +1137,16 @@ fn any_value_to_value(any_value: &AnyValue, span: Span) -> Result<Value, ShellEr
|
|||||||
any_value_to_value(&static_value, span)
|
any_value_to_value(&static_value, span)
|
||||||
}
|
}
|
||||||
AnyValue::StructOwned(struct_tuple) => {
|
AnyValue::StructOwned(struct_tuple) => {
|
||||||
let values: Result<Vec<Value>, ShellError> = struct_tuple
|
let record = struct_tuple
|
||||||
.0
|
|
||||||
.iter()
|
|
||||||
.map(|s| any_value_to_value(s, span))
|
|
||||||
.collect();
|
|
||||||
let fields = struct_tuple
|
|
||||||
.1
|
.1
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| f.name().to_string())
|
.zip(&struct_tuple.0)
|
||||||
.collect();
|
.map(|(field, val)| {
|
||||||
Ok(Value::Record {
|
any_value_to_value(val, span).map(|val| (field.name.to_string(), val))
|
||||||
val: Record::from_raw_cols_vals_unchecked(fields, values?),
|
|
||||||
internal_span: span,
|
|
||||||
})
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
Ok(Value::record(record, span))
|
||||||
}
|
}
|
||||||
AnyValue::StringOwned(s) => Ok(Value::string(s.to_string(), span)),
|
AnyValue::StringOwned(s) => Ok(Value::string(s.to_string(), span)),
|
||||||
AnyValue::Binary(bytes) => Ok(Value::binary(*bytes, span)),
|
AnyValue::Binary(bytes) => Ok(Value::binary(*bytes, span)),
|
||||||
|
@ -154,15 +154,13 @@ impl NuDataFrame {
|
|||||||
match value {
|
match value {
|
||||||
Value::CustomValue { .. } => return Self::try_from_value(value),
|
Value::CustomValue { .. } => return Self::try_from_value(value),
|
||||||
Value::List { vals, .. } => {
|
Value::List { vals, .. } => {
|
||||||
let cols = (0..vals.len())
|
let record = vals
|
||||||
.map(|i| format!("{i}"))
|
.into_iter()
|
||||||
.collect::<Vec<String>>();
|
.enumerate()
|
||||||
|
.map(|(i, val)| (format!("{i}"), val))
|
||||||
|
.collect();
|
||||||
|
|
||||||
conversion::insert_record(
|
conversion::insert_record(&mut column_values, record, &maybe_schema)?
|
||||||
&mut column_values,
|
|
||||||
Record::from_raw_cols_vals_unchecked(cols, vals),
|
|
||||||
&maybe_schema,
|
|
||||||
)?
|
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
conversion::insert_record(&mut column_values, record, &maybe_schema)?
|
conversion::insert_record(&mut column_values, record, &maybe_schema)?
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use nu_protocol::{Record, ShellError, Span, Value};
|
use nu_protocol::{ShellError, Span, Value};
|
||||||
use polars::prelude::{DataType, Field, Schema, SchemaRef, TimeUnit};
|
use polars::prelude::{DataType, Field, Schema, SchemaRef, TimeUnit};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -37,15 +37,14 @@ impl From<NuSchema> for SchemaRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fields_to_value(fields: impl Iterator<Item = Field>, span: Span) -> Value {
|
fn fields_to_value(fields: impl Iterator<Item = Field>, span: Span) -> Value {
|
||||||
let (cols, vals) = fields
|
let record = fields
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let val = dtype_to_value(field.data_type(), span);
|
|
||||||
let col = field.name().to_string();
|
let col = field.name().to_string();
|
||||||
|
let val = dtype_to_value(field.data_type(), span);
|
||||||
(col, val)
|
(col, val)
|
||||||
})
|
})
|
||||||
.unzip();
|
.collect();
|
||||||
|
|
||||||
let record = Record::from_raw_cols_vals_unchecked(cols, vals);
|
|
||||||
Value::record(record, Span::unknown())
|
Value::record(record, Span::unknown())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,42 +187,23 @@ fn str_to_time_unit(ts_string: &str, span: Span) -> Result<TimeUnit, ShellError>
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
|
use nu_protocol::record;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_value_to_schema() {
|
fn test_value_to_schema() {
|
||||||
let value = Value::Record {
|
let address = record! {
|
||||||
val: Record::from_raw_cols_vals_unchecked(
|
"street" => Value::test_string("str"),
|
||||||
vec!["name".into(), "age".into(), "address".into()],
|
"city" => Value::test_string("str"),
|
||||||
vec![
|
|
||||||
Value::String {
|
|
||||||
val: "str".into(),
|
|
||||||
internal_span: Span::test_data(),
|
|
||||||
},
|
|
||||||
Value::String {
|
|
||||||
val: "i32".into(),
|
|
||||||
internal_span: Span::test_data(),
|
|
||||||
},
|
|
||||||
Value::Record {
|
|
||||||
val: Record::from_raw_cols_vals_unchecked(
|
|
||||||
vec!["street".into(), "city".into()],
|
|
||||||
vec![
|
|
||||||
Value::String {
|
|
||||||
val: "str".into(),
|
|
||||||
internal_span: Span::test_data(),
|
|
||||||
},
|
|
||||||
Value::String {
|
|
||||||
val: "str".into(),
|
|
||||||
internal_span: Span::test_data(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
),
|
|
||||||
internal_span: Span::test_data(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
),
|
|
||||||
internal_span: Span::test_data(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let value = Value::test_record(record! {
|
||||||
|
"name" => Value::test_string("str"),
|
||||||
|
"age" => Value::test_string("i32"),
|
||||||
|
"address" => Value::test_record(address)
|
||||||
|
});
|
||||||
|
|
||||||
let schema = value_to_schema(&value, Span::unknown()).unwrap();
|
let schema = value_to_schema(&value, Span::unknown()).unwrap();
|
||||||
let expected = Schema::from_iter(vec![
|
let expected = Schema::from_iter(vec![
|
||||||
Field::new("name", DataType::String),
|
Field::new("name", DataType::String),
|
||||||
|
@ -4,7 +4,7 @@ mod roll_left;
|
|||||||
mod roll_right;
|
mod roll_right;
|
||||||
mod roll_up;
|
mod roll_up;
|
||||||
|
|
||||||
use nu_protocol::{Record, ShellError, Value};
|
use nu_protocol::{ShellError, Value};
|
||||||
pub use roll_::Roll;
|
pub use roll_::Roll;
|
||||||
pub use roll_down::RollDown;
|
pub use roll_down::RollDown;
|
||||||
pub use roll_left::RollLeft;
|
pub use roll_left::RollLeft;
|
||||||
@ -70,10 +70,8 @@ fn horizontal_rotate_value(
|
|||||||
HorizontalDirection::Left => vals.rotate_left(rotations),
|
HorizontalDirection::Left => vals.rotate_left(rotations),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::record(
|
let record = cols.into_iter().zip(vals).collect();
|
||||||
Record::from_raw_cols_vals_unchecked(cols, vals),
|
Ok(Value::record(record, span))
|
||||||
span,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
Value::List { vals, .. } => {
|
Value::List { vals, .. } => {
|
||||||
let values = vals
|
let values = vals
|
||||||
|
@ -4,7 +4,7 @@ use nu_engine::CallExt;
|
|||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
record, Category, Example, IntoPipelineData, PipelineData, Record, ShellError, Signature, Span,
|
record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span,
|
||||||
Spanned, SyntaxShape, Type, Value,
|
Spanned, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -239,13 +239,6 @@ fn histogram_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let result_cols = vec![
|
|
||||||
value_column_name.to_string(),
|
|
||||||
"count".to_string(),
|
|
||||||
"quantile".to_string(),
|
|
||||||
"percentage".to_string(),
|
|
||||||
freq_column.to_string(),
|
|
||||||
];
|
|
||||||
const MAX_FREQ_COUNT: f64 = 100.0;
|
const MAX_FREQ_COUNT: f64 = 100.0;
|
||||||
for (val, count) in counter.into_iter().sorted() {
|
for (val, count) in counter.into_iter().sorted() {
|
||||||
let quantile = match calc_method {
|
let quantile = match calc_method {
|
||||||
@ -259,16 +252,13 @@ fn histogram_impl(
|
|||||||
result.push((
|
result.push((
|
||||||
count, // attach count first for easily sorting.
|
count, // attach count first for easily sorting.
|
||||||
Value::record(
|
Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(
|
record! {
|
||||||
result_cols.clone(),
|
value_column_name => val.into_value(),
|
||||||
vec![
|
"count" => Value::int(count, span),
|
||||||
val.into_value(),
|
"quantile" => Value::float(quantile, span),
|
||||||
Value::int(count, span),
|
"percentage" => Value::string(percentage, span),
|
||||||
Value::float(quantile, span),
|
freq_column => Value::string(freq, span),
|
||||||
Value::string(percentage, span),
|
},
|
||||||
Value::string(freq, span),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
span,
|
span,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
@ -441,15 +441,15 @@ fn prepared_statement_to_nu_list(
|
|||||||
) -> Result<Value, SqliteError> {
|
) -> Result<Value, SqliteError> {
|
||||||
let column_names = stmt
|
let column_names = stmt
|
||||||
.column_names()
|
.column_names()
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|c| c.to_string())
|
.map(String::from)
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
let row_results = stmt.query_map([], |row| {
|
let row_results = stmt.query_map([], |row| {
|
||||||
Ok(convert_sqlite_row_to_nu_value(
|
Ok(convert_sqlite_row_to_nu_value(
|
||||||
row,
|
row,
|
||||||
call_span,
|
call_span,
|
||||||
column_names.clone(),
|
&column_names,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -491,18 +491,19 @@ fn read_entire_sqlite_db(
|
|||||||
Ok(Value::record(tables, call_span))
|
Ok(Value::record(tables, call_span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_sqlite_row_to_nu_value(row: &Row, span: Span, column_names: Vec<String>) -> Value {
|
pub fn convert_sqlite_row_to_nu_value(row: &Row, span: Span, column_names: &[String]) -> Value {
|
||||||
let mut vals = Vec::with_capacity(column_names.len());
|
let record = column_names
|
||||||
|
.iter()
|
||||||
for i in 0..column_names.len() {
|
.enumerate()
|
||||||
let val = convert_sqlite_value_to_nu_value(row.get_ref_unwrap(i), span);
|
.map(|(i, col)| {
|
||||||
vals.push(val);
|
(
|
||||||
}
|
col.clone(),
|
||||||
|
convert_sqlite_value_to_nu_value(row.get_ref_unwrap(i), span),
|
||||||
Value::record(
|
|
||||||
Record::from_raw_cols_vals_unchecked(column_names, vals),
|
|
||||||
span,
|
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Value::record(record, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_sqlite_value_to_nu_value(value: ValueRef, span: Span) -> Value {
|
pub fn convert_sqlite_value_to_nu_value(value: ValueRef, span: Span) -> Value {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use csv::{ReaderBuilder, Trim};
|
use csv::{ReaderBuilder, Trim};
|
||||||
use nu_protocol::{IntoPipelineData, PipelineData, Record, ShellError, Span, Value};
|
use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Span, Value};
|
||||||
|
|
||||||
fn from_delimited_string_to_value(
|
fn from_delimited_string_to_value(
|
||||||
DelimitedReaderConfig {
|
DelimitedReaderConfig {
|
||||||
@ -36,28 +36,28 @@ fn from_delimited_string_to_value(
|
|||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
for row in reader.records() {
|
for row in reader.records() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let output_row = (0..headers.len())
|
let columns = headers.iter().cloned();
|
||||||
.map(|i| {
|
let values = row
|
||||||
row.get(i)
|
.into_iter()
|
||||||
.map(|value| {
|
.map(|s| {
|
||||||
if no_infer {
|
if no_infer {
|
||||||
Value::string(value.to_string(), span)
|
Value::string(s, span)
|
||||||
} else if let Ok(i) = value.parse::<i64>() {
|
} else if let Ok(i) = s.parse() {
|
||||||
Value::int(i, span)
|
Value::int(i, span)
|
||||||
} else if let Ok(f) = value.parse::<f64>() {
|
} else if let Ok(f) = s.parse() {
|
||||||
Value::float(f, span)
|
Value::float(f, span)
|
||||||
} else {
|
} else {
|
||||||
Value::string(value.to_string(), span)
|
Value::string(s, span)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(Value::nothing(span))
|
.chain(std::iter::repeat(Value::nothing(span)));
|
||||||
})
|
|
||||||
.collect::<Vec<Value>>();
|
|
||||||
|
|
||||||
rows.push(Value::record(
|
// If there are more values than the number of headers,
|
||||||
Record::from_raw_cols_vals_unchecked(headers.clone(), output_row),
|
// then the remaining values are ignored.
|
||||||
span,
|
//
|
||||||
));
|
// Otherwise, if there are less values than headers,
|
||||||
|
// then `Value::nothing(span)` is used to fill the remaining columns.
|
||||||
|
rows.push(Value::record(columns.zip(values).collect(), span));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::list(rows, span))
|
Ok(Value::list(rows, span))
|
||||||
|
@ -421,15 +421,16 @@ fn convert_to_value(
|
|||||||
span: expr.span,
|
span: expr.span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let vals: Vec<Value> = row
|
|
||||||
.into_iter()
|
let record = cols
|
||||||
.map(|cell| convert_to_value(cell, span, original_text))
|
.iter()
|
||||||
|
.zip(row)
|
||||||
|
.map(|(col, cell)| {
|
||||||
|
convert_to_value(cell, span, original_text).map(|val| (col.clone(), val))
|
||||||
|
})
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
output.push(Value::record(
|
output.push(Value::record(record, span));
|
||||||
Record::from_raw_cols_vals_unchecked(cols.clone(), vals),
|
|
||||||
span,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::list(output, span))
|
Ok(Value::list(output, span))
|
||||||
|
@ -136,13 +136,11 @@ fn detect_columns(
|
|||||||
.map(move |x| {
|
.map(move |x| {
|
||||||
let row = find_columns(&x);
|
let row = find_columns(&x);
|
||||||
|
|
||||||
let mut cols = vec![];
|
let mut record = Record::new();
|
||||||
let mut vals = vec![];
|
|
||||||
|
|
||||||
if headers.len() == row.len() {
|
if headers.len() == row.len() {
|
||||||
for (header, val) in headers.iter().zip(row.iter()) {
|
for (header, val) in headers.iter().zip(row.iter()) {
|
||||||
cols.push(header.item.clone());
|
record.push(&header.item, Value::string(&val.item, name_span));
|
||||||
vals.push(Value::string(val.item.clone(), name_span));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut pre_output = vec![];
|
let mut pre_output = vec![];
|
||||||
@ -176,8 +174,7 @@ fn detect_columns(
|
|||||||
for header in &headers {
|
for header in &headers {
|
||||||
for pre_o in &pre_output {
|
for pre_o in &pre_output {
|
||||||
if pre_o.0 == header.item {
|
if pre_o.0 == header.item {
|
||||||
cols.push(header.item.clone());
|
record.push(&header.item, pre_o.1.clone());
|
||||||
vals.push(pre_o.1.clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,25 +184,25 @@ fn detect_columns(
|
|||||||
match nu_cmd_base::util::process_range(range) {
|
match nu_cmd_base::util::process_range(range) {
|
||||||
Ok((l_idx, r_idx)) => {
|
Ok((l_idx, r_idx)) => {
|
||||||
let l_idx = if l_idx < 0 {
|
let l_idx = if l_idx < 0 {
|
||||||
cols.len() as isize + l_idx
|
record.len() as isize + l_idx
|
||||||
} else {
|
} else {
|
||||||
l_idx
|
l_idx
|
||||||
};
|
};
|
||||||
|
|
||||||
let r_idx = if r_idx < 0 {
|
let r_idx = if r_idx < 0 {
|
||||||
cols.len() as isize + r_idx
|
record.len() as isize + r_idx
|
||||||
} else {
|
} else {
|
||||||
r_idx
|
r_idx
|
||||||
};
|
};
|
||||||
|
|
||||||
if !(l_idx <= r_idx && (r_idx >= 0 || l_idx < (cols.len() as isize))) {
|
if !(l_idx <= r_idx && (r_idx >= 0 || l_idx < (record.len() as isize))) {
|
||||||
return Value::record(
|
return Value::record(record, name_span);
|
||||||
Record::from_raw_cols_vals_unchecked(cols, vals),
|
|
||||||
name_span,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(l_idx.max(0) as usize, (r_idx as usize + 1).min(cols.len()))
|
(
|
||||||
|
l_idx.max(0) as usize,
|
||||||
|
(r_idx as usize + 1).min(record.len()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Err(processing_error) => {
|
Err(processing_error) => {
|
||||||
let err = processing_error("could not find range index", name_span);
|
let err = processing_error("could not find range index", name_span);
|
||||||
@ -213,9 +210,11 @@ fn detect_columns(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Value::record(Record::from_raw_cols_vals_unchecked(cols, vals), name_span);
|
return Value::record(record, name_span);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (mut cols, mut vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
|
||||||
|
|
||||||
// Merge Columns
|
// Merge Columns
|
||||||
((start_index + 1)..(cols.len() - end_index + start_index + 1)).for_each(|idx| {
|
((start_index + 1)..(cols.len() - end_index + start_index + 1)).for_each(|idx| {
|
||||||
cols.swap(idx, end_index - start_index - 1 + idx);
|
cols.swap(idx, end_index - start_index - 1 + idx);
|
||||||
@ -233,9 +232,12 @@ fn detect_columns(
|
|||||||
let last_seg = vals.split_off(end_index);
|
let last_seg = vals.split_off(end_index);
|
||||||
vals.truncate(start_index);
|
vals.truncate(start_index);
|
||||||
vals.push(binding);
|
vals.push(binding);
|
||||||
last_seg.into_iter().for_each(|v| vals.push(v));
|
vals.extend(last_seg);
|
||||||
|
|
||||||
Value::record(Record::from_raw_cols_vals_unchecked(cols, vals), name_span)
|
match Record::from_raw_cols_vals(cols, vals, Span::unknown(), name_span) {
|
||||||
|
Ok(record) => Value::record(record, name_span),
|
||||||
|
Err(err) => Value::error(err, name_span),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.into_pipeline_data(ctrlc))
|
.into_pipeline_data(ctrlc))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{io::Write, path::PathBuf};
|
use std::{io::Write, path::PathBuf};
|
||||||
|
|
||||||
use chrono::{DateTime, FixedOffset, NaiveDateTime, Offset};
|
use chrono::{DateTime, FixedOffset, NaiveDateTime, Offset};
|
||||||
use nu_protocol::{ast::PathMember, Record, Span, Value};
|
use nu_protocol::{ast::PathMember, record, Span, Value};
|
||||||
use nu_test_support::{
|
use nu_test_support::{
|
||||||
fs::{line_ending, Stub},
|
fs::{line_ending, Stub},
|
||||||
nu, pipeline,
|
nu, pipeline,
|
||||||
@ -234,22 +234,16 @@ impl TestRow {
|
|||||||
impl From<TestRow> for Value {
|
impl From<TestRow> for Value {
|
||||||
fn from(row: TestRow) -> Self {
|
fn from(row: TestRow) -> Self {
|
||||||
Value::record(
|
Value::record(
|
||||||
Record::from_iter(vec![
|
record! {
|
||||||
("somebool".into(), Value::bool(row.0, Span::unknown())),
|
"somebool" => Value::bool(row.0, Span::unknown()),
|
||||||
("someint".into(), Value::int(row.1, Span::unknown())),
|
"someint" => Value::int(row.1, Span::unknown()),
|
||||||
("somefloat".into(), Value::float(row.2, Span::unknown())),
|
"somefloat" => Value::float(row.2, Span::unknown()),
|
||||||
(
|
"somefilesize" => Value::filesize(row.3, Span::unknown()),
|
||||||
"somefilesize".into(),
|
"someduration" => Value::duration(row.4, Span::unknown()),
|
||||||
Value::filesize(row.3, Span::unknown()),
|
"somedate" => Value::date(row.5, Span::unknown()),
|
||||||
),
|
"somestring" => Value::string(row.6, Span::unknown()),
|
||||||
(
|
"somebinary" => Value::binary(row.7, Span::unknown()),
|
||||||
"someduration".into(),
|
},
|
||||||
Value::duration(row.4, Span::unknown()),
|
|
||||||
),
|
|
||||||
("somedate".into(), Value::date(row.5, Span::unknown())),
|
|
||||||
("somestring".into(), Value::string(row.6, Span::unknown())),
|
|
||||||
("somebinary".into(), Value::binary(row.7, Span::unknown())),
|
|
||||||
]),
|
|
||||||
Span::unknown(),
|
Span::unknown(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Expr,
|
ast::Expr,
|
||||||
engine::{Command, EngineState, Stack, Visibility},
|
engine::{Command, EngineState, Stack, Visibility},
|
||||||
record, ModuleId, Record, Signature, Span, SyntaxShape, Type, Value,
|
record, ModuleId, Signature, Span, SyntaxShape, Type, Value,
|
||||||
};
|
};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -185,101 +185,81 @@ impl<'e, 's> ScopeData<'e, 's> {
|
|||||||
) -> Vec<Value> {
|
) -> Vec<Value> {
|
||||||
let mut sig_records = vec![];
|
let mut sig_records = vec![];
|
||||||
|
|
||||||
let sig_cols = vec![
|
|
||||||
"parameter_name".to_string(),
|
|
||||||
"parameter_type".to_string(),
|
|
||||||
"syntax_shape".to_string(),
|
|
||||||
"is_optional".to_string(),
|
|
||||||
"short_flag".to_string(),
|
|
||||||
"description".to_string(),
|
|
||||||
"custom_completion".to_string(),
|
|
||||||
"parameter_default".to_string(),
|
|
||||||
];
|
|
||||||
|
|
||||||
// input
|
// input
|
||||||
sig_records.push(Value::record(
|
sig_records.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(
|
record! {
|
||||||
sig_cols.clone(),
|
"parameter_name" => Value::nothing(span),
|
||||||
vec![
|
"parameter_type" => Value::string("input", span),
|
||||||
Value::nothing(span),
|
"syntax_shape" => Value::string(input_type.to_shape().to_string(), span),
|
||||||
Value::string("input", span),
|
"is_optional" => Value::bool(false, span),
|
||||||
Value::string(input_type.to_shape().to_string(), span),
|
"short_flag" => Value::nothing(span),
|
||||||
Value::bool(false, span),
|
"description" => Value::nothing(span),
|
||||||
Value::nothing(span),
|
"custom_completion" => Value::nothing(span),
|
||||||
Value::nothing(span),
|
"parameter_default" => Value::nothing(span),
|
||||||
Value::nothing(span),
|
},
|
||||||
Value::nothing(span),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
|
|
||||||
// required_positional
|
// required_positional
|
||||||
for req in &signature.required_positional {
|
for req in &signature.required_positional {
|
||||||
let sig_vals = vec![
|
let custom = extract_custom_completion_from_arg(self.engine_state, &req.shape);
|
||||||
Value::string(&req.name, span),
|
|
||||||
Value::string("positional", span),
|
|
||||||
Value::string(req.shape.to_string(), span),
|
|
||||||
Value::bool(false, span),
|
|
||||||
Value::nothing(span),
|
|
||||||
Value::string(&req.desc, span),
|
|
||||||
Value::string(
|
|
||||||
extract_custom_completion_from_arg(self.engine_state, &req.shape),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
Value::nothing(span),
|
|
||||||
];
|
|
||||||
|
|
||||||
sig_records.push(Value::record(
|
sig_records.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(sig_cols.clone(), sig_vals),
|
record! {
|
||||||
|
"parameter_name" => Value::string(&req.name, span),
|
||||||
|
"parameter_type" => Value::string("positional", span),
|
||||||
|
"syntax_shape" => Value::string(req.shape.to_string(), span),
|
||||||
|
"is_optional" => Value::bool(false, span),
|
||||||
|
"short_flag" => Value::nothing(span),
|
||||||
|
"description" => Value::string(&req.desc, span),
|
||||||
|
"custom_completion" => Value::string(custom, span),
|
||||||
|
"parameter_default" => Value::nothing(span),
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional_positional
|
// optional_positional
|
||||||
for opt in &signature.optional_positional {
|
for opt in &signature.optional_positional {
|
||||||
let sig_vals = vec![
|
let custom = extract_custom_completion_from_arg(self.engine_state, &opt.shape);
|
||||||
Value::string(&opt.name, span),
|
let default = if let Some(val) = &opt.default_value {
|
||||||
Value::string("positional", span),
|
|
||||||
Value::string(opt.shape.to_string(), span),
|
|
||||||
Value::bool(true, span),
|
|
||||||
Value::nothing(span),
|
|
||||||
Value::string(&opt.desc, span),
|
|
||||||
Value::string(
|
|
||||||
extract_custom_completion_from_arg(self.engine_state, &opt.shape),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
if let Some(val) = &opt.default_value {
|
|
||||||
val.clone()
|
val.clone()
|
||||||
} else {
|
} else {
|
||||||
Value::nothing(span)
|
Value::nothing(span)
|
||||||
},
|
};
|
||||||
];
|
|
||||||
|
|
||||||
sig_records.push(Value::record(
|
sig_records.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(sig_cols.clone(), sig_vals),
|
record! {
|
||||||
|
"parameter_name" => Value::string(&opt.name, span),
|
||||||
|
"parameter_type" => Value::string("positional", span),
|
||||||
|
"syntax_shape" => Value::string(opt.shape.to_string(), span),
|
||||||
|
"is_optional" => Value::bool(true, span),
|
||||||
|
"short_flag" => Value::nothing(span),
|
||||||
|
"description" => Value::string(&opt.desc, span),
|
||||||
|
"custom_completion" => Value::string(custom, span),
|
||||||
|
"parameter_default" => default,
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// rest_positional
|
// rest_positional
|
||||||
if let Some(rest) = &signature.rest_positional {
|
if let Some(rest) = &signature.rest_positional {
|
||||||
let sig_vals = vec![
|
let name = if rest.name == "rest" { "" } else { &rest.name };
|
||||||
Value::string(if rest.name == "rest" { "" } else { &rest.name }, span),
|
let custom = extract_custom_completion_from_arg(self.engine_state, &rest.shape);
|
||||||
Value::string("rest", span),
|
|
||||||
Value::string(rest.shape.to_string(), span),
|
|
||||||
Value::bool(true, span),
|
|
||||||
Value::nothing(span),
|
|
||||||
Value::string(&rest.desc, span),
|
|
||||||
Value::string(
|
|
||||||
extract_custom_completion_from_arg(self.engine_state, &rest.shape),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
Value::nothing(span), // rest_positional does have default, but parser prohibits specifying it?!
|
|
||||||
];
|
|
||||||
|
|
||||||
sig_records.push(Value::record(
|
sig_records.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(sig_cols.clone(), sig_vals),
|
record! {
|
||||||
|
"parameter_name" => Value::string(name, span),
|
||||||
|
"parameter_type" => Value::string("rest", span),
|
||||||
|
"syntax_shape" => Value::string(rest.shape.to_string(), span),
|
||||||
|
"is_optional" => Value::bool(true, span),
|
||||||
|
"short_flag" => Value::nothing(span),
|
||||||
|
"description" => Value::string(&rest.desc, span),
|
||||||
|
"custom_completion" => Value::string(custom, span),
|
||||||
|
// rest_positional does have default, but parser prohibits specifying it?!
|
||||||
|
"parameter_default" => Value::nothing(span),
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -310,42 +290,39 @@ impl<'e, 's> ScopeData<'e, 's> {
|
|||||||
Value::nothing(span)
|
Value::nothing(span)
|
||||||
};
|
};
|
||||||
|
|
||||||
let sig_vals = vec![
|
let default = if let Some(val) = &named.default_value {
|
||||||
Value::string(&named.long, span),
|
|
||||||
flag_type,
|
|
||||||
shape,
|
|
||||||
Value::bool(!named.required, span),
|
|
||||||
short_flag,
|
|
||||||
Value::string(&named.desc, span),
|
|
||||||
Value::string(custom_completion_command_name, span),
|
|
||||||
if let Some(val) = &named.default_value {
|
|
||||||
val.clone()
|
val.clone()
|
||||||
} else {
|
} else {
|
||||||
Value::nothing(span)
|
Value::nothing(span)
|
||||||
},
|
};
|
||||||
];
|
|
||||||
|
|
||||||
sig_records.push(Value::record(
|
sig_records.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(sig_cols.clone(), sig_vals),
|
record! {
|
||||||
|
"parameter_name" => Value::string(&named.long, span),
|
||||||
|
"parameter_type" => flag_type,
|
||||||
|
"syntax_shape" => shape,
|
||||||
|
"is_optional" => Value::bool(!named.required, span),
|
||||||
|
"short_flag" => short_flag,
|
||||||
|
"description" => Value::string(&named.desc, span),
|
||||||
|
"custom_completion" => Value::string(custom_completion_command_name, span),
|
||||||
|
"parameter_default" => default,
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// output
|
// output
|
||||||
sig_records.push(Value::record(
|
sig_records.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(
|
record! {
|
||||||
sig_cols,
|
"parameter_name" => Value::nothing(span),
|
||||||
vec![
|
"parameter_type" => Value::string("output", span),
|
||||||
Value::nothing(span),
|
"syntax_shape" => Value::string(output_type.to_shape().to_string(), span),
|
||||||
Value::string("output", span),
|
"is_optional" => Value::bool(false, span),
|
||||||
Value::string(output_type.to_shape().to_string(), span),
|
"short_flag" => Value::nothing(span),
|
||||||
Value::bool(false, span),
|
"description" => Value::nothing(span),
|
||||||
Value::nothing(span),
|
"custom_completion" => Value::nothing(span),
|
||||||
Value::nothing(span),
|
"parameter_default" => Value::nothing(span),
|
||||||
Value::nothing(span),
|
},
|
||||||
Value::nothing(span),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use std::io::{self, Result};
|
|||||||
use crossterm::event::KeyEvent;
|
use crossterm::event::KeyEvent;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{EngineState, Stack},
|
engine::{EngineState, Stack},
|
||||||
record, Record, Value,
|
record, Value,
|
||||||
};
|
};
|
||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
|
|
||||||
@ -165,10 +165,7 @@ fn help_frame_data(
|
|||||||
|
|
||||||
let (cols, mut vals) = help_manual_data(manual, aliases);
|
let (cols, mut vals) = help_manual_data(manual, aliases);
|
||||||
let vals = vals.remove(0);
|
let vals = vals.remove(0);
|
||||||
Value::record(
|
Value::record(cols.into_iter().zip(vals).collect(), NuSpan::unknown())
|
||||||
Record::from_raw_cols_vals_unchecked(cols, vals),
|
|
||||||
NuSpan::unknown(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let commands = Value::list(commands, NuSpan::unknown());
|
let commands = Value::list(commands, NuSpan::unknown());
|
||||||
|
@ -701,16 +701,13 @@ fn build_last_value(v: &RecordView) -> Value {
|
|||||||
fn build_table_as_list(v: &RecordView) -> Value {
|
fn build_table_as_list(v: &RecordView) -> Value {
|
||||||
let layer = v.get_layer_last();
|
let layer = v.get_layer_last();
|
||||||
|
|
||||||
let headers = layer.columns.to_vec();
|
let cols = &layer.columns;
|
||||||
let vals = layer
|
let vals = layer
|
||||||
.records
|
.records
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
|
||||||
.map(|vals| {
|
.map(|vals| {
|
||||||
Value::record(
|
let record = cols.iter().cloned().zip(vals.iter().cloned()).collect();
|
||||||
Record::from_raw_cols_vals_unchecked(headers.clone(), vals),
|
Value::record(record, NuSpan::unknown())
|
||||||
NuSpan::unknown(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@ -720,13 +717,18 @@ fn build_table_as_list(v: &RecordView) -> Value {
|
|||||||
fn build_table_as_record(v: &RecordView) -> Value {
|
fn build_table_as_record(v: &RecordView) -> Value {
|
||||||
let layer = v.get_layer_last();
|
let layer = v.get_layer_last();
|
||||||
|
|
||||||
let cols = layer.columns.to_vec();
|
let record = if let Some(row) = layer.records.first() {
|
||||||
let vals = layer.records.first().map_or(Vec::new(), |row| row.clone());
|
layer
|
||||||
|
.columns
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.zip(row.iter().cloned())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
Record::new()
|
||||||
|
};
|
||||||
|
|
||||||
Value::record(
|
Value::record(record, NuSpan::unknown())
|
||||||
Record::from_raw_cols_vals_unchecked(cols, vals),
|
|
||||||
NuSpan::unknown(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_cursor_position(mode: UIMode, cursor: XYCursor) -> String {
|
fn report_cursor_position(mode: UIMode, cursor: XYCursor) -> String {
|
||||||
|
@ -119,13 +119,12 @@ pub trait Eval {
|
|||||||
|
|
||||||
let mut output_rows = vec![];
|
let mut output_rows = vec![];
|
||||||
for val in vals {
|
for val in vals {
|
||||||
let mut row = vec![];
|
let record = output_headers.iter().zip(val).map(|(col, expr)| {
|
||||||
for expr in val {
|
Self::eval(state, mut_state, expr).map(|val| (col.clone(), val))
|
||||||
row.push(Self::eval(state, mut_state, expr)?);
|
}).collect::<Result<_,_>>()?;
|
||||||
}
|
|
||||||
// length equality already ensured in parser
|
|
||||||
output_rows.push(Value::record(
|
output_rows.push(Value::record(
|
||||||
Record::from_raw_cols_vals_unchecked(output_headers.clone(), row),
|
record,
|
||||||
expr.span,
|
expr.span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -26,24 +26,11 @@ impl Record {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructor that checks that `cols` and `vals` are of the same length.
|
/// Create a [`Record`] from a `Vec` of columns and a `Vec` of [`Value`]s
|
||||||
///
|
///
|
||||||
/// WARNING! Panics with assertion failure if cols and vals have different length!
|
/// Returns an error if `cols` and `vals` have different lengths.
|
||||||
/// Should be used only when the same lengths are guaranteed!
|
|
||||||
///
|
///
|
||||||
/// For perf reasons does not validate the rest of the record assumptions.
|
/// For perf reasons, this will not validate the rest of the record assumptions:
|
||||||
/// - unique keys
|
|
||||||
pub fn from_raw_cols_vals_unchecked(cols: Vec<String>, vals: Vec<Value>) -> Self {
|
|
||||||
assert_eq!(cols.len(), vals.len());
|
|
||||||
|
|
||||||
Self { cols, vals }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructor that checks that `cols` and `vals` are of the same length.
|
|
||||||
///
|
|
||||||
/// Returns None if cols and vals have different length.
|
|
||||||
///
|
|
||||||
/// For perf reasons does not validate the rest of the record assumptions.
|
|
||||||
/// - unique keys
|
/// - unique keys
|
||||||
pub fn from_raw_cols_vals(
|
pub fn from_raw_cols_vals(
|
||||||
cols: Vec<String>,
|
cols: Vec<String>,
|
||||||
@ -70,11 +57,13 @@ impl Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.cols.is_empty() || self.vals.is_empty()
|
debug_assert_eq!(self.cols.len(), self.vals.len());
|
||||||
|
self.cols.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
usize::min(self.cols.len(), self.vals.len())
|
debug_assert_eq!(self.cols.len(), self.vals.len());
|
||||||
|
self.cols.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Naive push to the end of the datastructure.
|
/// Naive push to the end of the datastructure.
|
||||||
@ -99,14 +88,13 @@ impl Record {
|
|||||||
let curr_val = &mut self.vals[idx];
|
let curr_val = &mut self.vals[idx];
|
||||||
Some(std::mem::replace(curr_val, val))
|
Some(std::mem::replace(curr_val, val))
|
||||||
} else {
|
} else {
|
||||||
self.cols.push(col.into());
|
self.push(col, val);
|
||||||
self.vals.push(val);
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, col: impl AsRef<str>) -> bool {
|
pub fn contains(&self, col: impl AsRef<str>) -> bool {
|
||||||
self.cols.iter().any(|k| k == col.as_ref())
|
self.columns().any(|k| k == col.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
|
pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
|
||||||
@ -138,7 +126,6 @@ impl Record {
|
|||||||
|
|
||||||
/// Remove elements in-place that do not satisfy `keep`
|
/// Remove elements in-place that do not satisfy `keep`
|
||||||
///
|
///
|
||||||
/// Note: Panics if `vals.len() > cols.len()`
|
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use nu_protocol::{record, Value};
|
/// use nu_protocol::{record, Value};
|
||||||
///
|
///
|
||||||
@ -165,7 +152,6 @@ impl Record {
|
|||||||
///
|
///
|
||||||
/// This can for example be used to recursively prune nested records.
|
/// This can for example be used to recursively prune nested records.
|
||||||
///
|
///
|
||||||
/// Note: Panics if `vals.len() > cols.len()`
|
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use nu_protocol::{record, Record, Value};
|
/// use nu_protocol::{record, Record, Value};
|
||||||
///
|
///
|
||||||
@ -235,6 +221,7 @@ impl Record {
|
|||||||
/// Truncate record to the first `len` elements.
|
/// Truncate record to the first `len` elements.
|
||||||
///
|
///
|
||||||
/// `len > self.len()` will be ignored
|
/// `len > self.len()` will be ignored
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use nu_protocol::{record, Value};
|
/// use nu_protocol::{record, Value};
|
||||||
///
|
///
|
||||||
@ -299,11 +286,7 @@ impl Record {
|
|||||||
where
|
where
|
||||||
R: RangeBounds<usize> + Clone,
|
R: RangeBounds<usize> + Clone,
|
||||||
{
|
{
|
||||||
assert_eq!(
|
debug_assert_eq!(self.cols.len(), self.vals.len());
|
||||||
self.cols.len(),
|
|
||||||
self.vals.len(),
|
|
||||||
"Length of cols and vals must be equal for sane `Record::drain`"
|
|
||||||
);
|
|
||||||
Drain {
|
Drain {
|
||||||
keys: self.cols.drain(range.clone()),
|
keys: self.cols.drain(range.clone()),
|
||||||
values: self.vals.drain(range),
|
values: self.vals.drain(range),
|
||||||
@ -323,8 +306,7 @@ impl Extend<(String, Value)> for Record {
|
|||||||
fn extend<T: IntoIterator<Item = (String, Value)>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = (String, Value)>>(&mut self, iter: T) {
|
||||||
for (k, v) in iter {
|
for (k, v) in iter {
|
||||||
// TODO: should this .insert with a check?
|
// TODO: should this .insert with a check?
|
||||||
self.cols.push(k);
|
self.push(k, v)
|
||||||
self.vals.push(v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,11 +534,15 @@ impl ExactSizeIterator for Drain<'_> {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! record {
|
macro_rules! record {
|
||||||
|
// The macro only compiles if the number of columns equals the number of values,
|
||||||
|
// so it's safe to call `unwrap` below.
|
||||||
{$($col:expr => $val:expr),+ $(,)?} => {
|
{$($col:expr => $val:expr),+ $(,)?} => {
|
||||||
$crate::Record::from_raw_cols_vals_unchecked(
|
$crate::Record::from_raw_cols_vals(
|
||||||
::std::vec![$($col.into(),)+],
|
::std::vec![$($col.into(),)+],
|
||||||
::std::vec![$($val,)+]
|
::std::vec![$($val,)+],
|
||||||
)
|
$crate::Span::unknown(),
|
||||||
|
$crate::Span::unknown(),
|
||||||
|
).unwrap()
|
||||||
};
|
};
|
||||||
{} => {
|
{} => {
|
||||||
$crate::Record::new()
|
$crate::Record::new()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use nu_plugin::{EvaluatedCall, LabeledError};
|
use nu_plugin::{EvaluatedCall, LabeledError};
|
||||||
use nu_protocol::{Record, Value};
|
use nu_protocol::{record, Value};
|
||||||
pub struct Example;
|
pub struct Example;
|
||||||
|
|
||||||
impl Example {
|
impl Example {
|
||||||
@ -75,20 +75,16 @@ impl Example {
|
|||||||
pub fn test2(&self, call: &EvaluatedCall, input: &Value) -> Result<Value, LabeledError> {
|
pub fn test2(&self, call: &EvaluatedCall, input: &Value) -> Result<Value, LabeledError> {
|
||||||
self.print_values(2, call, input)?;
|
self.print_values(2, call, input)?;
|
||||||
|
|
||||||
let cols = vec!["one".to_string(), "two".to_string(), "three".to_string()];
|
|
||||||
|
|
||||||
let vals = (0..10i64)
|
let vals = (0..10i64)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let vals = (0..3)
|
let record = record! {
|
||||||
.map(|v| Value::int(v * i, call.head))
|
"one" => Value::int(i, call.head),
|
||||||
.collect::<Vec<Value>>();
|
"two" => Value::int(2 * i, call.head),
|
||||||
|
"three" => Value::int(3 * i, call.head),
|
||||||
Value::record(
|
};
|
||||||
Record::from_raw_cols_vals_unchecked(cols.clone(), vals),
|
Value::record(record, call.head)
|
||||||
call.head,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<Value>>();
|
.collect();
|
||||||
|
|
||||||
Ok(Value::list(vals, call.head))
|
Ok(Value::list(vals, call.head))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user