mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
REFACTOR: move the banner from the rust
source to the standard library (#8406)
Related to: - #8311 - #8353 # Description with the new `$nu.startup-time` from #8353 and as mentionned in #8311, we are now able to fully move the `nushell` banner from the `rust` source base to the standard library. this PR - removes all the `rust` source code for the banner - rewrites a perfect clone of the banner to `std.nu`, called `std banner` - call `std banner` from `default_config.nu` # User-Facing Changes see the demo: https://asciinema.org/a/566521 - no config will show the banner (e.g. `cargo run --release -- --no-config-file`) - a custom config without the `if $env.config.show_banner` block and no call to `std banner` would never show the banner - a custom config with the block and `config.show_banner = true` will show the banner - a custom config with the block and `config.show_banner = false` will NOT show the banner # Tests + Formatting a new test line has been added to `tests.nu` to check the length of the `std banner` output. - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` # After Submitting ``` $nothing ``` --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
parent
a8b4e81408
commit
43a3983d36
7 changed files with 281 additions and 126 deletions
|
@ -11,13 +11,13 @@ use miette::{IntoDiagnostic, Result};
|
|||
use nu_color_config::StyleComputer;
|
||||
use nu_command::hook::eval_hook;
|
||||
use nu_command::util::get_guaranteed_cwd;
|
||||
use nu_engine::{convert_env_values, eval_block};
|
||||
use nu_parser::{lex, parse, trim_quotes_str};
|
||||
use nu_engine::convert_env_values;
|
||||
use nu_parser::{lex, trim_quotes_str};
|
||||
use nu_protocol::{
|
||||
config::NuCursorShape,
|
||||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
format_duration, report_error, report_error_new, HistoryFileFormat, PipelineData, ShellError,
|
||||
Span, Spanned, Value,
|
||||
report_error, report_error_new, HistoryFileFormat, PipelineData, ShellError, Span, Spanned,
|
||||
Value,
|
||||
};
|
||||
use nu_utils::utils::perf;
|
||||
use reedline::{CursorConfig, DefaultHinter, EditCommand, Emacs, SqliteBackedHistory, Vi};
|
||||
|
@ -43,6 +43,7 @@ pub fn evaluate_repl(
|
|||
stack: &mut Stack,
|
||||
nushell_path: &str,
|
||||
prerun_command: Option<Spanned<String>>,
|
||||
load_std_lib: Option<Spanned<String>>,
|
||||
entire_start_time: Instant,
|
||||
) -> Result<()> {
|
||||
use nu_command::hook;
|
||||
|
@ -153,19 +154,8 @@ pub fn evaluate_repl(
|
|||
|
||||
start_time = std::time::Instant::now();
|
||||
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 {
|
||||
println!("{}", nu_utils::strip_ansi_string_likely(banner));
|
||||
}
|
||||
}
|
||||
perf(
|
||||
"get sysinfo/show banner",
|
||||
"get sysinfo",
|
||||
start_time,
|
||||
file!(),
|
||||
line!(),
|
||||
|
@ -185,6 +175,19 @@ pub fn evaluate_repl(
|
|||
engine_state.merge_env(stack, get_guaranteed_cwd(engine_state, stack))?;
|
||||
}
|
||||
|
||||
engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64);
|
||||
|
||||
if load_std_lib.is_none() && engine_state.get_config().show_banner {
|
||||
eval_source(
|
||||
engine_state,
|
||||
stack,
|
||||
r#"use std banner; banner"#.as_bytes(),
|
||||
"show_banner",
|
||||
PipelineData::empty(),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
loop {
|
||||
let loop_start_time = std::time::Instant::now();
|
||||
|
||||
|
@ -445,16 +448,6 @@ pub fn evaluate_repl(
|
|||
|
||||
entry_num += 1;
|
||||
|
||||
if entry_num == 1 {
|
||||
engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64);
|
||||
if show_banner {
|
||||
println!(
|
||||
"Startup Time: {}",
|
||||
format_duration(engine_state.get_startup_time())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let input = line_editor.read_line(prompt);
|
||||
let shell_integration = config.shell_integration;
|
||||
|
@ -740,104 +733,6 @@ fn map_nucursorshape_to_cursorshape(shape: NuCursorShape) -> SetCursorStyle {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_banner(engine_state: &mut EngineState, stack: &mut Stack) -> String {
|
||||
let age = match eval_string_with_input(
|
||||
engine_state,
|
||||
stack,
|
||||
None,
|
||||
"(date now) - ('2019-05-10 09:59:12-0700' | 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 {}https://nushell.sh{}
|
||||
{}Tweet{} us at {}@nu_shell{}
|
||||
Learn how to remove this at: {}https://nushell.sh/book/configuration.html#remove-welcome-message{}
|
||||
|
||||
It's been this long since {}Nushell{}'s first commit:
|
||||
{}{}
|
||||
"#,
|
||||
"\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 Welcome Message
|
||||
"\x1b[0m", //after Welcome Message
|
||||
"\x1b[32m", //before Nushell
|
||||
"\x1b[0m", //after Nushell
|
||||
age,
|
||||
"\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, None, source.as_bytes(), false);
|
||||
|
||||
(output, working_set.render())
|
||||
};
|
||||
|
||||
engine_state.merge_delta(delta)?;
|
||||
|
||||
let input_as_pipeline_data = match input {
|
||||
Some(input) => PipelineData::Value(input, None),
|
||||
None => PipelineData::empty(),
|
||||
};
|
||||
|
||||
eval_block(
|
||||
engine_state,
|
||||
stack,
|
||||
&block,
|
||||
input_as_pipeline_data,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.map(|x| x.into_value(Span::unknown()))
|
||||
}
|
||||
|
||||
pub fn get_command_finished_marker(stack: &Stack, engine_state: &EngineState) -> String {
|
||||
let exit_code = stack
|
||||
.get_env_var(engine_state, "LAST_EXIT_CODE")
|
||||
|
|
226
crates/nu-std/lib/dt.nu
Normal file
226
crates/nu-std/lib/dt.nu
Normal file
|
@ -0,0 +1,226 @@
|
|||
def borrow-year [from: record, current: record] {
|
||||
mut current = $current
|
||||
|
||||
$current.year = $current.year - 1
|
||||
$current.month = $current.month + 12
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def leap-year-days [year] {
|
||||
if $year mod 400 == 0 {
|
||||
29
|
||||
} else if $year mod 4 == 0 and $year mod 100 != 0 {
|
||||
29
|
||||
} else {
|
||||
28
|
||||
}
|
||||
}
|
||||
|
||||
def borrow-month [from: record, current: record] {
|
||||
mut current = $current
|
||||
if $from.month in [1, 3, 5, 7, 8, 10, 12] {
|
||||
$current.day = $current.day + 31
|
||||
$current.month = $current.month - 1
|
||||
if $current.month < 0 {
|
||||
$current = (borrow-year $from $current)
|
||||
}
|
||||
} else if $from.month in [4, 6, 9, 11] {
|
||||
$current.day = $current.day + 30
|
||||
$current.month = $current.month - 1
|
||||
if $current.month < 0 {
|
||||
$current = (borrow-year $from $current)
|
||||
}
|
||||
} else {
|
||||
# oh February
|
||||
let num_days_feb = (leap-year-days $current.year)
|
||||
$current.day = $current.day + $num_days_feb
|
||||
$current.month = $current.month - 1
|
||||
if $current.month < 0 {
|
||||
$current = (borrow-year $from $current)
|
||||
}
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def borrow-day [from: record, current: record] {
|
||||
mut current = $current
|
||||
$current.hour = $current.hour + 24
|
||||
$current.day = $current.day - 1
|
||||
if $current.day < 0 {
|
||||
$current = (borrow-month $from $current)
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def borrow-hour [from: record, current: record] {
|
||||
mut current = $current
|
||||
$current.minute = $current.minute + 60
|
||||
$current.hour = $current.hour - 1
|
||||
if $current.hour < 0 {
|
||||
$current = (borrow-day $from $current)
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def borrow-minute [from: record, current: record] {
|
||||
mut current = $current
|
||||
$current.second = $current.second + 60
|
||||
$current.minute = $current.minute - 1
|
||||
if $current.minute < 0 {
|
||||
$current = (borrow-hour $from $current)
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def borrow-second [from: record, current: record] {
|
||||
mut current = $current
|
||||
$current.millisecond = $current.millisecond + 1_000
|
||||
$current.second = $current.second - 1
|
||||
if $current.second < 0 {
|
||||
$current = (borrow-minute $from $current)
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def borrow-millisecond [from: record, current: record] {
|
||||
mut current = $current
|
||||
$current.microsecond = $current.microsecond + 1_000_000
|
||||
$current.millisecond = $current.millisecond - 1
|
||||
if $current.millisecond < 0 {
|
||||
$current = (borrow-second $from $current)
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
def borrow-microsecond [from: record, current: record] {
|
||||
mut current = $current
|
||||
$current.nanosecond = $current.nanosecond + 1_000_000_000
|
||||
$current.microsecond = $current.microsecond - 1
|
||||
if $current.microsecond < 0 {
|
||||
$current = (borrow-millisecond $from $current)
|
||||
}
|
||||
|
||||
$current
|
||||
}
|
||||
|
||||
# Subtract two datetimes and return a record with the difference
|
||||
# Examples
|
||||
# print (datetime-diff 2023-05-07T04:08:45+12:00 2019-05-10T09:59:12+12:00)
|
||||
# print (datetime-diff (date now) 2019-05-10T09:59:12-07:00)
|
||||
export def datetime-diff [from: datetime, to: datetime] {
|
||||
let from_expanded = ($from | date to-timezone utc | date to-record | merge { millisecond: 0, microsecond: 0})
|
||||
let to_expanded = ($to | date to-timezone utc | date to-record | merge { millisecond: 0, microsecond: 0})
|
||||
|
||||
mut result = { year: ($from_expanded.year - $to_expanded.year), month: ($from_expanded.month - $to_expanded.month)}
|
||||
|
||||
if $result.month < 0 {
|
||||
$result = (borrow-year $from_expanded $result)
|
||||
}
|
||||
|
||||
$result.day = $from_expanded.day - $to_expanded.day
|
||||
if $result.day < 0 {
|
||||
$result = (borrow-month $from_expanded $result)
|
||||
}
|
||||
|
||||
$result.hour = $from_expanded.hour - $to_expanded.hour
|
||||
if $result.hour < 0 {
|
||||
$result = (borrow-day $from_expanded $result)
|
||||
}
|
||||
|
||||
$result.minute = $from_expanded.minute - $to_expanded.minute
|
||||
if $result.minute < 0 {
|
||||
$result = (borrow-hour $from_expanded $result)
|
||||
}
|
||||
|
||||
$result.second = $from_expanded.second - $to_expanded.second
|
||||
if $result.second < 0 {
|
||||
$result = (borrow-minute $from_expanded $result)
|
||||
}
|
||||
|
||||
$result.nanosecond = $from_expanded.nanosecond - $to_expanded.nanosecond
|
||||
if $result.nanosecond < 0 {
|
||||
$result = (borrow-second $from_expanded $result)
|
||||
}
|
||||
|
||||
$result.millisecond = ($result.nanosecond / 1_000_000 | into int) # don't want a decimal
|
||||
$result.microsecond = (($result.nanosecond mod 1_000_000) / 1_000 | into int)
|
||||
$result.nanosecond = ($result.nanosecond mod 1_000 | into int)
|
||||
|
||||
$result
|
||||
}
|
||||
|
||||
export def pretty-print-duration [dur: duration] {
|
||||
mut result = ""
|
||||
if $dur.year > 0 {
|
||||
if $dur.year > 1 {
|
||||
$result = $"($dur.year)yrs "
|
||||
} else {
|
||||
$result = $"($dur.year)yr "
|
||||
}
|
||||
}
|
||||
if $dur.month > 0 {
|
||||
if $dur.month > 1 {
|
||||
$result = $"($result)($dur.month)months "
|
||||
} else {
|
||||
$result = $"($result)($dur.month)month "
|
||||
}
|
||||
}
|
||||
if $dur.day > 0 {
|
||||
if $dur.day > 1 {
|
||||
$result = $"($result)($dur.day)days "
|
||||
} else {
|
||||
$result = $"($result)($dur.day)day "
|
||||
}
|
||||
}
|
||||
if $dur.hour > 0 {
|
||||
if $dur.hour > 1 {
|
||||
$result = $"($result)($dur.hour)hrs "
|
||||
} else {
|
||||
$result = $"($result)($dur.hour)hr "
|
||||
}
|
||||
}
|
||||
if $dur.minute > 0 {
|
||||
if $dur.minute > 1 {
|
||||
$result = $"($result)($dur.minute)mins "
|
||||
} else {
|
||||
$result = $"($result)($dur.minute)min "
|
||||
}
|
||||
}
|
||||
if $dur.second > 0 {
|
||||
if $dur.second > 1 {
|
||||
$result = $"($result)($dur.second)secs "
|
||||
} else {
|
||||
$result = $"($result)($dur.second)sec "
|
||||
}
|
||||
}
|
||||
if $dur.millisecond > 0 {
|
||||
if $dur.millisecond > 1 {
|
||||
$result = $"($result)($dur.millisecond)ms "
|
||||
} else {
|
||||
$result = $"($result)($dur.millisecond)ms "
|
||||
}
|
||||
}
|
||||
if $dur.microsecond > 0 {
|
||||
if $dur.microsecond > 1 {
|
||||
$result = $"($result)($dur.microsecond)µs "
|
||||
} else {
|
||||
$result = $"($result)($dur.microsecond)µs "
|
||||
}
|
||||
}
|
||||
if $dur.nanosecond > 0 {
|
||||
if $dur.nanosecond > 1 {
|
||||
$result = $"($result)($dur.nanosecond)ns "
|
||||
} else {
|
||||
$result = $"($result)($dur.nanosecond)ns "
|
||||
}
|
||||
}
|
||||
|
||||
$result
|
||||
}
|
|
@ -9,6 +9,7 @@ export use iter *
|
|||
export use log *
|
||||
export use testing *
|
||||
export use xml *
|
||||
export use dt [datetime-diff, pretty-print-duration]
|
||||
|
||||
# Add the given paths to the PATH.
|
||||
#
|
||||
|
@ -224,3 +225,27 @@ export def bench [
|
|||
$report
|
||||
}
|
||||
}
|
||||
|
||||
# print a banner for nushell, with information about the project
|
||||
#
|
||||
# Example:
|
||||
# an example can be found in [this asciinema recording](https://asciinema.org/a/566513)
|
||||
export def banner [] {
|
||||
let dt = (datetime-diff (date now) 2019-05-10T09:59:12-07:00)
|
||||
$"(ansi green) __ ,(ansi reset)
|
||||
(ansi green) .--\(\)°'.' (ansi reset)Welcome to (ansi green)Nushell(ansi reset),
|
||||
(ansi green)'|, . ,' (ansi reset)based on the (ansi green)nu(ansi reset) language,
|
||||
(ansi green) !_-\(_\\ (ansi reset)where all data is structured!
|
||||
|
||||
Please join our (ansi purple)Discord(ansi reset) community at (ansi purple)https://discord.gg/NtAbbGn(ansi reset)
|
||||
Our (ansi green_bold)GitHub(ansi reset) repository is at (ansi green_bold)https://github.com/nushell/nushell(ansi reset)
|
||||
Our (ansi green)Documentation(ansi reset) is located at (ansi green)https://nushell.sh(ansi reset)
|
||||
(ansi cyan)Tweet(ansi reset) us at (ansi cyan_bold)@nu_shell(ansi reset)
|
||||
Learn how to remove this at: (ansi green)https://nushell.sh/book/configuration.html#remove-welcome-message(ansi reset)
|
||||
|
||||
It's been this long since (ansi green)Nushell(ansi reset)'s first commit:
|
||||
(pretty-print-duration $dt)
|
||||
|
||||
Startup Time: ($nu.startup-time)
|
||||
"
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ pub fn load_standard_library(
|
|||
("help", include_str!("../lib/help.nu")),
|
||||
("testing", include_str!("../lib/testing.nu")),
|
||||
("xml", include_str!("../lib/xml.nu")),
|
||||
("dt", include_str!("../lib/dt.nu")),
|
||||
];
|
||||
|
||||
// Define commands to be preloaded into the default (top level, unprefixed) namespace.
|
||||
|
|
|
@ -22,3 +22,7 @@ export def test_path_add [] {
|
|||
assert equal $env.PATH ["fooooo", "foo", "bar", "baz"]
|
||||
}
|
||||
}
|
||||
|
||||
export def test_banner [] {
|
||||
std assert ((std banner | lines | length) == 15)
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ pub(crate) fn run_repl(
|
|||
&mut stack,
|
||||
config_files::NUSHELL_FOLDER,
|
||||
parsed_nu_cli_args.execute,
|
||||
parsed_nu_cli_args.no_std_lib,
|
||||
entire_start_time,
|
||||
);
|
||||
perf(
|
||||
|
|
|
@ -6,6 +6,7 @@ use nu_engine::eval_block;
|
|||
use nu_parser::parse;
|
||||
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
|
||||
use nu_protocol::{CliError, PipelineData, Value};
|
||||
use nu_std::load_standard_library;
|
||||
// use nu_test_support::fs::in_directory;
|
||||
|
||||
/// Echo's value of env keys from args
|
||||
|
@ -175,10 +176,12 @@ pub fn nu_repl() {
|
|||
let mut engine_state = nu_cli::add_cli_context(create_default_context());
|
||||
let mut stack = Stack::new();
|
||||
|
||||
stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy()));
|
||||
engine_state.add_env_var("PWD".into(), Value::test_string(cwd.to_string_lossy()));
|
||||
|
||||
let mut last_output = String::new();
|
||||
|
||||
load_standard_library(&mut engine_state).expect("Could not load the standard library.");
|
||||
|
||||
for (i, line) in source_lines.iter().enumerate() {
|
||||
let cwd = nu_engine::env::current_dir(&engine_state, &stack)
|
||||
.unwrap_or_else(|err| outcome_err(&engine_state, &err));
|
||||
|
|
Loading…
Reference in a new issue