mirror of
https://github.com/nushell/nushell.git
synced 2025-04-02 20:27:11 +02:00
highlight term on PipelineData::Value() (#6997)
This commit is contained in:
parent
ecfee4c542
commit
ca9bf19041
@ -1,13 +1,14 @@
|
|||||||
use crate::help::highlight_search_string;
|
use crate::help::highlight_search_string;
|
||||||
|
|
||||||
use fancy_regex::Regex;
|
use fancy_regex::Regex;
|
||||||
use lscolors::{Color as LsColors_Color, Style as LsColors_Style};
|
use lscolors::{Color as LsColors_Color, LsColors, Style as LsColors_Style};
|
||||||
use nu_ansi_term::{Color, Color::Default, Style};
|
use nu_ansi_term::{Color, Color::Default, Style};
|
||||||
use nu_color_config::get_color_config;
|
use nu_color_config::get_color_config;
|
||||||
use nu_engine::{env_to_string, eval_block, CallExt};
|
use nu_engine::{env_to_string, eval_block, CallExt};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{CaptureBlock, Command, EngineState, Stack},
|
engine::{CaptureBlock, Command, EngineState, Stack},
|
||||||
Category, Example, IntoInterruptiblePipelineData, ListStream, PipelineData, ShellError,
|
Category, Config, Example, IntoInterruptiblePipelineData, ListStream, PipelineData, ShellError,
|
||||||
Signature, Span, SyntaxShape, Value,
|
Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
use nu_utils::get_ls_colors;
|
use nu_utils::get_ls_colors;
|
||||||
@ -278,6 +279,72 @@ fn find_with_predicate(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn highlight_terms_in_record(
|
||||||
|
cols: &mut [String],
|
||||||
|
vals: &mut Vec<Value>,
|
||||||
|
span: &mut Span,
|
||||||
|
config: &Config,
|
||||||
|
terms: &[Value],
|
||||||
|
string_style: Style,
|
||||||
|
ls_colors: &LsColors,
|
||||||
|
) -> Value {
|
||||||
|
let mut output = vec![];
|
||||||
|
for val in vals {
|
||||||
|
let val_str = val.into_string("", config);
|
||||||
|
let lower_val = val.into_string("", config).to_lowercase();
|
||||||
|
let mut term_added_to_output = false;
|
||||||
|
for term in terms {
|
||||||
|
let term_str = term.into_string("", config);
|
||||||
|
let lower_term = term.into_string("", config).to_lowercase();
|
||||||
|
if lower_val.contains(&lower_term) {
|
||||||
|
if config.use_ls_colors {
|
||||||
|
// Get the original LS_COLORS color
|
||||||
|
let style = ls_colors.style_for_path(val_str.clone());
|
||||||
|
let ansi_style = style
|
||||||
|
.map(LsColors_Style::to_crossterm_style)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let ls_colored_val = ansi_style.apply(&val_str).to_string();
|
||||||
|
|
||||||
|
let ansi_term_style = style
|
||||||
|
.map(to_nu_ansi_term_style)
|
||||||
|
.unwrap_or_else(|| string_style);
|
||||||
|
|
||||||
|
let hi =
|
||||||
|
match highlight_search_string(&ls_colored_val, &term_str, &ansi_term_style)
|
||||||
|
{
|
||||||
|
Ok(hi) => hi,
|
||||||
|
Err(_) => string_style.paint(term_str.to_string()).to_string(),
|
||||||
|
};
|
||||||
|
output.push(Value::String {
|
||||||
|
val: hi,
|
||||||
|
span: *span,
|
||||||
|
});
|
||||||
|
term_added_to_output = true;
|
||||||
|
} else {
|
||||||
|
// No LS_COLORS support, so just use the original value
|
||||||
|
let hi = match highlight_search_string(&val_str, &term_str, &string_style) {
|
||||||
|
Ok(hi) => hi,
|
||||||
|
Err(_) => string_style.paint(term_str.to_string()).to_string(),
|
||||||
|
};
|
||||||
|
output.push(Value::String {
|
||||||
|
val: hi,
|
||||||
|
span: *span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !term_added_to_output {
|
||||||
|
output.push(val.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Record {
|
||||||
|
cols: cols.to_vec(),
|
||||||
|
vals: output,
|
||||||
|
span: *span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn find_with_rest_and_highlight(
|
fn find_with_rest_and_highlight(
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
@ -315,177 +382,129 @@ fn find_with_rest_and_highlight(
|
|||||||
let ls_colors = get_ls_colors(ls_colors_env_str);
|
let ls_colors = get_ls_colors(ls_colors_env_str);
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(_, _) => input.filter(
|
PipelineData::Value(_, _) => input
|
||||||
move |value| {
|
.map(
|
||||||
let lower_value = if let Ok(span) = value.span() {
|
move |mut x| match &mut x {
|
||||||
Value::string(value.into_string("", &config).to_lowercase(), span)
|
Value::Record { cols, vals, span } => highlight_terms_in_record(
|
||||||
} else {
|
cols,
|
||||||
value.clone()
|
vals,
|
||||||
};
|
span,
|
||||||
|
&config,
|
||||||
lower_terms.iter().any(|term| match value {
|
&terms,
|
||||||
Value::Bool { .. }
|
string_style,
|
||||||
| Value::Int { .. }
|
&ls_colors,
|
||||||
| Value::Filesize { .. }
|
),
|
||||||
| Value::Duration { .. }
|
_ => x,
|
||||||
| Value::Date { .. }
|
},
|
||||||
| Value::Range { .. }
|
|
||||||
| Value::Float { .. }
|
|
||||||
| Value::Block { .. }
|
|
||||||
| Value::Nothing { .. }
|
|
||||||
| Value::Error { .. } => lower_value
|
|
||||||
.eq(span, term, span)
|
|
||||||
.map_or(false, |val| val.is_true()),
|
|
||||||
Value::String { .. }
|
|
||||||
| Value::List { .. }
|
|
||||||
| Value::CellPath { .. }
|
|
||||||
| Value::CustomValue { .. } => term
|
|
||||||
.r#in(span, &lower_value, span)
|
|
||||||
.map_or(false, |val| val.is_true()),
|
|
||||||
Value::Record { vals, .. } => vals.iter().any(|val| {
|
|
||||||
if let Ok(span) = val.span() {
|
|
||||||
let lower_val = Value::string(
|
|
||||||
val.into_string("", &config).to_lowercase(),
|
|
||||||
Span::test_data(),
|
|
||||||
);
|
|
||||||
|
|
||||||
term.r#in(span, &lower_val, span)
|
|
||||||
.map_or(false, |aval| aval.is_true())
|
|
||||||
} else {
|
|
||||||
term.r#in(span, val, span)
|
|
||||||
.map_or(false, |aval| aval.is_true())
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
Value::Binary { .. } => false,
|
|
||||||
}) != invert
|
|
||||||
},
|
|
||||||
ctrlc,
|
|
||||||
),
|
|
||||||
PipelineData::ListStream(stream, meta) => {
|
|
||||||
Ok(ListStream::from_stream(
|
|
||||||
stream
|
|
||||||
.map(move |mut x| match &mut x {
|
|
||||||
Value::Record { cols, vals, span } => {
|
|
||||||
let mut output = vec![];
|
|
||||||
for val in vals {
|
|
||||||
let val_str = val.into_string("", &config);
|
|
||||||
let lower_val = val.into_string("", &config).to_lowercase();
|
|
||||||
let mut term_added_to_output = false;
|
|
||||||
for term in terms.clone() {
|
|
||||||
let term_str = term.into_string("", &config);
|
|
||||||
let lower_term = term.into_string("", &config).to_lowercase();
|
|
||||||
if lower_val.contains(&lower_term) {
|
|
||||||
if config.use_ls_colors {
|
|
||||||
// Get the original LS_COLORS color
|
|
||||||
let style = ls_colors.style_for_path(val_str.clone());
|
|
||||||
let ansi_style = style
|
|
||||||
.map(LsColors_Style::to_crossterm_style)
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let ls_colored_val =
|
|
||||||
ansi_style.apply(&val_str).to_string();
|
|
||||||
|
|
||||||
let ansi_term_style = style
|
|
||||||
.map(to_nu_ansi_term_style)
|
|
||||||
.unwrap_or_else(|| string_style);
|
|
||||||
|
|
||||||
let hi = match highlight_search_string(
|
|
||||||
&ls_colored_val,
|
|
||||||
&term_str,
|
|
||||||
&ansi_term_style,
|
|
||||||
) {
|
|
||||||
Ok(hi) => hi,
|
|
||||||
Err(_) => string_style
|
|
||||||
.paint(term_str.to_string())
|
|
||||||
.to_string(),
|
|
||||||
};
|
|
||||||
output.push(Value::String {
|
|
||||||
val: hi,
|
|
||||||
span: *span,
|
|
||||||
});
|
|
||||||
term_added_to_output = true;
|
|
||||||
} else {
|
|
||||||
// No LS_COLORS support, so just use the original value
|
|
||||||
let hi = match highlight_search_string(
|
|
||||||
&val_str,
|
|
||||||
&term_str,
|
|
||||||
&string_style,
|
|
||||||
) {
|
|
||||||
Ok(hi) => hi,
|
|
||||||
Err(_) => string_style
|
|
||||||
.paint(term_str.to_string())
|
|
||||||
.to_string(),
|
|
||||||
};
|
|
||||||
output.push(Value::String {
|
|
||||||
val: hi,
|
|
||||||
span: *span,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !term_added_to_output {
|
|
||||||
output.push(val.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Record {
|
|
||||||
cols: cols.to_vec(),
|
|
||||||
vals: output,
|
|
||||||
span: *span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => x,
|
|
||||||
})
|
|
||||||
.filter(move |value| {
|
|
||||||
let lower_value = if let Ok(span) = value.span() {
|
|
||||||
Value::string(
|
|
||||||
value.into_string("", &filter_config).to_lowercase(),
|
|
||||||
span,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
value.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
lower_terms.iter().any(|term| match value {
|
|
||||||
Value::Bool { .. }
|
|
||||||
| Value::Int { .. }
|
|
||||||
| Value::Filesize { .. }
|
|
||||||
| Value::Duration { .. }
|
|
||||||
| Value::Date { .. }
|
|
||||||
| Value::Range { .. }
|
|
||||||
| Value::Float { .. }
|
|
||||||
| Value::Block { .. }
|
|
||||||
| Value::Nothing { .. }
|
|
||||||
| Value::Error { .. } => lower_value
|
|
||||||
.eq(span, term, span)
|
|
||||||
.map_or(false, |value| value.is_true()),
|
|
||||||
Value::String { .. }
|
|
||||||
| Value::List { .. }
|
|
||||||
| Value::CellPath { .. }
|
|
||||||
| Value::CustomValue { .. } => term
|
|
||||||
.r#in(span, &lower_value, span)
|
|
||||||
.map_or(false, |value| value.is_true()),
|
|
||||||
Value::Record { vals, .. } => vals.iter().any(|val| {
|
|
||||||
if let Ok(span) = val.span() {
|
|
||||||
let lower_val = Value::string(
|
|
||||||
val.into_string("", &filter_config).to_lowercase(),
|
|
||||||
Span::test_data(),
|
|
||||||
);
|
|
||||||
|
|
||||||
term.r#in(span, &lower_val, span)
|
|
||||||
.map_or(false, |value| value.is_true())
|
|
||||||
} else {
|
|
||||||
term.r#in(span, val, span)
|
|
||||||
.map_or(false, |value| value.is_true())
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
Value::Binary { .. } => false,
|
|
||||||
}) != invert
|
|
||||||
}),
|
|
||||||
ctrlc.clone(),
|
ctrlc.clone(),
|
||||||
)
|
)?
|
||||||
.into_pipeline_data(ctrlc)
|
.filter(
|
||||||
.set_metadata(meta))
|
move |value| {
|
||||||
}
|
let lower_value = if let Ok(span) = value.span() {
|
||||||
|
Value::string(value.into_string("", &filter_config).to_lowercase(), span)
|
||||||
|
} else {
|
||||||
|
value.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
lower_terms.iter().any(|term| match value {
|
||||||
|
Value::Bool { .. }
|
||||||
|
| Value::Int { .. }
|
||||||
|
| Value::Filesize { .. }
|
||||||
|
| Value::Duration { .. }
|
||||||
|
| Value::Date { .. }
|
||||||
|
| Value::Range { .. }
|
||||||
|
| Value::Float { .. }
|
||||||
|
| Value::Block { .. }
|
||||||
|
| Value::Nothing { .. }
|
||||||
|
| Value::Error { .. } => lower_value
|
||||||
|
.eq(span, term, span)
|
||||||
|
.map_or(false, |val| val.is_true()),
|
||||||
|
Value::String { .. }
|
||||||
|
| Value::List { .. }
|
||||||
|
| Value::CellPath { .. }
|
||||||
|
| Value::CustomValue { .. } => term
|
||||||
|
.r#in(span, &lower_value, span)
|
||||||
|
.map_or(false, |val| val.is_true()),
|
||||||
|
Value::Record { vals, .. } => vals.iter().any(|val| {
|
||||||
|
if let Ok(span) = val.span() {
|
||||||
|
let lower_val = Value::string(
|
||||||
|
val.into_string("", &filter_config).to_lowercase(),
|
||||||
|
Span::test_data(),
|
||||||
|
);
|
||||||
|
|
||||||
|
term.r#in(span, &lower_val, span)
|
||||||
|
.map_or(false, |aval| aval.is_true())
|
||||||
|
} else {
|
||||||
|
term.r#in(span, val, span)
|
||||||
|
.map_or(false, |aval| aval.is_true())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Value::Binary { .. } => false,
|
||||||
|
}) != invert
|
||||||
|
},
|
||||||
|
ctrlc,
|
||||||
|
),
|
||||||
|
PipelineData::ListStream(stream, meta) => Ok(ListStream::from_stream(
|
||||||
|
stream
|
||||||
|
.map(move |mut x| match &mut x {
|
||||||
|
Value::Record { cols, vals, span } => highlight_terms_in_record(
|
||||||
|
cols,
|
||||||
|
vals,
|
||||||
|
span,
|
||||||
|
&config,
|
||||||
|
&terms,
|
||||||
|
string_style,
|
||||||
|
&ls_colors,
|
||||||
|
),
|
||||||
|
_ => x,
|
||||||
|
})
|
||||||
|
.filter(move |value| {
|
||||||
|
let lower_value = if let Ok(span) = value.span() {
|
||||||
|
Value::string(value.into_string("", &filter_config).to_lowercase(), span)
|
||||||
|
} else {
|
||||||
|
value.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
lower_terms.iter().any(|term| match value {
|
||||||
|
Value::Bool { .. }
|
||||||
|
| Value::Int { .. }
|
||||||
|
| Value::Filesize { .. }
|
||||||
|
| Value::Duration { .. }
|
||||||
|
| Value::Date { .. }
|
||||||
|
| Value::Range { .. }
|
||||||
|
| Value::Float { .. }
|
||||||
|
| Value::Block { .. }
|
||||||
|
| Value::Nothing { .. }
|
||||||
|
| Value::Error { .. } => lower_value
|
||||||
|
.eq(span, term, span)
|
||||||
|
.map_or(false, |value| value.is_true()),
|
||||||
|
Value::String { .. }
|
||||||
|
| Value::List { .. }
|
||||||
|
| Value::CellPath { .. }
|
||||||
|
| Value::CustomValue { .. } => term
|
||||||
|
.r#in(span, &lower_value, span)
|
||||||
|
.map_or(false, |value| value.is_true()),
|
||||||
|
Value::Record { vals, .. } => vals.iter().any(|val| {
|
||||||
|
if let Ok(span) = val.span() {
|
||||||
|
let lower_val = Value::string(
|
||||||
|
val.into_string("", &filter_config).to_lowercase(),
|
||||||
|
Span::test_data(),
|
||||||
|
);
|
||||||
|
|
||||||
|
term.r#in(span, &lower_val, span)
|
||||||
|
.map_or(false, |value| value.is_true())
|
||||||
|
} else {
|
||||||
|
term.r#in(span, val, span)
|
||||||
|
.map_or(false, |value| value.is_true())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Value::Binary { .. } => false,
|
||||||
|
}) != invert
|
||||||
|
}),
|
||||||
|
ctrlc.clone(),
|
||||||
|
)
|
||||||
|
.into_pipeline_data(ctrlc)
|
||||||
|
.set_metadata(meta)),
|
||||||
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::new(span)),
|
PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::new(span)),
|
||||||
PipelineData::ExternalStream {
|
PipelineData::ExternalStream {
|
||||||
stdout: Some(stream),
|
stdout: Some(stream),
|
||||||
|
Loading…
Reference in New Issue
Block a user