mirror of
https://github.com/nushell/nushell.git
synced 2025-08-19 03:46:00 +02:00
Make some plugins optional, move ps to plugin
This commit is contained in:
@@ -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());
|
||||
}
|
Reference in New Issue
Block a user