mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 19:57:44 +02:00
Support o>>
, e>>
, o+e>>
to append output to an external file (#10764)
# Description Close: #10278 This pr introduces `o>>`, `e>>`, `o+e>>` to allow redirection to append to a file. Examples: ```nushell echo abc o>> a.txt echo abc o>> a.txt cat asdf e>> a.txt cat asdf e>> a.txt cat asdf o+e>> a.txt ``` ~~TODO:~~ ~~1. currently internal commands with `o+e>` redirect to a variable is broken: `let x = "a.txt"; echo abc o+e> $x`, not sure when it was introduced...~~ ~~2. redirect stdout and stderr with append mode doesn't supported yet: `cat asdf o>>a.txt e>>b.ext`~~ ~~For these 2 items, I'd like to fix them in different prs.~~ Already done in this pr
This commit is contained in:
@ -71,7 +71,7 @@ impl Block {
|
||||
if let Some(last) = last.elements.last() {
|
||||
match last {
|
||||
PipelineElement::Expression(_, expr) => expr.ty.clone(),
|
||||
PipelineElement::Redirection(_, _, _) => Type::Any,
|
||||
PipelineElement::Redirection(_, _, _, _) => Type::Any,
|
||||
PipelineElement::SeparateRedirection { .. } => Type::Any,
|
||||
PipelineElement::SameTargetRedirection { .. } => Type::Any,
|
||||
PipelineElement::And(_, expr) => expr.ty.clone(),
|
||||
|
@ -13,14 +13,17 @@ pub enum Redirection {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum PipelineElement {
|
||||
Expression(Option<Span>, Expression),
|
||||
Redirection(Span, Redirection, Expression),
|
||||
// final field indicates if it's in append mode
|
||||
Redirection(Span, Redirection, Expression, bool),
|
||||
// final bool field indicates if it's in append mode
|
||||
SeparateRedirection {
|
||||
out: (Span, Expression),
|
||||
err: (Span, Expression),
|
||||
out: (Span, Expression, bool),
|
||||
err: (Span, Expression, bool),
|
||||
},
|
||||
// redirection's final bool field indicates if it's in append mode
|
||||
SameTargetRedirection {
|
||||
cmd: (Option<Span>, Expression),
|
||||
redirection: (Span, Expression),
|
||||
redirection: (Span, Expression, bool),
|
||||
},
|
||||
And(Span, Expression),
|
||||
Or(Span, Expression),
|
||||
@ -30,9 +33,9 @@ impl PipelineElement {
|
||||
pub fn expression(&self) -> &Expression {
|
||||
match self {
|
||||
PipelineElement::Expression(_, expression) => expression,
|
||||
PipelineElement::Redirection(_, _, expression) => expression,
|
||||
PipelineElement::Redirection(_, _, expression, _) => expression,
|
||||
PipelineElement::SeparateRedirection {
|
||||
out: (_, expression),
|
||||
out: (_, expression, _),
|
||||
..
|
||||
} => expression,
|
||||
PipelineElement::SameTargetRedirection {
|
||||
@ -52,9 +55,9 @@ impl PipelineElement {
|
||||
..
|
||||
} => expression.span,
|
||||
PipelineElement::Expression(Some(span), expression)
|
||||
| PipelineElement::Redirection(span, _, expression)
|
||||
| PipelineElement::Redirection(span, _, expression, _)
|
||||
| PipelineElement::SeparateRedirection {
|
||||
out: (span, expression),
|
||||
out: (span, expression, _),
|
||||
..
|
||||
}
|
||||
| PipelineElement::And(span, expression)
|
||||
@ -71,7 +74,7 @@ impl PipelineElement {
|
||||
pub fn has_in_variable(&self, working_set: &StateWorkingSet) -> bool {
|
||||
match self {
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression)
|
||||
| PipelineElement::Redirection(_, _, expression, _)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression)
|
||||
| PipelineElement::SameTargetRedirection {
|
||||
@ -79,8 +82,8 @@ impl PipelineElement {
|
||||
..
|
||||
} => expression.has_in_variable(working_set),
|
||||
PipelineElement::SeparateRedirection {
|
||||
out: (_, out_expr),
|
||||
err: (_, err_expr),
|
||||
out: (_, out_expr, _),
|
||||
err: (_, err_expr, _),
|
||||
} => out_expr.has_in_variable(working_set) || err_expr.has_in_variable(working_set),
|
||||
}
|
||||
}
|
||||
@ -88,7 +91,7 @@ impl PipelineElement {
|
||||
pub fn replace_in_variable(&mut self, working_set: &mut StateWorkingSet, new_var_id: VarId) {
|
||||
match self {
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression)
|
||||
| PipelineElement::Redirection(_, _, expression, _)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression)
|
||||
| PipelineElement::SameTargetRedirection {
|
||||
@ -96,8 +99,8 @@ impl PipelineElement {
|
||||
..
|
||||
} => expression.replace_in_variable(working_set, new_var_id),
|
||||
PipelineElement::SeparateRedirection {
|
||||
out: (_, out_expr),
|
||||
err: (_, err_expr),
|
||||
out: (_, out_expr, _),
|
||||
err: (_, err_expr, _),
|
||||
} => {
|
||||
if out_expr.has_in_variable(working_set) {
|
||||
out_expr.replace_in_variable(working_set, new_var_id)
|
||||
@ -117,7 +120,7 @@ impl PipelineElement {
|
||||
) {
|
||||
match self {
|
||||
PipelineElement::Expression(_, expression)
|
||||
| PipelineElement::Redirection(_, _, expression)
|
||||
| PipelineElement::Redirection(_, _, expression, _)
|
||||
| PipelineElement::And(_, expression)
|
||||
| PipelineElement::Or(_, expression)
|
||||
| PipelineElement::SameTargetRedirection {
|
||||
@ -125,7 +128,7 @@ impl PipelineElement {
|
||||
..
|
||||
}
|
||||
| PipelineElement::SeparateRedirection {
|
||||
out: (_, expression),
|
||||
out: (_, expression, _),
|
||||
..
|
||||
} => expression.replace_span(working_set, replaced, new_span),
|
||||
}
|
||||
|
Reference in New Issue
Block a user