Skip to content

Commit

Permalink
docs(readme): contributing, uds subs + rust client
Browse files Browse the repository at this point in the history
This commit adds some contribution guidelines and updates the "Window
Manager Event Subscriptions" section with information on using
subscribe-socket and komorebi-client.
  • Loading branch information
LGUG2Z committed Feb 26, 2024
1 parent 0afcf6d commit de0db4d
Showing 1 changed file with 185 additions and 15 deletions.
200 changes: 185 additions & 15 deletions README.md
Expand Up @@ -101,20 +101,76 @@ widget enabled. The original video can be viewed

https://user-images.githubusercontent.com/13164844/163496414-a9cde3d1-b8a7-4a7a-96fb-a8985380bc70.mp4

# Development
# Contribution Guidelines

If you would like to contribute to `komorebi` please take the time to carefully read the guidelines below.

If you would like to contribute code to this repository, there are a few requests that I have to ensure a foundation of
code quality, consistency and commit hygiene:
## Commit hygiene

- Flatten all `use` statements
- Run `cargo +nightly clippy` and ensure that all lints and suggestions have been addressed before committing
- Run `cargo +stable clippy` and ensure that all lints and suggestions have been addressed before committing
- Run `cargo +nightly fmt --all` to ensure consistent formatting before committing
- Use `git cz` with
the [Commitizen CLI](https://github.com/commitizen/cz-cli#conventional-commit-messages-as-a-global-utility) to prepare
commit messages
- Provide at least one short sentence or paragraph in your commit message body to describe your thought process for the
- Provide **at least** one short sentence or paragraph in your commit message body to describe your thought process for the
changes being committed

## PRs should contain only a single feature or bug fix

It is very difficult to review pull requests which touch multiple unrelated features and parts of the codebase.

Please do not submit pull requests like this; you will be asked to separate them into smaller PRs that deal only with
one feature or bug fix at a time.

If you are working on multiple features and bug fixes, I suggest that you cut a branch called `local-trunk`
from `master` which you keep up to date, and rebase the various independent branches you are working on onto that branch
if you want to test them together or create a build with everything integrated.

## Refactors to the codebase must have prior approval

`komorebi` is mature codebase with an internal consistency and structure that has developed organically over close to
half a decade.

There are [countless hours of live coding videos](https://youtube.com/@LGUG2Z) demonstrating work on this project and
showing new contributors how to do everything from basic tasks like implementing new `komorebic` commands to
distinguishing monitors by manufacturer hardware identifiers and video card ports.

Refactors to the structure of the codebase are not taken lightly and require prior discussion and approval.

Please do not start refactoring the codebase with the expectation of having your changes integrated into the codebase
until you receive an explicit approval or a request to do so.

Similarly, when implementing features and bug fixes, please stick to the structure of the codebase as much as possible
and do not take this as an opportunity to do some "refactoring along the way".

It is extremely difficult to review PRs for features and bug fixes if they are lost in sweeping changes to the structure
of the codebase.

## Breaking changes to user-facing interfaces are unacceptable

This includes but is not limited to:

- All `komorebic` commands
- The `komorebi.json` schema
- The [`komorebi-application-specific-configuration`](https://github.com/LGUG2Z/komorebi-application-specific-configuration)
schema

No user should ever find that their configuration file has stopped working after upgrading to a new version
of `komorebi`.

More often than not there are ways to reformulate changes that may initially seem like they require breaking user-facing
interfaces into additive changes.

For some inspiration please take a look
at [this commit](https://github.com/LGUG2Z/komorebi/commit/e7d928a065eb63bb4ea1fb864c69c1cae8cc763b) which added the
ability for users to specify colours in `komorebi.json` in Hex format alongside RGB.

There is also a process in place for graceful, non-breaking, deprecation of configuration options that are no longer
required.

# Development

If you use IntelliJ, you should enable the following settings to ensure that code generated by macros is recognised by
the IDE for completions and navigation:

Expand Down Expand Up @@ -153,20 +209,21 @@ found, information about it will appear in the log which can be shared when open
# Window Manager State and Integrations

The current state of the window manager can be queried using the `komorebic state` command, which returns a JSON
representation of the `State` struct, which includes the current state of `WindowManager`.
representation of the `State` struct.

This may also be polled to build further integrations and widgets on top of (if you ever wanted to build something
like [Stackline](https://github.com/AdamWagner/stackline) for Windows, you could do it by polling this command).
This may also be polled to build further integrations and widgets on top of.

# Window Manager Event Subscriptions

It is also possible to subscribe to notifications of every `WindowManagerEvent` and `SocketMessage` handled
## Named Pipes

It is possible to subscribe to notifications of every `WindowManagerEvent` and `SocketMessage` handled
by `komorebi` using [Named Pipes](https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes).

First, your application must create a named pipe. Once the named pipe has been created, run the following command:

```powershell
komorebic.exe subscribe <your pipe name>
komorebic.exe subscribe-pipe <your pipe name>
```

Note that you do not have to include the full path of the named pipe, just the name.
Expand All @@ -190,12 +247,125 @@ You may then filter on the `type` key to listen to the events that you are inter
notification types, refer to the enum variants of `WindowManagerEvent` in `komorebi` and `SocketMessage`
in `komorebi-core`.

An example of how to create a named pipe and a subscription to `komorebi`'s handled events in Python
by [@denBot](https://github.com/denBot) can be
found [here](https://gist.github.com/denBot/4136279812f87819f86d99eba77c1ee0).
Below is an example of how you can subscribe to and filter on events using a named pipe in `nodejs`.

```javascript
const { exec } = require("child_process");
const net = require("net");

const pipeName = "\\\\.\\pipe\\komorebi-js";
const server = net.createServer((stream) => {
console.log("Client connected");

// Every time there is a workspace-related event, let's log the names of all
// workspaces on the currently focused monitor, and then log the name of the
// currently focused workspace on that monitor

stream.on("data", (data) => {
let json = JSON.parse(data.toString());
let event = json.event;

if (event.type.includes("Workspace")) {
let monitors = json.state.monitors;
let current_monitor = monitors.elements[monitors.focused];
let workspaces = monitors.elements[monitors.focused].workspaces;
let current_workspace = workspaces.elements[workspaces.focused];

console.log(
workspaces.elements
.map((workspace) => workspace.name)
.filter((name) => name !== null)
);
console.log(current_workspace.name);
}
});

stream.on("end", () => {
console.log("Client disconnected");
});
});

server.listen(pipeName, () => {
console.log("Named pipe server listening");
});

const command = "komorebic subscribe-pipe komorebi-js";

exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error}`);
return;
}
});
```

## Unix Domain Sockets

It is possible to subscribe to notifications of every `WindowManagerEvent` and `SocketMessage` handled
by `komorebi` using [Unix Domain Sockets](https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/).

UDS are also the only mode of communication between `komorebi` and `komorebic`.

First, your application must create a socket in `$ENV:LocalAppData\komorebi`. Once the socket has been created, run the
following command:

```powershell
komorebic.exe subscribe-socket <your socket name>
```

If the socket exists, komorebi will start pushing JSON data of successfully handled events and messages as in the
example above in the Named Pipes section.

## Rust Client

As of `v0.1.22` it is possible to use the `komorebi-client` crate to subscribe to notifications of
every `WindowManagerEvent` and `SocketMessage` handled by `komorebi` in a Rust codebase.

Below is a simple example of how to use `komorebi-client` in a basic Rust application.

```rust
// komorebi-client = { git = "https://github.com/LGUG2Z/komorebi", tag = "v0.1.22"}

use anyhow::Result;
use komorebi_client::Notification;
use komorebi_client::NotificationEvent;
use komorebi_client::UnixListener;
use komorebi_client::WindowManagerEvent;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

pub fn main() -> anyhow::Result<()> {
let socket = komorebi_client::subscribe(NAME)?;

for incoming in socket.incoming() {
match incoming {
Ok(data) => {
let reader = BufReader::new(data.try_clone()?);

for line in reader.lines().flatten() {
let notification: Notification = match serde_json::from_str(&line) {
Ok(notification) => notification,
Err(error) => {
log::debug!("discarding malformed komorebi notification: {error}");
continue;
}
};

// match and filter on desired notifications
}
}
Err(error) => {
log::debug!("{error}");
}
}
}

}
```

An example of how to create a named pipe and a subscription to `komorebi`'s handled events in Rust can also be found
in the [`komokana`](https://github.com/LGUG2Z/komokana) repository.
A read-world example can be found
in [komokana](https://github.com/LGUG2Z/komokana/blob/feature/komorebi-uds/src/main.rs).

## Subscription Event Notification Schema

Expand Down

0 comments on commit de0db4d

Please sign in to comment.