Allow open to work with 'from ...' block commands (#5049)

* Remove panic from BlockCommands run function

Instead of panicing, the run method now returns an error to prevent
nushell from unexpected termination.

* Add ability to open command to run with blocks

The open command tries to parse the content of the file
if there is a command called 'from (file ending)'.  This works
fine if the command was 'built in' because the run method doesn't
fail in this case.  It did fail on a BlockCommand, though.

This change will first probe if the command contains a block and
evaluate it, if this is the case.  If there is no block, it will run
the command the same way as before.

* Add test open files with BlockCommands

* Update open.rs

* Adjust file type on open with BlockCommand parser

Co-authored-by: JT <547158+jntrnr@users.noreply.github.com>
This commit is contained in:
Simon Goller 2022-04-01 20:52:32 +02:00 committed by GitHub
parent 2cb815b7b4
commit 19c3570cf9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 8 deletions

View file

@ -1,4 +1,4 @@
use nu_engine::{get_full_help, CallExt}; use nu_engine::{eval_block, get_full_help, CallExt};
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{ use nu_protocol::{
@ -141,12 +141,15 @@ impl Command for Open {
if let Some(ext) = ext { if let Some(ext) = ext {
match engine_state.find_decl(format!("from {}", ext).as_bytes()) { match engine_state.find_decl(format!("from {}", ext).as_bytes()) {
Some(converter_id) => engine_state.get_decl(converter_id).run( Some(converter_id) => {
engine_state, let decl = engine_state.get_decl(converter_id);
stack, if let Some(block_id) = decl.get_block_id() {
&Call::new(arg_span), let block = engine_state.get_block(block_id);
output, eval_block(engine_state, stack, block, output, false, false)
), } else {
decl.run(engine_state, stack, &Call::new(arg_span), output)
}
}
None => Ok(output), None => Ok(output),
} }
} else { } else {

View file

@ -260,3 +260,20 @@ fn open_dir_is_ls() {
assert_eq!(actual.out, "3"); assert_eq!(actual.out, "3");
}) })
} }
#[test]
fn test_open_block_command() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"
def "from blockcommandparser" [] { lines | split column ",|," }
let values = (open sample.blockcommandparser)
echo ($values | get column1 | get 0)
echo ($values | get column2 | get 0)
echo ($values | get column1 | get 1)
echo ($values | get column2 | get 1)
"#
);
assert_eq!(actual.out, "abcd")
}

View file

@ -8,6 +8,7 @@ use crate::engine::EngineState;
use crate::engine::Stack; use crate::engine::Stack;
use crate::BlockId; use crate::BlockId;
use crate::PipelineData; use crate::PipelineData;
use crate::ShellError;
use crate::SyntaxShape; use crate::SyntaxShape;
use crate::VarId; use crate::VarId;
@ -548,7 +549,9 @@ impl Command for BlockCommand {
_call: &Call, _call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<crate::PipelineData, crate::ShellError> { ) -> Result<crate::PipelineData, crate::ShellError> {
panic!("Internal error: can't run custom command with 'run', use block_id"); Err(ShellError::UnlabeledError(
"Internal error: can't run custom command with 'run', use block_id".to_string(),
))
} }
fn get_block_id(&self) -> Option<BlockId> { fn get_block_id(&self) -> Option<BlockId> {

View file

@ -0,0 +1,2 @@
a,|,b
c,|,d