Make some plugins optional, move ps to plugin

This commit is contained in:
Jonathan Turner 2019-09-08 19:06:15 +12:00
parent eecda3ecba
commit 448b1a4848
5 changed files with 106 additions and 90 deletions

View file

@ -50,7 +50,6 @@ git2 = { version = "0.10.0", default_features = false }
dirs = "2.0.2" dirs = "2.0.2"
glob = "0.3.0" glob = "0.3.0"
ctrlc = "3.1.3" ctrlc = "3.1.3"
ptree = "0.2"
surf = "1.0.2" surf = "1.0.2"
url = "2.1.0" url = "2.1.0"
roxmltree = "0.7.0" roxmltree = "0.7.0"
@ -62,29 +61,36 @@ subprocess = "0.1.18"
mime = "0.3.13" mime = "0.3.13"
regex = "1.2.1" regex = "1.2.1"
pretty-hex = "0.1.0" pretty-hex = "0.1.0"
neso = { version = "0.5.0", optional = true }
hex = "0.3.2" hex = "0.3.2"
crossterm = "0.10.2"
tempfile = "3.1.0" tempfile = "3.1.0"
image = { version = "0.22.1", default_features = false, features = ["png_codec", "jpeg"] }
semver = "0.9.0" 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" which = "2.0.1"
battery = "0.7.4" uuid = {version = "0.7.4", features = [ "v4", "serde" ]}
textwrap = {version = "0.11.0", features = ["term_size"]} 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" shellexpand = "1.0.0"
futures-timer = "0.3.0" futures-timer = "0.3.0"
pin-utils = "0.1.0-alpha.4" pin-utils = "0.1.0-alpha.4"
num-bigint = { version = "0.2.2", features = ["serde"] } num-bigint = { version = "0.2.2", features = ["serde"] }
bigdecimal = { version = "0.1.0", 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] [features]
raw-key = ["rawkey", "neso"] 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] [dependencies.rusqlite]
version = "0.20.0" version = "0.20.0"
@ -128,18 +134,27 @@ path = "src/plugins/skip.rs"
[[bin]] [[bin]]
name = "nu_plugin_sys" name = "nu_plugin_sys"
path = "src/plugins/sys.rs" path = "src/plugins/sys.rs"
required-features = ["sys"]
[[bin]]
name = "nu_plugin_ps"
path = "src/plugins/ps.rs"
required-features = ["ps"]
[[bin]] [[bin]]
name = "nu_plugin_tree" name = "nu_plugin_tree"
path = "src/plugins/tree.rs" path = "src/plugins/tree.rs"
required-features = ["tree"]
[[bin]] [[bin]]
name = "nu_plugin_binaryview" name = "nu_plugin_binaryview"
path = "src/plugins/binaryview.rs" path = "src/plugins/binaryview.rs"
required-features = ["binaryview"]
[[bin]] [[bin]]
name = "nu_plugin_textview" name = "nu_plugin_textview"
path = "src/plugins/textview.rs" path = "src/plugins/textview.rs"
required-features = ["textview"]
[[bin]] [[bin]]
name = "nu" name = "nu"

View file

@ -163,7 +163,6 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
use crate::commands::*; use crate::commands::*;
context.add_commands(vec![ context.add_commands(vec![
whole_stream_command(PS),
whole_stream_command(PWD), whole_stream_command(PWD),
whole_stream_command(LS), whole_stream_command(LS),
whole_stream_command(CD), whole_stream_command(CD),

View file

@ -39,7 +39,6 @@ pub(crate) mod pick;
pub(crate) mod plugin; pub(crate) mod plugin;
pub(crate) mod post; pub(crate) mod post;
pub(crate) mod prev; pub(crate) mod prev;
pub(crate) mod ps;
pub(crate) mod pwd; pub(crate) mod pwd;
pub(crate) mod reject; pub(crate) mod reject;
pub(crate) mod reverse; pub(crate) mod reverse;
@ -106,7 +105,6 @@ pub(crate) use open::Open;
pub(crate) use pick::Pick; pub(crate) use pick::Pick;
pub(crate) use post::Post; pub(crate) use post::Post;
pub(crate) use prev::Previous; pub(crate) use prev::Previous;
pub(crate) use ps::PS;
pub(crate) use pwd::PWD; pub(crate) use pwd::PWD;
pub(crate) use reject::Reject; pub(crate) use reject::Reject;
pub(crate) use reverse::Reverse; pub(crate) use reverse::Reverse;

View file

@ -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<OutputStream, ShellError> {
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<OutputStream, ShellError> {
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::<ratio::percent>()));
yield ReturnSuccess::value(dict.into_tagged_value());
}
}
};
Ok(stream.to_output_stream())
}

80
src/plugins/ps.rs Normal file
View file

@ -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<Tagged<Value>> {
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::<ratio::percent>()));
output.push(dict.into_tagged_value());
}
}
output
}
impl Plugin for Ps {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("ps")
.desc("View information about system processes.")
.filter())
}
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
Ok(block_on(ps(Tag::unknown_origin(callinfo.name_span)))
.into_iter()
.map(ReturnSuccess::value)
.collect())
}
fn filter(&mut self, _: Tagged<Value>) -> Result<Vec<ReturnValue>, ShellError> {
Ok(vec![])
}
}
fn main() {
serve_plugin(&mut Ps::new());
}