nushell/crates/nu-command/src/system/sys.rs

301 lines
9.3 KiB
Rust
Raw Normal View History

use chrono::prelude::DateTime;
use chrono::Local;
2021-10-01 06:53:47 +00:00
use nu_protocol::{
ast::Call,
2021-10-25 16:58:58 +00:00
engine::{Command, EngineState, Stack},
record, Category, Example, IntoPipelineData, LazyRecord, PipelineData, Record, ShellError,
Signature, Span, Type, Value,
2021-10-01 06:53:47 +00:00
};
use std::time::{Duration, UNIX_EPOCH};
use sysinfo::{
ComponentExt, CpuExt, CpuRefreshKind, DiskExt, NetworkExt, System, SystemExt, UserExt,
};
2021-10-01 06:53:47 +00:00
2021-10-25 04:01:02 +00:00
#[derive(Clone)]
2021-10-01 06:53:47 +00:00
pub struct Sys;
impl Command for Sys {
fn name(&self) -> &str {
"sys"
}
fn signature(&self) -> Signature {
Signature::build("sys")
.filter()
.category(Category::System)
.input_output_types(vec![(Type::Nothing, Type::Record(vec![]))])
2021-10-01 06:53:47 +00:00
}
fn usage(&self) -> &str {
"View information about the system."
}
fn run(
&self,
2021-10-25 06:31:39 +00:00
_engine_state: &EngineState,
_stack: &mut Stack,
2021-10-01 06:53:47 +00:00
call: &Call,
2021-10-25 04:01:02 +00:00
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let span = call.span();
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
let ret = Value::lazy_record(Box::new(SysResult { span }), span);
Ok(ret.into_pipeline_data())
2021-10-01 06:53:47 +00:00
}
2021-10-01 21:53:13 +00:00
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Show info about the system",
example: "sys",
result: None,
},
Example {
description: "Show the os system name with get",
example: "(sys).host | get name",
result: None,
},
Example {
description: "Show the os system name",
example: "(sys).host.name",
result: None,
},
]
2021-10-01 21:53:13 +00:00
}
2021-10-01 06:53:47 +00:00
}
Feature: Userland LazyRecords (#8332) # Description Despite the innocent-looking title, this PR involves quite a few backend changes as the existing LazyRecord trait was not at all friendly towards the idea of these values being generated on the fly from Nu code. In particular, here are a few changes involved: - The LazyRecord trait now involves a lifetime `'a`, and this lifetime is used in the return value of `get_column_names`. This means it no longer returns `'static str`s (but implementations still can return these). This is more stringent on the consumption side. - The LazyRecord trait now must be able to clone itself via a new `clone_value` method (as requiring `Clone` is not object safe). This pattern is borrowed from `Value::CustomValue`. - LazyRecord no longer requires being serde serializable and deserializable. These, in hand, allow for the following: - LazyRecord can now clone itself, which means that they don't have to be collected into a Record when being cloned. - This is especially useful in Stack, which is cloned on each repl line and in a few other cases. This would mean that _every_ LazyRecord instance stored in a variable would be collected in its entirety and cloned, which can be catastrophic for performance. See: `let nulol = $nu`. - LazyRecord's columns don't have to be static, they can have the same lifetime of the struct itself, so different instances of the same LazyRecord type can have different columns and values (like the new `NuLazyRecord`) - Serialization and deserialization are no longer meaningless, they are simply less. I would consider this PR very "drafty", but everything works. It probably requires some cleanup and testing, though, but I'd like some eyes and pointers first. # User-Facing Changes New command. New restrictions are largely internal. Maybe there are some plugins affected? Example of new command's usage: ``` lazy make --columns [a b c] --get-value { |name| print $"getting ($name)"; $name | str upcase } ``` You can also trivially implement something like `lazy make record` to take a record of closures and turn it into a getter-like lazy struct: ``` def "lazy make record" [ record: record ] { let columns = ($record | columns) lazy make --columns $columns --get-value { |col| do ($record | get $col) } } ``` Open to bikeshedding. `lazy make` is similar to `error make` which is also in the core commands. I didn't like `make lazy` since it sounded like some transformation was going on. # Tour for reviewers Take a look at LazyMake's examples. They have `None` as the results, as such they aren't _really_ correct and aren't being tested at all. I didn't do this because creating the Value::LazyRecord is a little tricky and didn't want to risk messing it up, especially as the necessary variables aren't available when creating the examples (like stack and engine state). Also take a look at NuLazyRecord's get_value implementation, or in general. It uses an Arc<Mutex<_>> for the stack, which must be accessed mutably for eval_block but get_value only provides us with a `&self`. This is a sad state of affairs, but I don't know if there's a better way. On the same code path, we also have pipeline handling, and any pipeline that isn't a Pipeline::Value will return Value::nothing. I believe returning a Value::Error is probably better, or maybe some other handling. Couldn't decide on which ShellError to settle with for that branch. The "unfortunate casualty" in the columns.rs file. I'm not sure just how bad that is, though, I simply had to fight a little with the borrow checker. A few leftover comments like derives, comments about the now non-existing serde requirements, and impls. I'll definitely get around to those eventually but they're in atm Should NuLazyRecord implement caching? I'm leaning heavily towards **yes**, this was one of the main reasons not to use a record of closures (besides convenience), but maybe it could be opt-out. I'd wonder about its implementation too, but a simple way would be to move a HashMap into the mutex state and keep cached values there.
2023-05-17 23:35:22 +00:00
#[derive(Debug, Clone)]
pub struct SysResult {
pub span: Span,
}
2021-10-01 06:53:47 +00:00
Feature: Userland LazyRecords (#8332) # Description Despite the innocent-looking title, this PR involves quite a few backend changes as the existing LazyRecord trait was not at all friendly towards the idea of these values being generated on the fly from Nu code. In particular, here are a few changes involved: - The LazyRecord trait now involves a lifetime `'a`, and this lifetime is used in the return value of `get_column_names`. This means it no longer returns `'static str`s (but implementations still can return these). This is more stringent on the consumption side. - The LazyRecord trait now must be able to clone itself via a new `clone_value` method (as requiring `Clone` is not object safe). This pattern is borrowed from `Value::CustomValue`. - LazyRecord no longer requires being serde serializable and deserializable. These, in hand, allow for the following: - LazyRecord can now clone itself, which means that they don't have to be collected into a Record when being cloned. - This is especially useful in Stack, which is cloned on each repl line and in a few other cases. This would mean that _every_ LazyRecord instance stored in a variable would be collected in its entirety and cloned, which can be catastrophic for performance. See: `let nulol = $nu`. - LazyRecord's columns don't have to be static, they can have the same lifetime of the struct itself, so different instances of the same LazyRecord type can have different columns and values (like the new `NuLazyRecord`) - Serialization and deserialization are no longer meaningless, they are simply less. I would consider this PR very "drafty", but everything works. It probably requires some cleanup and testing, though, but I'd like some eyes and pointers first. # User-Facing Changes New command. New restrictions are largely internal. Maybe there are some plugins affected? Example of new command's usage: ``` lazy make --columns [a b c] --get-value { |name| print $"getting ($name)"; $name | str upcase } ``` You can also trivially implement something like `lazy make record` to take a record of closures and turn it into a getter-like lazy struct: ``` def "lazy make record" [ record: record ] { let columns = ($record | columns) lazy make --columns $columns --get-value { |col| do ($record | get $col) } } ``` Open to bikeshedding. `lazy make` is similar to `error make` which is also in the core commands. I didn't like `make lazy` since it sounded like some transformation was going on. # Tour for reviewers Take a look at LazyMake's examples. They have `None` as the results, as such they aren't _really_ correct and aren't being tested at all. I didn't do this because creating the Value::LazyRecord is a little tricky and didn't want to risk messing it up, especially as the necessary variables aren't available when creating the examples (like stack and engine state). Also take a look at NuLazyRecord's get_value implementation, or in general. It uses an Arc<Mutex<_>> for the stack, which must be accessed mutably for eval_block but get_value only provides us with a `&self`. This is a sad state of affairs, but I don't know if there's a better way. On the same code path, we also have pipeline handling, and any pipeline that isn't a Pipeline::Value will return Value::nothing. I believe returning a Value::Error is probably better, or maybe some other handling. Couldn't decide on which ShellError to settle with for that branch. The "unfortunate casualty" in the columns.rs file. I'm not sure just how bad that is, though, I simply had to fight a little with the borrow checker. A few leftover comments like derives, comments about the now non-existing serde requirements, and impls. I'll definitely get around to those eventually but they're in atm Should NuLazyRecord implement caching? I'm leaning heavily towards **yes**, this was one of the main reasons not to use a record of closures (besides convenience), but maybe it could be opt-out. I'd wonder about its implementation too, but a simple way would be to move a HashMap into the mutex state and keep cached values there.
2023-05-17 23:35:22 +00:00
impl LazyRecord<'_> for SysResult {
fn column_names(&self) -> Vec<&'static str> {
vec!["host", "cpu", "disks", "mem", "temp", "net"]
2021-10-01 06:53:47 +00:00
}
fn get_column_value(&self, column: &str) -> Result<Value, ShellError> {
let span = self.span;
match column {
"host" => Ok(host(span)),
"cpu" => Ok(cpu(span)),
"disks" => Ok(disks(span)),
"mem" => Ok(mem(span)),
"temp" => Ok(temp(span)),
"net" => Ok(net(span)),
_ => Err(ShellError::LazyRecordAccessFailed {
message: format!("Could not find column '{column}'"),
column_name: column.to_string(),
span,
}),
}
2021-10-01 06:53:47 +00:00
}
fn span(&self) -> Span {
self.span
2021-10-01 06:53:47 +00:00
}
Feature: Userland LazyRecords (#8332) # Description Despite the innocent-looking title, this PR involves quite a few backend changes as the existing LazyRecord trait was not at all friendly towards the idea of these values being generated on the fly from Nu code. In particular, here are a few changes involved: - The LazyRecord trait now involves a lifetime `'a`, and this lifetime is used in the return value of `get_column_names`. This means it no longer returns `'static str`s (but implementations still can return these). This is more stringent on the consumption side. - The LazyRecord trait now must be able to clone itself via a new `clone_value` method (as requiring `Clone` is not object safe). This pattern is borrowed from `Value::CustomValue`. - LazyRecord no longer requires being serde serializable and deserializable. These, in hand, allow for the following: - LazyRecord can now clone itself, which means that they don't have to be collected into a Record when being cloned. - This is especially useful in Stack, which is cloned on each repl line and in a few other cases. This would mean that _every_ LazyRecord instance stored in a variable would be collected in its entirety and cloned, which can be catastrophic for performance. See: `let nulol = $nu`. - LazyRecord's columns don't have to be static, they can have the same lifetime of the struct itself, so different instances of the same LazyRecord type can have different columns and values (like the new `NuLazyRecord`) - Serialization and deserialization are no longer meaningless, they are simply less. I would consider this PR very "drafty", but everything works. It probably requires some cleanup and testing, though, but I'd like some eyes and pointers first. # User-Facing Changes New command. New restrictions are largely internal. Maybe there are some plugins affected? Example of new command's usage: ``` lazy make --columns [a b c] --get-value { |name| print $"getting ($name)"; $name | str upcase } ``` You can also trivially implement something like `lazy make record` to take a record of closures and turn it into a getter-like lazy struct: ``` def "lazy make record" [ record: record ] { let columns = ($record | columns) lazy make --columns $columns --get-value { |col| do ($record | get $col) } } ``` Open to bikeshedding. `lazy make` is similar to `error make` which is also in the core commands. I didn't like `make lazy` since it sounded like some transformation was going on. # Tour for reviewers Take a look at LazyMake's examples. They have `None` as the results, as such they aren't _really_ correct and aren't being tested at all. I didn't do this because creating the Value::LazyRecord is a little tricky and didn't want to risk messing it up, especially as the necessary variables aren't available when creating the examples (like stack and engine state). Also take a look at NuLazyRecord's get_value implementation, or in general. It uses an Arc<Mutex<_>> for the stack, which must be accessed mutably for eval_block but get_value only provides us with a `&self`. This is a sad state of affairs, but I don't know if there's a better way. On the same code path, we also have pipeline handling, and any pipeline that isn't a Pipeline::Value will return Value::nothing. I believe returning a Value::Error is probably better, or maybe some other handling. Couldn't decide on which ShellError to settle with for that branch. The "unfortunate casualty" in the columns.rs file. I'm not sure just how bad that is, though, I simply had to fight a little with the borrow checker. A few leftover comments like derives, comments about the now non-existing serde requirements, and impls. I'll definitely get around to those eventually but they're in atm Should NuLazyRecord implement caching? I'm leaning heavily towards **yes**, this was one of the main reasons not to use a record of closures (besides convenience), but maybe it could be opt-out. I'd wonder about its implementation too, but a simple way would be to move a HashMap into the mutex state and keep cached values there.
2023-05-17 23:35:22 +00:00
fn clone_value(&self, span: Span) -> Value {
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
Value::lazy_record(Box::new((*self).clone()), span)
2021-10-25 04:01:02 +00:00
}
2021-10-01 06:53:47 +00:00
}
pub fn trim_cstyle_null(s: String) -> String {
s.trim_matches(char::from(0)).to_string()
}
pub fn disks(span: Span) -> Value {
let mut sys = System::new();
2021-10-01 06:53:47 +00:00
sys.refresh_disks();
sys.refresh_disks_list();
let mut output = vec![];
for disk in sys.disks() {
let device = trim_cstyle_null(disk.name().to_string_lossy().to_string());
let typ = trim_cstyle_null(String::from_utf8_lossy(disk.file_system()).to_string());
let record = record! {
"device" => Value::string(device, span),
"type" => Value::string(typ, span),
"mount" => Value::string(disk.mount_point().to_string_lossy(), span),
"total" => Value::filesize(disk.total_space() as i64, span),
"free" => Value::filesize(disk.available_space() as i64, span),
"removable" => Value::bool(disk.is_removable(), span),
"kind" => Value::string(format!("{:?}", disk.kind()), span),
};
output.push(Value::record(record, span));
2021-10-01 06:53:47 +00:00
}
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
Value::list(output, span)
2021-10-01 06:53:47 +00:00
}
pub fn net(span: Span) -> Value {
let mut sys = System::new();
2021-10-01 06:53:47 +00:00
sys.refresh_networks();
sys.refresh_networks_list();
let mut output = vec![];
for (iface, data) in sys.networks() {
let record = record! {
"name" => Value::string(trim_cstyle_null(iface.to_string()), span),
"sent" => Value::filesize(data.total_transmitted() as i64, span),
"recv" => Value::filesize(data.total_received() as i64, span),
};
2021-10-01 06:53:47 +00:00
output.push(Value::record(record, span));
2021-10-01 06:53:47 +00:00
}
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
Value::list(output, span)
2021-10-01 06:53:47 +00:00
}
pub fn cpu(span: Span) -> Value {
let mut sys = System::new();
sys.refresh_cpu_specifics(CpuRefreshKind::everything());
// We must refresh the CPU twice a while apart to get valid usage data.
// In theory we could just sleep MINIMUM_CPU_UPDATE_INTERVAL, but I've noticed that
// that gives poor results (error of ~5%). Decided to wait 2x that long, somewhat arbitrarily
std::thread::sleep(System::MINIMUM_CPU_UPDATE_INTERVAL * 2);
sys.refresh_cpu_specifics(CpuRefreshKind::new().with_cpu_usage());
2021-10-01 06:53:47 +00:00
let mut output = vec![];
for cpu in sys.cpus() {
// sysinfo CPU usage numbers are not very precise unless you wait a long time between refreshes.
// Round to 1DP (chosen somewhat arbitrarily) so people aren't misled by high-precision floats.
let rounded_usage = (cpu.cpu_usage() * 10.0).round() / 10.0;
let load_avg = sys.load_average();
let load_avg = trim_cstyle_null(format!(
"{:.2}, {:.2}, {:.2}",
load_avg.one, load_avg.five, load_avg.fifteen
));
let record = record! {
"name" => Value::string(trim_cstyle_null(cpu.name().to_string()), span),
"brand" => Value::string(trim_cstyle_null(cpu.brand().to_string()), span),
"freq" => Value::int(cpu.frequency() as i64, span),
"cpu_usage" => Value::float(rounded_usage as f64, span),
"load_average" => Value::string(load_avg, span),
"vendor_id" => Value::string(trim_cstyle_null(cpu.vendor_id().to_string()), span),
};
output.push(Value::record(record, span));
2021-10-01 06:53:47 +00:00
}
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
Value::list(output, span)
2021-10-01 06:53:47 +00:00
}
pub fn mem(span: Span) -> Value {
let mut sys = System::new();
2021-10-01 06:53:47 +00:00
sys.refresh_memory();
let total_mem = sys.total_memory();
let free_mem = sys.free_memory();
let used_mem = sys.used_memory();
let avail_mem = sys.available_memory();
2021-10-01 06:53:47 +00:00
let total_swap = sys.total_swap();
let free_swap = sys.free_swap();
let used_swap = sys.used_swap();
2021-10-01 06:53:47 +00:00
let record = record! {
"total" => Value::filesize(total_mem as i64, span),
"free" => Value::filesize(free_mem as i64, span),
"used" => Value::filesize(used_mem as i64, span),
"available" => Value::filesize(avail_mem as i64, span),
"swap total" => Value::filesize(total_swap as i64, span),
"swap free" => Value::filesize(free_swap as i64, span),
"swap used" => Value::filesize(used_swap as i64, span),
};
Value::record(record, span)
2021-10-01 06:53:47 +00:00
}
pub fn host(span: Span) -> Value {
let mut sys = System::new();
2021-10-01 06:53:47 +00:00
sys.refresh_users_list();
let mut record = Record::new();
2021-10-01 06:53:47 +00:00
if let Some(name) = sys.name() {
record.push("name", Value::string(trim_cstyle_null(name), span));
2021-10-01 06:53:47 +00:00
}
if let Some(version) = sys.os_version() {
record.push("os_version", Value::string(trim_cstyle_null(version), span));
2021-10-01 06:53:47 +00:00
}
if let Some(long_version) = sys.long_os_version() {
record.push(
"long_os_version",
Value::string(trim_cstyle_null(long_version), span),
);
}
2021-10-01 06:53:47 +00:00
if let Some(version) = sys.kernel_version() {
record.push(
"kernel_version",
Value::string(trim_cstyle_null(version), span),
);
2021-10-01 06:53:47 +00:00
}
if let Some(hostname) = sys.host_name() {
record.push("hostname", Value::string(trim_cstyle_null(hostname), span));
2021-10-01 06:53:47 +00:00
}
record.push(
"uptime",
Value::duration(1000000000 * sys.uptime() as i64, span),
);
2021-10-01 06:53:47 +00:00
// Creates a new SystemTime from the specified number of whole seconds
let d = UNIX_EPOCH + Duration::from_secs(sys.boot_time());
// Create DateTime from SystemTime
let datetime = DateTime::<Local>::from(d);
// Convert to local time and then rfc3339
let timestamp_str = datetime.with_timezone(datetime.offset()).to_rfc3339();
record.push("boot_time", Value::string(timestamp_str, span));
2021-10-01 06:53:47 +00:00
let mut users = vec![];
for user in sys.users() {
let mut groups = vec![];
for group in user.groups() {
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
groups.push(Value::string(trim_cstyle_null(group.to_string()), span));
2021-10-01 06:53:47 +00:00
}
let record = record! {
"name" => Value::string(trim_cstyle_null(user.name().to_string()), span),
"groups" => Value::list(groups, span),
};
2021-10-01 06:53:47 +00:00
users.push(Value::record(record, span));
2021-10-01 06:53:47 +00:00
}
2021-10-01 06:53:47 +00:00
if !users.is_empty() {
record.push("sessions", Value::list(users, span));
2021-10-01 06:53:47 +00:00
}
Value::record(record, span)
2021-10-01 06:53:47 +00:00
}
pub fn temp(span: Span) -> Value {
let mut sys = System::new();
2021-10-01 06:53:47 +00:00
sys.refresh_components();
sys.refresh_components_list();
let mut output = vec![];
for component in sys.components() {
let mut record = record! {
"unit" => Value::string(component.label(), span),
"temp" => Value::float(component.temperature() as f64, span),
"high" => Value::float(component.max() as f64, span),
};
2021-10-01 06:53:47 +00:00
if let Some(critical) = component.critical() {
record.push("critical", Value::float(critical as f64, span));
2021-10-01 06:53:47 +00:00
}
output.push(Value::record(record, span));
2021-10-01 06:53:47 +00:00
}
Move Value to helpers, separate span call (#10121) # Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
2023-09-03 14:27:29 +00:00
Value::list(output, span)
2021-10-01 06:53:47 +00:00
}