Allow specifying a cellpath in input list to get the value to display (#11748)

# Description
When using a table (or a list of records) as input to `input list`,
allow specifying a cellpath for the field/column to use as the display
value.

For instance, at the moment, using a table as input results in the
following:

```
❯ [[name price]; [Banana 12] [Kiwi 4] [Pear 7]] | input list
> {name: Banana, price: 12}
  {name: Kiwi, price: 4}
  {name: Pear, price: 7}
```

With the new `--display` flag introduced by this PR, you can do the
following:

```
❯ [[name price]; [Banana 12] [Kiwi 4] [Pear 7]] | input list -d name
> Banana
  Kiwi
  Pear
```

Note that it doesn't change what gets returned after selecting an item:
the full row/record is still returned.

# User-Facing Changes
A new optional flag is allowed.

# Tests + Formatting

# After Submitting
This commit is contained in:
Antoine Büsch 2024-02-08 10:21:47 +11:00 committed by GitHub
parent f8a8eca836
commit 9fa2b77611
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,7 +1,7 @@
use dialoguer::{console::Term, Select}; use dialoguer::{console::Term, Select};
use dialoguer::{FuzzySelect, MultiSelect}; use dialoguer::{FuzzySelect, MultiSelect};
use nu_engine::CallExt; use nu_engine::CallExt;
use nu_protocol::ast::Call; use nu_protocol::ast::{Call, CellPath};
use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{ use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Type,
@ -50,6 +50,12 @@ impl Command for InputList {
) )
.switch("fuzzy", "Use a fuzzy select.", Some('f')) .switch("fuzzy", "Use a fuzzy select.", Some('f'))
.switch("index", "Returns list indexes.", Some('i')) .switch("index", "Returns list indexes.", Some('i'))
.named(
"display",
SyntaxShape::CellPath,
"Field to use as display value",
Some('d'),
)
.allow_variants_without_examples(true) .allow_variants_without_examples(true)
.category(Category::Platform) .category(Category::Platform)
} }
@ -78,17 +84,27 @@ impl Command for InputList {
let multi = call.has_flag(engine_state, stack, "multi")?; let multi = call.has_flag(engine_state, stack, "multi")?;
let fuzzy = call.has_flag(engine_state, stack, "fuzzy")?; let fuzzy = call.has_flag(engine_state, stack, "fuzzy")?;
let index = call.has_flag(engine_state, stack, "index")?; let index = call.has_flag(engine_state, stack, "index")?;
let display_path: Option<CellPath> = call.get_flag(engine_state, stack, "display")?;
let options: Vec<Options> = match input { let options: Vec<Options> = match input {
PipelineData::Value(Value::Range { .. }, ..) PipelineData::Value(Value::Range { .. }, ..)
| PipelineData::Value(Value::List { .. }, ..) | PipelineData::Value(Value::List { .. }, ..)
| PipelineData::ListStream { .. } => input | PipelineData::ListStream { .. } => input
.into_iter() .into_iter()
.map(move |val| Options { .map(move |val| {
name: val.into_string(", ", engine_state.get_config()), let display_value = if let Some(ref cellpath) = display_path {
val.clone()
.follow_cell_path(&cellpath.members, false)?
.into_string(", ", engine_state.get_config())
} else {
val.into_string(", ", engine_state.get_config())
};
Ok(Options {
name: display_value,
value: val, value: val,
}) })
.collect(), })
.collect::<Result<Vec<_>, ShellError>>()?,
_ => { _ => {
return Err(ShellError::TypeMismatch { return Err(ShellError::TypeMismatch {
@ -235,6 +251,11 @@ impl Command for InputList {
example: r#"[Banana Kiwi Pear Peach Strawberry] | input list --index"#, example: r#"[Banana Kiwi Pear Peach Strawberry] | input list --index"#,
result: None, result: None,
}, },
Example {
description: "Choose an item from a table using a column as display value",
example: r#"[[name price]; [Banana 12] [Kiwi 4] [Pear 7]] | input list -d name"#,
result: None,
},
] ]
} }
} }