mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 00:13:21 +01:00
Merge env into $nu and simplify table/get (#1463)
This commit is contained in:
parent
ebf139f5e5
commit
50fb97f6b7
@ -240,7 +240,6 @@ pub fn create_default_context(
|
||||
per_item_command(Ls),
|
||||
per_item_command(Du),
|
||||
whole_stream_command(Cd),
|
||||
whole_stream_command(Env),
|
||||
per_item_command(Remove),
|
||||
per_item_command(Open),
|
||||
whole_stream_command(Config),
|
||||
|
@ -23,7 +23,6 @@ pub(crate) mod du;
|
||||
pub(crate) mod echo;
|
||||
pub(crate) mod edit;
|
||||
pub(crate) mod enter;
|
||||
pub(crate) mod env;
|
||||
#[allow(unused)]
|
||||
pub(crate) mod evaluate_by;
|
||||
pub(crate) mod exit;
|
||||
@ -126,7 +125,6 @@ pub(crate) mod clear;
|
||||
pub(crate) use clear::Clear;
|
||||
pub(crate) mod touch;
|
||||
pub(crate) use enter::Enter;
|
||||
pub(crate) use env::Env;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use evaluate_by::EvaluateBy;
|
||||
pub(crate) use exit::Exit;
|
||||
|
@ -1,91 +0,0 @@
|
||||
use crate::cli::History;
|
||||
use crate::data::config;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Dictionary, Signature, TaggedDictBuilder, UntaggedValue, Value};
|
||||
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub struct Env;
|
||||
|
||||
impl WholeStreamCommand for Env {
|
||||
fn name(&self) -> &str {
|
||||
"env"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("env")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Get the current environment."
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
env(args, registry)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_environment(tag: Tag) -> Result<Value, Box<dyn std::error::Error>> {
|
||||
let mut indexmap = IndexMap::new();
|
||||
|
||||
let path = std::env::current_dir()?;
|
||||
indexmap.insert(
|
||||
"cwd".to_string(),
|
||||
UntaggedValue::path(path).into_value(&tag),
|
||||
);
|
||||
|
||||
if let Some(home) = dirs::home_dir() {
|
||||
indexmap.insert(
|
||||
"home".to_string(),
|
||||
UntaggedValue::path(home).into_value(&tag),
|
||||
);
|
||||
}
|
||||
|
||||
let config = config::default_path()?;
|
||||
indexmap.insert(
|
||||
"config".to_string(),
|
||||
UntaggedValue::path(config).into_value(&tag),
|
||||
);
|
||||
|
||||
let history = History::path();
|
||||
indexmap.insert(
|
||||
"history".to_string(),
|
||||
UntaggedValue::path(history).into_value(&tag),
|
||||
);
|
||||
|
||||
let temp = std::env::temp_dir();
|
||||
indexmap.insert(
|
||||
"temp".to_string(),
|
||||
UntaggedValue::path(temp).into_value(&tag),
|
||||
);
|
||||
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
for v in std::env::vars() {
|
||||
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
|
||||
}
|
||||
if !dict.is_empty() {
|
||||
indexmap.insert("vars".to_string(), dict.into_value());
|
||||
}
|
||||
|
||||
Ok(UntaggedValue::Row(Dictionary::from(indexmap)).into_value(&tag))
|
||||
}
|
||||
|
||||
pub fn env(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
let args = args.evaluate_once(registry)?;
|
||||
|
||||
let mut env_out = VecDeque::new();
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
|
||||
let value = get_environment(tag)?;
|
||||
env_out.push_back(value);
|
||||
|
||||
let env_out = futures::stream::iter(env_out);
|
||||
|
||||
Ok(env_out.to_output_stream())
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::data::base::shape::Shapes;
|
||||
use crate::prelude::*;
|
||||
use futures_util::pin_mut;
|
||||
use indexmap::set::IndexSet;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
@ -180,23 +178,15 @@ pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result<Value, ShellErr
|
||||
|
||||
pub fn get(
|
||||
GetArgs { rest: mut fields }: GetArgs,
|
||||
RunnableContext { input, .. }: RunnableContext,
|
||||
RunnableContext { mut input, .. }: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
if fields.is_empty() {
|
||||
let stream = async_stream! {
|
||||
let values = input.values;
|
||||
pin_mut!(values);
|
||||
let mut vec = input.drain_vec().await;
|
||||
|
||||
let mut shapes = Shapes::new();
|
||||
let mut index = 0;
|
||||
|
||||
while let Some(row) = values.next().await {
|
||||
shapes.add(&row, index);
|
||||
index += 1;
|
||||
}
|
||||
|
||||
for row in shapes.to_values() {
|
||||
yield ReturnSuccess::value(row);
|
||||
let descs = nu_protocol::merge_descriptors(&vec);
|
||||
for desc in descs {
|
||||
yield ReturnSuccess::value(desc);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value};
|
||||
use nu_protocol::{
|
||||
merge_descriptors, ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue,
|
||||
};
|
||||
use nu_source::{SpannedItem, Tagged};
|
||||
use nu_value_ext::get_data_by_key;
|
||||
|
||||
@ -52,18 +54,6 @@ impl WholeStreamCommand for Pivot {
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_descriptors(values: &[Value]) -> Vec<String> {
|
||||
let mut ret = vec![];
|
||||
for value in values {
|
||||
for desc in value.data_descriptors() {
|
||||
if !ret.contains(&desc) {
|
||||
ret.push(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn pivot(args: PivotArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
|
||||
let stream = async_stream! {
|
||||
let input = context.input.into_vec().await;
|
||||
|
@ -1,17 +1,11 @@
|
||||
use crate::prelude::*;
|
||||
use chrono::{DateTime, Utc};
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::RangeInclusion;
|
||||
use nu_protocol::{
|
||||
format_primitive, ColumnPath, Dictionary, Evaluate, Primitive, ShellTypeName,
|
||||
TaggedDictBuilder, UntaggedValue, Value,
|
||||
};
|
||||
use nu_protocol::{format_primitive, ColumnPath, Dictionary, Primitive, UntaggedValue, Value};
|
||||
use nu_source::{b, PrettyDebug};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
@ -193,13 +187,17 @@ impl PrettyDebug for FormatInlineShape {
|
||||
"[",
|
||||
b::kind("row")
|
||||
+ b::space()
|
||||
+ b::intersperse(
|
||||
row.keys().map(|key| match key {
|
||||
Column::String(string) => b::description(string),
|
||||
Column::Value => b::blank(),
|
||||
}),
|
||||
b::space(),
|
||||
),
|
||||
+ if row.keys().len() <= 6 {
|
||||
b::intersperse(
|
||||
row.keys().map(|key| match key {
|
||||
Column::String(string) => b::description(string),
|
||||
Column::Value => b::blank(),
|
||||
}),
|
||||
b::space(),
|
||||
)
|
||||
} else {
|
||||
b::description(format!("{} columns", row.keys().len()))
|
||||
},
|
||||
"]",
|
||||
)
|
||||
.group(),
|
||||
@ -269,113 +267,3 @@ impl Into<Column> for &str {
|
||||
Column::String(self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum Shape {
|
||||
Primitive(&'static str),
|
||||
Row(Vec<Column>),
|
||||
Table { from: usize, to: usize },
|
||||
Error(ShellError),
|
||||
Block(Evaluate),
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
pub fn for_value(value: &Value) -> Shape {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(p) => Shape::Primitive(p.type_name()),
|
||||
UntaggedValue::Row(row) => Shape::for_dict(row),
|
||||
UntaggedValue::Table(table) => Shape::Table {
|
||||
from: 0,
|
||||
to: table.len(),
|
||||
},
|
||||
UntaggedValue::Error(error) => Shape::Error(error.clone()),
|
||||
UntaggedValue::Block(block) => Shape::Block(block.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn for_dict(dict: &Dictionary) -> Shape {
|
||||
Shape::Row(dict.keys().map(|key| Column::String(key.clone())).collect())
|
||||
}
|
||||
|
||||
pub fn describe(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
Shape::Primitive(desc) => write!(w, "[{}]", desc),
|
||||
Shape::Row(d) => write!(
|
||||
w,
|
||||
"[row: {}]",
|
||||
d.iter()
|
||||
.map(|c| match c {
|
||||
Column::String(s) => s.clone(),
|
||||
Column::Value => "<value>".to_owned(),
|
||||
})
|
||||
.join(", ")
|
||||
),
|
||||
Shape::Table { to, .. } => {
|
||||
if *to == 1 {
|
||||
write!(w, "[table: {} row]", to)
|
||||
} else {
|
||||
write!(w, "[table: {} rows]", to)
|
||||
}
|
||||
}
|
||||
Shape::Error(_) => write!(w, "[error]"),
|
||||
Shape::Block(_) => write!(w, "[block]"),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_value(&self) -> Value {
|
||||
let mut out = vec![];
|
||||
self.describe(&mut out)
|
||||
.expect("Writing into a Vec can't fail");
|
||||
let string = String::from_utf8_lossy(&out);
|
||||
|
||||
UntaggedValue::string(string).into_untagged_value()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Shapes {
|
||||
shapes: IndexMap<Shape, Vec<usize>>,
|
||||
}
|
||||
|
||||
impl Shapes {
|
||||
pub fn new() -> Shapes {
|
||||
Shapes {
|
||||
shapes: IndexMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, value: &Value, row: usize) {
|
||||
let shape = Shape::for_value(value);
|
||||
|
||||
self.shapes
|
||||
.entry(shape)
|
||||
.and_modify(|indexes| indexes.push(row))
|
||||
.or_insert_with(|| vec![row]);
|
||||
}
|
||||
|
||||
pub fn to_values(&self) -> Vec<Value> {
|
||||
if self.shapes.len() == 1 {
|
||||
if let Some(shape) = self.shapes.keys().nth(0) {
|
||||
let mut tagged_dict = TaggedDictBuilder::new(Tag::unknown());
|
||||
tagged_dict.insert_untagged("type", shape.to_value());
|
||||
tagged_dict.insert_untagged("rows", UntaggedValue::string("all"));
|
||||
vec![tagged_dict.into_value()]
|
||||
} else {
|
||||
unreachable!("Internal error: impossible state in to_values")
|
||||
}
|
||||
} else {
|
||||
self.shapes
|
||||
.iter()
|
||||
.map(|(shape, rows)| {
|
||||
let rows = rows.iter().map(|i| i.to_string()).join(", ");
|
||||
|
||||
let mut tagged_dict = TaggedDictBuilder::new(Tag::unknown());
|
||||
tagged_dict.insert_untagged("type", shape.to_value());
|
||||
tagged_dict
|
||||
.insert_untagged("rows", UntaggedValue::string(format!("[ {} ]", rows)));
|
||||
|
||||
tagged_dict.into_value()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::cli::History;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
|
||||
use nu_source::Tag;
|
||||
@ -27,5 +28,24 @@ pub fn nu(tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||
}
|
||||
nu_dict.insert_value("path", UntaggedValue::table(&table).into_value(&tag));
|
||||
|
||||
let path = std::env::current_dir()?;
|
||||
nu_dict.insert_value("cwd", UntaggedValue::path(path).into_value(&tag));
|
||||
|
||||
if let Some(home) = dirs::home_dir() {
|
||||
nu_dict.insert_value("home-dir", UntaggedValue::path(home).into_value(&tag));
|
||||
}
|
||||
|
||||
let temp = std::env::temp_dir();
|
||||
nu_dict.insert_value("temp-dir", UntaggedValue::path(temp).into_value(&tag));
|
||||
|
||||
let config = crate::data::config::default_path()?;
|
||||
nu_dict.insert_value("config-path", UntaggedValue::path(config).into_value(&tag));
|
||||
|
||||
let history = History::path();
|
||||
nu_dict.insert_value(
|
||||
"history-path",
|
||||
UntaggedValue::path(history).into_value(&tag),
|
||||
);
|
||||
|
||||
Ok(nu_dict.into_value())
|
||||
}
|
||||
|
@ -26,27 +26,6 @@ enum TableMode {
|
||||
}
|
||||
|
||||
impl TableView {
|
||||
fn merge_descriptors(values: &[Value]) -> Vec<String> {
|
||||
let mut ret: Vec<String> = vec![];
|
||||
let value_column = "<value>".to_string();
|
||||
for value in values {
|
||||
let descs = value.data_descriptors();
|
||||
|
||||
if descs.is_empty() {
|
||||
if !ret.contains(&value_column) {
|
||||
ret.push("<value>".to_string());
|
||||
}
|
||||
} else {
|
||||
for desc in value.data_descriptors() {
|
||||
if !ret.contains(&desc) {
|
||||
ret.push(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn from_list(values: &[Value], starting_idx: usize) -> Option<TableView> {
|
||||
if values.is_empty() {
|
||||
return None;
|
||||
@ -55,7 +34,7 @@ impl TableView {
|
||||
// Different platforms want different amounts of buffer, not sure why
|
||||
let termwidth = std::cmp::max(textwrap::termwidth(), 20);
|
||||
|
||||
let mut headers = TableView::merge_descriptors(values);
|
||||
let mut headers = nu_protocol::merge_descriptors(values);
|
||||
let mut entries = values_to_entries(values, &mut headers, starting_idx);
|
||||
let max_per_column = max_per_column(&headers, &entries, values.len());
|
||||
|
||||
|
@ -23,4 +23,4 @@ pub use crate::value::evaluate::{Evaluate, EvaluateTrait, Scope};
|
||||
pub use crate::value::primitive::Primitive;
|
||||
pub use crate::value::primitive::{format_date, format_duration, format_primitive};
|
||||
pub use crate::value::range::{Range, RangeInclusion};
|
||||
pub use crate::value::{UntaggedValue, Value};
|
||||
pub use crate::value::{merge_descriptors, UntaggedValue, Value};
|
||||
|
@ -378,3 +378,24 @@ impl From<ShellError> for UntaggedValue {
|
||||
UntaggedValue::Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merge_descriptors(values: &[Value]) -> Vec<String> {
|
||||
let mut ret: Vec<String> = vec![];
|
||||
let value_column = "<value>".to_string();
|
||||
for value in values {
|
||||
let descs = value.data_descriptors();
|
||||
|
||||
if descs.is_empty() {
|
||||
if !ret.contains(&value_column) {
|
||||
ret.push("<value>".to_string());
|
||||
}
|
||||
} else {
|
||||
for desc in value.data_descriptors() {
|
||||
if !ret.contains(&desc) {
|
||||
ret.push(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
# env
|
||||
|
||||
The `env` command prints to terminal the environment of nushell
|
||||
|
||||
This includes
|
||||
- cwd : the path to the current working the directory (`cwd`),
|
||||
- home : the path to the home directory
|
||||
- config : the path to the config file for nushell
|
||||
- history : the path to the nushell command history
|
||||
- temp : the path to the temp file
|
||||
- vars : descriptor variable for the table
|
||||
|
||||
`env` does not take any arguments, and ignores any arguments given.
|
||||
|
||||
|
||||
## Examples -
|
||||
|
||||
|
||||
```shell
|
||||
/home/username/mynushell/docs/commands(master)> env
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━┯━━━━━━━━━━━━━━━━
|
||||
cwd │ home │ config │ history │ temp │ vars
|
||||
────────────────────────────────────────┼────────────────┼───────────────────────────────────────┼────────────────────────────────────────────┼──────┼────────────────
|
||||
/home/username/mynushell/docs/commands │ /home/username │ /home/username/.config/nu/config.toml │ /home/username/.local/share/nu/history.txt │ /tmp │ [table: 1 row]
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━┷━━━━━━━━━━━━━━━━
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user