Skip to content

Commit

Permalink
Make $nu constant (#10160)
Browse files Browse the repository at this point in the history
  • Loading branch information
kubouch committed Sep 1, 2023
1 parent 7d6b23e commit f35808c
Show file tree
Hide file tree
Showing 13 changed files with 284 additions and 218 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion crates/nu-cli/src/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ use nu_parser::{lex, parse, trim_quotes_str};
use nu_protocol::{
config::NuCursorShape,
engine::{EngineState, Stack, StateWorkingSet},
eval_const::create_nu_constant,
report_error, report_error_new, HistoryFileFormat, PipelineData, ShellError, Span, Spanned,
Value,
Value, NU_VARIABLE_ID,
};
use nu_utils::utils::perf;
use reedline::{
Expand Down Expand Up @@ -164,6 +165,10 @@ pub fn evaluate_repl(

engine_state.set_startup_time(entire_start_time.elapsed().as_nanos() as i64);

// Regenerate the $nu constant to contain the startup time and any other potential updates
let nu_const = create_nu_constant(engine_state, Span::unknown())?;
engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const);

if load_std_lib.is_none() && engine_state.get_config().show_banner {
eval_source(
engine_state,
Expand Down
8 changes: 7 additions & 1 deletion crates/nu-cli/tests/support/completions_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
PipelineData, ShellError, Span, Value,
eval_const::create_nu_constant,
PipelineData, ShellError, Span, Value, NU_VARIABLE_ID,
};
use nu_test_support::fs;
use reedline::Suggestion;
Expand All @@ -28,6 +29,11 @@ pub fn new_engine() -> (PathBuf, String, EngineState, Stack) {
// Create a new engine with default context
let mut engine_state = create_default_context();

// Add $nu
let nu_const =
create_nu_constant(&engine_state, Span::test_data()).expect("Failed creating $nu");
engine_state.set_variable_const_val(NU_VARIABLE_ID, nu_const);

// New stack
let mut stack = Stack::new();

Expand Down
2 changes: 0 additions & 2 deletions crates/nu-engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,5 @@ nu-path = { path = "../nu-path", version = "0.84.1" }
nu-glob = { path = "../nu-glob", version = "0.84.1" }
nu-utils = { path = "../nu-utils", version = "0.84.1" }

sysinfo = "0.29"

[features]
plugin = []
189 changes: 9 additions & 180 deletions crates/nu-engine/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ use nu_protocol::{
PipelineMetadata, Range, Record, ShellError, Span, Spanned, Unit, Value, VarId,
ENV_VARIABLE_ID,
};
use std::collections::HashMap;
use std::time::Instant;
use std::{collections::HashMap, path::PathBuf};
use sysinfo::SystemExt;

pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
match op {
Expand Down Expand Up @@ -1226,183 +1225,6 @@ pub fn eval_subexpression(
Ok(input)
}

pub fn eval_nu_variable(engine_state: &EngineState, span: Span) -> Result<Value, ShellError> {
fn canonicalize_path(engine_state: &EngineState, path: &PathBuf) -> PathBuf {
let cwd = engine_state.current_work_dir();

if path.exists() {
match nu_path::canonicalize_with(path, cwd) {
Ok(canon_path) => canon_path,
Err(_) => path.clone(),
}
} else {
path.clone()
}
}

let mut record = Record::new();

record.push(
"default-config-dir",
if let Some(mut path) = nu_path::config_dir() {
path.push("nushell");
Value::string(path.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not get config directory".into()),
span,
)
},
);

record.push(
"config-path",
if let Some(path) = engine_state.get_config_path("config-path") {
let canon_config_path = canonicalize_path(engine_state, path);
Value::string(canon_config_path.to_string_lossy(), span)
} else if let Some(mut path) = nu_path::config_dir() {
path.push("nushell");
path.push("config.nu");
Value::string(path.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not get config directory".into()),
span,
)
},
);

record.push(
"env-path",
if let Some(path) = engine_state.get_config_path("env-path") {
let canon_env_path = canonicalize_path(engine_state, path);
Value::string(canon_env_path.to_string_lossy(), span)
} else if let Some(mut path) = nu_path::config_dir() {
path.push("nushell");
path.push("env.nu");
Value::string(path.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not find environment path".into()),
span,
)
},
);

record.push(
"history-path",
if let Some(mut path) = nu_path::config_dir() {
path.push("nushell");
match engine_state.config.history_file_format {
nu_protocol::HistoryFileFormat::Sqlite => {
path.push("history.sqlite3");
}
nu_protocol::HistoryFileFormat::PlainText => {
path.push("history.txt");
}
}
let canon_hist_path = canonicalize_path(engine_state, &path);
Value::string(canon_hist_path.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not find history path".into()),
span,
)
},
);

record.push(
"loginshell-path",
if let Some(mut path) = nu_path::config_dir() {
path.push("nushell");
path.push("login.nu");
let canon_login_path = canonicalize_path(engine_state, &path);
Value::string(canon_login_path.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not find login shell path".into()),
span,
)
},
);

#[cfg(feature = "plugin")]
{
record.push(
"plugin-path",
if let Some(path) = &engine_state.plugin_signatures {
let canon_plugin_path = canonicalize_path(engine_state, path);
Value::string(canon_plugin_path.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not get plugin signature location".into()),
span,
)
},
);
}

record.push(
"home-path",
if let Some(path) = nu_path::home_dir() {
let canon_home_path = canonicalize_path(engine_state, &path);
Value::string(canon_home_path.to_string_lossy(), span)
} else {
Value::error(ShellError::IOError("Could not get home path".into()), span)
},
);

record.push("temp-path", {
let canon_temp_path = canonicalize_path(engine_state, &std::env::temp_dir());
Value::string(canon_temp_path.to_string_lossy(), span)
});

record.push("pid", Value::int(std::process::id().into(), span));

record.push("os-info", {
let sys = sysinfo::System::new();
let ver = match sys.kernel_version() {
Some(v) => v,
None => "unknown".into(),
};
Value::record(
record! {
"name" => Value::string(std::env::consts::OS, span),
"arch" => Value::string(std::env::consts::ARCH, span),
"family" => Value::string(std::env::consts::FAMILY, span),
"kernel_version" => Value::string(ver, span),
},
span,
)
});

record.push(
"startup-time",
Value::duration(engine_state.get_startup_time(), span),
);

record.push(
"is-interactive",
Value::bool(engine_state.is_interactive, span),
);

record.push("is-login", Value::bool(engine_state.is_login, span));

record.push(
"current-exe",
if let Ok(current_exe) = std::env::current_exe() {
Value::string(current_exe.to_string_lossy(), span)
} else {
Value::error(
ShellError::IOError("Could not get current executable path".to_string()),
span,
)
},
);

Ok(Value::record(record, span))
}

pub fn eval_variable(
engine_state: &EngineState,
stack: &Stack,
Expand All @@ -1411,7 +1233,14 @@ pub fn eval_variable(
) -> Result<Value, ShellError> {
match var_id {
// $nu
nu_protocol::NU_VARIABLE_ID => eval_nu_variable(engine_state, span),
nu_protocol::NU_VARIABLE_ID => {
if let Some(val) = engine_state.get_constant(var_id) {
Ok(val.clone())
} else {
Err(ShellError::VariableNotFoundAtRuntime { span })
}
}
// $env
ENV_VARIABLE_ID => {
let env_vars = stack.get_env_vars(engine_state);
let env_columns = env_vars.keys();
Expand Down
2 changes: 2 additions & 0 deletions crates/nu-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ bench = false

[dependencies]
nu-utils = { path = "../nu-utils", version = "0.84.1" }
nu-path = { path = "../nu-path", version = "0.84.1" }
nu-system = { path = "../nu-system", version = "0.84.1" }

byte-unit = "4.0"
chrono = { version = "0.4", features = [ "serde", "std", "unstable-locales" ], default-features = false }
Expand Down
9 changes: 9 additions & 0 deletions crates/nu-protocol/src/engine/engine_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,15 @@ impl EngineState {
.expect("internal error: missing variable")
}

pub fn get_constant(&self, var_id: VarId) -> Option<&Value> {
let var = self.get_var(var_id);
var.const_val.as_ref()
}

pub fn set_variable_const_val(&mut self, var_id: VarId, val: Value) {
self.vars[var_id].const_val = Some(val);
}

#[allow(clippy::borrowed_box)]
pub fn get_decl(&self, decl_id: DeclId) -> &Box<dyn Command> {
self.decls
Expand Down

0 comments on commit f35808c

Please sign in to comment.