forked from extern/nushell
Merge pull request #617 from jonathandturner/more_optional
Make some plugins optional, move ps to plugin
This commit is contained in:
commit
ffd92362b0
37
Cargo.toml
37
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"
|
||||
|
@ -163,7 +163,6 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
use crate::commands::*;
|
||||
|
||||
context.add_commands(vec![
|
||||
whole_stream_command(PS),
|
||||
whole_stream_command(PWD),
|
||||
whole_stream_command(LS),
|
||||
whole_stream_command(CD),
|
||||
|
@ -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;
|
||||
|
@ -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
80
src/plugins/ps.rs
Normal 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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user