mirror of
https://github.com/nushell/nushell.git
synced 2025-08-10 13:47:47 +02:00
Stdout/Stderr redirection (#7185)
This adds new pipeline connectors called out> and err> which redirect either stdout or stderr to a file. You can also use out+err> (or err+out>) to redirect both streams into a file.
This commit is contained in:
@ -2,38 +2,50 @@ use std::ops::{Index, IndexMut};
|
||||
|
||||
use crate::{ast::Expression, engine::StateWorkingSet, Span, VarId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Redirection {
|
||||
Stdout,
|
||||
Stderr,
|
||||
StdoutAndStderr,
|
||||
}
|
||||
|
||||
// Note: Span in the below is for the span of the connector not the whole element
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PipelineElement {
|
||||
Expression(Expression),
|
||||
Redirect(Expression),
|
||||
And(Expression),
|
||||
Or(Expression),
|
||||
Expression(Option<Span>, Expression),
|
||||
Redirection(Span, Redirection, Expression),
|
||||
And(Span, Expression),
|
||||
Or(Span, Expression),
|
||||
}
|
||||
|
||||
impl PipelineElement {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
PipelineElement::Expression(expression)
|
||||
| PipelineElement::Redirect(expression)
|
||||
| PipelineElement::And(expression)
|
||||
| PipelineElement::Or(expression) => expression.span,
|
||||
PipelineElement::Expression(None, expression) => expression.span,
|
||||
PipelineElement::Expression(Some(span), expression)
|
||||
| PipelineElement::Redirection(span, _, expression)
|
||||
| PipelineElement::And(span, expression)
|
||||
| PipelineElement::Or(span, expression) => Span {
|
||||
start: span.start,
|
||||
end: expression.span.end,
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn has_in_variable(&self, working_set: &StateWorkingSet) -> bool {
|
||||
match self {
|
||||
PipelineElement::Expression(expression)
|
||||
| PipelineElement::Redirect(expression)
|
||||
| PipelineElement::And(expression)
|
||||
| PipelineElement::Or(expression) => expression.has_in_variable(working_set),
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression) => expression.has_in_variable(working_set),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_in_variable(&mut self, working_set: &mut StateWorkingSet, new_var_id: VarId) {
|
||||
match self {
|
||||
PipelineElement::Expression(expression)
|
||||
| PipelineElement::Redirect(expression)
|
||||
| PipelineElement::And(expression)
|
||||
| PipelineElement::Or(expression) => {
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression) => {
|
||||
expression.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
}
|
||||
@ -46,10 +58,10 @@ impl PipelineElement {
|
||||
new_span: Span,
|
||||
) {
|
||||
match self {
|
||||
PipelineElement::Expression(expression)
|
||||
| PipelineElement::Redirect(expression)
|
||||
| PipelineElement::And(expression)
|
||||
| PipelineElement::Or(expression) => {
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression) => {
|
||||
expression.replace_span(working_set, replaced, new_span)
|
||||
}
|
||||
}
|
||||
@ -76,7 +88,10 @@ impl Pipeline {
|
||||
Self {
|
||||
elements: expressions
|
||||
.into_iter()
|
||||
.map(PipelineElement::Expression)
|
||||
.enumerate()
|
||||
.map(|(idx, x)| {
|
||||
PipelineElement::Expression(if idx == 0 { None } else { Some(x.span) }, x)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user