Skip to content

Commit

Permalink
feat(config): add static json loader and whkd flag
Browse files Browse the repository at this point in the history
This commit is an implementation of a static JSON configuration loader.

An example komorebi.json configuration file has been added.

The application-specific configurations can be loaded directly from a
file, and workspace configuration can be defined declaratively in the
JSON. Individual rules etc. can also be added directly in the static
configuration as one-offs.

A JSONSchema can be generated using komorebic's static-config-schema
command. This should be added to something like SchemaStore later.

Loading from static configuration is significantly faster on startup, as
the lock does not have to be reacquired for every command that is sent
over the socket.

When loading configuration from a static JSON file, a hotwatch instance
will automatically be created to listen to file changes and apply any
updates to both the global and window manager configuration state.

A new --whkd flag has been added to the komorebic start command to
optionally start whkd in a background process.

A new komorebic command 'generate-static-config' has been added to help
existing users migrate to a static JSON config file. Currently, custom
layout file path information can not be automatically populated in the
output of this command and must be added manually by the user if
required.

A new komorebic command 'fetch-asc' has been added to help users update
to the latest version of the application-specific configurations
in-place.

re #427
  • Loading branch information
LGUG2Z committed Jul 10, 2023
1 parent cf1f748 commit 5b44ecc
Show file tree
Hide file tree
Showing 14 changed files with 2,374 additions and 156 deletions.
619 changes: 616 additions & 3 deletions Cargo.lock

Large diffs are not rendered by default.

63 changes: 50 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ This means that:
### Quickstart

