summaryrefslogtreecommitdiff
path: root/src/status_cmd.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/status_cmd.rs')
-rw-r--r--src/status_cmd.rs86
1 files changed, 29 insertions, 57 deletions
diff --git a/src/status_cmd.rs b/src/status_cmd.rs
index 4d9c453..f6c9c2c 100644
--- a/src/status_cmd.rs
+++ b/src/status_cmd.rs
@@ -1,22 +1,22 @@
-use std::io::{BufRead, BufReader, Write};
-use std::os::unix::prelude::AsRawFd;
-use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio};
+use std::io::Write;
+use std::process::{Child, ChildStdin, Command, Stdio};
use anyhow::Result;
-use tokio::io::unix::AsyncFd;
-use tokio::io::Interest;
+use tokio::io::AsyncReadExt;
+use tokio::process::ChildStdout;
use crate::i3bar_protocol::{Block, Event, Protocol};
+const INITIAL_BUF_CAPACITY: usize = 4096;
+
#[derive(Debug)]
pub struct StatusCmd {
pub child: Child,
- output: BufReader<ChildStdout>,
+ pub output: ChildStdout,
input: ChildStdin,
protocol: Protocol,
buf: Vec<u8>,
- pub async_fd: AsyncFd<i32>,
}
impl StatusCmd {
@@ -28,73 +28,45 @@ impl StatusCmd {
.spawn()?;
let output = child.stdout.take().unwrap();
let input = child.stdin.take().unwrap();
- let async_fd = AsyncFd::with_interest(output.as_raw_fd(), Interest::READABLE)?;
Ok(Self {
child,
- output: BufReader::new(output),
+ output: ChildStdout::from_std(output)?,
input,
protocol: Protocol::Unknown,
- buf: Vec::new(),
- async_fd,
+ buf: Vec::with_capacity(INITIAL_BUF_CAPACITY),
})
}
pub fn notify_available(&mut self) -> Result<Option<Vec<Block>>> {
- let buf = self.output.fill_buf()?;
- if buf.is_empty() {
- bail!("status command exited");
- }
- if self.buf.is_empty() {
- let rem = self.protocol.process_new_bytes(buf)?;
- if !rem.is_empty() {
- self.buf.extend_from_slice(rem);
- }
+ let rem = self.protocol.process_new_bytes(&self.buf)?;
+ if rem.is_empty() {
+ self.buf.clear();
} else {
- self.buf.extend_from_slice(buf);
- let rem = self.protocol.process_new_bytes(&self.buf)?;
- if rem.is_empty() {
- self.buf.clear();
- } else {
- let used = self.buf.len() - rem.len();
- self.buf.drain(..used);
- }
+ let used = self.buf.len() - rem.len();
+ self.buf.drain(..used);
}
- let consumed = buf.len();
- self.output.consume(consumed);
Ok(self.protocol.get_blocks())
}
+ pub async fn read(&mut self) -> Result<()> {
+ assert!(self.buf.capacity() >= INITIAL_BUF_CAPACITY);
+ if self.buf.capacity() == self.buf.len() {
+ // Double the capacity
+ self.buf.reserve(self.buf.len());
+ }
+
+ let read_len = self.output.read_buf(&mut self.buf).await?;
+ if read_len == 0 {
+ bail!("status command exited");
+ }
+
+ Ok(())
+ }
+
pub fn send_click_event(&mut self, event: &Event) -> Result<()> {
if self.protocol.supports_clicks() {
writeln!(self.input, "{}", serde_json::to_string(event).unwrap())?;
}
Ok(())
}
-
- // pub fn quick_insert(&self, handle: LoopHandle<BarState>) {
- // handle
- // .insert_source(
- // calloop::generic::Generic::new(
- // self.output.get_ref().as_raw_fd(),
- // calloop::Interest {
- // readable: true,
- // writable: false,
- // },
- // calloop::Mode::Level,
- // ),
- // move |ready, _, bar_state| {
- // if ready.readable {
- // bar_state.notify_available()?;
- // Ok(calloop::PostAction::Continue)
- // } else {
- // bar_state.set_error("error reading from status command");
- // if let Some(mut child) = bar_state.status_cmd.take() {
- // let _ = child.child.kill();
- // }
- // Ok(calloop::PostAction::Remove)
- // }
- // },
- // )
- // .expect("failed to inser calloop source");
- // }
}