Skip to content

Commit

Permalink
feat: convert to using swayipc
Browse files Browse the repository at this point in the history
It is compatible with i3, so it can work for both sway and i3
  • Loading branch information
roosta committed Dec 13, 2024
1 parent 595145a commit f74d622
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 71 deletions.
47 changes: 23 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ itertools = "0.13"
regex = "1.11"
dirs = "5.0"
thiserror = "1.0"
# swayipc = "3.0"
swayipc = "3.0"

# log = "0.4"

[dependencies.i3ipc]
git = 'https://github.com/roosta/i3ipc-rs'
# [dependencies.i3ipc]
# git = 'https://github.com/roosta/i3ipc-rs'
# path = "../i3ipc-rs"
59 changes: 30 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use i3ipc::{
event::{
inner::{WindowChange, WorkspaceChange},
WindowEventInfo, WorkspaceEventInfo,
},
reply::{Node, NodeType, WindowProperty},
I3Connection,
use swayipc::{
Connection,
Node,
NodeType,
WindowChange,
WindowEvent,
WindowProperties,
WorkspaceChange,
WorkspaceEvent,
};
use itertools::Itertools;
use std::collections::HashMap;

pub mod config;
pub mod regex;
Expand Down Expand Up @@ -36,21 +37,21 @@ fn format_with_icon(icon: &char, title: &str, no_names: bool, no_icon_names: boo
}

fn get_title(
props: &HashMap<WindowProperty, String>,
props: &WindowProperties,
config: &Config,
res: &regex::Compiled,
) -> Result<String, Box<dyn Error>> {
let display_prop = config.get_general("display_property").unwrap_or_else(|| "class".to_string());

// Try to find an alias first
let title = find_alias(props.get(&WindowProperty::Title), &res.name)
.or_else(|| find_alias(props.get(&WindowProperty::Instance), &res.instance))
.or_else(|| find_alias(props.get(&WindowProperty::Class), &res.class))
// If no alias found, fall back to the configured display property
.or_else(|| match display_prop.as_str() {
"name" => props.get(&WindowProperty::Title).map(|s| s.to_string()),
"instance" => props.get(&WindowProperty::Instance).map(|s| s.to_string()),
_ => props.get(&WindowProperty::Class).map(|s| s.to_string()),
let title = find_alias(props.title.as_ref(), &res.name)
.or_else(|| find_alias(props.instance.as_ref(), &res.instance))
.or_else(|| find_alias(props.class.as_ref(), &res.class))
// If no alias found, fall back to the configured display property
.or_else(|| match display_prop.as_str() {
"name" => props.title.clone(),
"instance" => props.instance.clone(),
_ => props.class.clone(),
})
.ok_or_else(|| format!("failed to get alias, display_prop {}, or class", display_prop))?;

Expand All @@ -75,7 +76,7 @@ fn get_workspaces(tree: Node) -> Vec<Node> {
for output in tree.nodes {
for container in output.nodes {
for workspace in container.nodes {
if let NodeType::Workspace = workspace.nodetype {
if let NodeType::Workspace = workspace.node_type {
match &workspace.name {
Some(name) => {
if !name.eq("__i3_scratch") {
Expand All @@ -93,14 +94,14 @@ fn get_workspaces(tree: Node) -> Vec<Node> {
}

/// get window ids for any depth collection of nodes
fn get_properties(mut nodes: Vec<Vec<&Node>>) -> Vec<HashMap<WindowProperty, String>> {
fn get_properties(mut nodes: Vec<Vec<&Node>>) -> Vec<WindowProperties> {
let mut window_props = Vec::new();

while let Some(next) = nodes.pop() {
for n in next {
nodes.push(n.nodes.iter().collect());
if let Some(w) = &n.window_properties {
window_props.push(w.to_owned());
window_props.push(w.clone());
}
}
}
Expand Down Expand Up @@ -180,11 +181,11 @@ fn format_workspace_name(

/// Update all workspace names in tree
pub fn update_tree(
i3_conn: &mut I3Connection,
conn: &mut Connection,
config: &Config,
res: &regex::Compiled,
) -> Result<(), Box<dyn Error>> {
let tree = i3_conn.get_tree()?;
let tree = conn.get_tree()?;
let separator = config.get_general("separator").unwrap_or_else(|| " | ".to_string());
let split_at = get_split_char(config);

Expand Down Expand Up @@ -212,22 +213,22 @@ pub fn update_tree(
// Only send command if name changed
if old != &new {
let command = format!("rename workspace \"{}\" to \"{}\"", old, new);
i3_conn.run_command(&command)?;
conn.run_command(command)?;
}
}
Ok(())
}

/// handles new and close window events, to set the workspace name based on content
pub fn handle_window_event(
e: &WindowEventInfo,
i3_conn: &mut I3Connection,
e: &WindowEvent,
conn: &mut Connection,
config: &Config,
res: &regex::Compiled,
) -> Result<(), Box<dyn Error>> {
match e.change {
WindowChange::New | WindowChange::Close | WindowChange::Move | WindowChange::Title => {
update_tree(i3_conn, config, res)?;
update_tree(conn, config, res)?;
}
_ => (),
}
Expand All @@ -236,14 +237,14 @@ pub fn handle_window_event(

/// handles ws events,
pub fn handle_ws_event(
e: &WorkspaceEventInfo,
i3_conn: &mut I3Connection,
e: &WorkspaceEvent,
conn: &mut Connection,
config: &Config,
res: &regex::Compiled,
) -> Result<(), Box<dyn Error>> {
match e.change {
WorkspaceChange::Empty | WorkspaceChange::Focus => {
update_tree(i3_conn, config, res)?;
update_tree(conn, config, res)?;
}
_ => (),
}
Expand Down
29 changes: 14 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::{Parser, ValueEnum};
use dirs::config_dir;
use i3ipc::{event::Event, MessageError, I3Connection, I3EventListener, Subscription};
use swayipc::{Connection, Event, EventType, Fallible};
use i3wsr::config::{Config, ConfigError};
use std::error::Error;
use std::io;
Expand Down Expand Up @@ -117,21 +117,21 @@ fn setup() -> Result<Config, Box<dyn Error>> {
Ok(config)
}

/// Handles i3 events and updates workspace names
/// Handles sway events and updates workspace names
fn handle_event(
event: Result<Event, MessageError>,
i3_conn: &mut I3Connection,
event: Fallible<Event>,
conn: &mut Connection,
config: &Config,
res: &i3wsr::regex::Compiled,
) {
match event {
Ok(Event::WindowEvent(e)) => {
if let Err(error) = i3wsr::handle_window_event(&e, i3_conn, config, res) {
Ok(Event::Window(e)) => {
if let Err(error) = i3wsr::handle_window_event(&e, conn, config, res) {
eprintln!("Window event error: {}", error);
}
}
Ok(Event::WorkspaceEvent(e)) => {
if let Err(error) = i3wsr::handle_ws_event(&e, i3_conn, config, res) {
Ok(Event::Workspace(e)) => {
if let Err(error) = i3wsr::handle_ws_event(&e, conn, config, res) {
eprintln!("Workspace event error: {}", error);
}
}
Expand All @@ -140,19 +140,18 @@ fn handle_event(
}
}

/// Entry main loop: continuously listen to i3 window events and workspace events
/// Entry main loop: continuously listen to sway window events and workspace events
fn main() -> Result<(), Box<dyn Error>> {
let config = setup()?;
let res = i3wsr::regex::parse_config(&config)?;

let mut listener = I3EventListener::connect()?;
listener.subscribe(&[Subscription::Window, Subscription::Workspace])?;
let mut conn = Connection::new()?;
let subscriptions = [EventType::Window, EventType::Workspace];

let mut i3_conn = I3Connection::connect()?;
i3wsr::update_tree(&mut i3_conn, &config, &res)?;
i3wsr::update_tree(&mut conn, &config, &res)?;

for event in listener.listen() {
handle_event(event, &mut i3_conn, &config, &res);
for event in Connection::new()?.subscribe(&subscriptions)? {
handle_event(event, &mut conn, &config, &res);
}

Ok(())
Expand Down

0 comments on commit f74d622

Please sign in to comment.