support calling with the redirection mode of the caller
This commit is contained in:
parent
6d199fd219
commit
689cc49663
|
@ -25,20 +25,19 @@ const BLOCK_INPUT: RegId = RegId(0);
|
||||||
pub fn compile(working_set: &StateWorkingSet, block: &Block) -> Result<IrBlock, CompileError> {
|
pub fn compile(working_set: &StateWorkingSet, block: &Block) -> Result<IrBlock, CompileError> {
|
||||||
let mut builder = BlockBuilder::new();
|
let mut builder = BlockBuilder::new();
|
||||||
|
|
||||||
|
let span = block.span.unwrap_or(Span::unknown());
|
||||||
|
|
||||||
compile_block(
|
compile_block(
|
||||||
working_set,
|
working_set,
|
||||||
&mut builder,
|
&mut builder,
|
||||||
block,
|
block,
|
||||||
RedirectModes::default(),
|
RedirectModes::caller(span),
|
||||||
Some(BLOCK_INPUT),
|
Some(BLOCK_INPUT),
|
||||||
BLOCK_INPUT,
|
BLOCK_INPUT,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// A complete block has to end with a `return`
|
// A complete block has to end with a `return`
|
||||||
builder.push(
|
builder.push(Instruction::Return { src: BLOCK_INPUT }.into_spanned(span))?;
|
||||||
Instruction::Return { src: BLOCK_INPUT }
|
|
||||||
.into_spanned(block.span.unwrap_or(Span::unknown())),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(builder.finish())
|
Ok(builder.finish())
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,13 @@ impl RedirectModes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn caller(span: Span) -> RedirectModes {
|
||||||
|
RedirectModes {
|
||||||
|
out: Some(RedirectMode::Caller.into_spanned(span)),
|
||||||
|
err: Some(RedirectMode::Caller.into_spanned(span)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn with_pipe_out(&self, span: Span) -> Self {
|
pub(crate) fn with_pipe_out(&self, span: Span) -> Self {
|
||||||
RedirectModes {
|
RedirectModes {
|
||||||
out: Some(RedirectMode::Pipe.into_spanned(span)),
|
out: Some(RedirectMode::Pipe.into_spanned(span)),
|
||||||
|
|
|
@ -371,13 +371,11 @@ fn eval_instruction<D: DebugContext>(
|
||||||
Ok(Continue)
|
Ok(Continue)
|
||||||
}
|
}
|
||||||
Instruction::RedirectOut { mode } => {
|
Instruction::RedirectOut { mode } => {
|
||||||
let out_dest = eval_redirection(ctx, mode, *span)?;
|
ctx.redirect_out = eval_redirection(ctx, mode, *span, RedirectionStream::Out)?;
|
||||||
ctx.redirect_out = Some(out_dest);
|
|
||||||
Ok(Continue)
|
Ok(Continue)
|
||||||
}
|
}
|
||||||
Instruction::RedirectErr { mode } => {
|
Instruction::RedirectErr { mode } => {
|
||||||
let out_dest = eval_redirection(ctx, mode, *span)?;
|
ctx.redirect_err = eval_redirection(ctx, mode, *span, RedirectionStream::Err)?;
|
||||||
ctx.redirect_err = Some(out_dest);
|
|
||||||
Ok(Continue)
|
Ok(Continue)
|
||||||
}
|
}
|
||||||
Instruction::Call { decl_id, src_dst } => {
|
Instruction::Call { decl_id, src_dst } => {
|
||||||
|
@ -1093,17 +1091,23 @@ fn collect(data: PipelineData, fallback_span: Span) -> Result<PipelineData, Shel
|
||||||
Ok(PipelineData::Value(value, metadata))
|
Ok(PipelineData::Value(value, metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum RedirectionStream {
|
||||||
|
Out,
|
||||||
|
Err,
|
||||||
|
}
|
||||||
|
|
||||||
/// Set up a [`Redirection`] from a [`RedirectMode`]
|
/// Set up a [`Redirection`] from a [`RedirectMode`]
|
||||||
fn eval_redirection(
|
fn eval_redirection(
|
||||||
ctx: &mut EvalContext<'_>,
|
ctx: &mut EvalContext<'_>,
|
||||||
mode: &RedirectMode,
|
mode: &RedirectMode,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<Redirection, ShellError> {
|
which: RedirectionStream,
|
||||||
|
) -> Result<Option<Redirection>, ShellError> {
|
||||||
match mode {
|
match mode {
|
||||||
RedirectMode::Pipe => Ok(Redirection::Pipe(OutDest::Pipe)),
|
RedirectMode::Pipe => Ok(Some(Redirection::Pipe(OutDest::Pipe))),
|
||||||
RedirectMode::Capture => Ok(Redirection::Pipe(OutDest::Capture)),
|
RedirectMode::Capture => Ok(Some(Redirection::Pipe(OutDest::Capture))),
|
||||||
RedirectMode::Null => Ok(Redirection::Pipe(OutDest::Null)),
|
RedirectMode::Null => Ok(Some(Redirection::Pipe(OutDest::Null))),
|
||||||
RedirectMode::Inherit => Ok(Redirection::Pipe(OutDest::Inherit)),
|
RedirectMode::Inherit => Ok(Some(Redirection::Pipe(OutDest::Inherit))),
|
||||||
RedirectMode::File { path, append } => {
|
RedirectMode::File { path, append } => {
|
||||||
let path = ctx.collect_reg(*path, span)?;
|
let path = ctx.collect_reg(*path, span)?;
|
||||||
let path_expanded =
|
let path_expanded =
|
||||||
|
@ -1118,8 +1122,12 @@ fn eval_redirection(
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(path_expanded)
|
.open(path_expanded)
|
||||||
.map_err(|err| err.into_spanned(span))?;
|
.map_err(|err| err.into_spanned(span))?;
|
||||||
Ok(Redirection::File(file.into()))
|
Ok(Some(Redirection::File(file.into())))
|
||||||
}
|
}
|
||||||
|
RedirectMode::Caller => Ok(match which {
|
||||||
|
RedirectionStream::Out => ctx.stack.pipe_stdout().cloned().map(Redirection::Pipe),
|
||||||
|
RedirectionStream::Err => ctx.stack.pipe_stderr().cloned().map(Redirection::Pipe),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,7 @@ impl fmt::Display for RedirectMode {
|
||||||
RedirectMode::Null => write!(f, "null"),
|
RedirectMode::Null => write!(f, "null"),
|
||||||
RedirectMode::Inherit => write!(f, "inherit"),
|
RedirectMode::Inherit => write!(f, "inherit"),
|
||||||
RedirectMode::File { path, append } => write!(f, "file({path}, append={append})"),
|
RedirectMode::File { path, append } => write!(f, "file({path}, append={append})"),
|
||||||
|
RedirectMode::Caller => write!(f, "caller"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,8 @@ pub enum RedirectMode {
|
||||||
path: RegId,
|
path: RegId,
|
||||||
append: bool,
|
append: bool,
|
||||||
},
|
},
|
||||||
|
/// Use the redirection mode requested by the caller, for a pre-return call.
|
||||||
|
Caller,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Just a hack to allow `Arc<[u8]>` to be serialized and deserialized
|
/// Just a hack to allow `Arc<[u8]>` to be serialized and deserialized
|
||||||
|
|
Loading…
Reference in New Issue
Block a user