tokio-i3ipc

Crates.iotokio-i3ipc
lib.rstokio-i3ipc
version0.16.0
sourcesrc
created_at2019-04-21 02:22:37.502563
updated_at2022-12-31 00:40:53.955052
descriptionBindings for i3 and tokio allowing async applications to communicate with i3 over it's IPC interface. Contains futures implementations and convenience functions for working with i3.
homepage
repositoryhttps://github.com/leshow/tokio-i3ipc
max_upload_size
id129174
size37,163
Evan Cameron (leshow)

documentation

README

tokio-i3ipc

Now with tokio 1.0 support! Use version 0.12.0 and up for tokio 1.0

Build Status Crate API

This crate provides types and functions for working with i3's IPC protocol within tokio. It re-exports the crate i3ipc-types because it is also used for a synchronous version of the code.

I expect the most common use case will be to subscribe to some events and listen:

use std::io;
use tokio::stream::StreamExt;
use tokio_i3ipc::{
    event::{Event, Subscribe},
    I3,
};

#[tokio::main(flavor = "current_thread")]
async fn main() -> io::Result<()> {
    let mut i3 = I3::connect().await?;
    let resp = i3.subscribe([Subscribe::Window]).await?;

    println!("{:#?}", resp);
    let mut listener = i3.listen();
    while let Some(event) = listener.next().await {
        match event? {
            Event::Workspace(ev) => println!("workspace change event {:?}", ev),
            Event::Window(ev) => println!("window event {:?}", ev),
            Event::Output(ev) => println!("output event {:?}", ev),
            Event::Mode(ev) => println!("mode event {:?}", ev),
            Event::BarConfig(ev) => println!("bar config update {:?}", ev),
            Event::Binding(ev) => println!("binding event {:?}", ev),
            Event::Shutdown(ev) => println!("shutdown event {:?}", ev),
            Event::Tick(ev) => println!("tick event {:?}", ev),
        }
    }
    Ok(())
}

Another example, getting all workspaces from i3:

use std::io;
use tokio_i3ipc::{reply, I3};

#[tokio::main(flavor = "current_thread")]]
async fn main() -> io::Result<()> {
    let mut i3 = I3::connect().await?;
    // this type can be inferred, here is written explicitly:
    let worksp: reply::Workspaces = i3.get_workspaces().await?;
    println!("{:#?}", worksp);

    Ok(())
}

or, you could write any get_* yourself using the same methods it does:

use std::io;
use tokio_i3ipc::{msg, reply, MsgResponse, I3};

#[tokio::main(flavor = "current_thread")]
async fn main() -> io::Result<()> {
    let mut i3 = I3::connect().await?;
    // send msg RunCommand with a payload
    let payload = "some_command";
    i3.send_msg_body(msg::Msg::RunCommand, payload).await?;
    let resp: MsgResponse<Vec<reply::Success>> = i3.read_msg().await?;
    Ok(())
}

send_msg, will handle writing to i3. read_msg and will handle reading.

Sending Messages to i3

To send messages to i3, there are a number of convenience methods on I3.

use std::io;
use tokio_i3ipc::{reply, I3};

#[tokio::main(flavor = "current_thread")]]
async fn main() -> io::Result<()> {
    let mut i3 = I3::connect().await?;
    // this type can be inferred, here is written explicitly:
    let outputs = i3.get_outputs().await?;
    println!("{:#?}", worksp);

    Ok(())
}

"Real world" example

I have a fork of an i3 window-logging application that uses tokio-i3ipc (https://github.com/leshow/i3-tracker-rs/). The tracker subscribes to window events and logs how much time is spent on each node.

Commit count: 249

cargo fmt