mirror of
https://github.com/nushell/nushell.git
synced 2025-03-13 15:08:43 +01:00
Merge 1d713be69d
into 95dcb2fd6c
This commit is contained in:
commit
25cd4c1713
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -1639,6 +1639,15 @@ version = "1.0.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ecow"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54bfbb1708988623190a6c4dbedaeaf0f53c20c6395abd6a01feb327b3146f4b"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ego-tree"
|
name = "ego-tree"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -3956,6 +3965,7 @@ dependencies = [
|
|||||||
"chrono-humanize",
|
"chrono-humanize",
|
||||||
"dirs",
|
"dirs",
|
||||||
"dirs-sys",
|
"dirs-sys",
|
||||||
|
"ecow",
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"heck",
|
"heck",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -170,7 +170,7 @@ fn error_from_reedline(e: ReedlineError) -> ShellError {
|
|||||||
fn item_from_value(v: Value) -> Result<HistoryItem, ShellError> {
|
fn item_from_value(v: Value) -> Result<HistoryItem, ShellError> {
|
||||||
let span = v.span();
|
let span = v.span();
|
||||||
match v {
|
match v {
|
||||||
Value::Record { val, .. } => item_from_record(val.into_owned(), span),
|
Value::Record { val, .. } => item_from_record(val, span),
|
||||||
Value::String { val, .. } => Ok(HistoryItem {
|
Value::String { val, .. } => Ok(HistoryItem {
|
||||||
command_line: val,
|
command_line: val,
|
||||||
id: None,
|
id: None,
|
||||||
|
@ -58,7 +58,7 @@ fn horizontal_rotate_value(
|
|||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let rotations = by.map(|n| n % record.len()).unwrap_or(1);
|
let rotations = by.map(|n| n % record.len()).unwrap_or(1);
|
||||||
|
|
||||||
let (mut cols, mut vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
|
let (mut cols, mut vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
|
||||||
if !cells_only {
|
if !cells_only {
|
||||||
match direction {
|
match direction {
|
||||||
HorizontalDirection::Right => cols.rotate_right(rotations),
|
HorizontalDirection::Right => cols.rotate_right(rotations),
|
||||||
|
@ -174,7 +174,7 @@ pub fn rotate(
|
|||||||
let span = val.span();
|
let span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let (cols, vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
|
let (cols, vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
|
||||||
old_column_names = cols;
|
old_column_names = cols;
|
||||||
new_values.extend_from_slice(&vals);
|
new_values.extend_from_slice(&vals);
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,6 @@ impl Iterator for UpdateCellIterator {
|
|||||||
let mut value = self.iter.next()?;
|
let mut value = self.iter.next()?;
|
||||||
|
|
||||||
let value = if let Value::Record { val, .. } = &mut value {
|
let value = if let Value::Record { val, .. } = &mut value {
|
||||||
let val = val.to_mut();
|
|
||||||
if let Some(columns) = &self.columns {
|
if let Some(columns) = &self.columns {
|
||||||
for (col, val) in val.iter_mut() {
|
for (col, val) in val.iter_mut() {
|
||||||
if columns.contains(col) {
|
if columns.contains(col) {
|
||||||
|
@ -266,16 +266,15 @@ fn describe_value_inner(
|
|||||||
| Value::String { .. }
|
| Value::String { .. }
|
||||||
| Value::Glob { .. }
|
| Value::Glob { .. }
|
||||||
| Value::Nothing { .. } => Description::String(value.get_type().to_string()),
|
| Value::Nothing { .. } => Description::String(value.get_type().to_string()),
|
||||||
Value::Record { val, .. } => {
|
Value::Record { mut val, .. } => {
|
||||||
let mut columns = val.into_owned();
|
for (_, val) in &mut val {
|
||||||
for (_, val) in &mut columns {
|
|
||||||
*val =
|
*val =
|
||||||
describe_value_inner(std::mem::take(val), head, engine_state).into_value(head);
|
describe_value_inner(std::mem::take(val), head, engine_state).into_value(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
Description::Record(record! {
|
Description::Record(record! {
|
||||||
"type" => Value::string("record", head),
|
"type" => Value::string("record", head),
|
||||||
"columns" => Value::record(columns, head),
|
"columns" => Value::record(val, head),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Value::List { mut vals, .. } => {
|
Value::List { mut vals, .. } => {
|
||||||
|
@ -289,7 +289,7 @@ impl std::fmt::Debug for DebuggableValue<'_> {
|
|||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
write!(f, "{{")?;
|
write!(f, "{{")?;
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for (col, value) in (&**val).into_iter() {
|
for (col, value) in val {
|
||||||
if !first {
|
if !first {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ fn into_record(call: &Call, input: PipelineData) -> Result<PipelineData, ShellEr
|
|||||||
if matches!(expected_type, None | Some(ExpectedType::Record)) =>
|
if matches!(expected_type, None | Some(ExpectedType::Record)) =>
|
||||||
{
|
{
|
||||||
// Don't use .extend() unless that gets changed to check for duplicate keys
|
// Don't use .extend() unless that gets changed to check for duplicate keys
|
||||||
for (key, val) in val.into_owned() {
|
for (key, val) in val {
|
||||||
record.insert(key, val);
|
record.insert(key, val);
|
||||||
}
|
}
|
||||||
expected_type = Some(ExpectedType::Record);
|
expected_type = Some(ExpectedType::Record);
|
||||||
|
@ -110,8 +110,7 @@ impl Iterator for UpdateCellIterator {
|
|||||||
let span = val.span();
|
let span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val, .. } => Some(Value::record(
|
Value::Record { val, .. } => Some(Value::record(
|
||||||
val.into_owned()
|
val.into_iter()
|
||||||
.into_iter()
|
|
||||||
.map(|(col, val)| match &self.columns {
|
.map(|(col, val)| match &self.columns {
|
||||||
Some(cols) if !cols.contains(&col) => (col, val),
|
Some(cols) if !cols.contains(&col) => (col, val),
|
||||||
_ => (
|
_ => (
|
||||||
|
@ -465,7 +465,7 @@ pub fn nu_value_to_params(value: Value) -> Result<NuSqlParams, ShellError> {
|
|||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut params = Vec::with_capacity(val.len());
|
let mut params = Vec::with_capacity(val.len());
|
||||||
|
|
||||||
for (mut column, value) in val.into_owned().into_iter() {
|
for (mut column, value) in val {
|
||||||
let sql_type_erased = value_to_sql(value)?;
|
let sql_type_erased = value_to_sql(value)?;
|
||||||
|
|
||||||
if !column.starts_with([':', '@', '$']) {
|
if !column.starts_with([':', '@', '$']) {
|
||||||
|
@ -210,7 +210,7 @@ mod util {
|
|||||||
let span = value.span();
|
let span = value.span();
|
||||||
match value {
|
match value {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let (cols, vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
|
let (cols, vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
|
||||||
(
|
(
|
||||||
match cols.is_empty() {
|
match cols.is_empty() {
|
||||||
true => vec![String::from("")],
|
true => vec![String::from("")],
|
||||||
|
2
crates/nu-command/src/env/load_env.rs
vendored
2
crates/nu-command/src/env/load_env.rs
vendored
@ -43,7 +43,7 @@ impl Command for LoadEnv {
|
|||||||
let record = match arg {
|
let record = match arg {
|
||||||
Some(record) => record,
|
Some(record) => record,
|
||||||
None => match input {
|
None => match input {
|
||||||
PipelineData::Value(Value::Record { val, .. }, ..) => val.into_owned(),
|
PipelineData::Value(Value::Record { val, .. }, ..) => val,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::UnsupportedInput {
|
return Err(ShellError::UnsupportedInput {
|
||||||
msg: "'load-env' expects a single record".into(),
|
msg: "'load-env' expects a single record".into(),
|
||||||
|
@ -94,7 +94,6 @@ fn getcol(head: Span, input: PipelineData) -> Result<PipelineData, ShellError> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
Value::Record { val, .. } => val
|
Value::Record { val, .. } => val
|
||||||
.into_owned()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |(x, _)| Value::string(x, head))
|
.map(move |(x, _)| Value::string(x, head))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -102,7 +102,6 @@ fn default(
|
|||||||
val: ref mut record,
|
val: ref mut record,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let record = record.to_mut();
|
|
||||||
if let Some(val) = record.get_mut(&column.item) {
|
if let Some(val) = record.get_mut(&column.item) {
|
||||||
if matches!(val, Value::Nothing { .. }) {
|
if matches!(val, Value::Nothing { .. }) {
|
||||||
*val = value.clone();
|
*val = value.clone();
|
||||||
|
@ -128,7 +128,7 @@ fn drop_cols(
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let len = record.len().saturating_sub(columns);
|
let len = record.len().saturating_sub(columns);
|
||||||
record.to_mut().truncate(len);
|
record.truncate(len);
|
||||||
Ok(v.into_pipeline_data_with_metadata(metadata))
|
Ok(v.into_pipeline_data_with_metadata(metadata))
|
||||||
}
|
}
|
||||||
// Propagate errors
|
// Propagate errors
|
||||||
@ -149,7 +149,9 @@ fn drop_cols(
|
|||||||
fn drop_cols_set(val: &mut Value, head: Span, drop: usize) -> Result<HashSet<String>, ShellError> {
|
fn drop_cols_set(val: &mut Value, head: Span, drop: usize) -> Result<HashSet<String>, ShellError> {
|
||||||
if let Value::Record { val: record, .. } = val {
|
if let Value::Record { val: record, .. } = val {
|
||||||
let len = record.len().saturating_sub(drop);
|
let len = record.len().saturating_sub(drop);
|
||||||
Ok(record.to_mut().drain(len..).map(|(col, _)| col).collect())
|
let set = record.columns().skip(len).cloned().collect();
|
||||||
|
record.truncate(len);
|
||||||
|
Ok(set)
|
||||||
} else {
|
} else {
|
||||||
Err(unsupported_value_error(val, head))
|
Err(unsupported_value_error(val, head))
|
||||||
}
|
}
|
||||||
@ -161,7 +163,7 @@ fn drop_record_cols(
|
|||||||
drop_cols: &HashSet<String>,
|
drop_cols: &HashSet<String>,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
if let Value::Record { val, .. } = val {
|
if let Value::Record { val, .. } = val {
|
||||||
val.to_mut().retain(|col, _| !drop_cols.contains(col));
|
val.retain(|col, _| !drop_cols.contains(col));
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(unsupported_value_error(val, head))
|
Err(unsupported_value_error(val, head))
|
||||||
|
@ -156,7 +156,7 @@ fn flat_value(columns: &[CellPath], item: Value, all: bool) -> Vec<Value> {
|
|||||||
let mut out = IndexMap::<String, Value>::new();
|
let mut out = IndexMap::<String, Value>::new();
|
||||||
let mut inner_table = None;
|
let mut inner_table = None;
|
||||||
|
|
||||||
for (column_index, (column, value)) in val.into_owned().into_iter().enumerate() {
|
for (column_index, (column, value)) in val.into_iter().enumerate() {
|
||||||
let column_requested = columns.iter().find(|c| c.to_column_name() == column);
|
let column_requested = columns.iter().find(|c| c.to_column_name() == column);
|
||||||
let need_flatten = { columns.is_empty() || column_requested.is_some() };
|
let need_flatten = { columns.is_empty() || column_requested.is_some() };
|
||||||
let span = value.span();
|
let span = value.span();
|
||||||
@ -164,7 +164,7 @@ fn flat_value(columns: &[CellPath], item: Value, all: bool) -> Vec<Value> {
|
|||||||
match value {
|
match value {
|
||||||
Value::Record { ref val, .. } => {
|
Value::Record { ref val, .. } => {
|
||||||
if need_flatten {
|
if need_flatten {
|
||||||
for (col, val) in val.clone().into_owned() {
|
for (col, val) in val.clone() {
|
||||||
if out.contains_key(&col) {
|
if out.contains_key(&col) {
|
||||||
out.insert(format!("{column}_{col}"), val);
|
out.insert(format!("{column}_{col}"), val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,7 +142,6 @@ fn replace_headers(
|
|||||||
if let Value::Record { val: record, .. } = value {
|
if let Value::Record { val: record, .. } = value {
|
||||||
Ok(Value::record(
|
Ok(Value::record(
|
||||||
record
|
record
|
||||||
.into_owned()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(col, val)| {
|
.filter_map(|(col, val)| {
|
||||||
old_headers
|
old_headers
|
||||||
|
@ -49,7 +49,6 @@ impl Command for Items {
|
|||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut closure = ClosureEval::new(engine_state, stack, closure);
|
let mut closure = ClosureEval::new(engine_state, stack, closure);
|
||||||
Ok(val
|
Ok(val
|
||||||
.into_owned()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map_while(move |(col, val)| {
|
.map_while(move |(col, val)| {
|
||||||
let result = closure
|
let result = closure
|
||||||
|
@ -65,7 +65,7 @@ pub(crate) fn do_merge(
|
|||||||
Value::Record { val: lhs, .. },
|
Value::Record { val: lhs, .. },
|
||||||
Value::Record { val: rhs, .. },
|
Value::Record { val: rhs, .. },
|
||||||
) => Ok(Value::record(
|
) => Ok(Value::record(
|
||||||
merge_records(lhs.into_owned(), rhs.into_owned(), strategy, span)?,
|
merge_records(lhs, rhs, strategy, span)?,
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
// Deep merge records
|
// Deep merge records
|
||||||
@ -74,7 +74,7 @@ pub(crate) fn do_merge(
|
|||||||
Value::Record { val: lhs, .. },
|
Value::Record { val: lhs, .. },
|
||||||
Value::Record { val: rhs, .. },
|
Value::Record { val: rhs, .. },
|
||||||
) => Ok(Value::record(
|
) => Ok(Value::record(
|
||||||
merge_records(lhs.into_owned(), rhs.into_owned(), strategy, span)?,
|
merge_records(lhs, rhs, strategy, span)?,
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
// Merge lists by appending
|
// Merge lists by appending
|
||||||
|
@ -148,8 +148,7 @@ fn rename(
|
|||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let record =
|
let record =
|
||||||
if let Some(closure) = &mut closure {
|
if let Some(closure) = &mut closure {
|
||||||
record
|
record.into_iter()
|
||||||
.into_owned().into_iter()
|
|
||||||
.map(|(col, val)| {
|
.map(|(col, val)| {
|
||||||
let col = Value::string(col, span);
|
let col = Value::string(col, span);
|
||||||
let data = closure.run_with_value(col)?;
|
let data = closure.run_with_value(col)?;
|
||||||
@ -163,7 +162,7 @@ fn rename(
|
|||||||
// record columns are unique so we can track the number
|
// record columns are unique so we can track the number
|
||||||
// of renamed columns to check if any were missed
|
// of renamed columns to check if any were missed
|
||||||
let mut renamed = 0;
|
let mut renamed = 0;
|
||||||
let record = record.into_owned().into_iter().map(|(col, val)| {
|
let record = record.into_iter().map(|(col, val)| {
|
||||||
let col = if let Some(col) = columns.get(&col) {
|
let col = if let Some(col) = columns.get(&col) {
|
||||||
renamed += 1;
|
renamed += 1;
|
||||||
col.clone()
|
col.clone()
|
||||||
@ -194,7 +193,7 @@ fn rename(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Ok(record
|
None => Ok(record
|
||||||
.into_owned().into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (col, val))| {
|
.map(|(i, (col, val))| {
|
||||||
(columns.get(i).cloned().unwrap_or(col), val)
|
(columns.get(i).cloned().unwrap_or(col), val)
|
||||||
|
@ -146,13 +146,7 @@ impl Command for Sort {
|
|||||||
let sorted: Value = match value {
|
let sorted: Value = match value {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
// Records have two sorting methods, toggled by presence or absence of -v
|
// Records have two sorting methods, toggled by presence or absence of -v
|
||||||
let record = crate::sort_record(
|
let record = crate::sort_record(val, sort_by_value, reverse, insensitive, natural)?;
|
||||||
val.into_owned(),
|
|
||||||
sort_by_value,
|
|
||||||
reverse,
|
|
||||||
insensitive,
|
|
||||||
natural,
|
|
||||||
)?;
|
|
||||||
Value::record(record, span)
|
Value::record(record, span)
|
||||||
}
|
}
|
||||||
value @ Value::List { .. } => {
|
value @ Value::List { .. } => {
|
||||||
|
@ -194,7 +194,6 @@ fn sort_attributes(val: Value) -> Value {
|
|||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
// TODO: sort inplace
|
// TODO: sort inplace
|
||||||
let sorted = val
|
let sorted = val
|
||||||
.into_owned()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.sorted_by(|a, b| a.0.cmp(&b.0))
|
.sorted_by(|a, b| a.0.cmp(&b.0))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
@ -106,7 +106,7 @@ pub fn get_values<'a>(
|
|||||||
for item in input {
|
for item in input {
|
||||||
match item {
|
match item {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
for (k, v) in &**val {
|
for (k, v) in val {
|
||||||
if let Some(vec) = output.get_mut(k) {
|
if let Some(vec) = output.get_mut(k) {
|
||||||
vec.push(v.clone());
|
vec.push(v.clone());
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,7 +168,7 @@ pub fn value_to_json_value(
|
|||||||
}
|
}
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut m = nu_json::Map::new();
|
let mut m = nu_json::Map::new();
|
||||||
for (k, v) in &**val {
|
for (k, v) in val {
|
||||||
m.insert(
|
m.insert(
|
||||||
k.clone(),
|
k.clone(),
|
||||||
value_to_json_value(engine_state, v, serialize_types)?,
|
value_to_json_value(engine_state, v, serialize_types)?,
|
||||||
|
@ -178,7 +178,6 @@ fn local_into_string(
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(separator),
|
.join(separator),
|
||||||
Value::Record { val, .. } => val
|
Value::Record { val, .. } => val
|
||||||
.into_owned()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(x, y)| {
|
.map(|(x, y)| {
|
||||||
format!(
|
format!(
|
||||||
|
@ -65,7 +65,7 @@ fn helper(
|
|||||||
Value::String { val, .. } | Value::Glob { val, .. } => toml::Value::String(val.clone()),
|
Value::String { val, .. } | Value::Glob { val, .. } => toml::Value::String(val.clone()),
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut m = toml::map::Map::new();
|
let mut m = toml::map::Map::new();
|
||||||
for (k, v) in &**val {
|
for (k, v) in val {
|
||||||
m.insert(k.clone(), helper(engine_state, v, serialize_types)?);
|
m.insert(k.clone(), helper(engine_state, v, serialize_types)?);
|
||||||
}
|
}
|
||||||
toml::Value::Table(m)
|
toml::Value::Table(m)
|
||||||
|
@ -329,7 +329,7 @@ impl Job {
|
|||||||
// alternatives like {tag: a attributes: {} content: []}, {tag: a attribbutes: null
|
// alternatives like {tag: a attributes: {} content: []}, {tag: a attribbutes: null
|
||||||
// content: null}, {tag: a}. See to_xml_entry for more
|
// content: null}, {tag: a}. See to_xml_entry for more
|
||||||
let attrs = match attrs {
|
let attrs = match attrs {
|
||||||
Value::Record { val, .. } => val.into_owned(),
|
Value::Record { val, .. } => val,
|
||||||
Value::Nothing { .. } => Record::new(),
|
Value::Nothing { .. } => Record::new(),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::CantConvert {
|
return Err(ShellError::CantConvert {
|
||||||
|
@ -113,7 +113,7 @@ pub fn value_to_yaml_value(
|
|||||||
}
|
}
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut m = serde_yaml::Mapping::new();
|
let mut m = serde_yaml::Mapping::new();
|
||||||
for (k, v) in &**val {
|
for (k, v) in val {
|
||||||
m.insert(
|
m.insert(
|
||||||
serde_yaml::Value::String(k.clone()),
|
serde_yaml::Value::String(k.clone()),
|
||||||
value_to_yaml_value(engine_state, v, serialize_types)?,
|
value_to_yaml_value(engine_state, v, serialize_types)?,
|
||||||
|
@ -202,12 +202,11 @@ fn parse_closure_result(
|
|||||||
match value {
|
match value {
|
||||||
// {out: ..., next: ...} -> output and continue
|
// {out: ..., next: ...} -> output and continue
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let iter = val.into_owned().into_iter();
|
|
||||||
let mut out = None;
|
let mut out = None;
|
||||||
let mut next = None;
|
let mut next = None;
|
||||||
let mut err = None;
|
let mut err = None;
|
||||||
|
|
||||||
for (k, v) in iter {
|
for (k, v) in val {
|
||||||
if k.eq_ignore_ascii_case("out") {
|
if k.eq_ignore_ascii_case("out") {
|
||||||
out = Some(v);
|
out = Some(v);
|
||||||
} else if k.eq_ignore_ascii_case("next") {
|
} else if k.eq_ignore_ascii_case("next") {
|
||||||
|
@ -150,7 +150,7 @@ pub fn highlight_search_in_table(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let has_match = record.to_mut().iter_mut().try_fold(
|
let has_match = record.iter_mut().try_fold(
|
||||||
false,
|
false,
|
||||||
|acc: bool, (col, val)| -> Result<bool, ShellError> {
|
|acc: bool, (col, val)| -> Result<bool, ShellError> {
|
||||||
if !searched_cols.contains(&col.as_str()) {
|
if !searched_cols.contains(&col.as_str()) {
|
||||||
|
@ -27,7 +27,7 @@ fn helper_for_tables(
|
|||||||
for val in values {
|
for val in values {
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
for (key, value) in &**val {
|
for (key, value) in val {
|
||||||
column_values
|
column_values
|
||||||
.entry(key.clone())
|
.entry(key.clone())
|
||||||
.and_modify(|v: &mut Vec<Value>| v.push(value.clone()))
|
.and_modify(|v: &mut Vec<Value>| v.push(value.clone()))
|
||||||
@ -80,15 +80,13 @@ pub fn calculate(
|
|||||||
),
|
),
|
||||||
_ => mf(vals, span, name),
|
_ => mf(vals, span, name),
|
||||||
},
|
},
|
||||||
PipelineData::Value(Value::Record { val, .. }, ..) => {
|
PipelineData::Value(Value::Record { mut val, .. }, ..) => {
|
||||||
let mut record = val.into_owned();
|
val.iter_mut()
|
||||||
record
|
|
||||||
.iter_mut()
|
|
||||||
.try_for_each(|(_, val)| -> Result<(), ShellError> {
|
.try_for_each(|(_, val)| -> Result<(), ShellError> {
|
||||||
*val = mf(slice::from_ref(val), span, name)?;
|
*val = mf(slice::from_ref(val), span, name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
Ok(Value::record(record, span))
|
Ok(Value::record(val, span))
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Range { val, .. }, ..) => {
|
PipelineData::Value(Value::Range { val, .. }, ..) => {
|
||||||
let new_vals: Result<Vec<Value>, ShellError> = val
|
let new_vals: Result<Vec<Value>, ShellError> = val
|
||||||
|
@ -347,7 +347,7 @@ fn send_form_request(
|
|||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut data: Vec<(String, String)> = Vec::with_capacity(val.len());
|
let mut data: Vec<(String, String)> = Vec::with_capacity(val.len());
|
||||||
|
|
||||||
for (col, val) in val.into_owned() {
|
for (col, val) in val {
|
||||||
data.push((col, val.coerce_into_string()?))
|
data.push((col, val.coerce_into_string()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +380,7 @@ fn send_multipart_request(
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (col, val) in val.into_owned() {
|
for (col, val) in val {
|
||||||
if let Value::Binary { val, .. } = val {
|
if let Value::Binary { val, .. } = val {
|
||||||
let headers = [
|
let headers = [
|
||||||
"Content-Type: application/octet-stream".to_string(),
|
"Content-Type: application/octet-stream".to_string(),
|
||||||
@ -580,7 +580,7 @@ pub fn request_add_custom_headers(
|
|||||||
|
|
||||||
match &headers {
|
match &headers {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
for (k, v) in &**val {
|
for (k, v) in val {
|
||||||
custom_headers.insert(k.to_string(), v.clone());
|
custom_headers.insert(k.to_string(), v.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,7 +590,7 @@ pub fn request_add_custom_headers(
|
|||||||
// single row([key1 key2]; [val1 val2])
|
// single row([key1 key2]; [val1 val2])
|
||||||
match &table[0] {
|
match &table[0] {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
for (k, v) in &**val {
|
for (k, v) in val {
|
||||||
custom_headers.insert(k.to_string(), v.clone());
|
custom_headers.insert(k.to_string(), v.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,6 @@ impl Command for SubCommand {
|
|||||||
match value {
|
match value {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let url_components = val
|
let url_components = val
|
||||||
.into_owned()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_fold(UrlComponents::new(), |url, (k, v)| {
|
.try_fold(UrlComponents::new(), |url, (k, v)| {
|
||||||
url.add_component(k, v, head, engine_state)
|
url.add_component(k, v, head, engine_state)
|
||||||
|
@ -138,7 +138,7 @@ fn handle(
|
|||||||
values
|
values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|val| match val {
|
.map(|val| match val {
|
||||||
Value::Record { val, .. } => Ok(val.into_owned()),
|
Value::Record { val, .. } => Ok(val),
|
||||||
other => Err(ShellError::OnlySupportsThisInputType {
|
other => Err(ShellError::OnlySupportsThisInputType {
|
||||||
exp_input_type: "record".into(),
|
exp_input_type: "record".into(),
|
||||||
wrong_type: other.get_type().to_string(),
|
wrong_type: other.get_type().to_string(),
|
||||||
|
@ -120,7 +120,7 @@ fn handle(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
match value {
|
match value {
|
||||||
Value::Record { val, .. } => Ok(val.into_owned()),
|
Value::Record { val, .. } => Ok(val),
|
||||||
val => Err(ShellError::OnlySupportsThisInputType {
|
val => Err(ShellError::OnlySupportsThisInputType {
|
||||||
exp_input_type: "record".into(),
|
exp_input_type: "record".into(),
|
||||||
wrong_type: val.get_type().to_string(),
|
wrong_type: val.get_type().to_string(),
|
||||||
|
@ -117,7 +117,7 @@ prints out the list properly."#
|
|||||||
// dbg!("value::record");
|
// dbg!("value::record");
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
|
||||||
for (i, (c, v)) in val.into_owned().into_iter().enumerate() {
|
for (i, (c, v)) in val.into_iter().enumerate() {
|
||||||
items.push((i, c, v.to_expanded_string(", ", config)))
|
items.push((i, c, v.to_expanded_string(", ", config)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +450,7 @@ fn handle_table_command(mut input: CmdInput<'_>) -> ShellResult<PipelineData> {
|
|||||||
}
|
}
|
||||||
PipelineData::Value(Value::Record { val, .. }, ..) => {
|
PipelineData::Value(Value::Record { val, .. }, ..) => {
|
||||||
input.data = PipelineData::Empty;
|
input.data = PipelineData::Empty;
|
||||||
handle_record(input, val.into_owned())
|
handle_record(input, val)
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Error { error, .. }, ..) => {
|
PipelineData::Value(Value::Error { error, .. }, ..) => {
|
||||||
// Propagate this error outward, so that it goes to stderr
|
// Propagate this error outward, so that it goes to stderr
|
||||||
@ -688,7 +688,7 @@ fn handle_row_stream(
|
|||||||
stream.map(move |mut value| {
|
stream.map(move |mut value| {
|
||||||
if let Value::Record { val: record, .. } = &mut value {
|
if let Value::Record { val: record, .. } = &mut value {
|
||||||
// Only the name column gets special colors, for now
|
// Only the name column gets special colors, for now
|
||||||
if let Some(value) = record.to_mut().get_mut("name") {
|
if let Some(value) = record.get_mut("name") {
|
||||||
let span = value.span();
|
let span = value.span();
|
||||||
if let Value::String { val, .. } = value {
|
if let Value::String { val, .. } = value {
|
||||||
if let Some(val) =
|
if let Some(val) =
|
||||||
@ -709,7 +709,7 @@ fn handle_row_stream(
|
|||||||
}) => {
|
}) => {
|
||||||
stream.map(|mut value| {
|
stream.map(|mut value| {
|
||||||
if let Value::Record { val: record, .. } = &mut value {
|
if let Value::Record { val: record, .. } = &mut value {
|
||||||
for (rec_col, rec_val) in record.to_mut().iter_mut() {
|
for (rec_col, rec_val) in record.iter_mut() {
|
||||||
// Every column in the HTML theme table except 'name' is colored
|
// Every column in the HTML theme table except 'name' is colored
|
||||||
if rec_col != "name" {
|
if rec_col != "name" {
|
||||||
continue;
|
continue;
|
||||||
|
@ -380,7 +380,7 @@ fn get_argument_for_color_value(
|
|||||||
) -> Option<Argument> {
|
) -> Option<Argument> {
|
||||||
match color {
|
match color {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let record_exp: Vec<RecordItem> = (**val)
|
let record_exp: Vec<RecordItem> = val
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
RecordItem::Pair(
|
RecordItem::Pair(
|
||||||
|
@ -92,7 +92,7 @@ pub fn collect_input(value: Value) -> Result<(Vec<String>, Vec<Vec<Value>>)> {
|
|||||||
let span = value.span();
|
let span = value.span();
|
||||||
match value {
|
match value {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let (key, val): (_, Vec<Value>) = record.into_owned().into_iter().unzip();
|
let (key, val): (_, Vec<Value>) = record.into_iter().unzip();
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
key,
|
key,
|
||||||
|
@ -335,8 +335,8 @@ impl PluginTest {
|
|||||||
// reorder cols and vals to make more logically compare.
|
// reorder cols and vals to make more logically compare.
|
||||||
// more general, if two record have same col and values,
|
// more general, if two record have same col and values,
|
||||||
// the order of cols shouldn't affect the equal property.
|
// the order of cols shouldn't affect the equal property.
|
||||||
let mut a_rec = a_rec.clone().into_owned();
|
let mut a_rec = a_rec.clone();
|
||||||
let mut b_rec = b_rec.clone().into_owned();
|
let mut b_rec = b_rec.clone();
|
||||||
a_rec.sort_cols();
|
a_rec.sort_cols();
|
||||||
b_rec.sort_cols();
|
b_rec.sort_cols();
|
||||||
|
|
||||||
|
@ -23,14 +23,18 @@ nu-derive-value = { path = "../nu-derive-value", version = "0.102.1" }
|
|||||||
|
|
||||||
brotli = { workspace = true, optional = true }
|
brotli = { workspace = true, optional = true }
|
||||||
bytes = { workspace = true }
|
bytes = { workspace = true }
|
||||||
chrono = { workspace = true, features = [ "serde", "std", "unstable-locales" ], default-features = false }
|
chrono = { workspace = true, features = [
|
||||||
|
"serde",
|
||||||
|
"std",
|
||||||
|
"unstable-locales",
|
||||||
|
], default-features = false }
|
||||||
chrono-humanize = { workspace = true }
|
chrono-humanize = { workspace = true }
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
fancy-regex = { workspace = true }
|
fancy-regex = { workspace = true }
|
||||||
heck = { workspace = true }
|
heck = { workspace = true }
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
lru = { workspace = true }
|
lru = { workspace = true }
|
||||||
miette = { workspace = true, features = ["fancy-no-backtrace"]}
|
miette = { workspace = true, features = ["fancy-no-backtrace"] }
|
||||||
num-format = { workspace = true }
|
num-format = { workspace = true }
|
||||||
rmp-serde = { workspace = true, optional = true }
|
rmp-serde = { workspace = true, optional = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
@ -39,6 +43,7 @@ strum = { workspace = true }
|
|||||||
strum_macros = { workspace = true }
|
strum_macros = { workspace = true }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
typetag = "0.2"
|
typetag = "0.2"
|
||||||
|
ecow = { version = "0.2.2", features = ["serde"] }
|
||||||
os_pipe = { workspace = true, optional = true, features = ["io_safety"] }
|
os_pipe = { workspace = true, optional = true, features = ["io_safety"] }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
web-time = { workspace = true }
|
web-time = { workspace = true }
|
||||||
@ -53,16 +58,9 @@ windows-sys = { workspace = true }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["os"]
|
default = ["os"]
|
||||||
os = [
|
os = ["nu-utils/os", "os_pipe"]
|
||||||
"nu-utils/os",
|
|
||||||
"os_pipe",
|
|
||||||
]
|
|
||||||
|
|
||||||
plugin = [
|
plugin = ["brotli", "os", "rmp-serde"]
|
||||||
"brotli",
|
|
||||||
"os",
|
|
||||||
"rmp-serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
@ -23,7 +23,7 @@ impl Matcher for Pattern {
|
|||||||
Pattern::Record(field_patterns) => match value {
|
Pattern::Record(field_patterns) => match value {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
'top: for field_pattern in field_patterns {
|
'top: for field_pattern in field_patterns {
|
||||||
for (col, val) in &**val {
|
for (col, val) in val {
|
||||||
if col == &field_pattern.0 {
|
if col == &field_pattern.0 {
|
||||||
// We have found the field
|
// We have found the field
|
||||||
let result = field_pattern.1.match_value(val, matches);
|
let result = field_pattern.1.match_value(val, matches);
|
||||||
|
@ -87,7 +87,7 @@ pub trait Eval {
|
|||||||
let inner_span = inner.span(&state);
|
let inner_span = inner.span(&state);
|
||||||
match Self::eval::<D>(state, mut_state, inner)? {
|
match Self::eval::<D>(state, mut_state, inner)? {
|
||||||
Value::Record { val: inner_val, .. } => {
|
Value::Record { val: inner_val, .. } => {
|
||||||
for (col_name, val) in inner_val.into_owned() {
|
for (col_name, val) in inner_val {
|
||||||
if let Some(orig_span) = col_names.get(&col_name) {
|
if let Some(orig_span) = col_names.get(&col_name) {
|
||||||
return Err(ShellError::ColumnDefinedTwice {
|
return Err(ShellError::ColumnDefinedTwice {
|
||||||
col_name,
|
col_name,
|
||||||
|
@ -698,7 +698,7 @@ impl FromValue for Range {
|
|||||||
impl FromValue for Record {
|
impl FromValue for Record {
|
||||||
fn from_value(v: Value) -> Result<Self, ShellError> {
|
fn from_value(v: Value) -> Result<Self, ShellError> {
|
||||||
match v {
|
match v {
|
||||||
Value::Record { val, .. } => Ok(val.into_owned()),
|
Value::Record { val, .. } => Ok(val),
|
||||||
v => Err(ShellError::CantConvert {
|
v => Err(ShellError::CantConvert {
|
||||||
to_type: Self::expected_type().to_string(),
|
to_type: Self::expected_type().to_string(),
|
||||||
from_type: v.get_type().to_string(),
|
from_type: v.get_type().to_string(),
|
||||||
|
@ -31,7 +31,7 @@ use fancy_regex::Regex;
|
|||||||
use nu_utils::{
|
use nu_utils::{
|
||||||
contains_emoji,
|
contains_emoji,
|
||||||
locale::{get_system_locale_string, LOCALE_OVERRIDE_ENV_VAR},
|
locale::{get_system_locale_string, LOCALE_OVERRIDE_ENV_VAR},
|
||||||
IgnoreCaseExt, SharedCow,
|
IgnoreCaseExt,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
@ -112,7 +112,7 @@ pub enum Value {
|
|||||||
internal_span: Span,
|
internal_span: Span,
|
||||||
},
|
},
|
||||||
Record {
|
Record {
|
||||||
val: SharedCow<Record>,
|
val: Record,
|
||||||
/// note: spans are being refactored out of Value
|
/// note: spans are being refactored out of Value
|
||||||
/// please use .span() instead of matching this span value
|
/// please use .span() instead of matching this span value
|
||||||
#[serde(rename = "span")]
|
#[serde(rename = "span")]
|
||||||
@ -241,6 +241,11 @@ impl Clone for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is to document/enforce the size of `Value` in bytes.
|
||||||
|
// We should try to avoid increasing the size of `Value`,
|
||||||
|
// and PRs that do so will have to change the number below so that it's noted in review.
|
||||||
|
const _: () = assert!(std::mem::size_of::<Value>() <= 48);
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
fn cant_convert_to<T>(&self, typ: &str) -> Result<T, ShellError> {
|
fn cant_convert_to<T>(&self, typ: &str) -> Result<T, ShellError> {
|
||||||
Err(ShellError::CantConvert {
|
Err(ShellError::CantConvert {
|
||||||
@ -537,7 +542,7 @@ impl Value {
|
|||||||
/// Unwraps the inner [`Record`] value or returns an error if this `Value` is not a record
|
/// Unwraps the inner [`Record`] value or returns an error if this `Value` is not a record
|
||||||
pub fn into_record(self) -> Result<Record, ShellError> {
|
pub fn into_record(self) -> Result<Record, ShellError> {
|
||||||
if let Value::Record { val, .. } = self {
|
if let Value::Record { val, .. } = self {
|
||||||
Ok(val.into_owned())
|
Ok(val)
|
||||||
} else {
|
} else {
|
||||||
self.cant_convert_to("record")
|
self.cant_convert_to("record")
|
||||||
}
|
}
|
||||||
@ -1180,7 +1185,7 @@ impl Value {
|
|||||||
match current {
|
match current {
|
||||||
Value::Record { mut val, .. } => {
|
Value::Record { mut val, .. } => {
|
||||||
// Make reverse iterate to avoid duplicate column leads to first value, actually last value is expected.
|
// Make reverse iterate to avoid duplicate column leads to first value, actually last value is expected.
|
||||||
if let Some(found) = val.to_mut().iter_mut().rev().find(|x| {
|
if let Some(found) = val.iter_mut().rev().find(|x| {
|
||||||
if insensitive {
|
if insensitive {
|
||||||
x.0.eq_ignore_case(column_name)
|
x.0.eq_ignore_case(column_name)
|
||||||
} else {
|
} else {
|
||||||
@ -1215,15 +1220,13 @@ impl Value {
|
|||||||
let val_span = val.span();
|
let val_span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { mut val, .. } => {
|
Value::Record { mut val, .. } => {
|
||||||
if let Some(found) =
|
if let Some(found) = val.iter_mut().rev().find(|x| {
|
||||||
val.to_mut().iter_mut().rev().find(|x| {
|
if insensitive {
|
||||||
if insensitive {
|
x.0.eq_ignore_case(column_name)
|
||||||
x.0.eq_ignore_case(column_name)
|
} else {
|
||||||
} else {
|
x.0 == column_name
|
||||||
x.0 == column_name
|
}
|
||||||
}
|
}) {
|
||||||
})
|
|
||||||
{
|
|
||||||
Ok(std::mem::take(found.1))
|
Ok(std::mem::take(found.1))
|
||||||
} else if *optional {
|
} else if *optional {
|
||||||
Ok(Value::nothing(*origin_span))
|
Ok(Value::nothing(*origin_span))
|
||||||
@ -1329,7 +1332,6 @@ impl Value {
|
|||||||
for val in vals.iter_mut() {
|
for val in vals.iter_mut() {
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let record = record.to_mut();
|
|
||||||
if let Some(val) = record.get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
val.upsert_data_at_cell_path(path, new_val.clone())?;
|
val.upsert_data_at_cell_path(path, new_val.clone())?;
|
||||||
} else {
|
} else {
|
||||||
@ -1350,7 +1352,6 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let record = record.to_mut();
|
|
||||||
if let Some(val) = record.get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
val.upsert_data_at_cell_path(path, new_val)?;
|
val.upsert_data_at_cell_path(path, new_val)?;
|
||||||
} else {
|
} else {
|
||||||
@ -1432,7 +1433,7 @@ impl Value {
|
|||||||
let v_span = val.span();
|
let v_span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if let Some(val) = record.to_mut().get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
val.update_data_at_cell_path(path, new_val.clone())?;
|
val.update_data_at_cell_path(path, new_val.clone())?;
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::CantFindColumn {
|
return Err(ShellError::CantFindColumn {
|
||||||
@ -1454,7 +1455,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if let Some(val) = record.to_mut().get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
val.update_data_at_cell_path(path, new_val)?;
|
val.update_data_at_cell_path(path, new_val)?;
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::CantFindColumn {
|
return Err(ShellError::CantFindColumn {
|
||||||
@ -1519,7 +1520,7 @@ impl Value {
|
|||||||
let v_span = val.span();
|
let v_span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if record.to_mut().remove(col_name).is_none() && !optional {
|
if record.remove(col_name).is_none() && !optional {
|
||||||
return Err(ShellError::CantFindColumn {
|
return Err(ShellError::CantFindColumn {
|
||||||
col_name: col_name.clone(),
|
col_name: col_name.clone(),
|
||||||
span: Some(*span),
|
span: Some(*span),
|
||||||
@ -1539,7 +1540,7 @@ impl Value {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if record.to_mut().remove(col_name).is_none() && !optional {
|
if record.remove(col_name).is_none() && !optional {
|
||||||
return Err(ShellError::CantFindColumn {
|
return Err(ShellError::CantFindColumn {
|
||||||
col_name: col_name.clone(),
|
col_name: col_name.clone(),
|
||||||
span: Some(*span),
|
span: Some(*span),
|
||||||
@ -1594,7 +1595,7 @@ impl Value {
|
|||||||
let v_span = val.span();
|
let v_span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if let Some(val) = record.to_mut().get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
val.remove_data_at_cell_path(path)?;
|
val.remove_data_at_cell_path(path)?;
|
||||||
} else if !optional {
|
} else if !optional {
|
||||||
return Err(ShellError::CantFindColumn {
|
return Err(ShellError::CantFindColumn {
|
||||||
@ -1616,7 +1617,7 @@ impl Value {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
if let Some(val) = record.to_mut().get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
val.remove_data_at_cell_path(path)?;
|
val.remove_data_at_cell_path(path)?;
|
||||||
} else if !optional {
|
} else if !optional {
|
||||||
return Err(ShellError::CantFindColumn {
|
return Err(ShellError::CantFindColumn {
|
||||||
@ -1680,7 +1681,6 @@ impl Value {
|
|||||||
let v_span = val.span();
|
let v_span = val.span();
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let record = record.to_mut();
|
|
||||||
if let Some(val) = record.get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return Err(ShellError::ColumnAlreadyExists {
|
return Err(ShellError::ColumnAlreadyExists {
|
||||||
@ -1714,7 +1714,6 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => {
|
Value::Record { val: record, .. } => {
|
||||||
let record = record.to_mut();
|
|
||||||
if let Some(val) = record.get_mut(col_name) {
|
if let Some(val) = record.get_mut(col_name) {
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return Err(ShellError::ColumnAlreadyExists {
|
return Err(ShellError::ColumnAlreadyExists {
|
||||||
@ -1818,7 +1817,6 @@ impl Value {
|
|||||||
// Check for contained values
|
// Check for contained values
|
||||||
match self {
|
match self {
|
||||||
Value::Record { ref mut val, .. } => val
|
Value::Record { ref mut val, .. } => val
|
||||||
.to_mut()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.try_for_each(|(_, rec_value)| rec_value.recurse_mut(f)),
|
.try_for_each(|(_, rec_value)| rec_value.recurse_mut(f)),
|
||||||
Value::List { ref mut vals, .. } => vals
|
Value::List { ref mut vals, .. } => vals
|
||||||
@ -1953,7 +1951,7 @@ impl Value {
|
|||||||
|
|
||||||
pub fn record(val: Record, span: Span) -> Value {
|
pub fn record(val: Record, span: Span) -> Value {
|
||||||
Value::Record {
|
Value::Record {
|
||||||
val: SharedCow::new(val),
|
val,
|
||||||
internal_span: span,
|
internal_span: span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2350,8 +2348,8 @@ impl PartialOrd for Value {
|
|||||||
// reorder cols and vals to make more logically compare.
|
// reorder cols and vals to make more logically compare.
|
||||||
// more general, if two record have same col and values,
|
// more general, if two record have same col and values,
|
||||||
// the order of cols shouldn't affect the equal property.
|
// the order of cols shouldn't affect the equal property.
|
||||||
let mut lhs = lhs.clone().into_owned();
|
let mut lhs = lhs.clone();
|
||||||
let mut rhs = rhs.clone().into_owned();
|
let mut rhs = rhs.clone();
|
||||||
lhs.sort_cols();
|
lhs.sort_cols();
|
||||||
rhs.sort_cols();
|
rhs.sort_cols();
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
//! Our insertion ordered map-type [`Record`]
|
//! Our insertion ordered map-type [`Record`]
|
||||||
use std::{iter::FusedIterator, ops::RangeBounds};
|
|
||||||
|
|
||||||
use crate::{ShellError, Span, Value};
|
use crate::{ShellError, Span, Value};
|
||||||
|
use ecow::EcoVec;
|
||||||
use serde::{de::Visitor, ser::SerializeMap, Deserialize, Serialize};
|
use serde::{de::Visitor, ser::SerializeMap, Deserialize, Serialize};
|
||||||
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
inner: Vec<(String, Value)>,
|
inner: EcoVec<(String, Value)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Record {
|
impl Record {
|
||||||
@ -17,7 +16,7 @@ impl Record {
|
|||||||
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Vec::with_capacity(capacity),
|
inner: EcoVec::with_capacity(capacity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,12 +99,13 @@ impl Record {
|
|||||||
|
|
||||||
pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
|
pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
|
||||||
self.inner
|
self.inner
|
||||||
|
.make_mut()
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
|
.find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_index(&self, idx: usize) -> Option<(&String, &Value)> {
|
pub fn get_index(&self, idx: usize) -> Option<(&String, &Value)> {
|
||||||
self.inner.get(idx).map(|(col, val): &(_, _)| (col, val))
|
self.inner.get(idx).map(|(col, val)| (col, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove single value by key
|
/// Remove single value by key
|
||||||
@ -152,7 +152,7 @@ impl Record {
|
|||||||
///
|
///
|
||||||
/// fn remove_foo_recursively(val: &mut Value) {
|
/// fn remove_foo_recursively(val: &mut Value) {
|
||||||
/// if let Value::Record {val, ..} = val {
|
/// if let Value::Record {val, ..} = val {
|
||||||
/// val.to_mut().retain_mut(keep_non_foo);
|
/// val.retain_mut(keep_non_foo);
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -184,7 +184,7 @@ impl Record {
|
|||||||
where
|
where
|
||||||
F: FnMut(&str, &mut Value) -> bool,
|
F: FnMut(&str, &mut Value) -> bool,
|
||||||
{
|
{
|
||||||
self.inner.retain_mut(|(col, val)| keep(col, val));
|
self.inner.retain(|(k, v)| keep(k, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Truncate record to the first `len` elements.
|
/// Truncate record to the first `len` elements.
|
||||||
@ -235,35 +235,35 @@ impl Record {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain an iterator to remove elements in `range`
|
// /// Obtain an iterator to remove elements in `range`
|
||||||
///
|
// ///
|
||||||
/// Elements not consumed from the iterator will be dropped
|
// /// Elements not consumed from the iterator will be dropped
|
||||||
///
|
// ///
|
||||||
/// ```rust
|
// /// ```rust
|
||||||
/// use nu_protocol::{record, Value};
|
// /// use nu_protocol::{record, Value};
|
||||||
///
|
// ///
|
||||||
/// let mut rec = record!(
|
// /// let mut rec = record!(
|
||||||
/// "a" => Value::test_nothing(),
|
// /// "a" => Value::test_nothing(),
|
||||||
/// "b" => Value::test_int(42),
|
// /// "b" => Value::test_int(42),
|
||||||
/// "c" => Value::test_string("foo"),
|
// /// "c" => Value::test_string("foo"),
|
||||||
/// );
|
// /// );
|
||||||
/// {
|
// /// {
|
||||||
/// let mut drainer = rec.drain(1..);
|
// /// let mut drainer = rec.drain(1..);
|
||||||
/// assert_eq!(drainer.next(), Some(("b".into(), Value::test_int(42))));
|
// /// assert_eq!(drainer.next(), Some(("b".into(), Value::test_int(42))));
|
||||||
/// // Dropping the `Drain`
|
// /// // Dropping the `Drain`
|
||||||
/// }
|
// /// }
|
||||||
/// let mut rec_iter = rec.into_iter();
|
// /// let mut rec_iter = rec.into_iter();
|
||||||
/// assert_eq!(rec_iter.next(), Some(("a".into(), Value::test_nothing())));
|
// /// assert_eq!(rec_iter.next(), Some(("a".into(), Value::test_nothing())));
|
||||||
/// assert_eq!(rec_iter.next(), None);
|
// /// assert_eq!(rec_iter.next(), None);
|
||||||
/// ```
|
// /// ```
|
||||||
pub fn drain<R>(&mut self, range: R) -> Drain
|
// pub fn drain<R>(&mut self, range: R) -> Drain
|
||||||
where
|
// where
|
||||||
R: RangeBounds<usize> + Clone,
|
// R: RangeBounds<usize> + Clone,
|
||||||
{
|
// {
|
||||||
Drain {
|
// Drain {
|
||||||
iter: self.inner.drain(range),
|
// iter: self.inner.drain(range)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Sort the record by its columns.
|
/// Sort the record by its columns.
|
||||||
///
|
///
|
||||||
@ -288,7 +288,7 @@ impl Record {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub fn sort_cols(&mut self) {
|
pub fn sort_cols(&mut self) {
|
||||||
self.inner.sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
|
self.inner.make_mut().sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ impl Extend<(String, Value)> for Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct IntoIter {
|
pub struct IntoIter {
|
||||||
iter: std::vec::IntoIter<(String, Value)>,
|
iter: ecow::vec::IntoIter<(String, Value)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for IntoIter {
|
impl Iterator for IntoIter {
|
||||||
@ -503,7 +503,7 @@ impl<'a> IntoIterator for &'a mut Record {
|
|||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
IterMut {
|
IterMut {
|
||||||
iter: self.inner.iter_mut(),
|
iter: self.inner.make_mut().iter_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,7 +539,7 @@ impl ExactSizeIterator for Columns<'_> {
|
|||||||
impl FusedIterator for Columns<'_> {}
|
impl FusedIterator for Columns<'_> {}
|
||||||
|
|
||||||
pub struct IntoColumns {
|
pub struct IntoColumns {
|
||||||
iter: std::vec::IntoIter<(String, Value)>,
|
iter: ecow::vec::IntoIter<(String, Value)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for IntoColumns {
|
impl Iterator for IntoColumns {
|
||||||
@ -599,7 +599,7 @@ impl ExactSizeIterator for Values<'_> {
|
|||||||
impl FusedIterator for Values<'_> {}
|
impl FusedIterator for Values<'_> {}
|
||||||
|
|
||||||
pub struct IntoValues {
|
pub struct IntoValues {
|
||||||
iter: std::vec::IntoIter<(String, Value)>,
|
iter: ecow::vec::IntoIter<(String, Value)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for IntoValues {
|
impl Iterator for IntoValues {
|
||||||
@ -628,35 +628,39 @@ impl ExactSizeIterator for IntoValues {
|
|||||||
|
|
||||||
impl FusedIterator for IntoValues {}
|
impl FusedIterator for IntoValues {}
|
||||||
|
|
||||||
pub struct Drain<'a> {
|
// pub struct Drain<'a> {
|
||||||
iter: std::vec::Drain<'a, (String, Value)>,
|
// iter: std::slice::Iter<'a, (String, Value)>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Iterator for Drain<'_> {
|
// impl Iterator for Drain<'_> {
|
||||||
type Item = (String, Value);
|
// type Item = (String, Value);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
// fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.iter.next()
|
// self.iter
|
||||||
}
|
// .next()
|
||||||
|
// .map(|(col, val)| (col.clone(), val.clone()))
|
||||||
|
// }
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
// fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.iter.size_hint()
|
// self.iter.size_hint()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl DoubleEndedIterator for Drain<'_> {
|
// impl DoubleEndedIterator for Drain<'_> {
|
||||||
fn next_back(&mut self) -> Option<Self::Item> {
|
// fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
self.iter.next_back()
|
// self.iter
|
||||||
}
|
// .next_back()
|
||||||
}
|
// .map(|(col, val)| (col.clone(), val.clone()))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
impl ExactSizeIterator for Drain<'_> {
|
// impl ExactSizeIterator for Drain<'_> {
|
||||||
fn len(&self) -> usize {
|
// fn len(&self) -> usize {
|
||||||
self.iter.len()
|
// self.iter.len()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl FusedIterator for Drain<'_> {}
|
// impl FusedIterator for Drain<'_> {}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! record {
|
macro_rules! record {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use nu_ansi_term::Style;
|
use nu_ansi_term::Style;
|
||||||
use nu_color_config::StyleComputer;
|
use nu_color_config::StyleComputer;
|
||||||
use nu_protocol::{Config, Value};
|
use nu_protocol::{Config, Value};
|
||||||
use nu_utils::SharedCow;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{get_index_style, load_theme, nu_value_to_string_clean},
|
common::{get_index_style, load_theme, nu_value_to_string_clean},
|
||||||
@ -41,18 +40,14 @@ fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComp
|
|||||||
// Take ownership of the record and reassign to &mut
|
// Take ownership of the record and reassign to &mut
|
||||||
// We do this to have owned keys through `.into_iter`
|
// We do this to have owned keys through `.into_iter`
|
||||||
let record = std::mem::take(val);
|
let record = std::mem::take(val);
|
||||||
*val = SharedCow::new(
|
*val = record
|
||||||
record
|
.into_iter()
|
||||||
.into_owned()
|
.map(|(header, mut val)| {
|
||||||
.into_iter()
|
colorize_value(&mut val, config, style_computer);
|
||||||
.map(|(mut header, mut val)| {
|
let header = colorize_text(&header, style.color_style).unwrap_or(header);
|
||||||
colorize_value(&mut val, config, style_computer);
|
(header, val)
|
||||||
header = colorize_text(&header, style.color_style).unwrap_or(header);
|
})
|
||||||
|
.collect();
|
||||||
(header, val)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Value::List { vals, .. } => {
|
Value::List { vals, .. } => {
|
||||||
for val in vals {
|
for val in vals {
|
||||||
|
@ -71,7 +71,7 @@ fn build_table(
|
|||||||
|
|
||||||
fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue {
|
fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue {
|
||||||
match value {
|
match value {
|
||||||
Value::Record { val, .. } => build_vertical_map(val.into_owned(), config),
|
Value::Record { val, .. } => build_vertical_map(val, config),
|
||||||
Value::List { vals, .. } => {
|
Value::List { vals, .. } => {
|
||||||
let rebuild_array_as_map = is_valid_record(&vals) && count_columns_in_record(&vals) > 0;
|
let rebuild_array_as_map = is_valid_record(&vals) && count_columns_in_record(&vals) > 0;
|
||||||
if rebuild_array_as_map {
|
if rebuild_array_as_map {
|
||||||
@ -174,7 +174,7 @@ fn build_map_from_record(vals: Vec<Value>, config: &Config) -> TableValue {
|
|||||||
|
|
||||||
for val in vals {
|
for val in vals {
|
||||||
let val = get_as_record(val);
|
let val = get_as_record(val);
|
||||||
for (i, (_, val)) in val.into_owned().into_iter().enumerate() {
|
for (i, (_, val)) in val.into_iter().enumerate() {
|
||||||
let value = convert_nu_value_to_table_value(val, config);
|
let value = convert_nu_value_to_table_value(val, config);
|
||||||
let list = get_table_value_column_mut(&mut list[i]);
|
let list = get_table_value_column_mut(&mut list[i]);
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ fn get_table_value_column_mut(val: &mut TableValue) -> &mut Vec<TableValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_as_record(val: Value) -> nu_utils::SharedCow<Record> {
|
fn get_as_record(val: Value) -> Record {
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val, .. } => val,
|
Value::Record { val, .. } => val,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -183,11 +183,9 @@ impl NuDataFrame {
|
|||||||
|
|
||||||
conversion::insert_record(&mut column_values, record, &maybe_schema)?
|
conversion::insert_record(&mut column_values, record, &maybe_schema)?
|
||||||
}
|
}
|
||||||
Value::Record { val: record, .. } => conversion::insert_record(
|
Value::Record { val: record, .. } => {
|
||||||
&mut column_values,
|
conversion::insert_record(&mut column_values, record, &maybe_schema)?
|
||||||
record.into_owned(),
|
}
|
||||||
&maybe_schema,
|
|
||||||
)?,
|
|
||||||
_ => {
|
_ => {
|
||||||
let key = "0".to_string();
|
let key = "0".to_string();
|
||||||
conversion::insert_value(value, key.into(), &mut column_values, &maybe_schema)?
|
conversion::insert_value(value, key.into(), &mut column_values, &maybe_schema)?
|
||||||
|
@ -209,7 +209,7 @@ fn value_to_string(
|
|||||||
},
|
},
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
let mut collection = vec![];
|
let mut collection = vec![];
|
||||||
for (col, val) in &**val {
|
for (col, val) in val {
|
||||||
let col = if needs_quoting(col) {
|
let col = if needs_quoting(col) {
|
||||||
&escape_quote_string(col)
|
&escape_quote_string(col)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user