From 30fc83203508c1c2470a2f6ad188e90f7efbbcb8 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sun, 12 May 2024 11:19:28 +0000 Subject: [PATCH] Fix custom converters with `save` (#12833) # Description Fixes #10429 where `save` fails if a custom command is used as the file format converter. # Tests + Formatting Added a test. --- crates/nu-command/src/filesystem/save.rs | 41 +++++++++++------------- crates/nu-command/tests/commands/save.rs | 17 ++++++++++ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/crates/nu-command/src/filesystem/save.rs b/crates/nu-command/src/filesystem/save.rs index 3b92416ab5..0826284798 100644 --- a/crates/nu-command/src/filesystem/save.rs +++ b/crates/nu-command/src/filesystem/save.rs @@ -1,4 +1,5 @@ use crate::progress_bar; +use nu_engine::get_eval_block; #[allow(deprecated)] use nu_engine::{command_prelude::*, current_dir}; use nu_path::expand_path_with; @@ -311,12 +312,13 @@ fn input_to_bytes( .map(|name| name.to_string_lossy().to_string()) }; - if let Some(ext) = ext { - convert_to_extension(engine_state, &ext, stack, input, span) + let input = if let Some(ext) = ext { + convert_to_extension(engine_state, &ext, stack, input, span)? } else { - let value = input.into_value(span); - value_to_bytes(value) - } + input + }; + + value_to_bytes(input.into_value(span)) } /// Convert given data into content of file of specified extension if @@ -328,24 +330,19 @@ fn convert_to_extension( stack: &mut Stack, input: PipelineData, span: Span, -) -> Result, ShellError> { - let converter = engine_state.find_decl(format!("to {extension}").as_bytes(), &[]); - - let output = match converter { - Some(converter_id) => { - let output = engine_state.get_decl(converter_id).run( - engine_state, - stack, - &Call::new(span), - input, - )?; - - output.into_value(span) +) -> Result { + if let Some(decl_id) = engine_state.find_decl(format!("to {extension}").as_bytes(), &[]) { + let decl = engine_state.get_decl(decl_id); + if let Some(block_id) = decl.get_block_id() { + let block = engine_state.get_block(block_id); + let eval_block = get_eval_block(engine_state); + eval_block(engine_state, stack, block, input) + } else { + decl.run(engine_state, stack, &Call::new(span), input) } - None => input.into_value(span), - }; - - value_to_bytes(output) + } else { + Ok(input) + } } /// Convert [`Value::String`] [`Value::Binary`] or [`Value::List`] into [`Vec`] of bytes diff --git a/crates/nu-command/tests/commands/save.rs b/crates/nu-command/tests/commands/save.rs index b5776a7bb9..ef0304dc7c 100644 --- a/crates/nu-command/tests/commands/save.rs +++ b/crates/nu-command/tests/commands/save.rs @@ -407,3 +407,20 @@ fn save_same_file_without_extension_pipeline() { .contains("pipeline input and output are the same file")); }) } + +#[test] +fn save_with_custom_converter() { + Playground::setup("save_with_custom_converter", |dirs, _| { + let file = dirs.test().join("test.ndjson"); + + nu!(cwd: dirs.test(), pipeline( + r#" + def "to ndjson" []: any -> string { each { to json --raw } | to text } ; + {a: 1, b: 2} | save test.ndjson + "# + )); + + let actual = file_contents(file); + assert_eq!(actual, r#"{"a":1,"b":2}"#); + }) +}