diff --git a/Cargo.toml b/Cargo.toml index dee6503e5..f9e13c934 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,6 @@ git2 = { version = "0.10.0", default_features = false } dirs = "2.0.2" glob = "0.3.0" ctrlc = "3.1.3" -ptree = "0.2" surf = "1.0.2" url = "2.1.0" roxmltree = "0.7.0" @@ -62,29 +61,36 @@ subprocess = "0.1.18" mime = "0.3.13" regex = "1.2.1" pretty-hex = "0.1.0" -neso = { version = "0.5.0", optional = true } hex = "0.3.2" -crossterm = "0.10.2" tempfile = "3.1.0" -image = { version = "0.22.1", default_features = false, features = ["png_codec", "jpeg"] } semver = "0.9.0" -uuid = {version = "0.7.4", features = [ "v4", "serde" ]} -syntect = "3.2.0" -onig_sys = "=69.1.0" -heim = "0.0.7" which = "2.0.1" -battery = "0.7.4" +uuid = {version = "0.7.4", features = [ "v4", "serde" ]} textwrap = {version = "0.11.0", features = ["term_size"]} -rawkey = {version = "0.1.2", optional = true } -clipboard = {version = "0.5", optional = true } shellexpand = "1.0.0" futures-timer = "0.3.0" pin-utils = "0.1.0-alpha.4" num-bigint = { version = "0.2.2", features = ["serde"] } bigdecimal = { version = "0.1.0", features = ["serde"] } +neso = { version = "0.5.0", optional = true } +crossterm = { version = "0.10.2", optional = true } +syntect = {version = "3.2.0", optional = true } +onig_sys = {version = "=69.1.0", optional = true } +heim = {version = "0.0.7", optional = true } +battery = {version = "0.7.4", optional = true } +rawkey = {version = "0.1.2", optional = true } +clipboard = {version = "0.5", optional = true } +ptree = {version = "0.2", optional = true } +image = { version = "0.22.1", default_features = false, features = ["png_codec", "jpeg"], optional = true } + [features] raw-key = ["rawkey", "neso"] +textview = ["syntect", "onig_sys", "crossterm"] +binaryview = ["image", "crossterm"] +sys = ["heim", "battery"] +ps = ["heim"] +all = ["raw-key", "textview", "binaryview", "sys", "ps", "clipboard", "ptree"] [dependencies.rusqlite] version = "0.20.0" @@ -128,18 +134,27 @@ path = "src/plugins/skip.rs" [[bin]] name = "nu_plugin_sys" path = "src/plugins/sys.rs" +required-features = ["sys"] + +[[bin]] +name = "nu_plugin_ps" +path = "src/plugins/ps.rs" +required-features = ["ps"] [[bin]] name = "nu_plugin_tree" path = "src/plugins/tree.rs" +required-features = ["tree"] [[bin]] name = "nu_plugin_binaryview" path = "src/plugins/binaryview.rs" +required-features = ["binaryview"] [[bin]] name = "nu_plugin_textview" path = "src/plugins/textview.rs" +required-features = ["textview"] [[bin]] name = "nu" diff --git a/src/cli.rs b/src/cli.rs index cfd9d8de6..ec8c7085c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -163,7 +163,6 @@ pub async fn cli() -> Result<(), Box> { use crate::commands::*; context.add_commands(vec![ - whole_stream_command(PS), whole_stream_command(PWD), whole_stream_command(LS), whole_stream_command(CD), diff --git a/src/commands.rs b/src/commands.rs index f2885f369..c6cc7b728 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -39,7 +39,6 @@ pub(crate) mod pick; pub(crate) mod plugin; pub(crate) mod post; pub(crate) mod prev; -pub(crate) mod ps; pub(crate) mod pwd; pub(crate) mod reject; pub(crate) mod reverse; @@ -106,7 +105,6 @@ pub(crate) use open::Open; pub(crate) use pick::Pick; pub(crate) use post::Post; pub(crate) use prev::Previous; -pub(crate) use ps::PS; pub(crate) use pwd::PWD; pub(crate) use reject::Reject; pub(crate) use reverse::Reverse; diff --git a/src/commands/ps.rs b/src/commands/ps.rs deleted file mode 100644 index cdacd7113..000000000 --- a/src/commands/ps.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; -use crate::data::TaggedDictBuilder; -use crate::prelude::*; -use std::time::Duration; -use std::usize; - -use futures::stream::{StreamExt, TryStreamExt}; -use heim::process::{self as process, Process, ProcessResult}; -use heim::units::{ratio, Ratio}; - -pub struct PS; - -impl WholeStreamCommand for PS { - fn name(&self) -> &str { - "ps" - } - - fn signature(&self) -> Signature { - Signature::build("ps") - } - - fn usage(&self) -> &str { - "View current processes." - } - - fn run( - &self, - args: CommandArgs, - registry: &CommandRegistry, - ) -> Result { - ps(args, registry) - } -} - -async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio)> { - let usage_1 = process.cpu_usage().await?; - futures_timer::Delay::new(Duration::from_millis(100)).await?; - let usage_2 = process.cpu_usage().await?; - - Ok((process, usage_2 - usage_1)) -} - -fn ps(args: CommandArgs, registry: &CommandRegistry) -> Result { - let args = args.evaluate_once(registry)?; - let span = args.name_span(); - - let stream = async_stream_block! { - let processes = process::processes() - .map_ok(|process| { - // Note that there is no `.await` here, - // as we want to pass the returned future - // into the `.try_buffer_unordered`. - usage(process) - }) - .try_buffer_unordered(usize::MAX); - pin_utils::pin_mut!(processes); - - while let Some(res) = processes.next().await { - if let Ok((process, usage)) = res { - let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span)); - dict.insert("pid", Value::int(process.pid())); - if let Ok(name) = process.name().await { - dict.insert("name", Value::string(name)); - } - if let Ok(status) = process.status().await { - dict.insert("status", Value::string(format!("{:?}", status))); - } - dict.insert("cpu", Value::number(usage.get::())); - yield ReturnSuccess::value(dict.into_tagged_value()); - } - } - }; - - Ok(stream.to_output_stream()) -} diff --git a/src/plugins/ps.rs b/src/plugins/ps.rs new file mode 100644 index 000000000..0f06167bd --- /dev/null +++ b/src/plugins/ps.rs @@ -0,0 +1,80 @@ +use futures::executor::block_on; +use futures::stream::{StreamExt, TryStreamExt}; + +use heim::process::{self as process, Process, ProcessResult}; +use heim::units::{ratio, Ratio}; +use std::usize; + +use nu::{ + serve_plugin, CallInfo, Plugin, ReturnSuccess, ReturnValue, ShellError, Signature, Tag, Tagged, + TaggedDictBuilder, Value, +}; +use std::time::Duration; + +struct Ps; +impl Ps { + fn new() -> Ps { + Ps + } +} + +async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio)> { + let usage_1 = process.cpu_usage().await?; + futures_timer::Delay::new(Duration::from_millis(100)).await?; + let usage_2 = process.cpu_usage().await?; + + Ok((process, usage_2 - usage_1)) +} + +async fn ps(tag: Tag) -> Vec> { + let processes = process::processes() + .map_ok(|process| { + // Note that there is no `.await` here, + // as we want to pass the returned future + // into the `.try_buffer_unordered`. + usage(process) + }) + .try_buffer_unordered(usize::MAX); + pin_utils::pin_mut!(processes); + + let mut output = vec![]; + while let Some(res) = processes.next().await { + if let Ok((process, usage)) = res { + let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(tag.span)); + dict.insert("pid", Value::int(process.pid())); + if let Ok(name) = process.name().await { + dict.insert("name", Value::string(name)); + } + if let Ok(status) = process.status().await { + dict.insert("status", Value::string(format!("{:?}", status))); + } + dict.insert("cpu", Value::number(usage.get::())); + output.push(dict.into_tagged_value()); + } + } + + output +} + +impl Plugin for Ps { + fn config(&mut self) -> Result { + Ok(Signature::build("ps") + .desc("View information about system processes.") + .filter()) + } + + fn begin_filter(&mut self, callinfo: CallInfo) -> Result, ShellError> { + Ok(block_on(ps(Tag::unknown_origin(callinfo.name_span))) + .into_iter() + .map(ReturnSuccess::value) + .collect()) + } + + fn filter(&mut self, _: Tagged) -> Result, ShellError> { + Ok(vec![]) + } +} + +fn main() { + serve_plugin(&mut Ps::new()); +}