mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 18:27:46 +02:00
Merge branch 'nushell:main' into feature-PWD-per-drive
This commit is contained in:
1233
Cargo.lock
generated
1233
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,7 @@ brotli = "6.0"
|
||||
byteorder = "1.5"
|
||||
bytes = "1"
|
||||
bytesize = "1.3"
|
||||
calamine = "0.24.0"
|
||||
calamine = "0.26.1"
|
||||
chardetng = "0.1.17"
|
||||
chrono = { default-features = false, version = "0.4.34" }
|
||||
chrono-humanize = "0.2.3"
|
||||
@ -129,7 +129,7 @@ proc-macro-error = { version = "1.0", default-features = false }
|
||||
proc-macro2 = "1.0"
|
||||
procfs = "0.16.0"
|
||||
pwd = "1.3"
|
||||
quick-xml = "0.32.0"
|
||||
quick-xml = "0.37.0"
|
||||
quickcheck = "1.0"
|
||||
quickcheck_macros = "1.0"
|
||||
quote = "1.0"
|
||||
@ -156,7 +156,7 @@ syn = "2.0"
|
||||
sysinfo = "0.32"
|
||||
tabled = { version = "0.16.0", default-features = false }
|
||||
tempfile = "3.14"
|
||||
terminal_size = "0.3"
|
||||
terminal_size = "0.4"
|
||||
titlecase = "2.0"
|
||||
toml = "0.8"
|
||||
trash = "5.2"
|
||||
|
@ -9,6 +9,8 @@ use nu_protocol::{
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::util::print_pipeline;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct EvaluateCommandsOpts {
|
||||
pub table_mode: Option<Value>,
|
||||
@ -72,7 +74,7 @@ pub fn evaluate_commands(
|
||||
|
||||
if let Some(err) = working_set.compile_errors.first() {
|
||||
report_compile_error(&working_set, err);
|
||||
// Not a fatal error, for now
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
(output, working_set.render())
|
||||
@ -93,7 +95,7 @@ pub fn evaluate_commands(
|
||||
t_mode.coerce_str()?.parse().unwrap_or_default();
|
||||
}
|
||||
|
||||
pipeline.print(engine_state, stack, no_newline, false)?;
|
||||
print_pipeline(engine_state, stack, pipeline, no_newline)?;
|
||||
|
||||
info!("evaluate {}:{}:{}", file!(), line!(), column!());
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::util::eval_source;
|
||||
use crate::util::{eval_source, print_pipeline};
|
||||
use log::{info, trace};
|
||||
use nu_engine::{convert_env_values, eval_block};
|
||||
use nu_parser::parse;
|
||||
@ -89,7 +89,7 @@ pub fn evaluate_file(
|
||||
|
||||
if let Some(err) = working_set.compile_errors.first() {
|
||||
report_compile_error(&working_set, err);
|
||||
// Not a fatal error, for now
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// Look for blocks whose name starts with "main" and replace it with the filename.
|
||||
@ -119,7 +119,7 @@ pub fn evaluate_file(
|
||||
};
|
||||
|
||||
// Print the pipeline output of the last command of the file.
|
||||
pipeline.print(engine_state, stack, true, false)?;
|
||||
print_pipeline(engine_state, stack, pipeline, true)?;
|
||||
|
||||
// Invoke the main command with arguments.
|
||||
// Arguments with whitespaces are quoted, thus can be safely concatenated by whitespace.
|
||||
|
@ -65,8 +65,12 @@ Since this command has no output, there is no point in piping it with other comm
|
||||
arg.into_pipeline_data()
|
||||
.print_raw(engine_state, no_newline, to_stderr)?;
|
||||
} else {
|
||||
arg.into_pipeline_data()
|
||||
.print(engine_state, stack, no_newline, to_stderr)?;
|
||||
arg.into_pipeline_data().print_table(
|
||||
engine_state,
|
||||
stack,
|
||||
no_newline,
|
||||
to_stderr,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
} else if !input.is_nothing() {
|
||||
@ -78,7 +82,7 @@ Since this command has no output, there is no point in piping it with other comm
|
||||
if raw {
|
||||
input.print_raw(engine_state, no_newline, to_stderr)?;
|
||||
} else {
|
||||
input.print(engine_state, stack, no_newline, to_stderr)?;
|
||||
input.print_table(engine_state, stack, no_newline, to_stderr)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,6 +201,35 @@ fn gather_env_vars(
|
||||
}
|
||||
}
|
||||
|
||||
/// Print a pipeline with formatting applied based on display_output hook.
|
||||
///
|
||||
/// This function should be preferred when printing values resulting from a completed evaluation.
|
||||
/// For values printed as part of a command's execution, such as values printed by the `print` command,
|
||||
/// the `PipelineData::print_table` function should be preferred instead as it is not config-dependent.
|
||||
///
|
||||
/// `no_newline` controls if we need to attach newline character to output.
|
||||
pub fn print_pipeline(
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
pipeline: PipelineData,
|
||||
no_newline: bool,
|
||||
) -> Result<(), ShellError> {
|
||||
if let Some(hook) = engine_state.get_config().hooks.display_output.clone() {
|
||||
let pipeline = eval_hook(
|
||||
engine_state,
|
||||
stack,
|
||||
Some(pipeline),
|
||||
vec![],
|
||||
&hook,
|
||||
"display_output",
|
||||
)?;
|
||||
pipeline.print_raw(engine_state, no_newline, false)
|
||||
} else {
|
||||
// if display_output isn't set, we should still prefer to print with some formatting
|
||||
pipeline.print_table(engine_state, stack, no_newline, false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_source(
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
@ -267,7 +296,7 @@ fn evaluate_source(
|
||||
|
||||
if let Some(err) = working_set.compile_errors.first() {
|
||||
report_compile_error(&working_set, err);
|
||||
// Not a fatal error, for now
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
(output, working_set.render())
|
||||
@ -281,36 +310,12 @@ fn evaluate_source(
|
||||
eval_block::<WithoutDebug>(engine_state, stack, &block, input)
|
||||
}?;
|
||||
|
||||
if let PipelineData::ByteStream(..) = pipeline {
|
||||
// run the display hook on bytestreams too
|
||||
run_display_hook(engine_state, stack, pipeline, false)
|
||||
} else {
|
||||
run_display_hook(engine_state, stack, pipeline, true)
|
||||
}?;
|
||||
let no_newline = matches!(&pipeline, &PipelineData::ByteStream(..));
|
||||
print_pipeline(engine_state, stack, pipeline, no_newline)?;
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn run_display_hook(
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
pipeline: PipelineData,
|
||||
no_newline: bool,
|
||||
) -> Result<(), ShellError> {
|
||||
if let Some(hook) = engine_state.get_config().hooks.display_output.clone() {
|
||||
let pipeline = eval_hook(
|
||||
engine_state,
|
||||
stack,
|
||||
Some(pipeline),
|
||||
vec![],
|
||||
&hook,
|
||||
"display_output",
|
||||
)?;
|
||||
pipeline.print(engine_state, stack, no_newline, false)
|
||||
} else {
|
||||
pipeline.print(engine_state, stack, no_newline, false)
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -21,10 +21,10 @@ nu-protocol = { path = "../nu-protocol", version = "0.100.1" }
|
||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
||||
|
||||
itertools = { workspace = true }
|
||||
shadow-rs = { version = "0.35", default-features = false }
|
||||
shadow-rs = { version = "0.36", default-features = false }
|
||||
|
||||
[build-dependencies]
|
||||
shadow-rs = { version = "0.35", default-features = false }
|
||||
shadow-rs = { version = "0.36", default-features = false }
|
||||
|
||||
[features]
|
||||
mimalloc = []
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_parser::parse;
|
||||
use nu_protocol::engine::StateWorkingSet;
|
||||
use nu_parser::{flatten_block, parse};
|
||||
use nu_protocol::{engine::StateWorkingSet, record};
|
||||
use serde_json::{json, Value as JsonValue};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Ast;
|
||||
@ -16,109 +17,23 @@ impl Command for Ast {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("ast")
|
||||
.input_output_types(vec![(Type::String, Type::record())])
|
||||
.input_output_types(vec![
|
||||
(Type::Nothing, Type::table()),
|
||||
(Type::Nothing, Type::record()),
|
||||
(Type::Nothing, Type::String),
|
||||
])
|
||||
.required(
|
||||
"pipeline",
|
||||
SyntaxShape::String,
|
||||
"The pipeline to print the ast for.",
|
||||
)
|
||||
.switch("json", "serialize to json", Some('j'))
|
||||
.switch("minify", "minify the nuon or json output", Some('m'))
|
||||
.switch("json", "Serialize to json", Some('j'))
|
||||
.switch("minify", "Minify the nuon or json output", Some('m'))
|
||||
.switch("flatten", "An easier to read version of the ast", Some('f'))
|
||||
.allow_variants_without_examples(true)
|
||||
.category(Category::Debug)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let pipeline: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let to_json = call.has_flag(engine_state, stack, "json")?;
|
||||
let minify = call.has_flag(engine_state, stack, "minify")?;
|
||||
let mut working_set = StateWorkingSet::new(engine_state);
|
||||
let block_output = parse(&mut working_set, None, pipeline.item.as_bytes(), false);
|
||||
let error_output = working_set.parse_errors.first();
|
||||
let block_span = match &block_output.span {
|
||||
Some(span) => span,
|
||||
None => &pipeline.span,
|
||||
};
|
||||
if to_json {
|
||||
// Get the block as json
|
||||
let serde_block_str = if minify {
|
||||
serde_json::to_string(&*block_output)
|
||||
} else {
|
||||
serde_json::to_string_pretty(&*block_output)
|
||||
};
|
||||
let block_json = match serde_block_str {
|
||||
Ok(json) => json,
|
||||
Err(e) => Err(ShellError::CantConvert {
|
||||
to_type: "string".to_string(),
|
||||
from_type: "block".to_string(),
|
||||
span: *block_span,
|
||||
help: Some(format!(
|
||||
"Error: {e}\nCan't convert {block_output:?} to string"
|
||||
)),
|
||||
})?,
|
||||
};
|
||||
// Get the error as json
|
||||
let serde_error_str = if minify {
|
||||
serde_json::to_string(&error_output)
|
||||
} else {
|
||||
serde_json::to_string_pretty(&error_output)
|
||||
};
|
||||
|
||||
let error_json = match serde_error_str {
|
||||
Ok(json) => json,
|
||||
Err(e) => Err(ShellError::CantConvert {
|
||||
to_type: "string".to_string(),
|
||||
from_type: "error".to_string(),
|
||||
span: *block_span,
|
||||
help: Some(format!(
|
||||
"Error: {e}\nCan't convert {error_output:?} to string"
|
||||
)),
|
||||
})?,
|
||||
};
|
||||
|
||||
// Create a new output record, merging the block and error
|
||||
let output_record = Value::record(
|
||||
record! {
|
||||
"block" => Value::string(block_json, *block_span),
|
||||
"error" => Value::string(error_json, Span::test_data()),
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
Ok(output_record.into_pipeline_data())
|
||||
} else {
|
||||
let block_value = Value::string(
|
||||
if minify {
|
||||
format!("{block_output:?}")
|
||||
} else {
|
||||
format!("{block_output:#?}")
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
let error_value = Value::string(
|
||||
if minify {
|
||||
format!("{error_output:?}")
|
||||
} else {
|
||||
format!("{error_output:#?}")
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
let output_record = Value::record(
|
||||
record! {
|
||||
"block" => block_value,
|
||||
"error" => error_value
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
Ok(output_record.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
@ -147,8 +62,247 @@ impl Command for Ast {
|
||||
example: "ast 'for x in 1..10 { echo $x ' --json --minify",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Print the ast of a string flattened",
|
||||
example: r#"ast "'hello'" --flatten"#,
|
||||
result: Some(Value::test_list(vec![Value::test_record(record! {
|
||||
"content" => Value::test_string("'hello'"),
|
||||
"shape" => Value::test_string("shape_string"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(0),
|
||||
"end" => Value::test_int(7),}),
|
||||
})])),
|
||||
},
|
||||
Example {
|
||||
description: "Print the ast of a string flattened, as json, minified",
|
||||
example: r#"ast "'hello'" --flatten --json --minify"#,
|
||||
result: Some(Value::test_string(
|
||||
r#"[{"content":"'hello'","shape":"shape_string","span":{"start":0,"end":7}}]"#,
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Print the ast of a pipeline flattened",
|
||||
example: r#"ast 'ls | sort-by type name -i' --flatten"#,
|
||||
result: Some(Value::test_list(vec![
|
||||
Value::test_record(record! {
|
||||
"content" => Value::test_string("ls"),
|
||||
"shape" => Value::test_string("shape_external"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(0),
|
||||
"end" => Value::test_int(2),}),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"content" => Value::test_string("|"),
|
||||
"shape" => Value::test_string("shape_pipe"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(3),
|
||||
"end" => Value::test_int(4),}),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"content" => Value::test_string("sort-by"),
|
||||
"shape" => Value::test_string("shape_internalcall"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(5),
|
||||
"end" => Value::test_int(12),}),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"content" => Value::test_string("type"),
|
||||
"shape" => Value::test_string("shape_string"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(13),
|
||||
"end" => Value::test_int(17),}),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"content" => Value::test_string("name"),
|
||||
"shape" => Value::test_string("shape_string"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(18),
|
||||
"end" => Value::test_int(22),}),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"content" => Value::test_string("-i"),
|
||||
"shape" => Value::test_string("shape_flag"),
|
||||
"span" => Value::test_record(record! {
|
||||
"start" => Value::test_int(23),
|
||||
"end" => Value::test_int(25),}),
|
||||
}),
|
||||
])),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let pipeline: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||
let to_json = call.has_flag(engine_state, stack, "json")?;
|
||||
let minify = call.has_flag(engine_state, stack, "minify")?;
|
||||
let flatten = call.has_flag(engine_state, stack, "flatten")?;
|
||||
|
||||
let mut working_set = StateWorkingSet::new(engine_state);
|
||||
let offset = working_set.next_span_start();
|
||||
let parsed_block = parse(&mut working_set, None, pipeline.item.as_bytes(), false);
|
||||
|
||||
if flatten {
|
||||
let flat = flatten_block(&working_set, &parsed_block);
|
||||
if to_json {
|
||||
let mut json_val: JsonValue = json!([]);
|
||||
for (span, shape) in flat {
|
||||
let content =
|
||||
String::from_utf8_lossy(working_set.get_span_contents(span)).to_string();
|
||||
|
||||
let json = json!(
|
||||
{
|
||||
"content": content,
|
||||
"shape": shape.to_string(),
|
||||
"span": {
|
||||
"start": span.start.checked_sub(offset),
|
||||
"end": span.end.checked_sub(offset),
|
||||
},
|
||||
}
|
||||
);
|
||||
json_merge(&mut json_val, &json);
|
||||
}
|
||||
let json_string = if minify {
|
||||
if let Ok(json_str) = serde_json::to_string(&json_val) {
|
||||
json_str
|
||||
} else {
|
||||
"{}".to_string()
|
||||
}
|
||||
} else if let Ok(json_str) = serde_json::to_string_pretty(&json_val) {
|
||||
json_str
|
||||
} else {
|
||||
"{}".to_string()
|
||||
};
|
||||
|
||||
Ok(Value::string(json_string, pipeline.span).into_pipeline_data())
|
||||
} else {
|
||||
// let mut rec: Record = Record::new();
|
||||
let mut rec = vec![];
|
||||
for (span, shape) in flat {
|
||||
let content =
|
||||
String::from_utf8_lossy(working_set.get_span_contents(span)).to_string();
|
||||
let each_rec = record! {
|
||||
"content" => Value::test_string(content),
|
||||
"shape" => Value::test_string(shape.to_string()),
|
||||
"span" => Value::test_record(record!{
|
||||
"start" => Value::test_int(match span.start.checked_sub(offset) {
|
||||
Some(start) => start as i64,
|
||||
None => 0
|
||||
}),
|
||||
"end" => Value::test_int(match span.end.checked_sub(offset) {
|
||||
Some(end) => end as i64,
|
||||
None => 0
|
||||
}),
|
||||
}),
|
||||
};
|
||||
rec.push(Value::test_record(each_rec));
|
||||
}
|
||||
Ok(Value::list(rec, pipeline.span).into_pipeline_data())
|
||||
}
|
||||
} else {
|
||||
let error_output = working_set.parse_errors.first();
|
||||
let block_span = match &parsed_block.span {
|
||||
Some(span) => span,
|
||||
None => &pipeline.span,
|
||||
};
|
||||
if to_json {
|
||||
// Get the block as json
|
||||
let serde_block_str = if minify {
|
||||
serde_json::to_string(&*parsed_block)
|
||||
} else {
|
||||
serde_json::to_string_pretty(&*parsed_block)
|
||||
};
|
||||
let block_json = match serde_block_str {
|
||||
Ok(json) => json,
|
||||
Err(e) => Err(ShellError::CantConvert {
|
||||
to_type: "string".to_string(),
|
||||
from_type: "block".to_string(),
|
||||
span: *block_span,
|
||||
help: Some(format!(
|
||||
"Error: {e}\nCan't convert {parsed_block:?} to string"
|
||||
)),
|
||||
})?,
|
||||
};
|
||||
// Get the error as json
|
||||
let serde_error_str = if minify {
|
||||
serde_json::to_string(&error_output)
|
||||
} else {
|
||||
serde_json::to_string_pretty(&error_output)
|
||||
};
|
||||
|
||||
let error_json = match serde_error_str {
|
||||
Ok(json) => json,
|
||||
Err(e) => Err(ShellError::CantConvert {
|
||||
to_type: "string".to_string(),
|
||||
from_type: "error".to_string(),
|
||||
span: *block_span,
|
||||
help: Some(format!(
|
||||
"Error: {e}\nCan't convert {error_output:?} to string"
|
||||
)),
|
||||
})?,
|
||||
};
|
||||
|
||||
// Create a new output record, merging the block and error
|
||||
let output_record = Value::record(
|
||||
record! {
|
||||
"block" => Value::string(block_json, *block_span),
|
||||
"error" => Value::string(error_json, Span::test_data()),
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
Ok(output_record.into_pipeline_data())
|
||||
} else {
|
||||
let block_value = Value::string(
|
||||
if minify {
|
||||
format!("{parsed_block:?}")
|
||||
} else {
|
||||
format!("{parsed_block:#?}")
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
let error_value = Value::string(
|
||||
if minify {
|
||||
format!("{error_output:?}")
|
||||
} else {
|
||||
format!("{error_output:#?}")
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
let output_record = Value::record(
|
||||
record! {
|
||||
"block" => block_value,
|
||||
"error" => error_value
|
||||
},
|
||||
pipeline.span,
|
||||
);
|
||||
Ok(output_record.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn json_merge(a: &mut JsonValue, b: &JsonValue) {
|
||||
match (a, b) {
|
||||
(JsonValue::Object(ref mut a), JsonValue::Object(b)) => {
|
||||
for (k, v) in b {
|
||||
json_merge(a.entry(k).or_insert(JsonValue::Null), v);
|
||||
}
|
||||
}
|
||||
(JsonValue::Array(ref mut a), JsonValue::Array(b)) => {
|
||||
a.extend(b.clone());
|
||||
}
|
||||
(JsonValue::Array(ref mut a), JsonValue::Object(b)) => {
|
||||
a.extend([JsonValue::Object(b.clone())]);
|
||||
}
|
||||
(a, b) => {
|
||||
*a = b.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
37
crates/nu-command/src/env/config/config_env.rs
vendored
37
crates/nu-command/src/env/config/config_env.rs
vendored
@ -15,7 +15,16 @@ impl Command for ConfigEnv {
|
||||
Signature::build(self.name())
|
||||
.category(Category::Env)
|
||||
.input_output_types(vec![(Type::Nothing, Type::Any)])
|
||||
.switch("default", "Print default `env.nu` file instead.", Some('d'))
|
||||
.switch(
|
||||
"default",
|
||||
"Print the internal default `env.nu` file instead.",
|
||||
Some('d'),
|
||||
)
|
||||
.switch(
|
||||
"sample",
|
||||
"Print a commented, sample `env.nu` file instead.",
|
||||
Some('s'),
|
||||
)
|
||||
// TODO: Signature narrower than what run actually supports theoretically
|
||||
}
|
||||
|
||||
@ -26,18 +35,18 @@ impl Command for ConfigEnv {
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "allow user to open and update nu env",
|
||||
description: "open user's env.nu in the default editor",
|
||||
example: "config env",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "allow user to print default `env.nu` file",
|
||||
example: "config env --default,",
|
||||
description: "pretty-print a commented, sample `env.nu` that explains common settings",
|
||||
example: "config env --sample | nu-highlight,",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "allow saving the default `env.nu` locally",
|
||||
example: "config env --default | save -f ~/.config/nushell/default_env.nu",
|
||||
description: "pretty-print the internal `env.nu` file which is loaded before the user's environment",
|
||||
example: "config env --default | nu-highlight,",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
@ -50,12 +59,28 @@ impl Command for ConfigEnv {
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let default_flag = call.has_flag(engine_state, stack, "default")?;
|
||||
let sample_flag = call.has_flag(engine_state, stack, "sample")?;
|
||||
if default_flag && sample_flag {
|
||||
return Err(ShellError::IncompatibleParameters {
|
||||
left_message: "can't use `--default` at the same time".into(),
|
||||
left_span: call.get_flag_span(stack, "default").expect("has flag"),
|
||||
right_message: "because of `--sample`".into(),
|
||||
right_span: call.get_flag_span(stack, "sample").expect("has flag"),
|
||||
});
|
||||
}
|
||||
// `--default` flag handling
|
||||
if call.has_flag(engine_state, stack, "default")? {
|
||||
let head = call.head;
|
||||
return Ok(Value::string(nu_utils::get_default_env(), head).into_pipeline_data());
|
||||
}
|
||||
|
||||
// `--sample` flag handling
|
||||
if sample_flag {
|
||||
let head = call.head;
|
||||
return Ok(Value::string(nu_utils::get_sample_env(), head).into_pipeline_data());
|
||||
}
|
||||
|
||||
// Find the editor executable.
|
||||
let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?;
|
||||
let paths = nu_engine::env::path_str(engine_state, stack, call.head)?;
|
||||
|
37
crates/nu-command/src/env/config/config_nu.rs
vendored
37
crates/nu-command/src/env/config/config_nu.rs
vendored
@ -17,9 +17,14 @@ impl Command for ConfigNu {
|
||||
.input_output_types(vec![(Type::Nothing, Type::Any)])
|
||||
.switch(
|
||||
"default",
|
||||
"Print default `config.nu` file instead.",
|
||||
"Print the internal default `config.nu` file instead.",
|
||||
Some('d'),
|
||||
)
|
||||
.switch(
|
||||
"sample",
|
||||
"Print a commented, sample `config.nu` file instead.",
|
||||
Some('s'),
|
||||
)
|
||||
// TODO: Signature narrower than what run actually supports theoretically
|
||||
}
|
||||
|
||||
@ -30,18 +35,19 @@ impl Command for ConfigNu {
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "allow user to open and update nu config",
|
||||
description: "open user's config.nu in the default editor",
|
||||
example: "config nu",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "allow user to print default `config.nu` file",
|
||||
example: "config nu --default,",
|
||||
description: "pretty-print a commented, sample `config.nu` that explains common settings",
|
||||
example: "config nu --sample | nu-highlight",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "allow saving the default `config.nu` locally",
|
||||
example: "config nu --default | save -f ~/.config/nushell/default_config.nu",
|
||||
description:
|
||||
"pretty-print the internal `config.nu` file which is loaded before user's config",
|
||||
example: "config nu --default | nu-highlight",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
@ -54,12 +60,29 @@ impl Command for ConfigNu {
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let default_flag = call.has_flag(engine_state, stack, "default")?;
|
||||
let sample_flag = call.has_flag(engine_state, stack, "sample")?;
|
||||
if default_flag && sample_flag {
|
||||
return Err(ShellError::IncompatibleParameters {
|
||||
left_message: "can't use `--default` at the same time".into(),
|
||||
left_span: call.get_flag_span(stack, "default").expect("has flag"),
|
||||
right_message: "because of `--sample`".into(),
|
||||
right_span: call.get_flag_span(stack, "sample").expect("has flag"),
|
||||
});
|
||||
}
|
||||
|
||||
// `--default` flag handling
|
||||
if call.has_flag(engine_state, stack, "default")? {
|
||||
if default_flag {
|
||||
let head = call.head;
|
||||
return Ok(Value::string(nu_utils::get_default_config(), head).into_pipeline_data());
|
||||
}
|
||||
|
||||
// `--sample` flag handling
|
||||
if sample_flag {
|
||||
let head = call.head;
|
||||
return Ok(Value::string(nu_utils::get_sample_config(), head).into_pipeline_data());
|
||||
}
|
||||
|
||||
// Find the editor executable.
|
||||
let (editor_name, editor_args) = get_editor(engine_state, stack, call.head)?;
|
||||
let paths = nu_engine::env::path_str(engine_state, stack, call.head)?;
|
||||
|
@ -194,7 +194,7 @@ impl Command for Watch {
|
||||
|
||||
match result {
|
||||
Ok(val) => {
|
||||
val.print(engine_state, stack, false, false)?;
|
||||
val.print_table(engine_state, stack, false, false)?;
|
||||
}
|
||||
Err(err) => {
|
||||
let working_set = StateWorkingSet::new(engine_state);
|
||||
|
@ -1,5 +1,6 @@
|
||||
use indexmap::IndexMap;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::report_shell_warning;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SplitBy;
|
||||
@ -27,6 +28,15 @@ impl Command for SplitBy {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
report_shell_warning(
|
||||
engine_state,
|
||||
&ShellError::Deprecated {
|
||||
deprecated: "The `split_by` command",
|
||||
suggestion: "Please use the `group-by` command instead.",
|
||||
span: call.head,
|
||||
help: None,
|
||||
},
|
||||
);
|
||||
split_by(engine_state, stack, call, input)
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,10 @@ impl Command for FromCsv {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("from csv")
|
||||
.input_output_types(vec![(Type::String, Type::table())])
|
||||
.input_output_types(vec![
|
||||
(Type::String, Type::table()),
|
||||
(Type::String, Type::list(Type::Any)),
|
||||
])
|
||||
.named(
|
||||
"separator",
|
||||
SyntaxShape::String,
|
||||
@ -82,6 +85,26 @@ impl Command for FromCsv {
|
||||
})],
|
||||
))
|
||||
},
|
||||
Example {
|
||||
description: "Convert comma-separated data to a table, allowing variable number of columns per row",
|
||||
example: "\"ColA,ColB\n1,2\n3,4,5\n6\" | from csv --flexible",
|
||||
result: Some(Value::test_list (
|
||||
vec![
|
||||
Value::test_record(record! {
|
||||
"ColA" => Value::test_int(1),
|
||||
"ColB" => Value::test_int(2),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"ColA" => Value::test_int(3),
|
||||
"ColB" => Value::test_int(4),
|
||||
"column2" => Value::test_int(5),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"ColA" => Value::test_int(6),
|
||||
}),
|
||||
],
|
||||
))
|
||||
},
|
||||
Example {
|
||||
description: "Convert comma-separated data to a table, ignoring headers",
|
||||
example: "open data.txt | from csv --noheaders",
|
||||
|
@ -39,12 +39,7 @@ fn from_delimited_stream(
|
||||
.from_reader(input_reader);
|
||||
|
||||
let headers = if noheaders {
|
||||
(0..reader
|
||||
.headers()
|
||||
.map_err(|err| from_csv_error(err, span))?
|
||||
.len())
|
||||
.map(|i| format!("column{i}"))
|
||||
.collect::<Vec<String>>()
|
||||
vec![]
|
||||
} else {
|
||||
reader
|
||||
.headers()
|
||||
@ -54,32 +49,28 @@ fn from_delimited_stream(
|
||||
.collect()
|
||||
};
|
||||
|
||||
let n = headers.len();
|
||||
let columns = headers
|
||||
.into_iter()
|
||||
.chain((n..).map(|i| format!("column{i}")));
|
||||
let iter = reader.into_records().map(move |row| {
|
||||
let row = match row {
|
||||
Ok(row) => row,
|
||||
Err(err) => return Value::error(from_csv_error(err, span), span),
|
||||
};
|
||||
let columns = headers.iter().cloned();
|
||||
let values = row
|
||||
.into_iter()
|
||||
.map(|s| {
|
||||
if no_infer {
|
||||
Value::string(s, span)
|
||||
} else if let Ok(i) = s.parse() {
|
||||
Value::int(i, span)
|
||||
} else if let Ok(f) = s.parse() {
|
||||
Value::float(f, span)
|
||||
} else {
|
||||
Value::string(s, span)
|
||||
}
|
||||
})
|
||||
.chain(std::iter::repeat(Value::nothing(span)));
|
||||
let columns = columns.clone();
|
||||
let values = row.into_iter().map(|s| {
|
||||
if no_infer {
|
||||
Value::string(s, span)
|
||||
} else if let Ok(i) = s.parse() {
|
||||
Value::int(i, span)
|
||||
} else if let Ok(f) = s.parse() {
|
||||
Value::float(f, span)
|
||||
} else {
|
||||
Value::string(s, span)
|
||||
}
|
||||
});
|
||||
|
||||
// If there are more values than the number of headers,
|
||||
// then the remaining values are ignored.
|
||||
//
|
||||
// Otherwise, if there are less values than headers,
|
||||
// then `Value::nothing(span)` is used to fill the remaining columns.
|
||||
Value::record(columns.zip(values).collect(), span)
|
||||
});
|
||||
|
||||
|
@ -11,7 +11,10 @@ impl Command for FromTsv {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("from tsv")
|
||||
.input_output_types(vec![(Type::String, Type::table())])
|
||||
.input_output_types(vec![
|
||||
(Type::String, Type::table()),
|
||||
(Type::String, Type::list(Type::Any)),
|
||||
])
|
||||
.named(
|
||||
"comment",
|
||||
SyntaxShape::String,
|
||||
@ -76,6 +79,21 @@ impl Command for FromTsv {
|
||||
})],
|
||||
))
|
||||
},
|
||||
Example {
|
||||
description: "Convert comma-separated data to a table, allowing variable number of columns per row and ignoring headers",
|
||||
example: "\"value 1\nvalue 2\tdescription 2\" | from tsv --flexible --noheaders",
|
||||
result: Some(Value::test_list (
|
||||
vec![
|
||||
Value::test_record(record! {
|
||||
"column0" => Value::test_string("value 1"),
|
||||
}),
|
||||
Value::test_record(record! {
|
||||
"column0" => Value::test_string("value 2"),
|
||||
"column1" => Value::test_string("description 2"),
|
||||
}),
|
||||
],
|
||||
))
|
||||
},
|
||||
Example {
|
||||
description: "Create a tsv file with header columns and open it",
|
||||
example: r#"$'c1(char tab)c2(char tab)c3(char nl)1(char tab)2(char tab)3' | save tsv-data | open tsv-data | from tsv"#,
|
||||
|
@ -4,7 +4,7 @@ use nu_engine::command_prelude::*;
|
||||
|
||||
use quick_xml::{
|
||||
escape,
|
||||
events::{BytesEnd, BytesStart, BytesText, Event},
|
||||
events::{BytesEnd, BytesPI, BytesStart, BytesText, Event},
|
||||
};
|
||||
use std::{borrow::Cow, io::Cursor};
|
||||
|
||||
@ -406,7 +406,7 @@ impl Job {
|
||||
let content_text = format!("{} {}", tag, content);
|
||||
// PI content must NOT be escaped
|
||||
// https://www.w3.org/TR/xml/#sec-pi
|
||||
let pi_content = BytesText::from_escaped(content_text.as_str());
|
||||
let pi_content = BytesPI::new(content_text.as_str());
|
||||
|
||||
self.writer
|
||||
.write_event(Event::PI(pi_content))
|
||||
|
@ -43,6 +43,12 @@ impl Command for Input {
|
||||
"number of characters to read; suppresses output",
|
||||
Some('n'),
|
||||
)
|
||||
.named(
|
||||
"default",
|
||||
SyntaxShape::String,
|
||||
"default value if no input is provided",
|
||||
Some('d'),
|
||||
)
|
||||
.switch("suppress-output", "don't print keystroke values", Some('s'))
|
||||
.category(Category::Platform)
|
||||
}
|
||||
@ -72,8 +78,12 @@ impl Command for Input {
|
||||
});
|
||||
}
|
||||
|
||||
let default_val: Option<String> = call.get_flag(engine_state, stack, "default")?;
|
||||
if let Some(prompt) = &prompt {
|
||||
print!("{prompt}");
|
||||
match &default_val {
|
||||
None => print!("{prompt}"),
|
||||
Some(val) => print!("{prompt} (default: {val})"),
|
||||
}
|
||||
let _ = std::io::stdout().flush();
|
||||
}
|
||||
|
||||
@ -149,7 +159,10 @@ impl Command for Input {
|
||||
if !suppress_output {
|
||||
std::io::stdout().write_all(b"\n")?;
|
||||
}
|
||||
Ok(Value::string(buf, call.head).into_pipeline_data())
|
||||
match default_val {
|
||||
Some(val) if buf.is_empty() => Ok(Value::string(val, call.head).into_pipeline_data()),
|
||||
_ => Ok(Value::string(buf, call.head).into_pipeline_data()),
|
||||
}
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -164,6 +177,11 @@ impl Command for Input {
|
||||
example: "let user_input = (input --numchar 2)",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Get input from the user with default value, and assign to a variable",
|
||||
example: "let user_input = (input --default 10)",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -77,20 +77,6 @@ impl Command for SubCommand {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
if call.has_flag_const(working_set, "not")? {
|
||||
nu_protocol::report_shell_error(
|
||||
working_set.permanent(),
|
||||
&ShellError::GenericError {
|
||||
error: "Deprecated option".into(),
|
||||
msg: "`str contains --not {string}` is deprecated and will be removed in 0.95."
|
||||
.into(),
|
||||
span: Some(call.head),
|
||||
help: Some("Please use the `not` operator instead.".into()),
|
||||
inner: vec![],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let cell_paths: Vec<CellPath> = call.rest_const(working_set, 1)?;
|
||||
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
|
||||
let args = Arguments {
|
||||
|
@ -5,6 +5,8 @@ use nu_protocol::{did_you_mean, process::ChildProcess, ByteStream, NuGlob, OutDe
|
||||
use nu_system::ForegroundChild;
|
||||
use nu_utils::IgnoreCaseExt;
|
||||
use pathdiff::diff_paths;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::process::CommandExt;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
ffi::{OsStr, OsString},
|
||||
@ -91,6 +93,22 @@ impl Command for External {
|
||||
false
|
||||
};
|
||||
|
||||
// let's make sure it's a .ps1 script, but only on Windows
|
||||
let potential_powershell_script = if cfg!(windows) {
|
||||
if let Some(executable) = which(&expanded_name, "", cwd.as_ref()) {
|
||||
let ext = executable
|
||||
.extension()
|
||||
.unwrap_or_default()
|
||||
.to_string_lossy()
|
||||
.to_uppercase();
|
||||
ext == "PS1"
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Find the absolute path to the executable. On Windows, set the
|
||||
// executable to "cmd.exe" if it's a CMD internal command. If the
|
||||
// command is not found, display a helpful error message.
|
||||
@ -98,11 +116,16 @@ impl Command for External {
|
||||
&& (is_cmd_internal_command(&name_str) || potential_nuscript_in_windows)
|
||||
{
|
||||
PathBuf::from("cmd.exe")
|
||||
} else if cfg!(windows) && potential_powershell_script {
|
||||
// If we're on Windows and we're trying to run a PowerShell script, we'll use
|
||||
// `powershell.exe` to run it. We shouldn't have to check for powershell.exe because
|
||||
// it's automatically installed on all modern windows systems.
|
||||
PathBuf::from("powershell.exe")
|
||||
} else {
|
||||
// Determine the PATH to be used and then use `which` to find it - though this has no
|
||||
// effect if it's an absolute path already
|
||||
let paths = nu_engine::env::path_str(engine_state, stack, call.head)?;
|
||||
let Some(executable) = which(expanded_name, &paths, cwd.as_ref()) else {
|
||||
let Some(executable) = which(&expanded_name, &paths, cwd.as_ref()) else {
|
||||
return Err(command_not_found(&name_str, call.head, engine_state, stack));
|
||||
};
|
||||
executable
|
||||
@ -123,15 +146,29 @@ impl Command for External {
|
||||
let args = eval_arguments_from_call(engine_state, stack, call)?;
|
||||
#[cfg(windows)]
|
||||
if is_cmd_internal_command(&name_str) || potential_nuscript_in_windows {
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
// The /D flag disables execution of AutoRun commands from registry.
|
||||
// The /C flag followed by a command name instructs CMD to execute
|
||||
// that command and quit.
|
||||
command.args(["/D", "/C", &name_str]);
|
||||
command.args(["/D", "/C", &expanded_name.to_string_lossy()]);
|
||||
for arg in &args {
|
||||
command.raw_arg(escape_cmd_argument(arg)?);
|
||||
}
|
||||
} else if potential_powershell_script {
|
||||
use nu_path::canonicalize_with;
|
||||
|
||||
// canonicalize the path to the script so that tests pass
|
||||
let canon_path = if let Ok(cwd) = engine_state.cwd_as_string(None) {
|
||||
canonicalize_with(&expanded_name, cwd)?
|
||||
} else {
|
||||
// If we can't get the current working directory, just provide the expanded name
|
||||
expanded_name
|
||||
};
|
||||
// The -Command flag followed by a script name instructs PowerShell to
|
||||
// execute that script and quit.
|
||||
command.args(["-Command", &canon_path.to_string_lossy()]);
|
||||
for arg in &args {
|
||||
command.raw_arg(arg.item.clone());
|
||||
}
|
||||
} else {
|
||||
command.args(args.into_iter().map(|s| s.item));
|
||||
}
|
||||
|
@ -44,8 +44,29 @@ fn net(span: Span) -> Value {
|
||||
let networks = Networks::new_with_refreshed_list()
|
||||
.iter()
|
||||
.map(|(iface, data)| {
|
||||
let ip_addresses = data
|
||||
.ip_networks()
|
||||
.iter()
|
||||
.map(|ip| {
|
||||
let protocol = match ip.addr {
|
||||
std::net::IpAddr::V4(_) => "ipv4",
|
||||
std::net::IpAddr::V6(_) => "ipv6",
|
||||
};
|
||||
Value::record(
|
||||
record! {
|
||||
"address" => Value::string(ip.addr.to_string(), span),
|
||||
"protocol" => Value::string(protocol, span),
|
||||
"loop" => Value::bool(ip.addr.is_loopback(), span),
|
||||
"multicast" => Value::bool(ip.addr.is_multicast(), span),
|
||||
},
|
||||
span,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let record = record! {
|
||||
"name" => Value::string(trim_cstyle_null(iface), span),
|
||||
"mac" => Value::string(data.mac_address().to_string(), span),
|
||||
"ip" => Value::list(ip_addresses, span),
|
||||
"sent" => Value::filesize(data.total_transmitted() as i64, span),
|
||||
"recv" => Value::filesize(data.total_received() as i64, span),
|
||||
};
|
||||
|
@ -1088,7 +1088,7 @@ fn create_empty_placeholder(
|
||||
let data = vec![vec![cell]];
|
||||
let mut table = NuTable::from(data);
|
||||
table.set_data_style(TextStyle::default().dimmed());
|
||||
let out = TableOutput::new(table, false, false, false);
|
||||
let out = TableOutput::new(table, false, false, 1);
|
||||
|
||||
let style_computer = &StyleComputer::from_config(engine_state, stack);
|
||||
let config = create_nu_table_config(&config, style_computer, &out, false, TableMode::default());
|
||||
|
@ -355,9 +355,9 @@ fn external_command_receives_raw_binary_data() {
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn can_run_batch_files() {
|
||||
fn can_run_cmd_files() {
|
||||
use nu_test_support::fs::Stub::FileWithContent;
|
||||
Playground::setup("run a Windows batch file", |dirs, sandbox| {
|
||||
Playground::setup("run a Windows cmd file", |dirs, sandbox| {
|
||||
sandbox.with_files(&[FileWithContent(
|
||||
"foo.cmd",
|
||||
r#"
|
||||
@ -371,12 +371,30 @@ fn can_run_batch_files() {
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn can_run_batch_files() {
|
||||
use nu_test_support::fs::Stub::FileWithContent;
|
||||
Playground::setup("run a Windows batch file", |dirs, sandbox| {
|
||||
sandbox.with_files(&[FileWithContent(
|
||||
"foo.bat",
|
||||
r#"
|
||||
@echo off
|
||||
echo Hello World
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(cwd: dirs.test(), pipeline("foo.bat"));
|
||||
assert!(actual.out.contains("Hello World"));
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn can_run_batch_files_without_cmd_extension() {
|
||||
use nu_test_support::fs::Stub::FileWithContent;
|
||||
Playground::setup(
|
||||
"run a Windows batch file without specifying the extension",
|
||||
"run a Windows cmd file without specifying the extension",
|
||||
|dirs, sandbox| {
|
||||
sandbox.with_files(&[FileWithContent(
|
||||
"foo.cmd",
|
||||
@ -440,3 +458,20 @@ fn redirect_combine() {
|
||||
assert_eq!(actual.out, "FooBar");
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn can_run_ps1_files() {
|
||||
use nu_test_support::fs::Stub::FileWithContent;
|
||||
Playground::setup("run_a_windows_ps_file", |dirs, sandbox| {
|
||||
sandbox.with_files(&[FileWithContent(
|
||||
"foo.ps1",
|
||||
r#"
|
||||
Write-Host Hello World
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(cwd: dirs.test(), pipeline("foo.ps1"));
|
||||
assert!(actual.out.contains("Hello World"));
|
||||
});
|
||||
}
|
||||
|
@ -2941,3 +2941,123 @@ fn table_footer_inheritance() {
|
||||
assert_eq!(actual.out.match_indices("x2").count(), 1);
|
||||
assert_eq!(actual.out.match_indices("x3").count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_footer_inheritance_kv_rows() {
|
||||
let actual = nu!(
|
||||
concat!(
|
||||
"$env.config.table.footer_inheritance = true;",
|
||||
"$env.config.footer_mode = 7;",
|
||||
"[[a b]; ['kv' {0: 0, 1: 1, 2: 2, 3: 3, 4: 4} ], ['data' 0], ['data' 0] ] | table --expand --width=80",
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
"╭───┬──────┬───────────╮\
|
||||
│ # │ a │ b │\
|
||||
├───┼──────┼───────────┤\
|
||||
│ 0 │ kv │ ╭───┬───╮ │\
|
||||
│ │ │ │ 0 │ 0 │ │\
|
||||
│ │ │ │ 1 │ 1 │ │\
|
||||
│ │ │ │ 2 │ 2 │ │\
|
||||
│ │ │ │ 3 │ 3 │ │\
|
||||
│ │ │ │ 4 │ 4 │ │\
|
||||
│ │ │ ╰───┴───╯ │\
|
||||
│ 1 │ data │ 0 │\
|
||||
│ 2 │ data │ 0 │\
|
||||
╰───┴──────┴───────────╯"
|
||||
);
|
||||
|
||||
let actual = nu!(
|
||||
concat!(
|
||||
"$env.config.table.footer_inheritance = true;",
|
||||
"$env.config.footer_mode = 7;",
|
||||
"[[a b]; ['kv' {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5} ], ['data' 0], ['data' 0] ] | table --expand --width=80",
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
"╭───┬──────┬───────────╮\
|
||||
│ # │ a │ b │\
|
||||
├───┼──────┼───────────┤\
|
||||
│ 0 │ kv │ ╭───┬───╮ │\
|
||||
│ │ │ │ 0 │ 0 │ │\
|
||||
│ │ │ │ 1 │ 1 │ │\
|
||||
│ │ │ │ 2 │ 2 │ │\
|
||||
│ │ │ │ 3 │ 3 │ │\
|
||||
│ │ │ │ 4 │ 4 │ │\
|
||||
│ │ │ │ 5 │ 5 │ │\
|
||||
│ │ │ ╰───┴───╯ │\
|
||||
│ 1 │ data │ 0 │\
|
||||
│ 2 │ data │ 0 │\
|
||||
├───┼──────┼───────────┤\
|
||||
│ # │ a │ b │\
|
||||
╰───┴──────┴───────────╯"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_footer_inheritance_list_rows() {
|
||||
let actual = nu!(
|
||||
concat!(
|
||||
"$env.config.table.footer_inheritance = true;",
|
||||
"$env.config.footer_mode = 7;",
|
||||
"[[a b]; ['kv' {0: [[field]; [0] [1] [2] [3] [4]]} ], ['data' 0], ['data' 0] ] | table --expand --width=80",
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
"╭───┬──────┬───────────────────────╮\
|
||||
│ # │ a │ b │\
|
||||
├───┼──────┼───────────────────────┤\
|
||||
│ 0 │ kv │ ╭───┬───────────────╮ │\
|
||||
│ │ │ │ │ ╭───┬───────╮ │ │\
|
||||
│ │ │ │ 0 │ │ # │ field │ │ │\
|
||||
│ │ │ │ │ ├───┼───────┤ │ │\
|
||||
│ │ │ │ │ │ 0 │ 0 │ │ │\
|
||||
│ │ │ │ │ │ 1 │ 1 │ │ │\
|
||||
│ │ │ │ │ │ 2 │ 2 │ │ │\
|
||||
│ │ │ │ │ │ 3 │ 3 │ │ │\
|
||||
│ │ │ │ │ │ 4 │ 4 │ │ │\
|
||||
│ │ │ │ │ ╰───┴───────╯ │ │\
|
||||
│ │ │ ╰───┴───────────────╯ │\
|
||||
│ 1 │ data │ 0 │\
|
||||
│ 2 │ data │ 0 │\
|
||||
╰───┴──────┴───────────────────────╯"
|
||||
);
|
||||
|
||||
let actual = nu!(
|
||||
concat!(
|
||||
"$env.config.table.footer_inheritance = true;",
|
||||
"$env.config.footer_mode = 7;",
|
||||
"[[a b]; ['kv' {0: [[field]; [0] [1] [2] [3] [4] [5]]} ], ['data' 0], ['data' 0] ] | table --expand --width=80",
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
actual.out,
|
||||
"╭───┬──────┬───────────────────────╮\
|
||||
│ # │ a │ b │\
|
||||
├───┼──────┼───────────────────────┤\
|
||||
│ 0 │ kv │ ╭───┬───────────────╮ │\
|
||||
│ │ │ │ │ ╭───┬───────╮ │ │\
|
||||
│ │ │ │ 0 │ │ # │ field │ │ │\
|
||||
│ │ │ │ │ ├───┼───────┤ │ │\
|
||||
│ │ │ │ │ │ 0 │ 0 │ │ │\
|
||||
│ │ │ │ │ │ 1 │ 1 │ │ │\
|
||||
│ │ │ │ │ │ 2 │ 2 │ │ │\
|
||||
│ │ │ │ │ │ 3 │ 3 │ │ │\
|
||||
│ │ │ │ │ │ 4 │ 4 │ │ │\
|
||||
│ │ │ │ │ │ 5 │ 5 │ │ │\
|
||||
│ │ │ │ │ ╰───┴───────╯ │ │\
|
||||
│ │ │ ╰───┴───────────────╯ │\
|
||||
│ 1 │ data │ 0 │\
|
||||
│ 2 │ data │ 0 │\
|
||||
├───┼──────┼───────────────────────┤\
|
||||
│ # │ a │ b │\
|
||||
╰───┴──────┴───────────────────────╯"
|
||||
);
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ fn from_csv_test_flexible_extra_vals() {
|
||||
echo "a,b\n1,2,3" | from csv --flexible | first | values | to nuon
|
||||
"#
|
||||
));
|
||||
assert_eq!(actual.out, "[1, 2]");
|
||||
assert_eq!(actual.out, "[1, 2, 3]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -479,5 +479,5 @@ fn from_csv_test_flexible_missing_vals() {
|
||||
echo "a,b\n1" | from csv --flexible | first | values | to nuon
|
||||
"#
|
||||
));
|
||||
assert_eq!(actual.out, "[1, null]");
|
||||
assert_eq!(actual.out, "[1]");
|
||||
}
|
||||
|
@ -29,3 +29,20 @@ fn from_ods_file_to_table_select_sheet() {
|
||||
|
||||
assert_eq!(actual.out, "SalesOrders");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_ods_file_to_table_select_sheet_with_annotations() {
|
||||
let actual = nu!(
|
||||
cwd: "tests/fixtures/formats", pipeline(
|
||||
r#"
|
||||
open sample_data_with_annotation.ods --raw
|
||||
| from ods --sheets ["SalesOrders"]
|
||||
| get SalesOrders
|
||||
| get column4
|
||||
| get 0
|
||||
"#
|
||||
));
|
||||
|
||||
// The Units column in the sheet SalesOrders has an annotation and should be ignored.
|
||||
assert_eq!(actual.out, "Units");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ nu-plugin-core = { path = "../nu-plugin-core", version = "0.100.1", default-feat
|
||||
nu-utils = { path = "../nu-utils", version = "0.100.1" }
|
||||
|
||||
log = { workspace = true }
|
||||
thiserror = "1.0"
|
||||
thiserror = "2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { workspace = true }
|
||||
|
@ -36,7 +36,7 @@ num-format = { workspace = true }
|
||||
rmp-serde = { workspace = true, optional = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = "1.0"
|
||||
thiserror = "2.0"
|
||||
typetag = "0.2"
|
||||
os_pipe = { workspace = true, features = ["io_safety"] }
|
||||
log = { workspace = true }
|
||||
|
@ -1330,14 +1330,15 @@ This is an internal Nushell error, please file an issue https://github.com/nushe
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[error("Deprecated: {old_command}")]
|
||||
#[diagnostic(help("for more info see {url}"))]
|
||||
#[error("{deprecated} is deprecated and will be removed in a future release")]
|
||||
#[diagnostic()]
|
||||
Deprecated {
|
||||
old_command: String,
|
||||
new_suggestion: String,
|
||||
#[label("`{old_command}` is deprecated and will be removed in a future release. Please {new_suggestion} instead.")]
|
||||
deprecated: &'static str,
|
||||
suggestion: &'static str,
|
||||
#[label("{deprecated} is deprecated. {suggestion}")]
|
||||
span: Span,
|
||||
url: String,
|
||||
#[help]
|
||||
help: Option<&'static str>,
|
||||
},
|
||||
|
||||
/// Invalid glob pattern
|
||||
|
@ -203,7 +203,7 @@ impl PipelineData {
|
||||
) -> Result<Self, ShellError> {
|
||||
match stack.pipe_stdout().unwrap_or(&OutDest::Inherit) {
|
||||
OutDest::Print => {
|
||||
self.print(engine_state, stack, false, false)?;
|
||||
self.print_table(engine_state, stack, false, false)?;
|
||||
Ok(Self::Empty)
|
||||
}
|
||||
OutDest::Pipe | OutDest::PipeSeparate => Ok(self),
|
||||
@ -534,11 +534,14 @@ impl PipelineData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume and print self data immediately.
|
||||
/// Consume and print self data immediately, formatted using table command.
|
||||
///
|
||||
/// This does not respect the display_output hook. If a value is being printed out by a command,
|
||||
/// this function should be used. Otherwise, `nu_cli::util::print_pipeline` should be preferred.
|
||||
///
|
||||
/// `no_newline` controls if we need to attach newline character to output.
|
||||
/// `to_stderr` controls if data is output to stderr, when the value is false, the data is output to stdout.
|
||||
pub fn print(
|
||||
pub fn print_table(
|
||||
self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
|
@ -35,7 +35,7 @@ fn config_affected_when_mutated() {
|
||||
|
||||
#[test]
|
||||
fn config_affected_when_deep_mutated() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[
|
||||
r#"source default_config.nu"#,
|
||||
r#"$env.config.filesize.metric = true"#,
|
||||
r#"20mib | into string"#]));
|
||||
@ -45,7 +45,7 @@ fn config_affected_when_deep_mutated() {
|
||||
|
||||
#[test]
|
||||
fn config_add_unsupported_key() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[
|
||||
r#"source default_config.nu"#,
|
||||
r#"$env.config.foo = 2"#,
|
||||
r#";"#]));
|
||||
@ -57,7 +57,7 @@ fn config_add_unsupported_key() {
|
||||
|
||||
#[test]
|
||||
fn config_add_unsupported_type() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#"source default_config.nu"#,
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[r#"source default_config.nu"#,
|
||||
r#"$env.config.ls = '' "#,
|
||||
r#";"#]));
|
||||
|
||||
@ -66,7 +66,7 @@ fn config_add_unsupported_type() {
|
||||
|
||||
#[test]
|
||||
fn config_add_unsupported_value() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#"source default_config.nu"#,
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[r#"source default_config.nu"#,
|
||||
r#"$env.config.history.file_format = ''"#,
|
||||
r#";"#]));
|
||||
|
||||
@ -77,7 +77,7 @@ fn config_add_unsupported_value() {
|
||||
#[test]
|
||||
#[ignore = "Figure out how to make test_bins::nu_repl() continue execution after shell errors"]
|
||||
fn config_unsupported_key_reverted() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#"source default_config.nu"#,
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[r#"source default_config.nu"#,
|
||||
r#"$env.config.foo = 1"#,
|
||||
r#"'foo' in $env.config"#]));
|
||||
|
||||
@ -87,7 +87,7 @@ fn config_unsupported_key_reverted() {
|
||||
#[test]
|
||||
#[ignore = "Figure out how to make test_bins::nu_repl() continue execution after shell errors"]
|
||||
fn config_unsupported_type_reverted() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#" source default_config.nu"#,
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[r#" source default_config.nu"#,
|
||||
r#"$env.config.ls = ''"#,
|
||||
r#"$env.config.ls | describe"#]));
|
||||
|
||||
@ -97,7 +97,7 @@ fn config_unsupported_type_reverted() {
|
||||
#[test]
|
||||
#[ignore = "Figure out how to make test_bins::nu_repl() continue execution after errors"]
|
||||
fn config_unsupported_value_reverted() {
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#" source default_config.nu"#,
|
||||
let actual = nu!(cwd: "crates/nu-utils/src/default_files", nu_repl_code(&[r#" source default_config.nu"#,
|
||||
r#"$env.config.history.file_format = 'plaintext'"#,
|
||||
r#"$env.config.history.file_format = ''"#,
|
||||
r#"$env.config.history.file_format | to json"#]));
|
||||
|
@ -54,6 +54,7 @@ pub fn load_standard_library(
|
||||
("mod.nu", "std/math", include_str!("../std/math/mod.nu")),
|
||||
("mod.nu", "std/util", include_str!("../std/util/mod.nu")),
|
||||
("mod.nu", "std/xml", include_str!("../std/xml/mod.nu")),
|
||||
("mod.nu", "std/config", include_str!("../std/config/mod.nu")),
|
||||
];
|
||||
|
||||
for (filename, std_subdir_name, content) in std_submodules.drain(..) {
|
||||
|
139
crates/nu-std/std/config/mod.nu
Normal file
139
crates/nu-std/std/config/mod.nu
Normal file
@ -0,0 +1,139 @@
|
||||
# Returns a dark-mode theme that can be assigned to $env.config.color_config
|
||||
export def dark-theme [] {
|
||||
{
|
||||
# color for nushell primitives
|
||||
separator: white
|
||||
leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
|
||||
header: green_bold
|
||||
empty: blue
|
||||
# Closures can be used to choose colors for specific values.
|
||||
# The value (in this case, a bool) is piped into the closure.
|
||||
# eg) {|| if $in { 'light_cyan' } else { 'light_gray' } }
|
||||
bool: light_cyan
|
||||
int: white
|
||||
filesize: cyan
|
||||
duration: white
|
||||
date: purple
|
||||
range: white
|
||||
float: white
|
||||
string: white
|
||||
nothing: white
|
||||
binary: white
|
||||
cell-path: white
|
||||
row_index: green_bold
|
||||
record: white
|
||||
list: white
|
||||
block: white
|
||||
hints: dark_gray
|
||||
search_result: { bg: red fg: white }
|
||||
shape_and: purple_bold
|
||||
shape_binary: purple_bold
|
||||
shape_block: blue_bold
|
||||
shape_bool: light_cyan
|
||||
shape_closure: green_bold
|
||||
shape_custom: green
|
||||
shape_datetime: cyan_bold
|
||||
shape_directory: cyan
|
||||
shape_external: cyan
|
||||
shape_externalarg: green_bold
|
||||
shape_external_resolved: light_yellow_bold
|
||||
shape_filepath: cyan
|
||||
shape_flag: blue_bold
|
||||
shape_float: purple_bold
|
||||
# shapes are used to change the cli syntax highlighting
|
||||
shape_garbage: { fg: white bg: red attr: b }
|
||||
shape_glob_interpolation: cyan_bold
|
||||
shape_globpattern: cyan_bold
|
||||
shape_int: purple_bold
|
||||
shape_internalcall: cyan_bold
|
||||
shape_keyword: cyan_bold
|
||||
shape_list: cyan_bold
|
||||
shape_literal: blue
|
||||
shape_match_pattern: green
|
||||
shape_matching_brackets: { attr: u }
|
||||
shape_nothing: light_cyan
|
||||
shape_operator: yellow
|
||||
shape_or: purple_bold
|
||||
shape_pipe: purple_bold
|
||||
shape_range: yellow_bold
|
||||
shape_record: cyan_bold
|
||||
shape_redirection: purple_bold
|
||||
shape_signature: green_bold
|
||||
shape_string: green
|
||||
shape_string_interpolation: cyan_bold
|
||||
shape_table: blue_bold
|
||||
shape_variable: purple
|
||||
shape_vardecl: purple
|
||||
shape_raw_string: light_purple
|
||||
}
|
||||
}
|
||||
|
||||
# Returns a light-mode theme that can be assigned to $env.config.color_config
|
||||
export def light-theme [] {
|
||||
{
|
||||
# color for nushell primitives
|
||||
separator: dark_gray
|
||||
leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
|
||||
header: green_bold
|
||||
empty: blue
|
||||
# Closures can be used to choose colors for specific values.
|
||||
# The value (in this case, a bool) is piped into the closure.
|
||||
# eg) {|| if $in { 'dark_cyan' } else { 'dark_gray' } }
|
||||
bool: dark_cyan
|
||||
int: dark_gray
|
||||
filesize: cyan_bold
|
||||
duration: dark_gray
|
||||
date: purple
|
||||
range: dark_gray
|
||||
float: dark_gray
|
||||
string: dark_gray
|
||||
nothing: dark_gray
|
||||
binary: dark_gray
|
||||
cell-path: dark_gray
|
||||
row_index: green_bold
|
||||
record: dark_gray
|
||||
list: dark_gray
|
||||
block: dark_gray
|
||||
hints: dark_gray
|
||||
search_result: { fg: white bg: red }
|
||||
shape_and: purple_bold
|
||||
shape_binary: purple_bold
|
||||
shape_block: blue_bold
|
||||
shape_bool: light_cyan
|
||||
shape_closure: green_bold
|
||||
shape_custom: green
|
||||
shape_datetime: cyan_bold
|
||||
shape_directory: cyan
|
||||
shape_external: cyan
|
||||
shape_externalarg: green_bold
|
||||
shape_external_resolved: light_purple_bold
|
||||
shape_filepath: cyan
|
||||
shape_flag: blue_bold
|
||||
shape_float: purple_bold
|
||||
# shapes are used to change the cli syntax highlighting
|
||||
shape_garbage: { fg: white bg: red attr: b }
|
||||
shape_glob_interpolation: cyan_bold
|
||||
shape_globpattern: cyan_bold
|
||||
shape_int: purple_bold
|
||||
shape_internalcall: cyan_bold
|
||||
shape_keyword: cyan_bold
|
||||
shape_list: cyan_bold
|
||||
shape_literal: blue
|
||||
shape_match_pattern: green
|
||||
shape_matching_brackets: { attr: u }
|
||||
shape_nothing: light_cyan
|
||||
shape_operator: yellow
|
||||
shape_or: purple_bold
|
||||
shape_pipe: purple_bold
|
||||
shape_range: yellow_bold
|
||||
shape_record: cyan_bold
|
||||
shape_redirection: purple_bold
|
||||
shape_signature: green_bold
|
||||
shape_string: green
|
||||
shape_string_interpolation: cyan_bold
|
||||
shape_table: blue_bold
|
||||
shape_variable: purple
|
||||
shape_vardecl: purple
|
||||
shape_raw_string: light_purple
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ export module std/iter
|
||||
export module std/log
|
||||
export module std/math
|
||||
export module std/xml
|
||||
export module std/config
|
||||
|
||||
# Load main dirs command and all subcommands
|
||||
export use std/dirs main
|
||||
|
@ -18,8 +18,12 @@ pub fn create_nu_table_config(
|
||||
expand: bool,
|
||||
mode: TableMode,
|
||||
) -> NuTableConfig {
|
||||
let with_footer = (config.table.footer_inheritance && out.with_footer)
|
||||
|| with_footer(config, out.with_header, out.table.count_rows());
|
||||
let mut count_rows = out.table.count_rows();
|
||||
if config.table.footer_inheritance {
|
||||
count_rows = out.count_rows;
|
||||
}
|
||||
|
||||
let with_footer = with_footer(config, out.with_header, count_rows);
|
||||
|
||||
NuTableConfig {
|
||||
theme: load_theme(mode),
|
||||
|
@ -615,12 +615,15 @@ fn load_theme(
|
||||
if let Some(style) = sep_color {
|
||||
let color = convert_style(style);
|
||||
let color = ANSIBuf::from(color);
|
||||
// todo: use .modify(Segment::all(), color) --> it has this optimization
|
||||
table.get_config_mut().set_border_color_default(color);
|
||||
}
|
||||
|
||||
if !with_header {
|
||||
// todo: remove and use theme.remove_horizontal_lines();
|
||||
table.with(RemoveHorizontalLine);
|
||||
} else if with_footer {
|
||||
// todo: remove and set it on theme rather then here...
|
||||
table.with(CopyFirstHorizontalLineAtLast);
|
||||
}
|
||||
}
|
||||
@ -1257,6 +1260,7 @@ fn remove_row(recs: &mut NuRecords, row: usize) -> Vec<String> {
|
||||
columns
|
||||
}
|
||||
|
||||
// todo; use Format?
|
||||
struct StripColorFromRow(usize);
|
||||
|
||||
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for StripColorFromRow {
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
NuText, StringResult, TableResult, INDEX_COLUMN_NAME,
|
||||
},
|
||||
string_width,
|
||||
types::{has_footer, has_index},
|
||||
types::has_index,
|
||||
NuTable, NuTableCell, TableOpts, TableOutput,
|
||||
};
|
||||
use nu_color_config::{Alignment, StyleComputer, TextStyle};
|
||||
@ -63,22 +63,22 @@ struct Cfg<'a> {
|
||||
struct CellOutput {
|
||||
text: String,
|
||||
style: TextStyle,
|
||||
is_big: bool,
|
||||
size: usize,
|
||||
is_expanded: bool,
|
||||
}
|
||||
|
||||
impl CellOutput {
|
||||
fn new(text: String, style: TextStyle, is_big: bool, is_expanded: bool) -> Self {
|
||||
fn new(text: String, style: TextStyle, size: usize, is_expanded: bool) -> Self {
|
||||
Self {
|
||||
text,
|
||||
style,
|
||||
is_big,
|
||||
size,
|
||||
is_expanded,
|
||||
}
|
||||
}
|
||||
|
||||
fn clean(text: String, is_big: bool, is_expanded: bool) -> Self {
|
||||
Self::new(text, Default::default(), is_big, is_expanded)
|
||||
fn clean(text: String, size: usize, is_expanded: bool) -> Self {
|
||||
Self::new(text, Default::default(), size, is_expanded)
|
||||
}
|
||||
|
||||
fn text(text: String) -> Self {
|
||||
@ -86,7 +86,7 @@ impl CellOutput {
|
||||
}
|
||||
|
||||
fn styled(text: NuText) -> Self {
|
||||
Self::new(text.0, text.1, false, false)
|
||||
Self::new(text.0, text.1, 1, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
|
||||
let with_index = has_index(&cfg.opts, &headers);
|
||||
let row_offset = cfg.opts.index_offset;
|
||||
let mut is_footer_used = false;
|
||||
let mut rows_count = 0usize;
|
||||
|
||||
// The header with the INDEX is removed from the table headers since
|
||||
// it is added to the natural table index
|
||||
@ -199,9 +199,7 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
data[row].push(value);
|
||||
data_styles.insert((row, with_index as usize), cell.style);
|
||||
|
||||
if cell.is_big {
|
||||
is_footer_used = cell.is_big;
|
||||
}
|
||||
rows_count = rows_count.saturating_add(cell.size);
|
||||
}
|
||||
|
||||
let mut table = NuTable::from(data);
|
||||
@ -209,12 +207,7 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
table.set_index_style(get_index_style(cfg.opts.style_computer));
|
||||
set_data_styles(&mut table, data_styles);
|
||||
|
||||
return Ok(Some(TableOutput::new(
|
||||
table,
|
||||
false,
|
||||
with_index,
|
||||
is_footer_used,
|
||||
)));
|
||||
return Ok(Some(TableOutput::new(table, false, with_index, rows_count)));
|
||||
}
|
||||
|
||||
if !headers.is_empty() {
|
||||
@ -269,6 +262,8 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
}
|
||||
}
|
||||
|
||||
let mut column_rows = 0usize;
|
||||
|
||||
for (row, item) in input.iter().enumerate() {
|
||||
cfg.opts.signals.check(cfg.opts.span)?;
|
||||
|
||||
@ -294,9 +289,7 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
data[row + 1].push(value);
|
||||
data_styles.insert((row + 1, col + with_index as usize), cell.style);
|
||||
|
||||
if cell.is_big {
|
||||
is_footer_used = cell.is_big;
|
||||
}
|
||||
column_rows = column_rows.saturating_add(cell.size);
|
||||
}
|
||||
|
||||
let head_cell = NuTableCell::new(header);
|
||||
@ -316,6 +309,8 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
|
||||
available_width -= pad_space + column_width;
|
||||
rendered_column += 1;
|
||||
|
||||
rows_count = std::cmp::max(rows_count, column_rows);
|
||||
}
|
||||
|
||||
if truncate && rendered_column == 0 {
|
||||
@ -374,9 +369,7 @@ fn expanded_table_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
||||
table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1);
|
||||
set_data_styles(&mut table, data_styles);
|
||||
|
||||
let has_footer = is_footer_used || has_footer(&cfg.opts, table.count_rows() as u64);
|
||||
|
||||
Ok(Some(TableOutput::new(table, true, with_index, has_footer)))
|
||||
Ok(Some(TableOutput::new(table, true, with_index, rows_count)))
|
||||
}
|
||||
|
||||
fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
||||
@ -395,7 +388,7 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
||||
|
||||
let value_width = cfg.opts.width - key_width - count_borders - padding - padding;
|
||||
|
||||
let mut with_footer = false;
|
||||
let mut count_rows = 0usize;
|
||||
|
||||
let mut data = Vec::with_capacity(record.len());
|
||||
for (key, value) in record {
|
||||
@ -420,19 +413,17 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
||||
|
||||
data.push(row);
|
||||
|
||||
if cell.is_big {
|
||||
with_footer = cell.is_big;
|
||||
}
|
||||
count_rows = count_rows.saturating_add(cell.size);
|
||||
}
|
||||
|
||||
let mut table = NuTable::from(data);
|
||||
table.set_index_style(get_key_style(&cfg));
|
||||
table.set_indent(cfg.opts.indent.0, cfg.opts.indent.1);
|
||||
|
||||
let out = TableOutput::new(table, false, true, with_footer);
|
||||
let out = TableOutput::new(table, false, true, count_rows);
|
||||
|
||||
maybe_expand_table(out, cfg.opts.width, &cfg.opts)
|
||||
.map(|value| value.map(|value| CellOutput::clean(value, with_footer, false)))
|
||||
.map(|value| value.map(|value| CellOutput::clean(value, count_rows, false)))
|
||||
}
|
||||
|
||||
// the flag is used as an optimization to not do `value.lines().count()` search.
|
||||
@ -441,7 +432,7 @@ fn expand_table_value(value: &Value, value_width: usize, cfg: &Cfg<'_>) -> CellR
|
||||
if is_limited {
|
||||
return Ok(Some(CellOutput::clean(
|
||||
value_to_string_clean(value, cfg),
|
||||
false,
|
||||
1,
|
||||
false,
|
||||
)));
|
||||
}
|
||||
@ -457,7 +448,7 @@ fn expand_table_value(value: &Value, value_width: usize, cfg: &Cfg<'_>) -> CellR
|
||||
let cfg = create_table_cfg(cfg, &out);
|
||||
let value = out.table.draw(cfg, value_width);
|
||||
match value {
|
||||
Some(value) => Ok(Some(CellOutput::clean(value, out.with_footer, true))),
|
||||
Some(value) => Ok(Some(CellOutput::clean(value, out.count_rows, true))),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
@ -484,7 +475,7 @@ fn expand_table_value(value: &Value, value_width: usize, cfg: &Cfg<'_>) -> CellR
|
||||
let inner_cfg = update_config(dive_options(cfg, span), value_width);
|
||||
let result = expanded_table_kv(record, inner_cfg)?;
|
||||
match result {
|
||||
Some(result) => Ok(Some(CellOutput::clean(result.text, result.is_big, true))),
|
||||
Some(result) => Ok(Some(CellOutput::clean(result.text, result.size, true))),
|
||||
None => Ok(Some(CellOutput::text(value_to_wrapped_string(
|
||||
value,
|
||||
cfg,
|
||||
@ -575,7 +566,7 @@ fn expanded_table_entry2(item: &Value, cfg: Cfg<'_>) -> CellOutput {
|
||||
let table_config = create_table_cfg(&cfg, &out);
|
||||
let table = out.table.draw(table_config, usize::MAX);
|
||||
match table {
|
||||
Some(table) => CellOutput::clean(table, out.with_footer, false),
|
||||
Some(table) => CellOutput::clean(table, out.count_rows, false),
|
||||
None => CellOutput::styled(nu_value_to_string(
|
||||
item,
|
||||
cfg.opts.config,
|
||||
|
@ -56,8 +56,9 @@ fn kv_table(record: &Record, opts: TableOpts<'_>) -> StringResult {
|
||||
|
||||
let mut table = NuTable::from(data);
|
||||
table.set_index_style(TextStyle::default_field());
|
||||
let count_rows = table.count_rows();
|
||||
|
||||
let mut out = TableOutput::new(table, false, true, false);
|
||||
let mut out = TableOutput::new(table, false, true, count_rows);
|
||||
|
||||
let left = opts.config.table.padding.left;
|
||||
let right = opts.config.table.padding.right;
|
||||
@ -82,7 +83,10 @@ fn table(input: &[Value], opts: &TableOpts<'_>) -> TableResult {
|
||||
let with_header = !headers.is_empty();
|
||||
if !with_header {
|
||||
let table = to_table_with_no_header(input, with_index, row_offset, opts)?;
|
||||
let table = table.map(|table| TableOutput::new(table, false, with_index, false));
|
||||
let table = table.map(|table| {
|
||||
let count_rows = table.count_rows();
|
||||
TableOutput::new(table, false, with_index, count_rows)
|
||||
});
|
||||
return Ok(table);
|
||||
}
|
||||
|
||||
@ -98,7 +102,10 @@ fn table(input: &[Value], opts: &TableOpts<'_>) -> TableResult {
|
||||
.collect();
|
||||
|
||||
let table = to_table_with_header(input, &headers, with_index, row_offset, opts)?;
|
||||
let table = table.map(|table| TableOutput::new(table, true, with_index, false));
|
||||
let table = table.map(|table| {
|
||||
let count_rows = table.count_rows();
|
||||
TableOutput::new(table, true, with_index, count_rows)
|
||||
});
|
||||
|
||||
Ok(table)
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
use terminal_size::{terminal_size, Height, Width};
|
||||
use nu_color_config::StyleComputer;
|
||||
use nu_protocol::{Config, Signals, Span, TableIndexMode, TableMode};
|
||||
|
||||
use crate::{common::INDEX_COLUMN_NAME, NuTable};
|
||||
use nu_color_config::StyleComputer;
|
||||
use nu_protocol::{Config, FooterMode, Signals, Span, TableIndexMode, TableMode};
|
||||
|
||||
mod collapse;
|
||||
mod expanded;
|
||||
@ -16,16 +15,16 @@ pub struct TableOutput {
|
||||
pub table: NuTable,
|
||||
pub with_header: bool,
|
||||
pub with_index: bool,
|
||||
pub with_footer: bool,
|
||||
pub count_rows: usize,
|
||||
}
|
||||
|
||||
impl TableOutput {
|
||||
pub fn new(table: NuTable, with_header: bool, with_index: bool, with_footer: bool) -> Self {
|
||||
pub fn new(table: NuTable, with_header: bool, with_index: bool, count_rows: usize) -> Self {
|
||||
Self {
|
||||
table,
|
||||
with_header,
|
||||
with_index,
|
||||
with_footer,
|
||||
count_rows,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,23 +78,3 @@ fn has_index(opts: &TableOpts<'_>, headers: &[String]) -> bool {
|
||||
|
||||
with_index && !opts.index_remove
|
||||
}
|
||||
|
||||
fn has_footer(opts: &TableOpts<'_>, count_records: u64) -> bool {
|
||||
match opts.config.footer_mode {
|
||||
// Only show the footer if there are more than RowCount rows
|
||||
FooterMode::RowCount(limit) => count_records > limit,
|
||||
// Always show the footer
|
||||
FooterMode::Always => true,
|
||||
// Never show the footer
|
||||
FooterMode::Never => false,
|
||||
// Calculate the screen height and row count, if screen height is larger than row count, don't show footer
|
||||
FooterMode::Auto => {
|
||||
let (_width, height) = match terminal_size() {
|
||||
Some((w, h)) => (Width(w.0).0 as u64, Height(h.0).0 as u64),
|
||||
None => (Width(0).0 as u64, Height(0).0 as u64),
|
||||
};
|
||||
|
||||
height <= count_records
|
||||
}
|
||||
}
|
||||
}
|
||||
|
82
crates/nu-utils/src/default_files/README.md
Normal file
82
crates/nu-utils/src/default_files/README.md
Normal file
@ -0,0 +1,82 @@
|
||||
# Nushell configuration files
|
||||
|
||||
## `default_env.nu`:
|
||||
|
||||
* The internal default environment variables (other than `$env.config`) that will be set during Nushell startup.
|
||||
* Is loaded *before* the user's `env.nu`.
|
||||
* Will be loaded during any startup where the user's `env.nu` is also loaded. For example:
|
||||
* During normal startup with `nu`
|
||||
* During a startup where the user specifies an alternative `env.nu` via `nu --env-config <path>`
|
||||
* Likewise, is never loaded during a startup where the user's `env.nu` would not be loaded. For example:
|
||||
* `nu -n/--no-config`
|
||||
* `nu -c "ls"`
|
||||
* `nu <script.nu>`
|
||||
* Is not commented - Comments are in `sample_env.nu`.
|
||||
* Should be optimized for fastest load times.
|
||||
* Can be introspected via `config env --default | nu-highlight`
|
||||
|
||||
## `default_config.nu`:
|
||||
|
||||
Counterpart to `default_env.nu`.
|
||||
|
||||
* Contains any `$env.config` values that are not set via Rust defaults.
|
||||
* Is loaded *after* the user's `env.nu`.
|
||||
* Is loaded *before* the user's `config.nu`.
|
||||
* Will be loaded during any startup where the user's `config.nu` is also loaded. For example:
|
||||
* During normal startup with `nu`
|
||||
* During a startup where the user specifies an alternative `config.nu` via `nu --config <path>`
|
||||
* Likewise, is never loaded during a startup where the user's `config.nu` would not be loaded. For example:
|
||||
* `nu -n/--no-config`
|
||||
* `nu -c "ls"`
|
||||
* `nu <script.nu>`
|
||||
* Is not commented - Comments are in `sample_config.nu`.
|
||||
* Should be optimized for fastest load times. Whenever possible, values should be set via nu-protocol::config
|
||||
* Exception: `color_config` values are currently set in this file so that user's can introspect the values
|
||||
* TODO: Implement defaults for `color_config` in nu-protocol::config and remove from `default_config.nu`
|
||||
* Can be introspected via `config nu --default | nu-highlight`
|
||||
* An ideal `default_config.nu` (when all values are set via `nu-protocol::config`) will simply be:
|
||||
```
|
||||
$env.config = {}
|
||||
```
|
||||
|
||||
## `sample_env.nu`
|
||||
|
||||
* A commented file documenting the most common environment variables that a user might configure in `env.nu`
|
||||
* For convenient in-shell access
|
||||
* Can be pretty-printed via `config env --sample | nu-highlight`
|
||||
* Since this file is for documentation only, include actual Nushell code without comments so that it can be pretty-printed
|
||||
* No optimization necessary - Not intended for use other than documentation.
|
||||
* Consider replacing `config env --sample` with `help env.nu` at some point.
|
||||
* Uses a mix of default values (explained) as well as other examples that users might want in their own `env.nu`
|
||||
|
||||
## `sample_config.nu`
|
||||
|
||||
Counterpart to `sample_env.nu`.
|
||||
|
||||
TODO: **Not in final form**
|
||||
|
||||
* A commented file documenting the most common environment variables that a user might configure in `config.nu`
|
||||
* For convenient in-shell access
|
||||
* Can be pretty-printed via `config nu --sample | nu-highlight`
|
||||
* Since this file is for documentation only, include actual Nushell code without comments so that it can be pretty-printed
|
||||
* No optimization necessary - Not intended for use other than documentation.
|
||||
* Consider replacing `config nu --sample` with `help config.nu` at some point.
|
||||
* Uses a mix of default values (explained) as well as other examples that users might want in their own `config.nu`
|
||||
|
||||
## `scaffold_env.nu`
|
||||
|
||||
* This file is used *one-time* (typically) at **first** startup
|
||||
* If the `$nu.default-config-path` directory does not exist, the directory is created and then both `scaffold_env.nu` and `scaffold_config.nu` are written to it
|
||||
* Contains only commented lines explaining the purpose of the file to the user, along with information on the `config env` command.
|
||||
|
||||
## `scaffold_config.nu`
|
||||
|
||||
Counterpart to `scaffold_env.nu`.
|
||||
|
||||
* This file is used *one-time* (typically) at **first** startup
|
||||
* If the `$nu.default-config-path` directory does not exist, the directory is created and then both `scaffold_env.nu` and `scaffold_config.nu` are written to it
|
||||
* Contains only commented lines explaining the purpose of the file to the user, along with information on the `config nu` command.
|
||||
|
||||
## `sample_login.nu`
|
||||
|
||||
This file is not used by any Nushell code. Of course, if the user has a `login.nu`, then it will be evaluated during startup of a login shell.
|
63
crates/nu-utils/src/default_files/default_config.nu
Normal file
63
crates/nu-utils/src/default_files/default_config.nu
Normal file
@ -0,0 +1,63 @@
|
||||
# Nushell Config File
|
||||
#
|
||||
# version = "0.100.1"
|
||||
$env.config.color_config = {
|
||||
separator: white
|
||||
leading_trailing_space_bg: { attr: n }
|
||||
header: green_bold
|
||||
empty: blue
|
||||
bool: light_cyan
|
||||
int: white
|
||||
filesize: cyan
|
||||
duration: white
|
||||
date: purple
|
||||
range: white
|
||||
float: white
|
||||
string: white
|
||||
nothing: white
|
||||
binary: white
|
||||
cell-path: white
|
||||
row_index: green_bold
|
||||
record: white
|
||||
list: white
|
||||
block: white
|
||||
hints: dark_gray
|
||||
search_result: { bg: red fg: white }
|
||||
shape_and: purple_bold
|
||||
shape_binary: purple_bold
|
||||
shape_block: blue_bold
|
||||
shape_bool: light_cyan
|
||||
shape_closure: green_bold
|
||||
shape_custom: green
|
||||
shape_datetime: cyan_bold
|
||||
shape_directory: cyan
|
||||
shape_external: cyan
|
||||
shape_externalarg: green_bold
|
||||
shape_external_resolved: light_yellow_bold
|
||||
shape_filepath: cyan
|
||||
shape_flag: blue_bold
|
||||
shape_float: purple_bold
|
||||
shape_glob_interpolation: cyan_bold
|
||||
shape_globpattern: cyan_bold
|
||||
shape_int: purple_bold
|
||||
shape_internalcall: cyan_bold
|
||||
shape_keyword: cyan_bold
|
||||
shape_list: cyan_bold
|
||||
shape_literal: blue
|
||||
shape_match_pattern: green
|
||||
shape_matching_brackets: { attr: u }
|
||||
shape_nothing: light_cyan
|
||||
shape_operator: yellow
|
||||
shape_or: purple_bold
|
||||
shape_pipe: purple_bold
|
||||
shape_range: yellow_bold
|
||||
shape_record: cyan_bold
|
||||
shape_redirection: purple_bold
|
||||
shape_signature: green_bold
|
||||
shape_string: green
|
||||
shape_string_interpolation: cyan_bold
|
||||
shape_table: blue_bold
|
||||
shape_variable: purple
|
||||
shape_vardecl: purple
|
||||
shape_raw_string: light_purple
|
||||
}
|
57
crates/nu-utils/src/default_files/default_env.nu
Normal file
57
crates/nu-utils/src/default_files/default_env.nu
Normal file
@ -0,0 +1,57 @@
|
||||
# Default Nushell Environment Config File
|
||||
# These "sensible defaults" are set before the user's `env.nu` is loaded
|
||||
#
|
||||
# version = "0.100.1"
|
||||
|
||||
$env.PROMPT_COMMAND = {||
|
||||
let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) {
|
||||
null => $env.PWD
|
||||
'' => '~'
|
||||
$relative_pwd => ([~ $relative_pwd] | path join)
|
||||
}
|
||||
|
||||
let path_color = (if (is-admin) { ansi red_bold } else { ansi green_bold })
|
||||
let separator_color = (if (is-admin) { ansi light_red_bold } else { ansi light_green_bold })
|
||||
let path_segment = $"($path_color)($dir)(ansi reset)"
|
||||
|
||||
$path_segment | str replace --all (char path_sep) $"($separator_color)(char path_sep)($path_color)"
|
||||
}
|
||||
|
||||
$env.PROMPT_INDICATOR = "> "
|
||||
$env.PROMPT_INDICATOR_VI_NORMAL = "> "
|
||||
$env.PROMPT_INDICATOR_VI_INSERT = ": "
|
||||
$env.PROMPT_MULTILINE_INDICATOR = "::: "
|
||||
|
||||
$env.PROMPT_COMMAND_RIGHT = {||
|
||||
# create a right prompt in magenta with green separators and am/pm underlined
|
||||
let time_segment = ([
|
||||
(ansi reset)
|
||||
(ansi magenta)
|
||||
(date now | format date '%x %X') # try to respect user's locale
|
||||
] | str join | str replace --regex --all "([/:])" $"(ansi green)${1}(ansi magenta)" |
|
||||
str replace --regex --all "([AP]M)" $"(ansi magenta_underline)${1}")
|
||||
|
||||
let last_exit_code = if ($env.LAST_EXIT_CODE != 0) {([
|
||||
(ansi rb)
|
||||
($env.LAST_EXIT_CODE)
|
||||
] | str join)
|
||||
} else { "" }
|
||||
|
||||
([$last_exit_code, (char space), $time_segment] | str join)
|
||||
}
|
||||
|
||||
$env.ENV_CONVERSIONS = {
|
||||
"PATH": {
|
||||
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
|
||||
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
|
||||
}
|
||||
}
|
||||
|
||||
$env.NU_LIB_DIRS = [
|
||||
($nu.default-config-dir | path join 'scripts') # add <nushell-config-dir>/scripts
|
||||
($nu.data-dir | path join 'completions') # default home for nushell completions
|
||||
]
|
||||
|
||||
$env.NU_PLUGIN_DIRS = [
|
||||
($nu.default-config-dir | path join 'plugins') # add <nushell-config-dir>/plugins
|
||||
]
|
792
crates/nu-utils/src/default_files/sample_config.nu
Normal file
792
crates/nu-utils/src/default_files/sample_config.nu
Normal file
@ -0,0 +1,792 @@
|
||||
# Nushell Config File
|
||||
#
|
||||
# version = "0.99.2"
|
||||
#
|
||||
# A `config.nu` file is used to override default Nushell settings,
|
||||
# define (or import) custom commands, or run any other startup tasks.
|
||||
# See https://www.nushell.sh/book/configuration.html
|
||||
#
|
||||
# Nushell sets "sensible defaults" for most configuration settings, so
|
||||
# the user's `config.nu` only needs to override these defaults if
|
||||
# desired.
|
||||
#
|
||||
# This file serves as simple "in-shell" documentation for these
|
||||
# settings, or you can view a more complete discussion online at:
|
||||
# https://nushell.sh/book/configuration
|
||||
#
|
||||
# You can pretty-print and page this file using:
|
||||
# config nu --sample | nu-highlight | less -R
|
||||
|
||||
# $env.config
|
||||
# -----------
|
||||
# The $env.config environment variable is a record containing most Nushell
|
||||
# configuration settings. Keep in mind that, as a record, setting it to a
|
||||
# new record will remove any keys which aren't in the new record. Nushell
|
||||
# will then automatically merge in the internal defaults for missing keys.
|
||||
#
|
||||
# The same holds true for keys in the $env.config which are also records
|
||||
# or lists.
|
||||
#
|
||||
# For this reason, settings are typically changed by updating the value of
|
||||
# a particular key. Merging a new config record is also possible. See the
|
||||
# Configuration chapter of the book for more information.
|
||||
|
||||
# ------------------------
|
||||
# History-related settings
|
||||
# ------------------------
|
||||
# $env.config.history.*
|
||||
|
||||
# file_format (string): Either "sqlite" or "plaintext". While text-backed history
|
||||
# is currently the default for historical reasons, "sqlite" is stable and
|
||||
# provides more advanced history features.
|
||||
$env.config.history.file_format = "sqlite"
|
||||
|
||||
# max_size (int): The maximum number of entries allowed in the history.
|
||||
# After exceeding this value, the oldest history items will be removed
|
||||
# as new commands are added.
|
||||
$env.config.history.max_size = 5_000_000
|
||||
|
||||
# sync_on_enter (bool): Whether the plaintext history file is updated
|
||||
# each time a command is entered. If set to `false`, the plaintext history
|
||||
# is only updated/written when the shell exits. This setting has no effect
|
||||
# for SQLite-backed history.
|
||||
$env.config.history.sync_on_enter = true
|
||||
|
||||
# isolation (bool):
|
||||
# `true`: New history from other currently-open Nushell sessions is not
|
||||
# seen when scrolling through the history using PrevHistory (typically
|
||||
# the Up key) or NextHistory (Down key)
|
||||
# `false`: All commands entered in other Nushell sessions will be mixed with
|
||||
# those from the current shell.
|
||||
# Note: Older history items (from before the current shell was started) are
|
||||
# always shown.
|
||||
# This setting only applies to SQLite-backed history
|
||||
$env.config.history.isolation = true
|
||||
|
||||
# ----------------------
|
||||
# Miscellaneous Settings
|
||||
# ----------------------
|
||||
|
||||
# show_banner (bool): Enable or disable the welcome banner at startup
|
||||
$env.config.show_banner = true
|
||||
|
||||
# rm.always_trash (bool):
|
||||
# true: rm behaves as if the --trash/-t option is specified
|
||||
# false: rm behaves as if the --permanent/-p option is specified (default)
|
||||
# Explicitly calling `rm` with `--trash` or `--permanent` always override this setting
|
||||
# Note that this feature is dependent on the host OS trashcan support.
|
||||
$env.config.rm.always_trash = false
|
||||
|
||||
# recursion_limit (int): how many times a command can call itself recursively
|
||||
# before an error will be generated.
|
||||
$env.config.recursion_limit = 50
|
||||
|
||||
# ---------------------------
|
||||
# Commandline Editor Settings
|
||||
# ---------------------------
|
||||
|
||||
# edit_mode (string) "vi" or "emacs" sets the editing behavior of Reedline
|
||||
edit_mode: "emacs"
|
||||
|
||||
# Command that will be used to edit the current line buffer with Ctrl+O.
|
||||
# If unset, uses $env.VISUAL and then $env.EDITOR
|
||||
#
|
||||
# Tip: Set to "editor" to use the default editor on Unix platforms using
|
||||
# the Alternatives system or equivalent
|
||||
buffer_editor: "editor"
|
||||
|
||||
# cursor_shape_* (string)
|
||||
# -----------------------
|
||||
# The following variables accept a string from the following selections:
|
||||
# "block", "underscore", "line", "blink_block", "blink_underscore", "blink_line", or "inherit"
|
||||
# "inherit" skips setting cursor shape and uses the current terminal setting.
|
||||
$env.config.cursor_shape.emacs = "inherit" # Cursor shape in emacs mode
|
||||
$env.config.cursor_shape.vi_insert = "block" # Cursor shape in vi-insert mode
|
||||
$env.config.cursor_shape.vi_normal = "underscore" # Cursor shape in normal vi mode
|
||||
|
||||
# --------------------
|
||||
# Completions Behavior
|
||||
# --------------------
|
||||
# $env.config.completions.*
|
||||
# Apply to the Nushell completion system
|
||||
|
||||
# algorithm (string): Either "prefix" or "fuzzy"
|
||||
$env.config.completions.algorithm = "prefix"
|
||||
|
||||
# sort (string): One of "smart" or "alphabetical"
|
||||
# In "smart" mode sort order is based on the "algorithm" setting.
|
||||
# When using the "prefix" algorithm, results are alphabetically sorted.
|
||||
# When using the "fuzzy" algorithm, results are sorted based on their fuzzy score.
|
||||
$env.config.completions.sort = "smart"
|
||||
|
||||
# case_sensitive (bool): true/false to enable/disable case-sensitive completions
|
||||
$env.config.completions.case_sensitive = false
|
||||
|
||||
# quick (bool):
|
||||
# true: auto-select the completion when only one remains
|
||||
# false: prevents auto-select of the final result
|
||||
$env.config.completions.quick = true
|
||||
|
||||
# partial (bool):
|
||||
# true: Partially complete up to the best possible match
|
||||
# false: Do not partially complete
|
||||
# Partial Example: If a directory contains only files named "forage", "food", and "forest",
|
||||
# then typing "ls " and pressing <Tab> will partially complete the first two
|
||||
# letters, "f" and "o". If the directory also includes a file named "faster",
|
||||
# then only "f" would be partially completed.
|
||||
$env.config.completions.partial = true
|
||||
|
||||
# use_ls_colors (bool): When true, apply LS_COLORS to file/path/directory matches
|
||||
$env.config.completions.use_ls_colors = true
|
||||
|
||||
# --------------------
|
||||
# External Completions
|
||||
# --------------------
|
||||
# completions.external.*: Settings related to completing external commands
|
||||
# and additional completers
|
||||
|
||||
# external.exnable (bool)
|
||||
# true: search for external commands on the Path
|
||||
# false: disabling might be desired for performance if your path includes
|
||||
# directories on a slower filesystem
|
||||
$env.config.completions.external.enable = true
|
||||
|
||||
# max_results (int): Limit the number of external commands retrieved from
|
||||
# path to this value. Has no effect if `...external.enable` (above) is set to `false`
|
||||
$env.config.completions.external.max_results = 50
|
||||
|
||||
# completer (closure with a |spans| parameter): A command to call for *argument* completions
|
||||
# to commands (internal or external).
|
||||
#
|
||||
# The |spans| parameter is a list of strings representing the tokens (spans)
|
||||
# on the current commandline. It is always a list of at least two strings - The
|
||||
# command being completed plus the first argument of that command ("" if no argument has
|
||||
# been partially typed yet), and additional strings for additional arguments beyond
|
||||
# the first.
|
||||
#
|
||||
# This setting is usually set to a closure which will call a third-party completion system, such
|
||||
# as Carapace.
|
||||
#
|
||||
# Note: The following is an over-simplified completer command that will call Carapace if it
|
||||
# is installed. Please use the official Carapace completer, which can be generated automatically
|
||||
# by Carapace itself. See the Carapace documentation for the proper syntax.
|
||||
$env.config.completions.external.completer = {|spans|
|
||||
carapace $spans.0 nushell ...$spans | from json
|
||||
}
|
||||
|
||||
# --------------------
|
||||
# Terminal Integration
|
||||
# --------------------
|
||||
# Nushell can output a number of escape codes to enable advanced features in Terminal Emulators
|
||||
# that support them. Settings in this section enable or disable these features in Nushell.
|
||||
# Features aren't supported by your Terminal can be disabled. Features can also be disabled,
|
||||
# of course, if there is a conflict between the Nushell and Terminal's implementation.
|
||||
|
||||
# use_kitty_protocol (bool):
|
||||
# A keyboard enhancement protocol supported by the Kitty Terminal. Additional keybindings are
|
||||
# available when using this protocol in a supported terminal. For example, without this protocol,
|
||||
# Ctrl+I is interpreted as the Tab Key. With this protocol, Ctrl+I and Tab can be mapped separately.
|
||||
$env.config.use_kitty_protocol = false
|
||||
|
||||
# osc2 (bool):
|
||||
# When true, the current directory and running command are shown in the terminal tab/window title.
|
||||
# Also abbreviates the directory name by prepending ~ to the home directory and its subdirectories.
|
||||
$env.config.shell_integration.osc2 = true
|
||||
|
||||
# osc7 (bool):
|
||||
# Nushell will report the current directory to the terminal using OSC 7. This is useful when
|
||||
# spawning new tabs in the same directory.
|
||||
$env.config.shell_integration.osc7 = true
|
||||
|
||||
# osc9_9 (bool):
|
||||
# Enables/Disables OSC 9;9 support, originally a ConEmu terminal feature. This is an
|
||||
# alternative to OSC 7 which also communicates the current path to the terminal.
|
||||
$env.config.shell_integration.osc9_9 = false
|
||||
|
||||
# osc8 (bool):
|
||||
# When true, the `ls` command will generate clickable links that can be launched in another
|
||||
# application by the terminal.
|
||||
# Note: This setting replaces the now deprecated `ls.show_clickable_links`
|
||||
$env.config.shell.integration.osc8: true
|
||||
|
||||
# Deprecated
|
||||
# $env.config.ls.clickable_links = true
|
||||
|
||||
# osc133 (bool):
|
||||
# true/false to enable/disable OSC 133 support, a set of several escape sequences which
|
||||
# report the (1) starting location of the prompt, (2) ending location of the prompt,
|
||||
# (3) starting location of the command output, and (4) the exit code of the command.
|
||||
|
||||
# originating with Final Term. These sequences report information regarding the prompt
|
||||
# location as well as command status to the terminal. This enables advanced features in
|
||||
# some terminals, including the ability to provide separate background colors for the
|
||||
# command vs. the output, collapsible output, or keybindings to scroll between prompts.
|
||||
$env.config.shell_integration.osc133 = true
|
||||
|
||||
# osc633 (bool):
|
||||
# true/false to enable/disable OSC 633, an extension to OSC 133 for Visual Studio Code
|
||||
$env.config.shell_integration.osc633 = true
|
||||
|
||||
# reset_application_mode (bool):
|
||||
# true/false to enable/disable sending ESC[?1l to the terminal
|
||||
# This sequence is commonly used to keep cursor key modes in sync between the local
|
||||
# terminal and a remove SSH host.
|
||||
$env.config.shell_integration.reset_application_mode = true
|
||||
|
||||
# bracketed_paste (bool):
|
||||
# true/false to enable/disable the bracketed-paste feature, which allows multiple-lines
|
||||
# to be pasted into Nushell at once without immediate execution. When disabled,
|
||||
# each pasted line is executed as it is received.
|
||||
# Note that bracketed paste is not currently supported on the Windows version of
|
||||
# Nushell.
|
||||
$env.config.bracketed_paste = true
|
||||
|
||||
# use_ansi_coloring (bool):
|
||||
# true/false to enable/disable the use of ANSI colors in Nushell internal commands.
|
||||
# When disabled, output from Nushell built-in commands will display only in the default
|
||||
# foreground color.
|
||||
# Note: Does not apply to the `ansi` command.
|
||||
$env.config.use_ansi_coloring = true
|
||||
|
||||
# ----------------------
|
||||
# Error Display Settings
|
||||
# ----------------------
|
||||
|
||||
# error_style (string): One of "fancy" or "plain"
|
||||
# Plain: Display plain-text errors for screen-readers
|
||||
# Fancy: Display errors using line-drawing characters to point to the span in which the
|
||||
# problem occurred.
|
||||
$env.config.error_style = "fancy"
|
||||
|
||||
# display_errors.exit_code (bool):
|
||||
# true: Display a Nushell error when an external command returns a non-zero exit code
|
||||
# false: Display only the error information printed by the external command itself
|
||||
# Note: Core dump errors are always printed; SIGPIPE never triggers an error
|
||||
$env.config.display_errors.exit_code = false
|
||||
|
||||
# display_errors.termination_signal (bool):
|
||||
# true/false to enable/disable displaying a Nushell error when a child process is
|
||||
# terminated via any signal
|
||||
$env.config.display_errors.termination_signal = true
|
||||
|
||||
# -------------
|
||||
# Table Display
|
||||
# -------------
|
||||
# footer_mode (string or int):
|
||||
# Specifies when to display table footers with column names. Allowed values:
|
||||
# "always"
|
||||
# "never"
|
||||
# "auto": When the length of the table would scroll the header past the first line of the terminal
|
||||
# (int): When the number of table rows meets or exceeds this value
|
||||
# Note: Does not take into account rows with multiple lines themselves
|
||||
$env.config.footer_mode = 25
|
||||
|
||||
# table.*
|
||||
# table_mode (string):
|
||||
# One of: "default", "basic", "compact", "compact_double", "heavy", "light", "none", "reinforced",
|
||||
# "rounded", "thin", "with_love", "psql", "markdown", "dots", "restructured", "ascii_rounded",
|
||||
# or "basic_compact"
|
||||
# Can be overridden by passing a table to `| table --theme/-t`
|
||||
$env.config.table.mode = "default"
|
||||
|
||||
# index_mode (string) - One of:
|
||||
# "never": never show the index column in a table or list
|
||||
# "always": always show the index column in tables and lists
|
||||
# "auto": show the column only when there is an explicit "index" column in the table
|
||||
# Can be overridden by passing a table to `| table --index/-i`
|
||||
$env.config.table.index_mode = "always"
|
||||
|
||||
# show_empty (bool):
|
||||
# true: show "empty list" or "empty table" when no values exist
|
||||
# false: display no output when no values exist
|
||||
$env.config.table.show_empty = true
|
||||
|
||||
# padding.left/right (int): The number of spaces to pad around values in each column
|
||||
$env.config.table.padding.left = 1
|
||||
$env.config.table.padding.right = 1
|
||||
|
||||
# trim.*: The rules that will be used to display content in a table row when it would cause the
|
||||
# table to exceed the terminal width.
|
||||
# methodology (string): One of "wrapping" or "truncating"
|
||||
# truncating_suffix (string): The text to show at the end of the row to indicate that it has
|
||||
# been truncated. Only valid when `methodology = "truncating"`.
|
||||
# wrapping_try_keep_words (bool): true to keep words together based on whitespace
|
||||
# false to allow wrapping in the middle of a word.
|
||||
# Only valid when `methodology = wrapping`.
|
||||
$env.config.table.trim = {
|
||||
methodology: "wrapping"
|
||||
wrapping_try_keep_words: true
|
||||
}
|
||||
# or
|
||||
$env.config.table.trim = {
|
||||
methodology: "truncating"
|
||||
truncating_suffix: "..."
|
||||
}
|
||||
|
||||
# header_on_separator (bool):
|
||||
# true: Displays the column headers as part of the top (or bottom) border of the table
|
||||
# false: Displays the column header in its own row with a separator below.
|
||||
$env.config.table.header_on_separator = false
|
||||
|
||||
# abbreviated_row_count (int or nothing):
|
||||
# If set to an int, all tables will be abbreviated to only show the first <n> and last <n> rows
|
||||
# If set to `null`, all table rows will be displayed
|
||||
# Can be overridden by passing a table to `| table --abbreviated/-a`
|
||||
$env.config.table.abbreviated_row_count
|
||||
|
||||
# footer_inheritance (bool): Footer behavior in nested tables
|
||||
# true: If a nested table is long enough on its own to display a footer (per `footer_mode` above),
|
||||
# then also display the footer for the parent table
|
||||
# false: Always apply `footer_mode` rules to the parent table
|
||||
$env.config.table.footer_inheritance = false
|
||||
|
||||
# ----------------
|
||||
# Datetime Display
|
||||
# ----------------
|
||||
# datetime_format.* (string or nothing):
|
||||
# Format strings that will be used for datetime values.
|
||||
# When set to `null`, the default behavior is to "humanize" the value (e.g., "now" or "a day ago")
|
||||
|
||||
# datetime_format.table (string or nothing):
|
||||
# The format string (or `null`) that will be used to display a datetime value when it appears in a
|
||||
# structured value such as a table, list, or record.
|
||||
$env.config.datetime_format.table = null
|
||||
|
||||
# datetime_format.normal (string or nothing):
|
||||
# The format string (or `null`) that will be used to display a datetime value when it appears as
|
||||
# a raw value.
|
||||
$env.config.datetime_format.normal = "%m/%d/%y %I:%M:%S%p"
|
||||
|
||||
# ----------------
|
||||
# Filesize Display
|
||||
# ----------------
|
||||
# filesize.metric (bool): When displaying filesize values ...
|
||||
# true: Use the ISO-standard KB, MB, GB
|
||||
# false: Use the Windows-standard KiB, MiB, GiB
|
||||
$env.config.filesize.metric = false
|
||||
|
||||
# filesize.format (string): One of either:
|
||||
# - The filesize units such as "KB", "KiB", etc. In this case, filesize values always display using
|
||||
# this unit.
|
||||
# - Or "auto": Filesizes are displayed using the closest unit. For example, 1_000_000_000b will display
|
||||
# as 953.7 MiB (when `metric = false`) or 1.0GB (when `metric = true`)
|
||||
$env.config.filesize.format = "auto"
|
||||
|
||||
# ---------------------
|
||||
# Miscellaneous Display
|
||||
# ---------------------
|
||||
|
||||
# render_right_prompt_on_last_line(bool):
|
||||
# true: When using a multi-line left-prompt, the right-prompt will be displayed on the last line
|
||||
# false: The right-prompt is displayed on the first line of the left-prompt
|
||||
$env.config.render_right_prompt_on_last_line = false
|
||||
|
||||
# float_precision (int):
|
||||
# Float values will be rounded to this precision when displaying in structured values such as lists,
|
||||
# tables, or records.
|
||||
$env.config.float_precision = 2
|
||||
|
||||
# ls.use_ls_colors (bool):
|
||||
# true: The `ls` command will apply the $env.LS_COLORS standard to filenames
|
||||
# false: Filenames in the `ls` table will use the color_config for strings
|
||||
$env.config.ls = true
|
||||
|
||||
# Hooks
|
||||
# -----
|
||||
# $env.config.hooks is a record containing the five different types of Nushell hooks.
|
||||
# See the Hooks documentation at https://www.nushell.sh/book/hooks for details
|
||||
#
|
||||
# Most hooks can accept a string, a closure, or a list containing strings and/or closures.
|
||||
# The display_output record can only accept a string or a closure, but never a list
|
||||
#
|
||||
# WARNING: A malformed display_output hook can suppress all Nushell output to the terminal.
|
||||
# It can be reset by assigning an empty string as below:
|
||||
|
||||
$env.config.hooks.pre_prompt = [] # Before each prompt is displayed
|
||||
$env.config.hooks.pre_execution = [] # After <enter> is pressed; before the commandline
|
||||
# is executed
|
||||
$env.config.hooks.env_change = [] # When a specified environment variable changes
|
||||
$env.config.hooks.display_output = "" # Before Nushell output is displayed in the terminal
|
||||
$env.config.hooks.command_not_found = [] # When a command is not found
|
||||
|
||||
# -----------
|
||||
# Keybindings
|
||||
# -----------
|
||||
# keybindings (list): A list of user-defined keybindings
|
||||
# Nushell/Reedline keybindings can be added or overridden using this setting.
|
||||
# See https://www.nushell.sh/book/line_editor.html#keybindings for details.
|
||||
#
|
||||
# Example - Add a new Alt+. keybinding to insert the last token used on the previous commandline
|
||||
$env.config.keybindings ++= [
|
||||
{
|
||||
name: insert_last_token
|
||||
modifier: alt
|
||||
keycode: char_.
|
||||
mode: [emacs vi_normal vi_insert]
|
||||
event: [
|
||||
{ edit: InsertString, value: "!$" }
|
||||
{ send: Enter }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
# Example: Override the F1 keybinding with a user-defined help menu (see "Menus" below):
|
||||
$env.config.keybindings ++= [
|
||||
{
|
||||
name: help_menu
|
||||
modifier: none
|
||||
keycode: f1
|
||||
mode: [emacs, vi_insert, vi_normal]
|
||||
event: { send: menu name: help_menu }
|
||||
}
|
||||
]
|
||||
|
||||
# -----
|
||||
# Menus
|
||||
# -----
|
||||
# menus (list):
|
||||
#
|
||||
# Nushell/Reedline menus can be created and modified using this setting.
|
||||
# See https://www.nushell.sh/book/line_editor.html#menus for details.
|
||||
#
|
||||
# Note that menus are usually activated via keybindings, which are defined in
|
||||
# $env.config.keybindings (above).
|
||||
#
|
||||
# Simple example - Add a new Help menu to the list (note that a similar menu is already
|
||||
# defined internally):
|
||||
$env.config.menus ++= [
|
||||
{
|
||||
name: help_menu
|
||||
only_buffer_difference: true
|
||||
marker: "? "
|
||||
type: {
|
||||
layout: description
|
||||
columns: 4
|
||||
col_width: 20 # Optional value. If missing all the screen width is used to calculate column width
|
||||
col_padding: 2
|
||||
selection_rows: 4
|
||||
description_rows: 10
|
||||
}
|
||||
style: {
|
||||
text: green
|
||||
selected_text: green_reverse
|
||||
description_text: yellow
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
# ---------------
|
||||
# Plugin behavior
|
||||
# ---------------
|
||||
# Per-plugin configuration. See https://www.nushell.sh/contributor-book/plugins.html#configuration.
|
||||
plugins: {}
|
||||
$env.config.plugins
|
||||
$env.config.plugin_gc
|
||||
$env.config.plugin_gc.default
|
||||
$env.config.plugin_gc.default.enabled
|
||||
$env.config.plugin_gc.default.stop_after
|
||||
$env.config.plugin_gc.plugins
|
||||
plugin_gc: {
|
||||
# Configuration for plugin garbage collection
|
||||
default: {
|
||||
enabled: true # true to enable stopping of inactive plugins
|
||||
stop_after: 10sec # how long to wait after a plugin is inactive to stop it
|
||||
}
|
||||
plugins: {
|
||||
# alternate configuration for specific plugins, by name, for example:
|
||||
#
|
||||
# gstat: {
|
||||
# enabled: false
|
||||
# }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# -------------------------------------
|
||||
# Themes/Colors and Syntax Highlighting
|
||||
# -------------------------------------
|
||||
# For more information on defining custom themes, see
|
||||
# https://www.nushell.sh/book/coloring_and_theming.html
|
||||
|
||||
# Use and/or contribute to the theme collection at
|
||||
# https://github.com/nushell/nu_scripts/tree/main/themes
|
||||
|
||||
# Values:
|
||||
|
||||
# highlight_resolved_externals (bool):
|
||||
# true: Applies the `color_config.shape_external_resolved` color (below) to external commands
|
||||
# which are found (resolved) on the path
|
||||
# false: Applies the `color_config.shape_external` color to *all* externals simply based on whether
|
||||
# or not they would be *parsed* as an external command based on their position.
|
||||
# Defaults to false for systems with a slower search path
|
||||
$env.config.highlight_resolved_externals = true
|
||||
|
||||
# color_config (record): A record of shapes, types, UI elements, etc. that can be styled (e.g.,
|
||||
# colorized) in Nushell, either on the commandline itself (shapes) or in output.
|
||||
#
|
||||
# Note that this is usually set through a theme provided by a record in a custom command. For
|
||||
# instance, the standard library contains two "starter" theme commands: "dark-theme" and
|
||||
# "light-theme". For example:
|
||||
use std/config dark-theme
|
||||
$env.config.color_config = (dark-theme)
|
||||
|
||||
# Or, individual color settings can be configured or overridden.
|
||||
#
|
||||
# Values can be one of:
|
||||
# - A color name such as "red" (see `ansi -l` for a list)
|
||||
# - A color RGB value in the form of "#C4C9C6"
|
||||
# - A record including:
|
||||
# * `fg` (color)
|
||||
# * `bg` (color)
|
||||
# * `attr`: a string with one or more of:
|
||||
# - 'n': normal
|
||||
# - 'b': bold
|
||||
# - 'u': underline
|
||||
# - 'r': reverse
|
||||
# - 'i': italics
|
||||
# - 'd': dimmed
|
||||
|
||||
# foreground, background, and cursor colors are not handled by Nushell, but can be used by
|
||||
# custom-commands such as `theme` from the nu_scripts repository. That `theme` command can be
|
||||
# used to set the terminal foreground, background, and cursor colors.
|
||||
$env.config.color_config.foreground
|
||||
$env.config.color_config.background
|
||||
$env.config.color_config.cursor
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# shape_: Applies syntax highlighting based on the "shape" (inferred or declared type) of an
|
||||
# element on the commandline. Nushell's parser can identify shapes based on many criteria, often
|
||||
# as the commandline is being typed.
|
||||
|
||||
# shape_string: Can appear as a single-or-quoted value, a bareword string, the key of a record,
|
||||
# an argument which has been declared as a string, and other parsed strings.
|
||||
$env.config.color_config.shape_string
|
||||
|
||||
# shape_string_interpolation: A single-or-double-quoted string interpolation. This style
|
||||
# applies to the dollar sign and quotes of the string. The elements inside the string are
|
||||
# styled according to their own shape.
|
||||
$env.config.color_config.shape_string_interpolation
|
||||
|
||||
# shape_raw_string: a raw string literal. E.g., r#'This is a raw string'#. This style applies
|
||||
# to the entire raw string.
|
||||
$env.config.color_config.shape_raw_string
|
||||
|
||||
# shape_record: A record-literal. This style applies to the brackets around the record. The keys
|
||||
# and values will be styled according to their individual shapes.
|
||||
$env.config.color_config.shape_record
|
||||
|
||||
# shape_list: A list-literal. This style applies to the brackets and list separator only. The
|
||||
# items in a list are styled according to their individual shapes.
|
||||
$env.config.color_config.shape_list
|
||||
|
||||
# shape_table: A table-literl. Color applies to the brackets, semicolon, and list separators. The
|
||||
# items in the table are style according to their individual shapes.
|
||||
$env.config.color_config.shape_table
|
||||
|
||||
# shape_bool: A boolean-literal `true` or `false` value
|
||||
$env.config.color_config.shape_bool
|
||||
|
||||
# shape_int: Integer literals
|
||||
$env.config.color_config.shape_int
|
||||
|
||||
# shape_float: Float literals. E.g., 5.4
|
||||
# Also integer literals in a float-argument position
|
||||
$env.config.color_config.shape_float
|
||||
|
||||
# shape_range: Range literals
|
||||
$env.config.color_config.shape_range
|
||||
|
||||
# shape_binary: Binary literals
|
||||
$env.config.color_config.shape_binary
|
||||
|
||||
# shape_datetime: Datetime literals
|
||||
$env.config.color_config.shape_datetime
|
||||
|
||||
# shape_custom: A custom value, usually from a plugin
|
||||
$env.config.color_config.shape_custom
|
||||
|
||||
# shape_nothing: A literal `null`
|
||||
$env.config.color_config.shape_nothing
|
||||
|
||||
# shape_literal: Not currently used
|
||||
$env.config.color_config.shape_literal
|
||||
|
||||
# shape_operator: An operator such as +, -, ++, in, not-in, etc.
|
||||
$env.config.color_config.shape_operator
|
||||
|
||||
# shape_filepath: An argument that appears in the position of a `path` shape for a command
|
||||
$env.config.color_config.shape_filepath
|
||||
|
||||
# shape_directory: A more specific 'path' shape that only accepts a directory.
|
||||
$env.config.color_config.shape_directory
|
||||
|
||||
# shape_globpattern: An argument in the position of a glob parameter. E.g., the asterisk (or any other string) in `ls *`.
|
||||
$env.config.color_config.shape_globpattern
|
||||
|
||||
# shape_glob_interpolation: Deprecated
|
||||
$env.config.color_config.shape_glob_interpolation
|
||||
|
||||
# shape_garbage: When an argument is of the wrong type or cannot otherwise be parsed.
|
||||
# E.g., `ls {a: 5}` - A record argument to `ls` is 'garbage'. Also applied in real-time when
|
||||
# an expression is not (yet) properly closed.
|
||||
$env.config.color_config.shape_garbage
|
||||
|
||||
# shape_or and shape_and: The and and or operators.
|
||||
# Note: Not currently implemented.
|
||||
$env.config.color_config.shape_or
|
||||
$env.config.color_config.shape_and
|
||||
|
||||
# shape_variable: The *use* of a variable. E.g., `$env` or `$a`.
|
||||
$env.config.color_config.shape_variable
|
||||
|
||||
# shape_vardecl: The *declaration* of a variable. E.g. the "a" in `let a = 5`.
|
||||
$env.config.color_config.shape_vardecl
|
||||
|
||||
# shape_matching_brackets: When the cursor is positioned on an opening or closing bracket (e.g,
|
||||
# braces, curly braces, or parenthesis), and there is a matching opening/closing bracket, both will
|
||||
# temporarily have this style applied.
|
||||
$env.config.color_config.shape_matching_brackets
|
||||
|
||||
# shape_pipe: The pipe `|` when used to separate expressions in a pipeline
|
||||
$env.config.color_config.shape_pipe
|
||||
|
||||
# shape_internalcall: A known Nushell built-in or custom command in the "command position" (usually
|
||||
# the first bare word of an expression).
|
||||
$env.config.color_config.shape_internalcall
|
||||
|
||||
# shape_external: A token in the "command position" (see above) that is not a known Nushell
|
||||
# built-in or custom command. This is assumed to be an external command.
|
||||
$env.config.color_config.shape_external
|
||||
|
||||
# shape_external_resolved: Requires "highlight_resolved_externals" (above) to be enabled.
|
||||
# When a token matches the "external" requirement (above) and is also a *confirmed* external
|
||||
# command, this style will be applied.
|
||||
$env.config.color_config.shape_external_resolved
|
||||
|
||||
# shape_externalarg: Arguments to an external command (whether resolved or not)
|
||||
$env.config.color_config.shape_externalarg
|
||||
|
||||
# shape_match_pattern: The matching pattern for each arm in a match expression. Does not
|
||||
# include the guard expression (if present).
|
||||
$env.config.color_config.shape_match_pattern
|
||||
|
||||
# shape_block: The curly-braces around a block. Expressions within the block will have their
|
||||
# their own shapes' styles applied.
|
||||
$env.config.color_config.shape_block
|
||||
|
||||
# shape_signature: The parameter definitions and input/output types for a command signature.
|
||||
$env.config.color_config.shape_signature
|
||||
|
||||
# shape_keyword: Not current used
|
||||
$env.config.color_config.shape_keyword
|
||||
|
||||
# shape_closure: Styles the brackets and arguments of a closure.
|
||||
$env.config.color_config.shape_closure
|
||||
|
||||
# shape_direction: The redirection symbols such as `o>`, `error>`, `e>|`, etc.
|
||||
$env.config.color_config.shape_redirection
|
||||
|
||||
# shape_flag: Flags and switches to internal and custom-commands. Only the `--flag` (`-f`) portion
|
||||
# is styled. The argument to a flag will be styled using its own shape.
|
||||
$env.config.color_config.shape_flag
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
# color.config.<type>
|
||||
# *Values* of a particular *type* can be styled differently than the *shape*.
|
||||
# Note that the style is applied only when this type is displayed in *structured* data (list,
|
||||
# record, or table). It is not currently applied to basic raw values.
|
||||
#
|
||||
# Note that some types are rarely or never seen in a context in which styling would be applied.
|
||||
# For example, a cell-path *value* is unlikely to (but can) appear in a list, record, or table.
|
||||
#
|
||||
# Tip: In addition to the styles above (fg, bg, attr), types typically accept a closure which can
|
||||
# dynamically change the style based on the *value*. For instance, the themes in the nu_scripts
|
||||
# repository will style filesizes difference in an `ls` (or other table) differently depending on
|
||||
# their magnitude.
|
||||
|
||||
# Simple examples:
|
||||
|
||||
# bool: A boolean value
|
||||
$env.config.color_config.bool = {||
|
||||
if $in {
|
||||
{
|
||||
bg: 'light_green'
|
||||
fg: 'white'
|
||||
attr: 'b'
|
||||
}
|
||||
} else {
|
||||
{
|
||||
bg: 'yellow'
|
||||
fg: 'black'
|
||||
attr: 'b'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# int: An integer value
|
||||
$env.config.color_config.int = {||
|
||||
if $in == 42 { 'green' } else { 'red' }
|
||||
}
|
||||
|
||||
# Additional type values (without examples):
|
||||
$env.config.color_config.string # String
|
||||
$env.config.color_config.float # Float value
|
||||
$env.config.color_config.glob # Glob value (must be declared)
|
||||
$env.config.color_config.binary # Binary value
|
||||
$env.config.color_config.custom # Custom value (often from a plugin)
|
||||
$env.config.color_config.nothing # Not used, since a null is not displayed
|
||||
$env.config.color_config.date # datetime value
|
||||
$env.config.color_config.filesize # filesize value
|
||||
$env.config.color_config.list # Not currently used. Lists are displayed using their
|
||||
# members' styles
|
||||
$env.config.color_config.record # Not currently used. Records are displayed using their
|
||||
# member's styles
|
||||
$env.config.color_config.duration # Duration type
|
||||
$env.config.color_config.range # Range value
|
||||
$env.config.color_config.cell-path # Cell-path value
|
||||
$env.config.color_config.closure # Not currently used
|
||||
$env.config.color_config.block # Not currently used
|
||||
|
||||
# Additional UI elements
|
||||
# hints: The (usually dimmed) style in which completion hints are displayed
|
||||
$env.config.color_config.hints
|
||||
|
||||
# search_result: The style applied to `find` search results
|
||||
$env.config.color_config.search_result
|
||||
|
||||
# header: The column names in a table header
|
||||
$env.config.color_config.header
|
||||
|
||||
# separator: Used for table/list/record borders
|
||||
$env.config.color_config.separator
|
||||
|
||||
# row_index: The `#` or `index` column of a table or list
|
||||
$env.config.color_config.row_index
|
||||
|
||||
# empty: This style is applied to empty/missing values in a table. However, since the ❎
|
||||
# emoji is used for this purpose, there is limited styling that can be applied.
|
||||
$env.config.color_config.empty
|
||||
|
||||
# leading_trailing_space_bg: When a string value inside structured data has leading or trailing
|
||||
# whitespace, that whitespace will be displayed using this style.
|
||||
# Use { attr: n } to disable.
|
||||
$env.config.color_config.leading_trailing_space_bg = { bg: 'red' }
|
||||
|
||||
# ------------------------
|
||||
# `explore` command colors
|
||||
# ------------------------
|
||||
# Configure the UI colors of the `explore` command
|
||||
# Allowed values are the same as for the `color_config` options above.
|
||||
# Example:
|
||||
$env.config.explore = {
|
||||
status_bar_background: { fg: "#1D1F21", bg: "#C4C9C6" },
|
||||
command_bar_text: { fg: "#C4C9C6" },
|
||||
highlight: { fg: "black", bg: "yellow" },
|
||||
status: {
|
||||
error: { fg: "white", bg: "red" },
|
||||
warn: {}
|
||||
info: {}
|
||||
},
|
||||
selected_cell: { bg: light_blue },
|
||||
}
|
135
crates/nu-utils/src/default_files/sample_env.nu
Normal file
135
crates/nu-utils/src/default_files/sample_env.nu
Normal file
@ -0,0 +1,135 @@
|
||||
# Sample Nushell Environment Config File
|
||||
#
|
||||
# Environment variables are usually configured in `env.nu`. Nushell
|
||||
# sets sensible defaults for many environment variables, so the user's
|
||||
# `env.nu` only needs to override these defaults if desired.
|
||||
#
|
||||
# This file serves as simple "in-shell" documentation for these
|
||||
# settings, or you can view a more complete discussion online at:
|
||||
# https://nushell.sh/book/configuration
|
||||
#
|
||||
# You can pretty-print and page this file using:
|
||||
# config env --sample | nu-highlight | less -R
|
||||
|
||||
# PROMPT_*
|
||||
# --------
|
||||
# Prompt configuration
|
||||
# PROMPT_ variables accept either a string or a closure that returns a string
|
||||
|
||||
# PROMPT_COMMAND
|
||||
# --------------
|
||||
# Defines the primary prompt. Note that the PROMPT_INDICATOR (below) is appended to this value.
|
||||
# Simple example - Static string:
|
||||
$env.PROMPT_COMMAND = "Nushell"
|
||||
# Simple example - Dynamic closure displaying the path:
|
||||
$env.PROMPT_COMMAND = {|| pwd}
|
||||
|
||||
# PROMPT_INDICATOR*
|
||||
# -----------------
|
||||
# The prompt indicators are environmental variables that represent
|
||||
# the state of the prompt. The specified character(s) will appear
|
||||
# immediately following the PROMPT_COMMAND
|
||||
|
||||
# When in Emacs mode (default):
|
||||
$env.PROMPT_INDICATOR = "> "
|
||||
|
||||
# When in normal vi mode:
|
||||
$env.PROMPT_INDICATOR_VI_NORMAL = "> "
|
||||
# When in vi insert-mode:
|
||||
$env.PROMPT_INDICATOR_VI_INSERT = ": "
|
||||
|
||||
# When a commandline extends across multiple lines:
|
||||
$env.PROMPT_MULTILINE_INDICATOR = "::: "
|
||||
|
||||
# TRANSIENT_PROMPT_*
|
||||
# ------------------
|
||||
# Allows a different prompt to be shown after a command has been executed. This
|
||||
# can be useful if you have a 2-line prompt. Instead of each previously-entered
|
||||
# command taking up at least 2 lines, the transient prompt can condense it to a
|
||||
# shorter version. The following example shows a rocket emoji before each
|
||||
# previously-entered command:
|
||||
$env.TRANSIENT_PROMPT_COMMAND = "🚀 "
|
||||
$env.TRANSIENT_PROMPT_INDICATOR = ""
|
||||
$env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = ""
|
||||
$env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = ""
|
||||
# Tip: Removing the transient multiline indicator and right-prompt can simplify
|
||||
# copying from the terminal
|
||||
$env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = ""
|
||||
$env.TRANSIENT_PROMPT_COMMAND_RIGHT = ""
|
||||
|
||||
# ENV_CONVERSIONS
|
||||
# ---------------
|
||||
# Certain variables, such as those containing multiple paths, are often stored as a
|
||||
# colon-separated string in other shells. Nushell can convert these automatically to a
|
||||
# more convenient Nushell list. The ENV_CONVERSIONS variable specifies how environment
|
||||
# variables are:
|
||||
# - converted from a string to a value on Nushell startup (from_string)
|
||||
# - converted from a value back to a string when running external commands (to_string)
|
||||
#
|
||||
# Note: The OS Path variable is automatically converted before env.nu loads, so it can
|
||||
# be treated a list in this file.
|
||||
#
|
||||
# Note: Environment variables are not case-sensitive, so the following will work
|
||||
# for both Windows and Unix-like platforms.
|
||||
#
|
||||
# By default, the internal conversion looks something like the following, so there
|
||||
# is no need to add this in your actual env.nu:
|
||||
$env.ENV_CONVERSIONS = {
|
||||
"Path": {
|
||||
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
|
||||
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
|
||||
}
|
||||
}
|
||||
|
||||
# Here's an example converts the XDG_DATA_DIRS variable to and from a list:
|
||||
$env.ENV_CONVERSIONS = $env.ENV_CONVERSIONS | merge {
|
||||
"XDG_DATA_DIRS": {
|
||||
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
|
||||
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
|
||||
}
|
||||
}
|
||||
#
|
||||
# Other common directory-lists for conversion: TERMINFO_DIRS.
|
||||
# Note that other variable conversions take place after `config.nu` is loaded.
|
||||
|
||||
# NU_LIB_DIRS
|
||||
# -----------
|
||||
# Directories in this environment variable are searched by the
|
||||
# `use` and `source` commands.
|
||||
#
|
||||
# By default, the `scripts` subdirectory of the default configuration
|
||||
# directory is included:
|
||||
$env.NU_LIB_DIRS = [
|
||||
($nu.default-config-dir | path join 'scripts') # add <nushell-config-dir>/scripts
|
||||
($nu.data-dir | path join 'completions') # default home for nushell completions
|
||||
]
|
||||
# You can replace (override) or append to this list:
|
||||
$env.NU_LIB_DIRS ++= ($nu.default-config-dir | path join 'modules')
|
||||
|
||||
# NU_PLUGIN_DIRS
|
||||
# --------------
|
||||
# Directories to search for plugin binaries when calling register.
|
||||
|
||||
# By default, the `plugins` subdirectory of the default configuration
|
||||
# directory is included:
|
||||
$env.NU_PLUGIN_DIRS = [
|
||||
($nu.default-config-dir | path join 'plugins') # add <nushell-config-dir>/plugins
|
||||
]
|
||||
|
||||
# Appending to the OS path is a common configuration task.
|
||||
# Because of the previous ENV_CONVERSIONS (performed internally
|
||||
# before your env.nu loads), the path variable is a list that can
|
||||
# be appended to using, for example:
|
||||
$env.path ++= "~/.local/bin"
|
||||
|
||||
# Or prepend using
|
||||
$env.path = "~/.local/bin" ++ $env.path
|
||||
|
||||
# The `path add` function from the Standard Library also provides
|
||||
# a convenience method for prepending to the path:
|
||||
use std/util "path add"
|
||||
path add "~/.local/bin"
|
||||
path add ($env.CARGO_HOME | path join "bin")
|
||||
|
||||
# You can remove duplicate directories from the path using:
|
||||
$env.PATH = ($env.PATH | uniq)
|
19
crates/nu-utils/src/default_files/scaffold_config.nu
Normal file
19
crates/nu-utils/src/default_files/scaffold_config.nu
Normal file
@ -0,0 +1,19 @@
|
||||
# config.nu
|
||||
#
|
||||
# This file is used to override default Nushell settings, define
|
||||
# (or import) custom commands, or run any other startup tasks.
|
||||
# See https://www.nushell.sh/book/configuration.html
|
||||
#
|
||||
# This file is loaded after env.nu and before login.nu
|
||||
#
|
||||
# You can open this file in your default editor using:
|
||||
# config nu
|
||||
#
|
||||
# To pretty-print a sample config.nu with documentation, run:
|
||||
# config nu --sample | nu-highlight | less -R
|
||||
#
|
||||
# To pretty-print the default configuration values, run:
|
||||
# config nu --default | nu-highlight | less -R
|
||||
#
|
||||
# You can remove these comments if you want or leave
|
||||
# them for future reference.
|
18
crates/nu-utils/src/default_files/scaffold_env.nu
Normal file
18
crates/nu-utils/src/default_files/scaffold_env.nu
Normal file
@ -0,0 +1,18 @@
|
||||
# env.nu
|
||||
#
|
||||
# This file is typically used to add or override environment variables.
|
||||
# See https://www.nushell.sh/book/configuration.html
|
||||
#
|
||||
# This file is loaded before config.nu and login.nu
|
||||
#
|
||||
# You can open this file in your default editor using:
|
||||
# config env
|
||||
#
|
||||
# To pretty-print a sample env.nu with documentation, run:
|
||||
# config env --sample | nu-highlight | less -R
|
||||
#
|
||||
# To pretty-print the default environment values, run:
|
||||
# config env --default | nu-highlight | less -R
|
||||
#
|
||||
# You can remove these comments if you want or leave
|
||||
# them for future reference.
|
@ -10,8 +10,9 @@ pub mod utils;
|
||||
|
||||
pub use locale::get_system_locale;
|
||||
pub use utils::{
|
||||
enable_vt_processing, get_default_config, get_default_env, get_ls_colors,
|
||||
stderr_write_all_and_flush, stdout_write_all_and_flush,
|
||||
enable_vt_processing, get_default_config, get_default_env, get_ls_colors, get_sample_config,
|
||||
get_sample_env, get_scaffold_config, get_scaffold_env, stderr_write_all_and_flush,
|
||||
stdout_write_all_and_flush,
|
||||
};
|
||||
|
||||
pub use casing::IgnoreCaseExt;
|
||||
|
@ -1,899 +0,0 @@
|
||||
# Nushell Config File
|
||||
#
|
||||
# version = "0.100.1"
|
||||
|
||||
# For more information on defining custom themes, see
|
||||
# https://www.nushell.sh/book/coloring_and_theming.html
|
||||
# And here is the theme collection
|
||||
# https://github.com/nushell/nu_scripts/tree/main/themes
|
||||
let dark_theme = {
|
||||
# color for nushell primitives
|
||||
separator: white
|
||||
leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
|
||||
header: green_bold
|
||||
empty: blue
|
||||
# Closures can be used to choose colors for specific values.
|
||||
# The value (in this case, a bool) is piped into the closure.
|
||||
# eg) {|| if $in { 'light_cyan' } else { 'light_gray' } }
|
||||
bool: light_cyan
|
||||
int: white
|
||||
filesize: cyan
|
||||
duration: white
|
||||
date: purple
|
||||
range: white
|
||||
float: white
|
||||
string: white
|
||||
nothing: white
|
||||
binary: white
|
||||
cell-path: white
|
||||
row_index: green_bold
|
||||
record: white
|
||||
list: white
|
||||
block: white
|
||||
hints: dark_gray
|
||||
search_result: { bg: red fg: white }
|
||||
shape_and: purple_bold
|
||||
shape_binary: purple_bold
|
||||
shape_block: blue_bold
|
||||
shape_bool: light_cyan
|
||||
shape_closure: green_bold
|
||||
shape_custom: green
|
||||
shape_datetime: cyan_bold
|
||||
shape_directory: cyan
|
||||
shape_external: cyan
|
||||
shape_externalarg: green_bold
|
||||
shape_external_resolved: light_yellow_bold
|
||||
shape_filepath: cyan
|
||||
shape_flag: blue_bold
|
||||
shape_float: purple_bold
|
||||
# shapes are used to change the cli syntax highlighting
|
||||
shape_garbage: { fg: white bg: red attr: b }
|
||||
shape_glob_interpolation: cyan_bold
|
||||
shape_globpattern: cyan_bold
|
||||
shape_int: purple_bold
|
||||
shape_internalcall: cyan_bold
|
||||
shape_keyword: cyan_bold
|
||||
shape_list: cyan_bold
|
||||
shape_literal: blue
|
||||
shape_match_pattern: green
|
||||
shape_matching_brackets: { attr: u }
|
||||
shape_nothing: light_cyan
|
||||
shape_operator: yellow
|
||||
shape_or: purple_bold
|
||||
shape_pipe: purple_bold
|
||||
shape_range: yellow_bold
|
||||
shape_record: cyan_bold
|
||||
shape_redirection: purple_bold
|
||||
shape_signature: green_bold
|
||||
shape_string: green
|
||||
shape_string_interpolation: cyan_bold
|
||||
shape_table: blue_bold
|
||||
shape_variable: purple
|
||||
shape_vardecl: purple
|
||||
shape_raw_string: light_purple
|
||||
}
|
||||
|
||||
let light_theme = {
|
||||
# color for nushell primitives
|
||||
separator: dark_gray
|
||||
leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
|
||||
header: green_bold
|
||||
empty: blue
|
||||
# Closures can be used to choose colors for specific values.
|
||||
# The value (in this case, a bool) is piped into the closure.
|
||||
# eg) {|| if $in { 'dark_cyan' } else { 'dark_gray' } }
|
||||
bool: dark_cyan
|
||||
int: dark_gray
|
||||
filesize: cyan_bold
|
||||
duration: dark_gray
|
||||
date: purple
|
||||
range: dark_gray
|
||||
float: dark_gray
|
||||
string: dark_gray
|
||||
nothing: dark_gray
|
||||
binary: dark_gray
|
||||
cell-path: dark_gray
|
||||
row_index: green_bold
|
||||
record: dark_gray
|
||||
list: dark_gray
|
||||
block: dark_gray
|
||||
hints: dark_gray
|
||||
search_result: { fg: white bg: red }
|
||||
shape_and: purple_bold
|
||||
shape_binary: purple_bold
|
||||
shape_block: blue_bold
|
||||
shape_bool: light_cyan
|
||||
shape_closure: green_bold
|
||||
shape_custom: green
|
||||
shape_datetime: cyan_bold
|
||||
shape_directory: cyan
|
||||
shape_external: cyan
|
||||
shape_externalarg: green_bold
|
||||
shape_external_resolved: light_purple_bold
|
||||
shape_filepath: cyan
|
||||
shape_flag: blue_bold
|
||||
shape_float: purple_bold
|
||||
# shapes are used to change the cli syntax highlighting
|
||||
shape_garbage: { fg: white bg: red attr: b }
|
||||
shape_glob_interpolation: cyan_bold
|
||||
shape_globpattern: cyan_bold
|
||||
shape_int: purple_bold
|
||||
shape_internalcall: cyan_bold
|
||||
shape_keyword: cyan_bold
|
||||
shape_list: cyan_bold
|
||||
shape_literal: blue
|
||||
shape_match_pattern: green
|
||||
shape_matching_brackets: { attr: u }
|
||||
shape_nothing: light_cyan
|
||||
shape_operator: yellow
|
||||
shape_or: purple_bold
|
||||
shape_pipe: purple_bold
|
||||
shape_range: yellow_bold
|
||||
shape_record: cyan_bold
|
||||
shape_redirection: purple_bold
|
||||
shape_signature: green_bold
|
||||
shape_string: green
|
||||
shape_string_interpolation: cyan_bold
|
||||
shape_table: blue_bold
|
||||
shape_variable: purple
|
||||
shape_vardecl: purple
|
||||
shape_raw_string: light_purple
|
||||
}
|
||||
|
||||
# External completer example
|
||||
# let carapace_completer = {|spans|
|
||||
# carapace $spans.0 nushell ...$spans | from json
|
||||
# }
|
||||
|
||||
# The default config record. This is where much of your global configuration is setup.
|
||||
$env.config = {
|
||||
show_banner: true # true or false to enable or disable the welcome banner at startup
|
||||
|
||||
ls: {
|
||||
use_ls_colors: true # use the LS_COLORS environment variable to colorize output
|
||||
clickable_links: true # enable or disable clickable links. Your terminal has to support links.
|
||||
}
|
||||
|
||||
rm: {
|
||||
always_trash: false # always act as if -t was given. Can be overridden with -p
|
||||
}
|
||||
|
||||
table: {
|
||||
mode: rounded # basic, compact, compact_double, light, thin, with_love, rounded, reinforced, heavy, none, other
|
||||
index_mode: always # "always" show indexes, "never" show indexes, "auto" = show indexes when a table has "index" column
|
||||
show_empty: true # show 'empty list' and 'empty record' placeholders for command output
|
||||
padding: { left: 1, right: 1 } # a left right padding of each column in a table
|
||||
trim: {
|
||||
methodology: wrapping # wrapping or truncating
|
||||
wrapping_try_keep_words: true # A strategy used by the 'wrapping' methodology
|
||||
truncating_suffix: "..." # A suffix used by the 'truncating' methodology
|
||||
}
|
||||
header_on_separator: false # show header text on separator/border line
|
||||
footer_inheritance: false # render footer in parent table if child is big enough (extended table option)
|
||||
# abbreviated_row_count: 10 # limit data rows from top and bottom after reaching a set point
|
||||
}
|
||||
|
||||
error_style: "fancy" # "fancy" or "plain" for screen reader-friendly error messages
|
||||
|
||||
# Whether an error message should be printed if an error of a certain kind is triggered.
|
||||
display_errors: {
|
||||
exit_code: false # assume the external command prints an error message
|
||||
# Core dump errors are always printed, and SIGPIPE never triggers an error.
|
||||
# The setting below controls message printing for termination by all other signals.
|
||||
termination_signal: true
|
||||
}
|
||||
|
||||
# datetime_format determines what a datetime rendered in the shell would look like.
|
||||
# Behavior without this configuration point will be to "humanize" the datetime display,
|
||||
# showing something like "a day ago."
|
||||
datetime_format: {
|
||||
# normal: '%a, %d %b %Y %H:%M:%S %z' # shows up in displays of variables or other datetime's outside of tables
|
||||
# table: '%m/%d/%y %I:%M:%S%p' # generally shows up in tabular outputs such as ls. commenting this out will change it to the default human readable datetime format
|
||||
}
|
||||
|
||||
explore: {
|
||||
status_bar_background: { fg: "#1D1F21", bg: "#C4C9C6" },
|
||||
command_bar_text: { fg: "#C4C9C6" },
|
||||
highlight: { fg: "black", bg: "yellow" },
|
||||
status: {
|
||||
error: { fg: "white", bg: "red" },
|
||||
warn: {}
|
||||
info: {}
|
||||
},
|
||||
selected_cell: { bg: light_blue },
|
||||
}
|
||||
|
||||
history: {
|
||||
max_size: 100_000 # Session has to be reloaded for this to take effect
|
||||
sync_on_enter: true # Enable to share history between multiple sessions, else you have to close the session to write history to file
|
||||
file_format: "plaintext" # "sqlite" or "plaintext"
|
||||
isolation: false # only available with sqlite file_format. true enables history isolation, false disables it. true will allow the history to be isolated to the current session using up/down arrows. false will allow the history to be shared across all sessions.
|
||||
}
|
||||
|
||||
completions: {
|
||||
case_sensitive: false # set to true to enable case-sensitive completions
|
||||
quick: true # set this to false to prevent auto-selecting completions when only one remains
|
||||
partial: true # set this to false to prevent partial filling of the prompt
|
||||
algorithm: "prefix" # prefix or fuzzy
|
||||
sort: "smart" # "smart" (alphabetical for prefix matching, fuzzy score for fuzzy matching) or "alphabetical"
|
||||
external: {
|
||||
enable: true # set to false to prevent nushell looking into $env.PATH to find more suggestions, `false` recommended for WSL users as this look up may be very slow
|
||||
max_results: 100 # setting it lower can improve completion performance at the cost of omitting some options
|
||||
completer: null # check 'carapace_completer' above as an example
|
||||
}
|
||||
use_ls_colors: true # set this to true to enable file/path/directory completions using LS_COLORS
|
||||
}
|
||||
|
||||
filesize: {
|
||||
metric: false # true => KB, MB, GB (ISO standard), false => KiB, MiB, GiB (Windows standard)
|
||||
format: "auto" # b, kb, kib, mb, mib, gb, gib, tb, tib, pb, pib, eb, eib, auto
|
||||
}
|
||||
|
||||
cursor_shape: {
|
||||
emacs: line # block, underscore, line, blink_block, blink_underscore, blink_line, inherit to skip setting cursor shape (line is the default)
|
||||
vi_insert: block # block, underscore, line, blink_block, blink_underscore, blink_line, inherit to skip setting cursor shape (block is the default)
|
||||
vi_normal: underscore # block, underscore, line, blink_block, blink_underscore, blink_line, inherit to skip setting cursor shape (underscore is the default)
|
||||
}
|
||||
|
||||
color_config: $dark_theme # if you want a more interesting theme, you can replace the empty record with `$dark_theme`, `$light_theme` or another custom record
|
||||
footer_mode: 25 # always, never, number_of_rows, auto
|
||||
float_precision: 2 # the precision for displaying floats in tables
|
||||
buffer_editor: null # command that will be used to edit the current line buffer with ctrl+o, if unset fallback to $env.VISUAL and $env.EDITOR
|
||||
use_ansi_coloring: true
|
||||
bracketed_paste: true # enable bracketed paste, currently useless on windows
|
||||
edit_mode: emacs # emacs, vi
|
||||
shell_integration: {
|
||||
# osc2 abbreviates the path if in the home_dir, sets the tab/window title, shows the running command in the tab/window title
|
||||
osc2: true
|
||||
# osc7 is a way to communicate the path to the terminal, this is helpful for spawning new tabs in the same directory
|
||||
osc7: true
|
||||
# osc8 is also implemented as the deprecated setting ls.show_clickable_links, it shows clickable links in ls output if your terminal supports it. show_clickable_links is deprecated in favor of osc8
|
||||
osc8: true
|
||||
# osc9_9 is from ConEmu and is starting to get wider support. It's similar to osc7 in that it communicates the path to the terminal
|
||||
osc9_9: false
|
||||
# osc133 is several escapes invented by Final Term which include the supported ones below.
|
||||
# 133;A - Mark prompt start
|
||||
# 133;B - Mark prompt end
|
||||
# 133;C - Mark pre-execution
|
||||
# 133;D;exit - Mark execution finished with exit code
|
||||
# This is used to enable terminals to know where the prompt is, the command is, where the command finishes, and where the output of the command is
|
||||
osc133: true
|
||||
# osc633 is closely related to osc133 but only exists in visual studio code (vscode) and supports their shell integration features
|
||||
# 633;A - Mark prompt start
|
||||
# 633;B - Mark prompt end
|
||||
# 633;C - Mark pre-execution
|
||||
# 633;D;exit - Mark execution finished with exit code
|
||||
# 633;E - Explicitly set the command line with an optional nonce
|
||||
# 633;P;Cwd=<path> - Mark the current working directory and communicate it to the terminal
|
||||
# and also helps with the run recent menu in vscode
|
||||
osc633: true
|
||||
# reset_application_mode is escape \x1b[?1l and was added to help ssh work better
|
||||
reset_application_mode: true
|
||||
}
|
||||
render_right_prompt_on_last_line: false # true or false to enable or disable right prompt to be rendered on last line of the prompt.
|
||||
use_kitty_protocol: false # enables keyboard enhancement protocol implemented by kitty console, only if your terminal support this.
|
||||
highlight_resolved_externals: false # true enables highlighting of external commands in the repl resolved by which.
|
||||
recursion_limit: 50 # the maximum number of times nushell allows recursion before stopping it
|
||||
|
||||
plugins: {} # Per-plugin configuration. See https://www.nushell.sh/contributor-book/plugins.html#configuration.
|
||||
|
||||
plugin_gc: {
|
||||
# Configuration for plugin garbage collection
|
||||
default: {
|
||||
enabled: true # true to enable stopping of inactive plugins
|
||||
stop_after: 10sec # how long to wait after a plugin is inactive to stop it
|
||||
}
|
||||
plugins: {
|
||||
# alternate configuration for specific plugins, by name, for example:
|
||||
#
|
||||
# gstat: {
|
||||
# enabled: false
|
||||
# }
|
||||
}
|
||||
}
|
||||
|
||||
hooks: {
|
||||
pre_prompt: [{ null }] # run before the prompt is shown
|
||||
pre_execution: [{ null }] # run before the repl input is run
|
||||
env_change: {
|
||||
PWD: [{|before, after| null }] # run if the PWD environment is different since the last repl input
|
||||
}
|
||||
display_output: "if (term size).columns >= 100 { table -e } else { table }" # run to display the output of a pipeline
|
||||
command_not_found: { null } # return an error message when a command is not found
|
||||
}
|
||||
|
||||
menus: [
|
||||
# Configuration for default nushell menus
|
||||
# Note the lack of source parameter
|
||||
{
|
||||
name: completion_menu
|
||||
only_buffer_difference: false
|
||||
marker: "| "
|
||||
type: {
|
||||
layout: columnar
|
||||
columns: 4
|
||||
col_width: 20 # Optional value. If missing all the screen width is used to calculate column width
|
||||
col_padding: 2
|
||||
}
|
||||
style: {
|
||||
text: green
|
||||
selected_text: { attr: r }
|
||||
description_text: yellow
|
||||
match_text: { attr: u }
|
||||
selected_match_text: { attr: ur }
|
||||
}
|
||||
}
|
||||
{
|
||||
name: ide_completion_menu
|
||||
only_buffer_difference: false
|
||||
marker: "| "
|
||||
type: {
|
||||
layout: ide
|
||||
min_completion_width: 0,
|
||||
max_completion_width: 50,
|
||||
max_completion_height: 10, # will be limited by the available lines in the terminal
|
||||
padding: 0,
|
||||
border: true,
|
||||
cursor_offset: 0,
|
||||
description_mode: "prefer_right"
|
||||
min_description_width: 0
|
||||
max_description_width: 50
|
||||
max_description_height: 10
|
||||
description_offset: 1
|
||||
# If true, the cursor pos will be corrected, so the suggestions match up with the typed text
|
||||
#
|
||||
# C:\> str
|
||||
# str join
|
||||
# str trim
|
||||
# str split
|
||||
correct_cursor_pos: false
|
||||
}
|
||||
style: {
|
||||
text: green
|
||||
selected_text: { attr: r }
|
||||
description_text: yellow
|
||||
match_text: { attr: u }
|
||||
selected_match_text: { attr: ur }
|
||||
}
|
||||
}
|
||||
{
|
||||
name: history_menu
|
||||
only_buffer_difference: true
|
||||
marker: "? "
|
||||
type: {
|
||||
layout: list
|
||||
page_size: 10
|
||||
}
|
||||
style: {
|
||||
text: green
|
||||
selected_text: green_reverse
|
||||
description_text: yellow
|
||||
}
|
||||
}
|
||||
{
|
||||
name: help_menu
|
||||
only_buffer_difference: true
|
||||
marker: "? "
|
||||
type: {
|
||||
layout: description
|
||||
columns: 4
|
||||
col_width: 20 # Optional value. If missing all the screen width is used to calculate column width
|
||||
col_padding: 2
|
||||
selection_rows: 4
|
||||
description_rows: 10
|
||||
}
|
||||
style: {
|
||||
text: green
|
||||
selected_text: green_reverse
|
||||
description_text: yellow
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
keybindings: [
|
||||
{
|
||||
name: completion_menu
|
||||
modifier: none
|
||||
keycode: tab
|
||||
mode: [emacs vi_normal vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menu name: completion_menu }
|
||||
{ send: menunext }
|
||||
{ edit: complete }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: completion_previous_menu
|
||||
modifier: shift
|
||||
keycode: backtab
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: menuprevious }
|
||||
}
|
||||
{
|
||||
name: ide_completion_menu
|
||||
modifier: control
|
||||
keycode: space
|
||||
mode: [emacs vi_normal vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menu name: ide_completion_menu }
|
||||
{ send: menunext }
|
||||
{ edit: complete }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: history_menu
|
||||
modifier: control
|
||||
keycode: char_r
|
||||
mode: [emacs, vi_insert, vi_normal]
|
||||
event: { send: menu name: history_menu }
|
||||
}
|
||||
{
|
||||
name: help_menu
|
||||
modifier: none
|
||||
keycode: f1
|
||||
mode: [emacs, vi_insert, vi_normal]
|
||||
event: { send: menu name: help_menu }
|
||||
}
|
||||
{
|
||||
name: next_page_menu
|
||||
modifier: control
|
||||
keycode: char_x
|
||||
mode: emacs
|
||||
event: { send: menupagenext }
|
||||
}
|
||||
{
|
||||
name: undo_or_previous_page_menu
|
||||
modifier: control
|
||||
keycode: char_z
|
||||
mode: emacs
|
||||
event: {
|
||||
until: [
|
||||
{ send: menupageprevious }
|
||||
{ edit: undo }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: escape
|
||||
modifier: none
|
||||
keycode: escape
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: esc } # NOTE: does not appear to work
|
||||
}
|
||||
{
|
||||
name: cancel_command
|
||||
modifier: control
|
||||
keycode: char_c
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: ctrlc }
|
||||
}
|
||||
{
|
||||
name: quit_shell
|
||||
modifier: control
|
||||
keycode: char_d
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: ctrld }
|
||||
}
|
||||
{
|
||||
name: clear_screen
|
||||
modifier: control
|
||||
keycode: char_l
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: clearscreen }
|
||||
}
|
||||
{
|
||||
name: search_history
|
||||
modifier: control
|
||||
keycode: char_q
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: searchhistory }
|
||||
}
|
||||
{
|
||||
name: open_command_editor
|
||||
modifier: control
|
||||
keycode: char_o
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { send: openeditor }
|
||||
}
|
||||
{
|
||||
name: move_up
|
||||
modifier: none
|
||||
keycode: up
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menuup }
|
||||
{ send: up }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_down
|
||||
modifier: none
|
||||
keycode: down
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menudown }
|
||||
{ send: down }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_left
|
||||
modifier: none
|
||||
keycode: left
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menuleft }
|
||||
{ send: left }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_right_or_take_history_hint
|
||||
modifier: none
|
||||
keycode: right
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintcomplete }
|
||||
{ send: menuright }
|
||||
{ send: right }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_one_word_left
|
||||
modifier: control
|
||||
keycode: left
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { edit: movewordleft }
|
||||
}
|
||||
{
|
||||
name: move_one_word_right_or_take_history_hint
|
||||
modifier: control
|
||||
keycode: right
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintwordcomplete }
|
||||
{ edit: movewordright }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_to_line_start
|
||||
modifier: none
|
||||
keycode: home
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { edit: movetolinestart }
|
||||
}
|
||||
{
|
||||
name: move_to_line_start
|
||||
modifier: control
|
||||
keycode: char_a
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { edit: movetolinestart }
|
||||
}
|
||||
{
|
||||
name: move_to_line_end_or_take_history_hint
|
||||
modifier: none
|
||||
keycode: end
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintcomplete }
|
||||
{ edit: movetolineend }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_to_line_end_or_take_history_hint
|
||||
modifier: control
|
||||
keycode: char_e
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintcomplete }
|
||||
{ edit: movetolineend }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_to_line_start
|
||||
modifier: control
|
||||
keycode: home
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { edit: movetolinestart }
|
||||
}
|
||||
{
|
||||
name: move_to_line_end
|
||||
modifier: control
|
||||
keycode: end
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: { edit: movetolineend }
|
||||
}
|
||||
{
|
||||
name: move_down
|
||||
modifier: control
|
||||
keycode: char_n
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menudown }
|
||||
{ send: down }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_up
|
||||
modifier: control
|
||||
keycode: char_p
|
||||
mode: [emacs, vi_normal, vi_insert]
|
||||
event: {
|
||||
until: [
|
||||
{ send: menuup }
|
||||
{ send: up }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: delete_one_character_backward
|
||||
modifier: none
|
||||
keycode: backspace
|
||||
mode: [emacs, vi_insert]
|
||||
event: { edit: backspace }
|
||||
}
|
||||
{
|
||||
name: delete_one_word_backward
|
||||
modifier: control
|
||||
keycode: backspace
|
||||
mode: [emacs, vi_insert]
|
||||
event: { edit: backspaceword }
|
||||
}
|
||||
{
|
||||
name: delete_one_character_forward
|
||||
modifier: none
|
||||
keycode: delete
|
||||
mode: [emacs, vi_insert]
|
||||
event: { edit: delete }
|
||||
}
|
||||
{
|
||||
name: delete_one_character_forward
|
||||
modifier: control
|
||||
keycode: delete
|
||||
mode: [emacs, vi_insert]
|
||||
event: { edit: delete }
|
||||
}
|
||||
{
|
||||
name: delete_one_character_backward
|
||||
modifier: control
|
||||
keycode: char_h
|
||||
mode: [emacs, vi_insert]
|
||||
event: { edit: backspace }
|
||||
}
|
||||
{
|
||||
name: delete_one_word_backward
|
||||
modifier: control
|
||||
keycode: char_w
|
||||
mode: [emacs, vi_insert]
|
||||
event: { edit: backspaceword }
|
||||
}
|
||||
{
|
||||
name: move_left
|
||||
modifier: none
|
||||
keycode: backspace
|
||||
mode: vi_normal
|
||||
event: { edit: moveleft }
|
||||
}
|
||||
{
|
||||
name: newline_or_run_command
|
||||
modifier: none
|
||||
keycode: enter
|
||||
mode: emacs
|
||||
event: { send: enter }
|
||||
}
|
||||
{
|
||||
name: move_left
|
||||
modifier: control
|
||||
keycode: char_b
|
||||
mode: emacs
|
||||
event: {
|
||||
until: [
|
||||
{ send: menuleft }
|
||||
{ send: left }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_right_or_take_history_hint
|
||||
modifier: control
|
||||
keycode: char_f
|
||||
mode: emacs
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintcomplete }
|
||||
{ send: menuright }
|
||||
{ send: right }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: redo_change
|
||||
modifier: control
|
||||
keycode: char_g
|
||||
mode: emacs
|
||||
event: { edit: redo }
|
||||
}
|
||||
{
|
||||
name: undo_change
|
||||
modifier: control
|
||||
keycode: char_z
|
||||
mode: emacs
|
||||
event: { edit: undo }
|
||||
}
|
||||
{
|
||||
name: paste_before
|
||||
modifier: control
|
||||
keycode: char_y
|
||||
mode: emacs
|
||||
event: { edit: pastecutbufferbefore }
|
||||
}
|
||||
{
|
||||
name: cut_word_left
|
||||
modifier: control
|
||||
keycode: char_w
|
||||
mode: emacs
|
||||
event: { edit: cutwordleft }
|
||||
}
|
||||
{
|
||||
name: cut_line_to_end
|
||||
modifier: control
|
||||
keycode: char_k
|
||||
mode: emacs
|
||||
event: { edit: cuttolineend }
|
||||
}
|
||||
{
|
||||
name: cut_line_from_start
|
||||
modifier: control
|
||||
keycode: char_u
|
||||
mode: emacs
|
||||
event: { edit: cutfromstart }
|
||||
}
|
||||
{
|
||||
name: swap_graphemes
|
||||
modifier: control
|
||||
keycode: char_t
|
||||
mode: emacs
|
||||
event: { edit: swapgraphemes }
|
||||
}
|
||||
{
|
||||
name: move_one_word_left
|
||||
modifier: alt
|
||||
keycode: left
|
||||
mode: emacs
|
||||
event: { edit: movewordleft }
|
||||
}
|
||||
{
|
||||
name: move_one_word_right_or_take_history_hint
|
||||
modifier: alt
|
||||
keycode: right
|
||||
mode: emacs
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintwordcomplete }
|
||||
{ edit: movewordright }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: move_one_word_left
|
||||
modifier: alt
|
||||
keycode: char_b
|
||||
mode: emacs
|
||||
event: { edit: movewordleft }
|
||||
}
|
||||
{
|
||||
name: move_one_word_right_or_take_history_hint
|
||||
modifier: alt
|
||||
keycode: char_f
|
||||
mode: emacs
|
||||
event: {
|
||||
until: [
|
||||
{ send: historyhintwordcomplete }
|
||||
{ edit: movewordright }
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
name: delete_one_word_forward
|
||||
modifier: alt
|
||||
keycode: delete
|
||||
mode: emacs
|
||||
event: { edit: deleteword }
|
||||
}
|
||||
{
|
||||
name: delete_one_word_backward
|
||||
modifier: alt
|
||||
keycode: backspace
|
||||
mode: emacs
|
||||
event: { edit: backspaceword }
|
||||
}
|
||||
{
|
||||
name: delete_one_word_backward
|
||||
modifier: alt
|
||||
keycode: char_m
|
||||
mode: emacs
|
||||
event: { edit: backspaceword }
|
||||
}
|
||||
{
|
||||
name: cut_word_to_right
|
||||
modifier: alt
|
||||
keycode: char_d
|
||||
mode: emacs
|
||||
event: { edit: cutwordright }
|
||||
}
|
||||
{
|
||||
name: upper_case_word
|
||||
modifier: alt
|
||||
keycode: char_u
|
||||
mode: emacs
|
||||
event: { edit: uppercaseword }
|
||||
}
|
||||
{
|
||||
name: lower_case_word
|
||||
modifier: alt
|
||||
keycode: char_l
|
||||
mode: emacs
|
||||
event: { edit: lowercaseword }
|
||||
}
|
||||
{
|
||||
name: capitalize_char
|
||||
modifier: alt
|
||||
keycode: char_c
|
||||
mode: emacs
|
||||
event: { edit: capitalizechar }
|
||||
}
|
||||
# The following bindings with `*system` events require that Nushell has
|
||||
# been compiled with the `system-clipboard` feature.
|
||||
# If you want to use the system clipboard for visual selection or to
|
||||
# paste directly, uncomment the respective lines and replace the version
|
||||
# using the internal clipboard.
|
||||
{
|
||||
name: copy_selection
|
||||
modifier: control_shift
|
||||
keycode: char_c
|
||||
mode: emacs
|
||||
event: { edit: copyselection }
|
||||
# event: { edit: copyselectionsystem }
|
||||
}
|
||||
{
|
||||
name: cut_selection
|
||||
modifier: control_shift
|
||||
keycode: char_x
|
||||
mode: emacs
|
||||
event: { edit: cutselection }
|
||||
# event: { edit: cutselectionsystem }
|
||||
}
|
||||
# {
|
||||
# name: paste_system
|
||||
# modifier: control_shift
|
||||
# keycode: char_v
|
||||
# mode: emacs
|
||||
# event: { edit: pastesystem }
|
||||
# }
|
||||
{
|
||||
name: select_all
|
||||
modifier: control_shift
|
||||
keycode: char_a
|
||||
mode: emacs
|
||||
event: { edit: selectall }
|
||||
}
|
||||
]
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
# Nushell Environment Config File
|
||||
#
|
||||
# version = "0.100.1"
|
||||
|
||||
def create_left_prompt [] {
|
||||
let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) {
|
||||
null => $env.PWD
|
||||
'' => '~'
|
||||
$relative_pwd => ([~ $relative_pwd] | path join)
|
||||
}
|
||||
|
||||
let path_color = (if (is-admin) { ansi red_bold } else { ansi green_bold })
|
||||
let separator_color = (if (is-admin) { ansi light_red_bold } else { ansi light_green_bold })
|
||||
let path_segment = $"($path_color)($dir)(ansi reset)"
|
||||
|
||||
$path_segment | str replace --all (char path_sep) $"($separator_color)(char path_sep)($path_color)"
|
||||
}
|
||||
|
||||
def create_right_prompt [] {
|
||||
# create a right prompt in magenta with green separators and am/pm underlined
|
||||
let time_segment = ([
|
||||
(ansi reset)
|
||||
(ansi magenta)
|
||||
(date now | format date '%x %X') # try to respect user's locale
|
||||
] | str join | str replace --regex --all "([/:])" $"(ansi green)${1}(ansi magenta)" |
|
||||
str replace --regex --all "([AP]M)" $"(ansi magenta_underline)${1}")
|
||||
|
||||
let last_exit_code = if ($env.LAST_EXIT_CODE != 0) {([
|
||||
(ansi rb)
|
||||
($env.LAST_EXIT_CODE)
|
||||
] | str join)
|
||||
} else { "" }
|
||||
|
||||
([$last_exit_code, (char space), $time_segment] | str join)
|
||||
}
|
||||
|
||||
# Use nushell functions to define your right and left prompt
|
||||
$env.PROMPT_COMMAND = {|| create_left_prompt }
|
||||
# FIXME: This default is not implemented in rust code as of 2023-09-08.
|
||||
$env.PROMPT_COMMAND_RIGHT = {|| create_right_prompt }
|
||||
|
||||
# The prompt indicators are environmental variables that represent
|
||||
# the state of the prompt
|
||||
$env.PROMPT_INDICATOR = {|| "> " }
|
||||
$env.PROMPT_INDICATOR_VI_INSERT = {|| ": " }
|
||||
$env.PROMPT_INDICATOR_VI_NORMAL = {|| "> " }
|
||||
$env.PROMPT_MULTILINE_INDICATOR = {|| "::: " }
|
||||
|
||||
# If you want previously entered commands to have a different prompt from the usual one,
|
||||
# you can uncomment one or more of the following lines.
|
||||
# This can be useful if you have a 2-line prompt and it's taking up a lot of space
|
||||
# because every command entered takes up 2 lines instead of 1. You can then uncomment
|
||||
# the line below so that previously entered commands show with a single `🚀`.
|
||||
# $env.TRANSIENT_PROMPT_COMMAND = {|| "🚀 " }
|
||||
# $env.TRANSIENT_PROMPT_INDICATOR = {|| "" }
|
||||
# $env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = {|| "" }
|
||||
# $env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = {|| "" }
|
||||
# $env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = {|| "" }
|
||||
# $env.TRANSIENT_PROMPT_COMMAND_RIGHT = {|| "" }
|
||||
|
||||
# Specifies how environment variables are:
|
||||
# - converted from a string to a value on Nushell startup (from_string)
|
||||
# - converted from a value back to a string when running external commands (to_string)
|
||||
# Note: The conversions happen *after* config.nu is loaded
|
||||
$env.ENV_CONVERSIONS = {
|
||||
"PATH": {
|
||||
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
|
||||
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
|
||||
}
|
||||
"Path": {
|
||||
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
|
||||
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
|
||||
}
|
||||
}
|
||||
|
||||
# Directories to search for scripts when calling source or use
|
||||
# The default for this is $nu.default-config-dir/scripts
|
||||
$env.NU_LIB_DIRS = [
|
||||
($nu.default-config-dir | path join 'scripts') # add <nushell-config-dir>/scripts
|
||||
($nu.data-dir | path join 'completions') # default home for nushell completions
|
||||
]
|
||||
|
||||
# Directories to search for plugin binaries when calling register
|
||||
# The default for this is $nu.default-config-dir/plugins
|
||||
$env.NU_PLUGIN_DIRS = [
|
||||
($nu.default-config-dir | path join 'plugins') # add <nushell-config-dir>/plugins
|
||||
]
|
||||
|
||||
# To add entries to PATH (on Windows you might use Path), you can use the following pattern:
|
||||
# $env.PATH = ($env.PATH | split row (char esep) | prepend '/some/path')
|
||||
# An alternate way to add entries to $env.PATH is to use the custom command `path add`
|
||||
# which is built into the nushell stdlib:
|
||||
# use std "path add"
|
||||
# $env.PATH = ($env.PATH | split row (char esep))
|
||||
# path add /some/path
|
||||
# path add ($env.CARGO_HOME | path join "bin")
|
||||
# path add ($env.HOME | path join ".local" "bin")
|
||||
# $env.PATH = ($env.PATH | uniq)
|
||||
|
||||
# To load from a custom file you can use:
|
||||
# source ($nu.default-config-dir | path join 'custom.nu')
|
@ -85,12 +85,29 @@ where
|
||||
ret
|
||||
}
|
||||
|
||||
// See default_files/README.md for a description of these files
|
||||
pub fn get_default_env() -> &'static str {
|
||||
include_str!("sample_config/default_env.nu")
|
||||
include_str!("default_files/default_env.nu")
|
||||
}
|
||||
|
||||
pub fn get_scaffold_env() -> &'static str {
|
||||
include_str!("default_files/scaffold_env.nu")
|
||||
}
|
||||
|
||||
pub fn get_sample_env() -> &'static str {
|
||||
include_str!("default_files/sample_env.nu")
|
||||
}
|
||||
|
||||
pub fn get_default_config() -> &'static str {
|
||||
include_str!("sample_config/default_config.nu")
|
||||
include_str!("default_files/default_config.nu")
|
||||
}
|
||||
|
||||
pub fn get_scaffold_config() -> &'static str {
|
||||
include_str!("default_files/scaffold_config.nu")
|
||||
}
|
||||
|
||||
pub fn get_sample_config() -> &'static str {
|
||||
include_str!("default_files/sample_config.nu")
|
||||
}
|
||||
|
||||
pub fn get_ls_colors(lscolors_env_string: Option<String>) -> LsColors {
|
||||
|
@ -2,12 +2,13 @@ use log::warn;
|
||||
#[cfg(feature = "plugin")]
|
||||
use nu_cli::read_plugin_file;
|
||||
use nu_cli::{eval_config_contents, eval_source};
|
||||
use nu_engine::convert_env_values;
|
||||
use nu_path::canonicalize_with;
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
report_parse_error, report_shell_error, Config, ParseError, PipelineData, Spanned,
|
||||
};
|
||||
use nu_utils::{get_default_config, get_default_env};
|
||||
use nu_utils::{get_default_config, get_default_env, get_scaffold_config, get_scaffold_env, perf};
|
||||
use std::{
|
||||
fs,
|
||||
fs::File,
|
||||
@ -26,12 +27,47 @@ pub(crate) fn read_config_file(
|
||||
stack: &mut Stack,
|
||||
config_file: Option<Spanned<String>>,
|
||||
is_env_config: bool,
|
||||
ask_to_create: bool,
|
||||
create_scaffold: bool,
|
||||
) {
|
||||
warn!(
|
||||
"read_config_file() config_file_specified: {:?}, is_env_config: {is_env_config}",
|
||||
&config_file
|
||||
);
|
||||
|
||||
if is_env_config {
|
||||
eval_default_config(engine_state, stack, get_default_env(), is_env_config);
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let config = engine_state.get_config();
|
||||
let use_color = config.use_ansi_coloring;
|
||||
// Translate environment variables from Strings to Values
|
||||
if let Err(e) = convert_env_values(engine_state, stack) {
|
||||
report_shell_error(engine_state, &e);
|
||||
}
|
||||
|
||||
perf!(
|
||||
"translate env vars after default_env.nu",
|
||||
start_time,
|
||||
use_color
|
||||
);
|
||||
} else {
|
||||
let start_time = std::time::Instant::now();
|
||||
let config = engine_state.get_config();
|
||||
let use_color = config.use_ansi_coloring;
|
||||
if let Err(e) = convert_env_values(engine_state, stack) {
|
||||
report_shell_error(engine_state, &e);
|
||||
}
|
||||
perf!(
|
||||
"translate env vars before default_config.nu",
|
||||
start_time,
|
||||
use_color
|
||||
);
|
||||
|
||||
eval_default_config(engine_state, stack, get_default_config(), is_env_config);
|
||||
};
|
||||
|
||||
warn!("read_config_file() loading_defaults is_env_config: {is_env_config}");
|
||||
|
||||
// Load config startup file
|
||||
if let Some(file) = config_file {
|
||||
match engine_state.cwd_as_string(Some(stack)) {
|
||||
@ -59,41 +95,16 @@ pub(crate) fn read_config_file(
|
||||
config_path.push(if is_env_config { ENV_FILE } else { CONFIG_FILE });
|
||||
|
||||
if !config_path.exists() {
|
||||
let file_msg = if is_env_config {
|
||||
"environment config"
|
||||
let scaffold_config_file = if is_env_config {
|
||||
get_scaffold_env()
|
||||
} else {
|
||||
"config"
|
||||
get_scaffold_config()
|
||||
};
|
||||
|
||||
let will_create_file = match ask_to_create {
|
||||
true => {
|
||||
println!(
|
||||
"No {} file found at {}",
|
||||
file_msg,
|
||||
config_path.to_string_lossy()
|
||||
);
|
||||
println!("Would you like to create one with defaults (Y/n): ");
|
||||
|
||||
let mut answer = String::new();
|
||||
std::io::stdin()
|
||||
.read_line(&mut answer)
|
||||
.expect("Failed to read user input");
|
||||
|
||||
matches!(answer.trim(), "y" | "Y" | "")
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let config_file = if is_env_config {
|
||||
get_default_env()
|
||||
} else {
|
||||
get_default_config()
|
||||
};
|
||||
|
||||
match will_create_file {
|
||||
match create_scaffold {
|
||||
true => {
|
||||
if let Ok(mut output) = File::create(&config_path) {
|
||||
if write!(output, "{config_file}").is_ok() {
|
||||
if write!(output, "{scaffold_config_file}").is_ok() {
|
||||
let config_type = if is_env_config {
|
||||
"Environment config"
|
||||
} else {
|
||||
@ -109,17 +120,14 @@ pub(crate) fn read_config_file(
|
||||
"Unable to write to {}, sourcing default file instead",
|
||||
config_path.to_string_lossy(),
|
||||
);
|
||||
eval_default_config(engine_state, stack, config_file, is_env_config);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
eprintln!("Unable to create {config_file}, sourcing default file instead");
|
||||
eval_default_config(engine_state, stack, config_file, is_env_config);
|
||||
eprintln!("Unable to create {scaffold_config_file}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
eval_default_config(engine_state, stack, config_file, is_env_config);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -227,11 +235,7 @@ fn eval_default_config(
|
||||
config_file: &str,
|
||||
is_env_config: bool,
|
||||
) {
|
||||
warn!(
|
||||
"eval_default_config() config_file_specified: {:?}, is_env_config: {}",
|
||||
&config_file, is_env_config
|
||||
);
|
||||
// Just use the contents of "default_config.nu" or "default_env.nu"
|
||||
warn!("eval_default_config() is_env_config: {}", is_env_config);
|
||||
eval_source(
|
||||
engine_state,
|
||||
stack,
|
||||
@ -264,20 +268,14 @@ pub(crate) fn setup_config(
|
||||
&config_file, &env_file, is_login_shell
|
||||
);
|
||||
|
||||
let ask_to_create_config = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
let create_scaffold = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
|
||||
let result = catch_unwind(AssertUnwindSafe(|| {
|
||||
#[cfg(feature = "plugin")]
|
||||
read_plugin_file(engine_state, plugin_file);
|
||||
|
||||
read_config_file(engine_state, stack, env_file, true, ask_to_create_config);
|
||||
read_config_file(
|
||||
engine_state,
|
||||
stack,
|
||||
config_file,
|
||||
false,
|
||||
ask_to_create_config,
|
||||
);
|
||||
read_config_file(engine_state, stack, env_file, true, create_scaffold);
|
||||
read_config_file(engine_state, stack, config_file, false, create_scaffold);
|
||||
|
||||
if is_login_shell {
|
||||
read_loginshell_file(engine_state, stack);
|
||||
|
10
src/main.rs
10
src/main.rs
@ -282,6 +282,16 @@ fn main() -> Result<()> {
|
||||
Value::string(env!("CARGO_PKG_VERSION"), Span::unknown()),
|
||||
);
|
||||
|
||||
// Add SHLVL if interactive
|
||||
if engine_state.is_interactive {
|
||||
let mut shlvl = engine_state
|
||||
.get_env_var("SHLVL")
|
||||
.map(|x| x.as_str().unwrap_or("0").parse::<i64>().unwrap_or(0))
|
||||
.unwrap_or(0);
|
||||
shlvl += 1;
|
||||
engine_state.add_env_var("SHLVL".to_string(), Value::int(shlvl, Span::unknown()));
|
||||
}
|
||||
|
||||
if parsed_nu_cli_args.no_std_lib.is_none() {
|
||||
load_standard_library(&mut engine_state)?;
|
||||
}
|
||||
|
14
src/run.rs
14
src/run.rs
@ -23,7 +23,7 @@ pub(crate) fn run_commands(
|
||||
trace!("run_commands");
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let ask_to_create_config = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
let create_scaffold = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
|
||||
let mut stack = Stack::new();
|
||||
|
||||
@ -46,7 +46,7 @@ pub(crate) fn run_commands(
|
||||
&mut stack,
|
||||
parsed_nu_cli_args.env_file,
|
||||
true,
|
||||
ask_to_create_config,
|
||||
create_scaffold,
|
||||
);
|
||||
} else {
|
||||
config_files::read_default_env_file(engine_state, &mut stack)
|
||||
@ -55,7 +55,7 @@ pub(crate) fn run_commands(
|
||||
perf!("read env.nu", start_time, use_color);
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let ask_to_create_config = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
let create_scaffold = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
|
||||
// If we have a config file parameter *OR* we have a login shell parameter, read the config file
|
||||
if parsed_nu_cli_args.config_file.is_some() || parsed_nu_cli_args.login_shell.is_some() {
|
||||
@ -64,7 +64,7 @@ pub(crate) fn run_commands(
|
||||
&mut stack,
|
||||
parsed_nu_cli_args.config_file,
|
||||
false,
|
||||
ask_to_create_config,
|
||||
create_scaffold,
|
||||
);
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ pub(crate) fn run_file(
|
||||
// if the --no-config-file(-n) flag is passed, do not load plugin, env, or config files
|
||||
if parsed_nu_cli_args.no_config_file.is_none() {
|
||||
let start_time = std::time::Instant::now();
|
||||
let ask_to_create_config = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
let create_scaffold = nu_path::nu_config_dir().map_or(false, |p| !p.exists());
|
||||
#[cfg(feature = "plugin")]
|
||||
read_plugin_file(engine_state, parsed_nu_cli_args.plugin_file);
|
||||
perf!("read plugins", start_time, use_color);
|
||||
@ -136,7 +136,7 @@ pub(crate) fn run_file(
|
||||
&mut stack,
|
||||
parsed_nu_cli_args.env_file,
|
||||
true,
|
||||
ask_to_create_config,
|
||||
create_scaffold,
|
||||
);
|
||||
} else {
|
||||
config_files::read_default_env_file(engine_state, &mut stack)
|
||||
@ -150,7 +150,7 @@ pub(crate) fn run_file(
|
||||
&mut stack,
|
||||
parsed_nu_cli_args.config_file,
|
||||
false,
|
||||
ask_to_create_config,
|
||||
create_scaffold,
|
||||
);
|
||||
}
|
||||
perf!("read config.nu", start_time, use_color);
|
||||
|
BIN
tests/fixtures/formats/sample_data_with_annotation.ods
vendored
Normal file
BIN
tests/fixtures/formats/sample_data_with_annotation.ods
vendored
Normal file
Binary file not shown.
@ -221,8 +221,8 @@ fn test_default_config_path_symlinked_config_files() {
|
||||
|
||||
#[test]
|
||||
fn test_alternate_config_path() {
|
||||
let config_file = "crates/nu-utils/src/sample_config/default_config.nu";
|
||||
let env_file = "crates/nu-utils/src/sample_config/default_env.nu";
|
||||
let config_file = "crates/nu-utils/src/default_files/scaffold_config.nu";
|
||||
let env_file = "crates/nu-utils/src/default_files/scaffold_env.nu";
|
||||
|
||||
let cwd = std::env::current_dir().expect("Could not get current working directory");
|
||||
|
||||
|
Reference in New Issue
Block a user