mirror of
https://github.com/nushell/nushell
synced 2024-11-10 07:04:13 +00:00
add a new welcome banner to nushell (#6163)
* add a new welcome banner to nushell * remove top line * tweaked colors and wording * changed to dimmed white * removed a comment * make config nu stand out a little * fix type-o
This commit is contained in:
parent
767201c40d
commit
7a820b1304
5 changed files with 149 additions and 2 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2537,6 +2537,7 @@ dependencies = [
|
|||
"reedline",
|
||||
"regex",
|
||||
"rstest",
|
||||
"strip-ansi-escapes",
|
||||
"sysinfo",
|
||||
"thiserror",
|
||||
]
|
||||
|
|
|
@ -30,6 +30,7 @@ is_executable = "1.0.1"
|
|||
lazy_static = "1.4.0"
|
||||
log = "0.4"
|
||||
regex = "1.5.4"
|
||||
strip-ansi-escapes = "0.1.1"
|
||||
sysinfo = "0.24.1"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -14,12 +14,14 @@ use nu_parser::{lex, parse};
|
|||
use nu_protocol::{
|
||||
ast::PathMember,
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
BlockId, HistoryFileFormat, PipelineData, PositionalArg, ShellError, Span, Type, Value, VarId,
|
||||
format_duration, BlockId, HistoryFileFormat, PipelineData, PositionalArg, ShellError, Span,
|
||||
Type, Value, VarId,
|
||||
};
|
||||
use reedline::{DefaultHinter, Emacs, SqliteBackedHistory, Vi};
|
||||
use regex::Regex;
|
||||
use std::io::{self, Write};
|
||||
use std::{sync::atomic::Ordering, time::Instant};
|
||||
use strip_ansi_escapes::strip;
|
||||
use sysinfo::SystemExt;
|
||||
|
||||
// According to Daniel Imms @Tyriar, we need to do these this way:
|
||||
|
@ -119,6 +121,25 @@ pub fn evaluate_repl(
|
|||
|
||||
let sys = sysinfo::System::new();
|
||||
|
||||
let show_banner = config.show_banner;
|
||||
let use_ansi = config.use_ansi_coloring;
|
||||
if show_banner {
|
||||
let banner = get_banner(engine_state, stack);
|
||||
if use_ansi {
|
||||
println!("{}", banner);
|
||||
} else {
|
||||
let stripped_string = {
|
||||
if let Ok(bytes) = strip(&banner) {
|
||||
String::from_utf8_lossy(&bytes).to_string()
|
||||
} else {
|
||||
banner
|
||||
}
|
||||
};
|
||||
|
||||
println!("{}", stripped_string);
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
if is_perf_true {
|
||||
info!(
|
||||
|
@ -460,6 +481,121 @@ pub fn evaluate_repl(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_banner(engine_state: &mut EngineState, stack: &mut Stack) -> String {
|
||||
let age = match eval_string_with_input(
|
||||
engine_state,
|
||||
stack,
|
||||
None,
|
||||
"(date now) - ('05/10/2019' | into datetime)",
|
||||
) {
|
||||
Ok(Value::Duration { val, .. }) => format_duration(val),
|
||||
_ => "".to_string(),
|
||||
};
|
||||
|
||||
let banner = format!(
|
||||
r#"{} __ ,
|
||||
{} .--()°'.' {}Welcome to {}Nushell{},
|
||||
{}'|, . ,' {}based on the {}nu{} language,
|
||||
{} !_-(_\ {}where all data is structured!
|
||||
|
||||
Please join our {}Discord{} community at {}https://discord.gg/NtAbbGn{}
|
||||
Our {}GitHub{} repository is at {}https://github.com/nushell/nushell{}
|
||||
Our {}Documentation{} is located at {}http://nushell.sh{}
|
||||
{}Tweet{} us at {}@nu_shell{}
|
||||
|
||||
{}Nushell{} has been around for:
|
||||
{}
|
||||
|
||||
{}You can disable this banner using the {}config nu{}{} command
|
||||
to modify the config.nu file and setting show_banner to false.
|
||||
|
||||
let-env config {{
|
||||
show_banner: false
|
||||
...
|
||||
}}{}
|
||||
"#,
|
||||
"\x1b[32m", //start line 1 green
|
||||
"\x1b[32m", //start line 2
|
||||
"\x1b[0m", //before welcome
|
||||
"\x1b[32m", //before nushell
|
||||
"\x1b[0m", //after nushell
|
||||
"\x1b[32m", //start line 3
|
||||
"\x1b[0m", //before based
|
||||
"\x1b[32m", //before nu
|
||||
"\x1b[0m", //after nu
|
||||
"\x1b[32m", //start line 4
|
||||
"\x1b[0m", //before where
|
||||
"\x1b[35m", //before Discord purple
|
||||
"\x1b[0m", //after Discord
|
||||
"\x1b[35m", //before Discord URL
|
||||
"\x1b[0m", //after Discord URL
|
||||
"\x1b[1;32m", //before GitHub green_bold
|
||||
"\x1b[0m", //after GitHub
|
||||
"\x1b[1;32m", //before GitHub URL
|
||||
"\x1b[0m", //after GitHub URL
|
||||
"\x1b[32m", //before Documentation
|
||||
"\x1b[0m", //after Documentation
|
||||
"\x1b[32m", //before Documentation URL
|
||||
"\x1b[0m", //after Documentation URL
|
||||
"\x1b[36m", //before Tweet blue
|
||||
"\x1b[0m", //after Tweet
|
||||
"\x1b[1;36m", //before @nu_shell cyan_bold
|
||||
"\x1b[0m", //after @nu_shell
|
||||
"\x1b[32m", //before Nushell
|
||||
"\x1b[0m", //after Nushell
|
||||
age,
|
||||
"\x1b[2;37m", //before banner disable dim white
|
||||
"\x1b[2;36m", //before config nu dim cyan
|
||||
"\x1b[0m", //after config nu
|
||||
"\x1b[2;37m", //after config nu dim white
|
||||
"\x1b[0m", //after banner disable
|
||||
);
|
||||
|
||||
banner
|
||||
}
|
||||
|
||||
// Taken from Nana's simple_eval
|
||||
/// Evaluate a block of Nu code, optionally with input.
|
||||
/// For example, source="$in * 2" will multiply the value in input by 2.
|
||||
pub fn eval_string_with_input(
|
||||
engine_state: &mut EngineState,
|
||||
stack: &mut Stack,
|
||||
input: Option<Value>,
|
||||
source: &str,
|
||||
) -> Result<Value, ShellError> {
|
||||
let (block, delta) = {
|
||||
let mut working_set = StateWorkingSet::new(engine_state);
|
||||
let (output, _) = parse(
|
||||
&mut working_set,
|
||||
Some("nana"),
|
||||
source.as_bytes(),
|
||||
false,
|
||||
&[],
|
||||
);
|
||||
|
||||
(output, working_set.render())
|
||||
};
|
||||
|
||||
if let Err(err) = engine_state.merge_delta(delta) {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
let input_as_pipeline_data = match input {
|
||||
Some(input) => PipelineData::Value(input, None),
|
||||
None => PipelineData::new(Span::test_data()),
|
||||
};
|
||||
|
||||
eval_block(
|
||||
engine_state,
|
||||
stack,
|
||||
&block,
|
||||
input_as_pipeline_data,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.map(|x| x.into_value(Span::test_data()))
|
||||
}
|
||||
|
||||
pub fn get_command_finished_marker(stack: &Stack, engine_state: &EngineState) -> String {
|
||||
let exit_code = stack
|
||||
.get_env_var(engine_state, "LAST_EXIT_CODE")
|
||||
|
|
|
@ -81,6 +81,7 @@ pub struct Config {
|
|||
pub case_sensitive_completions: bool,
|
||||
pub enable_external_completion: bool,
|
||||
pub trim_strategy: TrimStrategy,
|
||||
pub show_banner: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
@ -115,6 +116,7 @@ impl Default for Config {
|
|||
case_sensitive_completions: false,
|
||||
enable_external_completion: true,
|
||||
trim_strategy: TRIM_STRATEGY_DEFAULT,
|
||||
show_banner: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,6 +390,13 @@ impl Value {
|
|||
}
|
||||
}
|
||||
"table_trim" => config.trim_strategy = try_parse_trim_strategy(value, &config)?,
|
||||
"show_banner" => {
|
||||
if let Ok(b) = value.as_bool() {
|
||||
config.show_banner = b;
|
||||
} else {
|
||||
eprintln!("$config.show_banner is not a bool")
|
||||
}
|
||||
}
|
||||
x => {
|
||||
eprintln!("$config.{} is an unknown config setting", x)
|
||||
}
|
||||
|
|
|
@ -257,7 +257,6 @@ let-env config = {
|
|||
case_sensitive_completions: false # set to true to enable case-sensitive completions
|
||||
enable_external_completion: true # set to false to prevent nushell looking into $env.PATH to find more suggestions, `false` recommended for WSL users as this look up my be very slow
|
||||
max_external_completion_results: 100 # setting it lower can improve completion performance at the cost of omitting some options
|
||||
|
||||
# A strategy of managing table view in case of limited space.
|
||||
table_trim: {
|
||||
methodology: wrapping, # truncating
|
||||
|
@ -266,6 +265,7 @@ let-env config = {
|
|||
# A suffix which will be used with 'truncating' methodology
|
||||
# truncating_suffix: "..."
|
||||
}
|
||||
show_banner: true # true or false to enable or disable the banner
|
||||
|
||||
hooks: {
|
||||
pre_prompt: [{
|
||||
|
|
Loading…
Reference in a new issue