Make sure that you have either the [Scoop Package Manager](https://scoop.sh) or WinGet installed, then run the following
commands at a PowerShell prompt.
commands at a PowerShell prompt. If you are using WinGet, make sure that you open a new terminal window or reload your
profile after running the installation steps. Since this is not required when using `scoop`, I personally recommend that
you use `scoop` for this process.

As of v0.1.17, the quickstart recommends the use of a static configuration file. If you would like to see older versions
of this quickstart which recommend the use of dynamic configuration scripts, please refer to
the [README file of v0.1.16](https://github.com/LGUG2Z/komorebi/tree/v0.1.16).

```powershell
# if using scoop
Expand All @@ -173,20 +179,20 @@ scoop install komorebi
winget install LGUG2Z.whkd
winget install LGUG2Z.komorebi
# save the latest generated app-specific config tweaks and fixes to ~/komorebi.generated.ps1
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/komorebi.generated.ps1 -OutFile $Env:USERPROFILE\komorebi.generated.ps1
# save the example configuration to ~/komorebi.json
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/komorebi.example.json -OutFile $Env:USERPROFILE\komorebi.example.json
# save the sample komorebi configuration file to ~/komorebi.ps1
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/komorebi.sample.ps1 -OutFile $Env:USERPROFILE\komorebi.ps1
# save the latest generated app-specific config tweaks and fixes
komorebic fetch-app-specific-configuration
# ensure the ~/.config folder exists
mkdir $Env:USERPROFILE\.config -ea 0
# save the sample whkdrc file with key bindings to ~/.config/whkdrc
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/whkdrc.sample -OutFile $Env:USERPROFILE\.config\whkdrc
# start komorebi
komorebic start --await-configuration
# start komorebi and whkd
komorebic start -c $Env:USERPROFILE\komorebi.json --whkd
```

Thanks to [@sitiom](https://github.com/sitiom) for getting _komorebi_ added to both the popular Scoop Extras bucket and
Expand All @@ -204,7 +210,9 @@ Generally, users who opt for AHK will have specific needs that can only be addre
and so they are assumed to be able to craft their own configuration files.

If you would like to try out AHK, a simple sample configuration powered by `komorebic.lib.ahk` is provided as a starting
point.
point. This sample configuration does not take into account the use of a static configuration file; if you choose to use
a static configuration file alongside AHK, you can remove all the configuration options from your `komorebi.ahk` and use
it solely to handle hotkey bindings.

```powershell
# save the latest generated komorebic library to ~/komorebic.lib.ahk
Expand Down Expand Up @@ -239,7 +247,12 @@ cargo install --path komorebic --locked

### Running

Run `komorebic start --await-configuration` at a Powershell prompt, and you will see the following output:
`komorebi` can be run in two ways, using either a static configuration file or a dynamic configuration script.

The quickstart covers running with a static configuration file.

If you would like to use a dynamic configuration script, ensure that you have a `komorebi.ps1` or `komorebi.ahk` file
present, run `komorebic start --await-configuration` at a Powershell prompt, and you will see the following output:

```
Start-Process komorebi.exe -ArgumentList '--await-configuration' -WindowStyle hidden
Expand All @@ -249,15 +262,37 @@ Waiting for komorebi.exe to start...Started!
This means that `komorebi` is now running in the background, tiling all your windows, and listening for commands sent to
it by `komorebic`. You can similarly stop the process by running `komorebic stop`.

For further information on running with a dynamic configuration script, please refer to
the quickstart section in the [README file of v0.1.16](https://github.com/LGUG2Z/komorebi/tree/v0.1.16)

### Configuring

If you followed the quickstart, `komorebi` will find the sample `komorebi.ps1` file in your `$Env:USERPROFILE` directory
and automatically load it. This file also starts `whkd` using the sample `whkrc` file in your `$Env:USERPROFILE\.config`
directory.
If you followed the quickstart, `komorebi.json` will be the single place where you declaratively configure the behaviour
of the window manager. There is a [complete JSON Schema for this configuration file](schema.json) available to provide
users with auto-completions in their editors.

If you are running with a dynamic configuration script as recommended in v0.1.16 and earlier, `komorebi` will find the
sample `komorebi.ps1` file in your `$Env:USERPROFILE` directory and automatically load it. This file also starts `whkd` using the sample `whkrc` file
in your `$Env:USERPROFILE\.config` directory.

Alternatively, if you have AutoHotKey installed and a `komorebi.ahk` file in `$Env:UserProfile` directory, `komorebi`
will automatically try to load it when starting.

#### Migrating to a Static Configuration File

If you have been using `komorebi` with a dynamic configuration script and wish to migrate to using a static
configuration file, once you have `komorebi` running in the desired configuration state, you can
run `komorebic generate-static-config`.

This will print a static configuration that mostly represents your current configuration to the terminal.

There are four configuration options that you may need to set yourself, if you make use of them:

- Custom layouts paths for workspaces
- Custom layout rules for workspaces
- The applications.yaml path
- Any individual application rules you have that are not in applications.yaml

#### Configuration with `komorebic`

As previously mentioned, this project does not handle anything related to keybindings and shortcuts directly. I
Expand Down Expand Up @@ -336,6 +371,8 @@ exist in this folder.

#### Generating Common Application-Specific Configurations

❗️**NOTE**: This section is only relevant for people who use dynamic configuration scripts.

A curated selection of application-specific configurations can be generated to
help ease the setup for first-time users.
[`komorebi-application-specific-configuration`](https://github.com/LGUG2Z/komorebi-application-specific-configuration)
Expand Down Expand Up @@ -407,7 +444,7 @@ komorebic.exe workspace-padding <MONITOR_INDEX> <WORKSPACE_INDEX> 0

#### Multiple Layout Changes on Startup

❗️**NOTE**: If you followed the quickstart and are using the sample configurations, this is already the default behaviour.
❗️**NOTE**: This section is only relevant for people who use dynamic configuration scripts.

Depending on what is in your configuration, when `komorebi` is started, you may experience the layout rapidly being adjusted
with many retile events.
Expand Down
2 changes: 1 addition & 1 deletion komorebi-core/src/config_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub struct ApplicationConfiguration {
pub struct ApplicationConfigurationGenerator;

impl ApplicationConfigurationGenerator {
fn load(content: &str) -> Result<Vec<ApplicationConfiguration>> {
pub fn load(content: &str) -> Result<Vec<ApplicationConfiguration>> {
Ok(serde_yaml::from_str(content)?)
}

Expand Down
18 changes: 17 additions & 1 deletion komorebi-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ pub enum SocketMessage {
ClearNamedWorkspaceLayoutRules(String),
// Configuration
ReloadConfiguration,
ReloadStaticConfiguration(PathBuf),
WatchConfiguration(bool),
CompleteConfiguration,
AltFocusHack(bool),
Expand Down Expand Up @@ -151,6 +152,8 @@ pub enum SocketMessage {
RemoveSubscriber(String),
NotificationSchema,
SocketSchema,
StaticConfigSchema,
GenerateStaticConfig,
}

impl SocketMessage {
Expand Down Expand Up @@ -192,10 +195,12 @@ pub enum StateQuery {
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
)]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum ApplicationIdentifier {
#[serde(alias = "exe")]
Exe,
#[serde(alias = "class")]
Class,
#[serde(alias = "title")]
Title,
}

Expand All @@ -204,7 +209,9 @@ pub enum ApplicationIdentifier {
)]
#[strum(serialize_all = "snake_case")]
pub enum FocusFollowsMouseImplementation {
/// A custom FFM implementation (slightly more CPU-intensive)
Komorebi,
/// The native (legacy) Windows FFM implementation
Windows,
}

Expand All @@ -213,7 +220,9 @@ pub enum FocusFollowsMouseImplementation {
)]
#[strum(serialize_all = "snake_case")]
pub enum WindowContainerBehaviour {
/// Create a new container for each new window
Create,
/// Append new windows to the focused window container
Append,
}

Expand All @@ -222,7 +231,9 @@ pub enum WindowContainerBehaviour {
)]
#[strum(serialize_all = "snake_case")]
pub enum MoveBehaviour {
/// Swap the window container with the window container at the edge of the adjacent monitor
Swap,
/// Insert the window container into the focused workspace on the adjacent monitor
Insert,
}

Expand All @@ -231,8 +242,11 @@ pub enum MoveBehaviour {
)]
#[strum(serialize_all = "snake_case")]
pub enum HidingBehaviour {
/// Use the SW_HIDE flag to hide windows when switching workspaces (has issues with Electron apps)
Hide,
/// Use the SW_MINIMIZE flag to hide windows when switching workspaces (has issues with frequent workspace switching)
Minimize,
/// Use the undocumented SetCloak Win32 function to hide windows when switching workspaces (has foregrounding issues)
Cloak,
}

Expand All @@ -241,7 +255,9 @@ pub enum HidingBehaviour {
)]
#[strum(serialize_all = "snake_case")]
pub enum OperationBehaviour {
/// Process komorebic commands on temporarily unmanaged/floated windows
Op,
/// Ignore komorebic commands on temporarily unmanaged/floated windows
NoOp,
}

Expand Down
4 changes: 4 additions & 0 deletions komorebi-core/src/rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ use windows::Win32::Foundation::RECT;

#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, Eq, PartialEq, JsonSchema)]
pub struct Rect {
/// The left point in a Win32 Rect
pub left: i32,
/// The top point in a Win32 Rect
pub top: i32,
/// The right point in a Win32 Rect
pub right: i32,
/// The bottom point in a Win32 Rect
pub bottom: i32,
}

Expand Down
25 changes: 25 additions & 0 deletions komorebi.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"app_specific_configuration_path": "$Env:USERPROFILE/applications.yaml",
"window_hiding_behaviour": "Cloak",
"cross_monitor_move_behaviour": "Insert",
"alt_focus_hack": true,
"default_workspace_padding": 20,
"default_container_padding": 20,
"active_window_border": false,
"active_window_border_colours": {
"single": { "r": 66, "g": 165, "b": 245 },
"stack": { "r": 256, "g": 165, "b": 66 },
"monocle": { "r": 255, "g": 51, "b": 153 }
},
"monitors": [
{
"workspaces": [
{ "name": "I", "layout": "BSP" },
{ "name": "II", "layout": "VerticalStack" },
{ "name": "III", "layout": "HorizontalStack" },
{ "name": "IV", "layout": "UltrawideVerticalStack" },
{ "name": "V", "layout": "Rows" }
]
}
]
}
Loading

0 comments on commit 5b44ecc

Please sign in to comment.