mirror of
https://github.com/nushell/nushell.git
synced 2025-01-22 14:18:55 +01:00
5f550a355b
* Split OutputStream into ActionStream/OutputStream * Fmt * Missed update * Cleanup helper names * Fmt
118 lines
3.3 KiB
Rust
118 lines
3.3 KiB
Rust
use crate::prelude::*;
|
|
use nu_engine::WholeStreamCommand;
|
|
use nu_errors::ShellError;
|
|
use nu_protocol::{
|
|
merge_descriptors, ColumnPath, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder,
|
|
UntaggedValue,
|
|
};
|
|
use nu_source::{SpannedItem, Tagged};
|
|
use nu_value_ext::ValueExt;
|
|
|
|
pub struct Command;
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct Arguments {
|
|
rest: Vec<Tagged<String>>,
|
|
}
|
|
|
|
impl WholeStreamCommand for Command {
|
|
fn name(&self) -> &str {
|
|
"rotate"
|
|
}
|
|
|
|
fn signature(&self) -> Signature {
|
|
Signature::build("rotate").rest(
|
|
SyntaxShape::String,
|
|
"the names to give columns once rotated",
|
|
)
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
"Rotates the table by 90 degrees clockwise."
|
|
}
|
|
|
|
fn run_with_actions(&self, args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|
rotate(args)
|
|
}
|
|
}
|
|
|
|
pub fn rotate(args: CommandArgs) -> Result<ActionStream, ShellError> {
|
|
let name = args.call_info.name_tag.clone();
|
|
let (Arguments { rest }, input) = args.process()?;
|
|
|
|
let input = input.into_vec();
|
|
let total_rows = input.len();
|
|
let descs = merge_descriptors(&input);
|
|
let total_descriptors = descs.len();
|
|
|
|
let descs = descs.into_iter().rev().collect::<Vec<_>>();
|
|
|
|
if total_rows == 0 {
|
|
return Ok(ActionStream::empty());
|
|
}
|
|
|
|
let mut headers: Vec<String> = vec![];
|
|
|
|
for i in 0..=total_rows {
|
|
headers.push(format!("Column{}", i));
|
|
}
|
|
|
|
let first = input[0].clone();
|
|
|
|
let name = if first.tag.anchor().is_some() {
|
|
first.tag
|
|
} else {
|
|
name
|
|
};
|
|
|
|
let values =
|
|
UntaggedValue::table(&input.into_iter().rev().collect::<Vec<_>>()).into_value(&name);
|
|
|
|
let values = nu_data::utils::group(
|
|
&values,
|
|
&Some(Box::new(move |row_number: usize, _| {
|
|
Ok(match headers.get(row_number) {
|
|
Some(name) => name.clone(),
|
|
None => String::new(),
|
|
})
|
|
})),
|
|
&name,
|
|
)?;
|
|
|
|
Ok(((0..total_descriptors)
|
|
.map(move |row_number| {
|
|
let mut row = TaggedDictBuilder::new(&name);
|
|
|
|
for (current_numbered_column, (column_name, _)) in values.row_entries().enumerate() {
|
|
let raw_column_path =
|
|
format!("{}.0.{}", column_name, descs[row_number]).spanned_unknown();
|
|
let path = ColumnPath::build(&raw_column_path);
|
|
|
|
match &values.get_data_by_column_path(&path, Box::new(move |_, _, error| error)) {
|
|
Ok(x) => {
|
|
row.insert_value(
|
|
rest.get(current_numbered_column)
|
|
.map(|c| c.item.clone())
|
|
.unwrap_or_else(|| column_name.to_string()),
|
|
x.clone(),
|
|
);
|
|
}
|
|
Err(_) => {}
|
|
}
|
|
}
|
|
|
|
row.insert_value(
|
|
rest.get(total_rows)
|
|
.map(|c| c.item.clone())
|
|
.unwrap_or_else(|| format!("Column{}", total_rows)),
|
|
UntaggedValue::string(&descs[row_number]).into_untagged_value(),
|
|
);
|
|
|
|
ReturnSuccess::value(row.into_value())
|
|
})
|
|
.rev()
|
|
.collect::<Vec<_>>())
|
|
.into_iter()
|
|
.to_action_stream())
|
|
}
|