input: process history list from pipe

This commit is contained in:
Florent Vilmart 2025-03-23 09:58:18 -04:00
parent f5719513d1
commit 3ae38d374c

View File

@ -24,7 +24,9 @@ impl Command for Input {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("input") Signature::build("input")
.input_output_types(vec![(Type::Nothing, Type::Any)]) .input_output_types(vec![
(Type::Nothing, Type::Any),
(Type::List(Box::new(Type::String)), Type::Any)])
.allow_variants_without_examples(true) .allow_variants_without_examples(true)
.optional("prompt", SyntaxShape::String, "Prompt to show the user.") .optional("prompt", SyntaxShape::String, "Prompt to show the user.")
.named( .named(
@ -46,12 +48,9 @@ impl Command for Input {
Some('d'), Some('d'),
) )
.named( .named(
"history", "history-file",
SyntaxShape::OneOf(vec![
SyntaxShape::List(Box::new(SyntaxShape::String)),
SyntaxShape::Filepath, SyntaxShape::Filepath,
]), "path to a file to read/write history",
"path to a file to read/write history or a list of history entries",
None, None,
) )
.named( .named(
@ -69,7 +68,7 @@ impl Command for Input {
engine_state: &EngineState, engine_state: &EngineState,
stack: &mut Stack, stack: &mut Stack,
call: &Call, call: &Call,
_input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
// Those options are not supported by reedline, default to the legacy // Those options are not supported by reedline, default to the legacy
// implementation // implementation
@ -84,12 +83,12 @@ impl Command for Input {
.any(|x| *x); .any(|x| *x);
if use_legacy { if use_legacy {
return self.legacy_input(engine_state, stack, call, _input); return self.legacy_input(engine_state, stack, call, input);
} }
let prompt_str: Option<String> = call.opt(engine_state, stack, 0)?; let prompt_str: Option<String> = call.opt(engine_state, stack, 0)?;
let default_val: Option<String> = call.get_flag(engine_state, stack, "default")?; let default_val: Option<String> = call.get_flag(engine_state, stack, "default")?;
let history_val: Option<Value> = call.get_flag(engine_state, stack, "history")?; let history_file_val: Option<String> = call.get_flag(engine_state, stack, "history-file")?;
let max_history: usize = call let max_history: usize = call
.get_flag::<i64>(engine_state, stack, "max-history")? .get_flag::<i64>(engine_state, stack, "max-history")?
.map(|l| if l < 0 { 0 } else { l as usize }) .map(|l| if l < 0 { 0 } else { l as usize })
@ -102,31 +101,31 @@ impl Command for Input {
_ => "".to_string(), _ => "".to_string(),
}; };
// Here we will render the default prompt to the right let history_entries = match input {
let history = match history_val { PipelineData::Value(Value::List { vals, .. }, ..) => {
None => None, Some(vals)
Some(Value::String { val, .. }) => Some( }
FileBackedHistory::with_file(max_history, val.into()) _ => None,
.expect("Error creating history file"), };
),
Some(Value::List { vals, .. }) => { // If we either have history entries or history file, we create an history
let mut history = let history = match (history_entries.is_some(), history_file_val.is_some()) {
FileBackedHistory::new(max_history).expect("Error creating history file"); (false, false) => None,
_ => {
let mut history = match history_file_val {
Some(file) => FileBackedHistory::with_file(max_history, file.into()),
None => FileBackedHistory::new(max_history)
}.expect("Error creating history file");
if let Some(vals) = history_entries {
vals.iter().for_each(|val| { vals.iter().for_each(|val| {
if let Value::String { val, .. } = val { if let Value::String { val, .. } = val {
let _ = history.save(HistoryItem::from_command_line(val.clone())); let _ = history.save(HistoryItem::from_command_line(val.clone()));
} }
}); });
Some(history)
} }
Some(h) => { Some(history)
return Err(ShellError::UnsupportedInput { },
msg: "Unsupported history type".to_string(),
input: "value originated from here".to_string(),
msg_span: call.head,
input_span: h.span(),
})
} // Value::List { vals, .. } => Some(Box::new((usize::MAX, val.into()))),
}; };
let prompt = ReedlinePrompt { let prompt = ReedlinePrompt {
@ -187,12 +186,12 @@ impl Command for Input {
}, },
Example { Example {
description: "Get input from the user with history, and assign to a variable", description: "Get input from the user with history, and assign to a variable",
example: "let user_input = (input --history [past,command,entries])", example: "let user_input = ([past,command,entries] | input)",
result: None, result: None,
}, },
Example { Example {
description: "Get input from the user with history backed by a file, and assign to a variable", description: "Get input from the user with history backed by a file, and assign to a variable",
example: "let user_input = (input --history ./history.txt)", example: "let user_input = (input --history-file ./history.txt)",
result: None, result: None,
}, },
] ]