From de0db4d01463a4f166ae47e6b89ece2b0ffe4f04 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Sun, 25 Feb 2024 21:51:30 -0800 Subject: [PATCH] docs(readme): contributing, uds subs + rust client This commit adds some contribution guidelines and updates the "Window Manager Event Subscriptions" section with information on using subscribe-socket and komorebi-client. --- README.md | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 185 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index decb74ae..8bca40ba 100644 --- a/README.md +++ b/README.md @@ -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 code to this repository, there are a few requests that I have to ensure a foundation of -code quality, consistency and commit hygiene: +If you would like to contribute to `komorebi` please take the time to carefully read the guidelines below. + +## 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: @@ -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 +komorebic.exe subscribe-pipe ``` Note that you do not have to include the full path of the named pipe, just the name. @@ -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`. -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. +```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 +``` + +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}"); + } + } + } + +} +``` + +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