diff --git a/site/make_version.sh b/site/make_version.sh index 75b15a1..b29bb5a 100755 --- a/site/make_version.sh +++ b/site/make_version.sh @@ -1,5 +1,11 @@ #!/bin/sh +echo -n "Current is: " +pypr version +echo -n "Available: " +ls versions + if [ -z "$1" ]; then + echo -n "Archive current version as: " read version else version=$1 diff --git a/site/versions/2.4.0/Development.md b/site/versions/2.4.0/Development.md new file mode 100644 index 0000000..0480464 --- /dev/null +++ b/site/versions/2.4.0/Development.md @@ -0,0 +1,146 @@ +# Development + +It's easy to write your own plugin by making a python package and then indicating it's name as the plugin name. + +[Contributing guidelines](https://github.com/hyprland-community/pyprland/blob/main/CONTRIBUTING.md) + +# Writing plugins + +Plugins can be loaded with full python module path, eg: `"mymodule.pyprlandplugin"`, the loaded module must provide an `Extension` class. + +Check the `interface.py` file to know the base methods, also have a look at the example below. + +To get more details when an error is occurring, use `pypr --debug `, it will also display the log in the console. + +> [!note] +> To quickly get started, you can directly edit the `experimental` built-in plugin. +> In order to distribute it, make your own Python package or trigger a pull request. +> If you prefer to make a separate package, check the [examples](https://github.com/hyprland-community/pyprland/blob/main/sample_extension/)'s package + +The `Extension` interface provides a couple of built-in attributes: + +- `config` : object exposing the plugin section in `pyprland.toml` +- `notify` ,`notify_error`, `notify_info` : access to Hyprland's notification system +- `hyprctl`, `hyprctl_json` : invoke [Hyprland's IPC system](https://wiki.hyprland.org/Configuring/Dispatchers/) + + +> [!important] +> Contact me to get your extension listed on the home page + +> [!tip] +> You can set a `plugins_paths=["/custom/path/example"]` in the `hyprland` section of the configuration to add extra paths (eg: during development). + +> [!Note] +> If your extension is at the root of the plugin (this is not recommended, preferable add a name space, as in `johns_pyprland.super_feature`, rather than `super_feature`) you can still import it using the `external:` prefix when you refer to it in the `plugins` list. + +# API Documentation + +Run `tox run -e doc` then visit `http://localhost:8080` + +The most important to know are: + +- `hyprctl_json` to get a response from an IPC query +- `hyprctl` to trigger general IPC commands +- `on_reload` to be implemented, called when the config is (re)loaded +- `run_` to implement a command +- `event_` called when the given event is emitted by Hyprland + +All those methods are _async_ + +On top of that: + +- the first line of a `run_*` command's docstring will be used by the `help` command +- `self.config` in your _Extension_ contains the entry corresponding to your plugin name in the TOML file +- `state` from `..common` module contains ready to use information +- there is a `MenuMixin` in `..adapters.menus` to make menu-based plugins easy + +# Workflow + +Just `^C` when you make a change and repeat: + +```sh +pypr exit ; pypr --debug /tmp/output.log +``` + + +## Creating a plugin + +```python +from .interface import Plugin + + +class Extension(Plugin): + " My plugin " + + async def init(self): + await self.notify("My plugin loaded") +``` + +## Adding a command + +Just add a method called `run_` to your `Extension` class, eg with "togglezoom" command: + +```python + zoomed = False + + async def run_togglezoom(self, args): + """ this doc string will show in `help` to document `togglezoom` + But this line will not show in the CLI help + """ + if self.zoomed: + await self.hyprctl('misc:cursor_zoom_factor 1', 'keyword') + else: + await self.hyprctl('misc:cursor_zoom_factor 2', 'keyword') + self.zoomed = not self.zoomed +``` + +## Reacting to an event + +Similar as a command, implement some `async def event_` method. + +## Code safety + +Pypr ensures only one `run_` or `event_` handler runs at a time, allowing the plugins code to stay simple and avoid the need for concurrency handling. +However, each plugin can run its handlers in parallel. + +# Reusable code + +```py +from ..common import state, CastBoolMixin +``` + +- `state` provides a couple of handy variables so you don't have to fetch them, allow optimizing the most common operations +- `Mixins` are providing common code, for instance the `CastBoolMixin` provides the `cast_bool` method to your `Extension`. + +If you want to use menus, then the `MenuMixin` will provide: +- `menu` to show a menu +- `ensure_menu_configured` to call before you require a menu in your plugin + +# Example + +You'll find a basic external plugin in the [examples](https://github.com/hyprland-community/pyprland/blob/main/sample_extension/) folder. + +It provides one command: `pypr dummy`. + +Read the [plugin code](https://github.com/hyprland-community/pyprland/blob/main/sample_extension/pypr_examples/focus_counter.py) + +It's a simple python package. To install it for development without a need to re-install it for testing, you can use `pip install -e .` in this folder. +It's ready to be published using `poetry publish`, don't forget to update the details in the `pyproject.toml` file. + +## Usage + +Ensure you added `pypr_examples.focus_counter` to your `plugins` list: + +```toml +[pyprland] +plugins = [ + "pypr_examples.focus_counter" +] +``` + +Optionally you can customize one color: + +```toml +["pypr_examples.focus_counter"] +color = "FFFF00" +``` diff --git a/site/versions/2.4.0/Getting-started.md b/site/versions/2.4.0/Getting-started.md new file mode 100644 index 0000000..676a8e4 --- /dev/null +++ b/site/versions/2.4.0/Getting-started.md @@ -0,0 +1,183 @@ +# Getting started + +Pypr consists in two things: + +- **a tool**: `pypr` which runs the daemon (service), but also allows to interact with it +- **some config file**: `~/.config/hypr/pyprland.toml` (or the path set using `--config`) using the [TOML](https://toml.io/en/) format + +The `pypr` tool only have a few built-in commands: + +- `help` lists available commands (including plugins commands) +- `exit` will terminate the service process +- `edit` edit the configuration using your `$EDITOR` (or `vi`), reloads on exit +- `dumpjson` shows a JSON representation of the configuration (after other files have been `include`d) +- `reload` reads the configuration file and apply some changes: + - new plugins will be loaded + - configuration items will be updated (most plugins will use the new values on the next usage) + +Other commands are implemented by adding [plugins](./Plugins). + +> [!important] +> - with no argument it runs the daemon (doesn't fork in the background) +> +> - if you pass parameters, it will interact with the daemon instead. + +> [!tip] +> Pypr *command* names are documented using underscores (`_`) but you can use dashes (`-`) instead. +> Eg: `pypr shift_monitors` and `pypr shift-monitors` will run the same command + + +## Configuration file + +The configuration file uses a [TOML format](https://toml.io/) with the following as the bare minimum: + +```toml +[pyprland] +plugins = ["plugin_name", "other_plugin"] +``` + +Additionally some plugins require **Configuration** options, using the following format: + +```toml +[plugin_name] +plugin_option = 42 + +[plugin_name.another_plugin_option] +suboption = "config value" +``` + +You can also split your configuration into [Multiple configuration files](./MultipleConfigurationFiles). + +## Installation + +Check your OS package manager first, eg: + +- Archlinux: you can find it on AUR, eg with [yay](https://github.com/Jguer/yay): `yay pyprland` +- NixOS: Instructions in the [Nix](./Nix) page + +Otherwise, use the python package manager (pip) [inside a virtual environment](InstallVirtualEnvironment) + +```sh +pip install pyprland +``` + +## Running + +> [!caution] +> If you messed with something else than your OS packaging system to get `pypr` installed, use the full path to the `pypr` command. + +Preferably start the process with hyprland, adding to `hyprland.conf`: + +```ini +exec-once = /usr/bin/pypr +``` + +or if you run into troubles (use the first version once your configuration is stable): + +```ini +exec-once = /usr/bin/pypr --debug /tmp/pypr.log +``` + +> [!warning] +> To avoid issues (eg: you have a complex setup, maybe using a virtual environment), you may want to set the full path (eg: `/home/bob/venv/bin/pypr`). +> You can get it from `which pypr` in a working terminal + +Once the `pypr` daemon is started (cf `exec-once`), you can list the eventual commands which have been added by the plugins using `pypr -h` or `pypr help`, those commands are generally meant to be use via key bindings, see the `hyprland.conf` part of *Configuring* section below. + +## Configuring + +Create a configuration file in `~/.config/hypr/pyprland.toml` enabling a list of plugins, each plugin may have its own configuration needs or don't need any configuration at all. +Most default values should be acceptable for most users, options which hare not mandatory are marked as such. + +> [!important] +> Provide the values for the configuration options which have no annotation such as "(optional)" + +Check the [TOML format](https://toml.io/) for details about the syntax. + +Simple example: + +```toml +[pyprland] +plugins = [ + "shift_monitors", + "workspaces_follow_focus" +] +``` + +
+ +More complex example + + +```toml +[pyprland] +plugins = [ + "scratchpads", + "lost_windows", + "monitors", + "toggle_dpms", + "magnify", + "expose", + "shift_monitors", + "workspaces_follow_focus", +] + +[monitors.placement] +"Acer".top_center_of = "Sony" + +[workspaces_follow_focus] +max_workspaces = 9 + +[expose] +include_special = false + +[scratchpads.stb] +animation = "fromBottom" +command = "kitty --class kitty-stb sstb" +class = "kitty-stb" +lazy = true +size = "75% 45%" + +[scratchpads.stb-logs] +animation = "fromTop" +command = "kitty --class kitty-stb-logs stbLog" +class = "kitty-stb-logs" +lazy = true +size = "75% 40%" + +[scratchpads.term] +animation = "fromTop" +command = "kitty --class kitty-dropterm" +class = "kitty-dropterm" +size = "75% 60%" + +[scratchpads.volume] +animation = "fromRight" +command = "pavucontrol" +class = "org.pulseaudio.pavucontrol" +lazy = true +size = "40% 90%" +unfocus = "hide" +``` + +Some of those plugins may require changes in your `hyprland.conf` to fully operate or to provide a convenient access to a command, eg: + +```bash +bind = $mainMod SHIFT, Z, exec, pypr zoom +bind = $mainMod ALT, P,exec, pypr toggle_dpms +bind = $mainMod SHIFT, O, exec, pypr shift_monitors +1 +bind = $mainMod, B, exec, pypr expose +bind = $mainMod, K, exec, pypr change_workspace +1 +bind = $mainMod, J, exec, pypr change_workspace -1 +bind = $mainMod,L,exec, pypr toggle_dpms +bind = $mainMod SHIFT,M,exec,pypr toggle stb stb-logs +bind = $mainMod,A,exec,pypr toggle term +bind = $mainMod,V,exec,pypr toggle volume +``` + +
+ +> [!tip] +> Consult or share [configuration files](https://github.com/hyprland-community/pyprland/tree/main/examples) +> +> You might also be interested in [optimizations](./Optimizations). diff --git a/site/versions/2.4.0/InstallVirtualEnvironment.md b/site/versions/2.4.0/InstallVirtualEnvironment.md new file mode 100644 index 0000000..92b26e8 --- /dev/null +++ b/site/versions/2.4.0/InstallVirtualEnvironment.md @@ -0,0 +1,46 @@ +# Virtual env + +Even though the best way to get Pyprland installed is to use your operating system package manager, +for some usages or users it can be convenient to use a virtual environment. + +This is very easy to achieve in a couple of steps: + +```shell +python -m venv ~/pypr-env +~/pypr-env/bin/pip install pyprland +``` + +**That's all folks!** + +The only extra care to take is to use `pypr` from the virtual environment, eg: + +- adding the environment's "bin" folder to the `PATH` (using `export PATH="$PATH:~/pypr-env/bin/"` in your shell configuration file) +- always using the full path to the pypr command (in `hyprland.conf`: `exec-once = ~/pypr-env/bin/pypr --debug /tmp/pypr.log`) + +# Going bleeding edge! + +If you would rather like to use the latest version available (not released yet), then you can clone the git repository and install from it: + +```shell +cd ~/pypr-env +git clone git@github.com:hyprland-community/pyprland.git pyprland-sources +cd pyprland-sources +../bin/pip install -e . +``` + +## Updating + +```shell +cd ~/pypr-env +git pull -r +``` + +# Troubelshooting + +If things go wrong, try (eg: after a system upgrade where Python got updated): + +```shell +python -m venv --upgrade ~/pypr-env +cd ~/pypr-env +../bin/pip install -e . +``` diff --git a/site/versions/2.4.0/Menu.md b/site/versions/2.4.0/Menu.md new file mode 100644 index 0000000..77bd04f --- /dev/null +++ b/site/versions/2.4.0/Menu.md @@ -0,0 +1,36 @@ +# Menu capability + +Menu based plugins have the following configuration options: + +### `engine` + +Not set by default, will autodetect the available menu engine. + +Supported engines: + +- tofi +- rofi +- wofi +- bemenu +- dmenu +- anyrun + +> [!note] +> If your menu system isn't supported, you can open a [feature request](https://github.com/hyprland-community/pyprland/issues/new?assignees=fdev31&labels=bug&projects=&template=feature_request.md&title=%5BFEAT%5D+Description+of+the+feature) +> +> In case the engine isn't recognized, `engine` + `parameters` configuration options will be used to start the process, it requires a dmenu-like behavior. + +### `parameters` + +Extra parameters added to the engine command, the default value is specific to each engine. + +> [!important] +> Setting this will override the default value! +> +> In general, *rofi*-like programs will require at least `-dmenu` option. + +> [!tip] +> You can use '[prompt]' in the parameters, it will be replaced by the prompt, eg: +> ```sh +> -dmenu -matching fuzzy -i -p '[prompt]' +> ``` diff --git a/site/versions/2.4.0/MultipleConfigurationFiles.md b/site/versions/2.4.0/MultipleConfigurationFiles.md new file mode 100644 index 0000000..894ab8e --- /dev/null +++ b/site/versions/2.4.0/MultipleConfigurationFiles.md @@ -0,0 +1,25 @@ +### Multiple configuration files + +You can also split your configuration into multiple files that will be loaded in the provided order after the main file: +```toml +[pyprland] +include = ["/shared/pyprland.toml", "~/pypr_extra_config.toml"] +``` +You can also load folders, in which case TOML files in the folder will be loaded in alphabetical order: +```toml +[pyprland] +include = ["~/.config/pypr.d/"] +``` + +And then add a `~/.config/pypr.d/monitors.toml` file: +```toml +pyprland.plugins = [ "monitors" ] + +[monitors.placement] +BenQ.Top_Center_Of = "DP-1" # projo +"CJFH277Q3HCB".top_of = "eDP-1" # work +``` + +> [!tip] +> To check the final merged configuration, you can use the `dumpjson` command. + diff --git a/site/versions/2.4.0/Nix.md b/site/versions/2.4.0/Nix.md new file mode 100644 index 0000000..71c8078 --- /dev/null +++ b/site/versions/2.4.0/Nix.md @@ -0,0 +1,63 @@ +# Nix + +You are recommended to get the latest pyprland package from the [flake.nix](https://github.com/hyprland-community/pyprland/blob/main/flake.nix) +provided within this repository. To use it in your system, you may add pyprland +to your flake inputs. + +## Flake + +```nix +## flake.nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + pyprland.url = "github:hyprland-community/pyprland"; + }; + + outputs = { self, nixpkgs, pyprland, ...}: let + in { + nixosConfigurations. = nixpkgs.lib.nixosSystem { + # remember to replace this with your system arch ↓ + environment.systemPackages = [ pyprland.packages."x86_64-linux".pyprland ]; + # ... + }; + }; +} +``` + +Alternatively, if you are using the Nix package manager but not NixOS as your +main distribution, you may use `nix profile` tool to install pyprland from this +repository using the following command. + +```bash +nix profile install github:nix-community/pyprland +``` + +The package will now be in your latest profile. You may use `nix profile list` +to verify your installation. + +## Nixpkgs + +Pyprland is available under nixpkgs, and can be installed by adding +`pkgs.pyprland` to either `environment.systemPackages` or `home.packages` +depending on whether you want it available system-wide or to only a single +user using home-manager. If the derivation available in nixpkgs is out-of-date +then you may consider using `overrideAttrs` to update the source locally. + +```nix +let + pyprland = pkgs.pyprland.overrideAttrs { + version = "your-version-here"; + src = fetchFromGitHub { + owner = "hyprland-community"; + repo = "pyprland"; + rev = "tag-or-revision"; + # leave empty for the first time, add the new hash from the error message + hash = ""; + }; + }; +in { + # add the overridden package to systemPackages + environment.systemPackages = [pyprland]; +} +``` diff --git a/site/versions/2.4.0/Optimizations.md b/site/versions/2.4.0/Optimizations.md new file mode 100644 index 0000000..2dd5ff0 --- /dev/null +++ b/site/versions/2.4.0/Optimizations.md @@ -0,0 +1,18 @@ +## Optimizing + +### Plugins + +- Only enable the plugins you are using in the `plugins` array (in `[pyprland]` section). +- Leaving the configuration for plugins which are not enabled will have no impact. +- Using multiple configuration files only have a small impact on the startup time. + +### Pypr command + +In case you want to save some time when interacting with the daemon +you can use `socat` instead (needs to be installed). Example of a `pypr-cli` command (should be reachable from your environment's `PATH`): +```sh +#!/bin/sh +socat - "UNIX-CONNECT:${XDG_RUNTIME_DIR}/hypr/${HYPRLAND_INSTANCE_SIGNATURE}/.pyprland.sock" <<< $@ +``` +On slow systems this may make a difference. +Note that the "help" command will require usage of the standard `pypr` command. diff --git a/site/versions/2.4.0/Plugins.md b/site/versions/2.4.0/Plugins.md new file mode 100644 index 0000000..9c4ac3b --- /dev/null +++ b/site/versions/2.4.0/Plugins.md @@ -0,0 +1,9 @@ + + +This page lists every plugin provided by Pyprland out of the box, more can be enabled if you install the matching package. + +"🌟" indicates some maturity & reliability level of the plugin, considering age, attention paid and complexity - from 0 to 3. + + diff --git a/site/versions/2.4.0/Troubleshooting.md b/site/versions/2.4.0/Troubleshooting.md new file mode 100644 index 0000000..a4f56ed --- /dev/null +++ b/site/versions/2.4.0/Troubleshooting.md @@ -0,0 +1,29 @@ +# Troubleshooting + +## General + +In case of trouble running a `pypr` command: +- kill the existing pypr if any (try `pypr exit` first) +- run from the terminal adding `--debug /dev/null` to the arguments to get more information + +If the client says it can't connect, then there is a high chance pypr daemon didn't start, check if it's running using `ps axuw |grep pypr`. You can try to run it from a terminal with the same technique: `pypr --debug /dev/null` and see if any error occurs. + +## Force hyprland version + +In case your `hyprctl version -j` command isn't returning an accurate version, you can make Pyprland ignore it and use a provided value instead: + +```toml +[pyprland] +hyprland_version = "0.41.0" +``` + +## Unresponsive scratchpads + +Scratchpads aren't responding for few seconds after trying to show one (which didn't show!) + +This may happen if an application is very slow to start. +In that case pypr will wait for a window blocking other scratchpad's operation, before giving up after a few seconds. + +Note that other plugins shouldn't be blocked by it. + +More scratchpads troubleshooting can be found [here](./scratchpads_nonstandard). diff --git a/site/versions/2.4.0/Variables.md b/site/versions/2.4.0/Variables.md new file mode 100644 index 0000000..8ea915c --- /dev/null +++ b/site/versions/2.4.0/Variables.md @@ -0,0 +1,15 @@ +# Variables & substitutions + +Some commands support shared global variables, they must be defined in the *pyprland* section of the configuration: +```toml +[pyprland.variables] +term = "foot" +term_classed = "foot -a" # kitty uses --class +``` + +If a plugin supports it, you can then use the variables in the attribute that supports it, eg: + +```toml +[myplugin] +some_variable = "the terminal is [term]" +``` diff --git a/site/versions/2.4.0/expose.md b/site/versions/2.4.0/expose.md new file mode 100644 index 0000000..6462ba4 --- /dev/null +++ b/site/versions/2.4.0/expose.md @@ -0,0 +1,43 @@ +--- +commands: + - name: expose + description: Expose every client on the active workspace. If expose is already active, then restores everything and move to the focused window. +--- + +# expose + +Implements the "expose" effect, showing every client window on the focused screen. + +For a similar feature using a menu, try the [fetch_client_menu](./fetch_client_menu) plugin (less intrusive). + +Sample `hyprland.conf`: + +```bash +# Setup the key binding +bind = $mainMod, B, exec, pypr expose + +# Add some style to the "exposed" workspace +workspace = special:exposed,gapsout:60,gapsin:30,bordersize:5,border:true,shadow:false +``` + +`MOD+B` will bring every client to the focused workspace, pressed again it will go to this workspace. + +Check [workspace rules](https://wiki.hyprland.org/Configuring/Workspace-Rules/#rules) for styling options. + +> [!note] +> If you are looking for `toggle_minimized`, check the [toggle_special](./toggle_special) plugin + + +## Command + + + +## Configuration + + +### `include_special` + +default value is `false` + +Also include windows in the special workspaces during the expose. + diff --git a/site/versions/2.4.0/fetch_client_menu.md b/site/versions/2.4.0/fetch_client_menu.md new file mode 100644 index 0000000..7896500 --- /dev/null +++ b/site/versions/2.4.0/fetch_client_menu.md @@ -0,0 +1,28 @@ +--- +commands: + - name: fetch_client_menu + description: Bring any window to the active workspace using a menu. +--- + +# fetch_client_menu + +Bring any window to the active workspace using a menu. + +A bit like the [expose](./expose) plugin but using a menu instead (less intrusive). + +It brings the window to the current workspace, while [expose](./expose) moves the currently focused screen to the application workspace. + +## Command + + + +## Configuration + +All the [Menu](Menu) configuration items are also available. + +### `separator` + +default value is `"|"` + +Changes the character (or string) used to separate a menu entry from its entry number. + diff --git a/site/versions/2.4.0/filters.md b/site/versions/2.4.0/filters.md new file mode 100644 index 0000000..9b77d01 --- /dev/null +++ b/site/versions/2.4.0/filters.md @@ -0,0 +1,13 @@ +# Text filters + +At the moment there is only one filter, close match of [sed's "s" command](https://www.gnu.org/software/sed/manual/html_node/The-_0022s_0022-Command.html). + +The only supported flag is "g" + +## Example + +```toml +filter = 's/foo/bar/' +filter = 's/.*started (.*)/\1 has started/' +filter = 's###g' +``` diff --git a/site/versions/2.4.0/gbar.md b/site/versions/2.4.0/gbar.md new file mode 100644 index 0000000..c7407af --- /dev/null +++ b/site/versions/2.4.0/gbar.md @@ -0,0 +1,33 @@ +--- +commands: + - name: gbar restart + description: Restart/refresh gBar on the "best" monitor. +--- + +# gbar + +Runs [gBar](https://github.com/scorpion-26/gBar) on the "best" monitor from a list of monitors. + +- Will take care of starting gbar on startup (you must not run it from another source like `hyprland.conf`). +- Automatically restarts gbar on crash +- Checks which monitors are on and take the best one from a provided list + +## Command + + + + +## Configuration + + +### `monitors` (REQUIRED) + +List of monitors to chose from, the first have higher priority over the second one etc... + + +## Example + +```sh +[gbar] +monitors = ["DP-1", "HDMI-1", "HDMI-1-A"] +``` diff --git a/site/versions/2.4.0/index.md b/site/versions/2.4.0/index.md new file mode 100644 index 0000000..eda19da --- /dev/null +++ b/site/versions/2.4.0/index.md @@ -0,0 +1,31 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + text: "Hyprland extensions" + tagline: Enhance your desktop capabilities with Pyprland + image: + src: /logo.svg + alt: logo + actions: + - theme: brand + text: Getting started + link: ./Getting-started + - theme: alt + text: Plugins + link: ./Plugins + - theme: alt + text: Report something + link: https://github.com/hyprland-community/pyprland/issues/new/choose + +features: + - title: TOML format + details: Simple and flexible configuration file(s) + - title: Customizable + details: Create your own Hyprland experience + - title: Fast and easy + details: Designed for performance and simplicity +--- + +## Version 2.4.0 archive diff --git a/site/versions/2.4.0/layout_center.md b/site/versions/2.4.0/layout_center.md new file mode 100644 index 0000000..40c579c --- /dev/null +++ b/site/versions/2.4.0/layout_center.md @@ -0,0 +1,144 @@ +--- +commands: + - name: layout_center toggle + description: toggles the layout on and off + - name: layout_center next + description: switches to the next window (if layout is on) else runs the next command + - name: layout_center prev + description: switches to the previous window (if layout is on) else runs the prev command + - name: layout_center next2 + description: switches to the next window (if layout is on) else runs the next2 command + - name: layout_center prev2 + description: switches to the previous window (if layout is on) else runs the prev2 command + +--- +# layout_center + +Implements a workspace layout where one window is bigger and centered, +other windows are tiled as usual in the background. + +On `toggle`, the active window is made floating and centered if the layout wasn't enabled, else reverts the floating status. + +With `next` and `prev` you can cycle the active window, keeping the same layout type. +If the layout_center isn't active and `next` or `prev` is used, it will call the [next](#next-optional) and [prev](#prev-optional) configuration options. + +To allow full override of the focus keys, [next2](#next2-optional) and [prev2](#prev2-optional) are provided, they do the same actions as "next" and "prev" but allow different fallback commands. + +
+Configuration sample + +```toml +[layout_center] +margin = 60 +offset = [0, 30] +next = "movefocus r" +prev = "movefocus l" +next2 = "movefocus d" +prev2 = "movefocus u" +``` + +using the following in `hyprland.conf`: +```sh +bind = $mainMod, M, exec, pypr layout_center toggle # toggle the layout +## focus change keys +bind = $mainMod, left, exec, pypr layout_center prev +bind = $mainMod, right, exec, pypr layout_center next +bind = $mainMod, up, exec, pypr layout_center prev2 +bind = $mainMod, down, exec, pypr layout_center next2 +``` + +You can completely ignore `next2` and `prev2` if you are allowing focus change in a single direction (when the layout is enabled), eg: + +```sh +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d +``` + +
+ + +## Commands + + + +## Configuration + +### `on_new_client` + +Defaults to `"foreground"`. + +Changes the behavior when a new window opens, possible options are: + +- "foreground" to make the new window the main window +- "background" to make the new window appear in the background +- "close" to stop the centered layout when a new window opens + +### `style` + +| Requires Hyprland > 0.40.0 + +Not set by default. + +Allow to set a list of styles to the main (centered) window, eg: + +```toml +style = ["opacity 1", "bordercolor rgb(FFFF00)"] +``` + +### `margin` + +default value is `60` + +margin (in pixels) used when placing the center window, calculated from the border of the screen. + +Example to make the main window be 100px far from the monitor's limits: +```toml +margin = 100 +``` + +You can also set a different margin for width and height by using a list: +```toml +margin = [10, 60] +``` + +### `offset` + +default value is `[0, 0]` + +offset in pixels applied to the main window position + +Example shift the main window 20px down: +```toml +offset = [0, 20] +``` + +### `next` +### `next2` + +not set by default + +When the *layout_center* isn't active and the *next* command is triggered, defines the hyprland dispatcher command to run. + +`next2` is a similar option, used by the `next2` command, allowing to map "next" to both vertical and horizontal focus change. + +Eg: +```toml +next = "movefocus r" +``` + +### `prev` +### `prev2` + +Same as `next` but for the `prev` and `prev2` commands. + + +### `captive_focus` + +default value is `false` + +```toml +captive_focus = true +``` + +Sets the focus on the main window when the focus changes. +You may love it or hate it... diff --git a/site/versions/2.4.0/lost_windows.md b/site/versions/2.4.0/lost_windows.md new file mode 100644 index 0000000..d1a4fc5 --- /dev/null +++ b/site/versions/2.4.0/lost_windows.md @@ -0,0 +1,13 @@ +--- +commands: + - name: attract_lost + description: Bring windows which are not reachable in the currently focused workspace. +--- +# lost_windows + +Bring windows which are not reachable in the currently focused workspace. +*Deprecated:* Was used to work around issues in Hyprland which have been fixed since then. + +## Command + + diff --git a/site/versions/2.4.0/magnify.md b/site/versions/2.4.0/magnify.md new file mode 100644 index 0000000..6d41a07 --- /dev/null +++ b/site/versions/2.4.0/magnify.md @@ -0,0 +1,73 @@ +--- +commands: + - name: zoom [value] + description: Set the current zoom level (absolute or relative) - toggle zooming if no value is provided +--- +# magnify + +Zooms in and out with an optional animation. + + +
+ Example + +```sh +pypr zoom # sets zoom to `factor` (2 by default) +pypr zoom +1 # will set zoom to 3x +pypr zoom # will set zoom to 1x +pypr zoom 1 # will (also) set zoom to 1x - effectively doing nothing +``` + +Sample `hyprland.conf`: + +```sh +bind = $mainMod , Z, exec, pypr zoom ++0.5 +bind = $mainMod SHIFT, Z, exec, pypr zoom +``` + +
+ +## Command + + + +### `[value]` + +#### unset / not specified + +Will zoom to [factor](#factor-optional) if not zoomed, else will set the zoom to 1x. + +#### floating or integer value + +Will set the zoom to the provided value. + +#### +value / -value + +Update (increment or decrement) the current zoom level by the provided value. + +#### ++value / --value + +Update (increment or decrement) the current zoom level by a non-linear scale. +It _looks_ more linear changes than using a single + or -. + +> [!NOTE] +> +> The non-linear scale is calculated as powers of two, eg: +> +> - `zoom ++1` → 2x, 4x, 8x, 16x... +> - `zoom ++0.7` → 1.6x, 2.6x, 4.3x, 7.0x, 11.3x, 18.4x... +> - `zoom ++0.5` → 1.4x, 2x, 2.8x, 4x, 5.7x, 8x, 11.3x, 16x... + +## Configuration + +### `factor` + +default value is `2` + +Scaling factor to be used when no value is provided. + +### `duration` + +Default value is `15` + +Duration in tenths of a second for the zoom animation to last, set to `0` to disable animations. diff --git a/site/versions/2.4.0/monitors.md b/site/versions/2.4.0/monitors.md new file mode 100644 index 0000000..17898f5 --- /dev/null +++ b/site/versions/2.4.0/monitors.md @@ -0,0 +1,143 @@ +--- +commands: + - name: relayout + description: Apply the configuration and update the layout +--- + +# monitors + +> First, simpler version of the plugin is still available under the name `monitors_v0` + +Allows relative placement of monitors depending on the model ("description" returned by `hyprctl monitors`). +Useful if you have multiple monitors connected to a video signal switch or using a laptop and plugging monitors having different relative positions. + +Syntax: + +```toml +[monitors.placement] +"description match".placement = "other description match" +``` + +
+ Example to set a Sony monitor on top of a BenQ monitor + +```toml +[monitors.placement] +Sony.topOf = "BenQ" + +## Character case is ignored, "_" can be added +Sony.Top_Of = ["BenQ"] + +## Thanks to TOML format, complex configurations can use separate "sections" for clarity, eg: + +[monitors.placement."My monitor brand"] +## You can also use "port" names such as *HDMI-A-1*, *DP-1*, etc... +leftOf = "eDP-1" + +## lists are possible on the right part of the assignment: +rightOf = ["Sony", "BenQ"] + +## > 2.3.2: you can also set scale, transform & rate for a given monitor +[monitors.placement.Microstep] +rate = 100 +``` + +Try to keep the rules as simple as possible, but relatively complex scenarios are supported. + +> [!note] +> Check [wlr layout UI](https://github.com/fdev31/wlr-layout-ui) which is a nice complement to configure your monitor settings. + +
+ +## Command + + + +## Configuration + +### `placement` (REQUIRED) + +Supported placements are: + +- leftOf +- topOf +- rightOf +- bottomOf +- \(center|middle|end)Of + +> [!important] +> If you don't like the screen to align on the start of the given border, +> you can use `center` (or `middle`) to center it or `end` to stick it to the opposite border. +> Eg: "topCenterOf", "leftEndOf", etc... + +You can separate the terms with "_" to improve the readability, as in "top_center_of". + +#### monitor settings + +Not only can you place monitors relatively to each other, but you can also set specific settings for a given monitor. + +The following settings are supported: + +- scale +- transform +- rate +- resolution + +```toml +[monitors.placement."My monitor brand"] +rate = 60 +scale = 1.5 +transform = 1 # 0: normal, 1: 90°, 2: 180°, 3: 270°, 4: flipped, 5: flipped 90°, 6: flipped 180°, 7: flipped 270° +resolution = "1920x1080" # can also be expressed as [1920, 1080] +``` + +### `startup_relayout` + +Default to `ŧrue`. + +When set to `false`, +do not initialize the monitor layout on startup or when configuration is reloaded. + +### `new_monitor_delay` + +By default, +the layout computation happens one second after the event is received to let time for things to settle. + +You can change this value using this option. + +### `hotplug_command` + +None by default, allows to run a command when any monitor is plugged. + + +```toml +[monitors] +hotplug_commands = "wlrlui -m" +``` + +### `hotplug_commands` + +None by default, allows to run a command when a given monitor is plugged. + +Example to load a specific profile using [wlr layout ui](https://github.com/fdev31/wlr-layout-ui): + +```toml +[monitors.hotplug_commands] +"DELL P2417H CJFH277Q3HCB" = "wlrlui rotated" +``` + +### `unknown` + +None by default, +allows to run a command when no monitor layout has been changed (no rule applied). + +```toml +[monitors] +unknown = "wlrlui" +``` + +### `trim_offset` + +`true` by default, + +Prevents having arbitrary window offsets or negative values. diff --git a/site/versions/2.4.0/scratchpads.md b/site/versions/2.4.0/scratchpads.md new file mode 100644 index 0000000..e570208 --- /dev/null +++ b/site/versions/2.4.0/scratchpads.md @@ -0,0 +1,169 @@ +--- +commands: + - name: toggle [scratchpad name] + description: Toggle the given scratchpad + - name: show [scratchpad name] + description: Show the given scratchpad + - name: hide [scratchpad name] + description: Hide the given scratchpad + - name: attach + description: Toggle attaching/anchoring the currently focused window to the (last used) scratchpad +--- +# scratchpads + +Easily toggle the visibility of applications you use the most. + +Configurable and flexible, while supporting complex setups it's easy to get started with: + +```toml +[scratchpads.name] +command = "command to run" +class = "the window's class" # check: hyprctl clients | grep class +size = "[width] [height]" # size of the window relative to the screen size +``` + +
+Example + +As an example, defining two scratchpads: + +- _term_ which would be a kitty terminal on upper part of the screen +- _volume_ which would be a pavucontrol window on the right part of the screen + + +```toml +[scratchpads.term] +animation = "fromTop" +command = "kitty --class kitty-dropterm" +class = "kitty-dropterm" +size = "75% 60%" +max_size = "1920px 100%" +margin = 50 + +[scratchpads.volume] +animation = "fromRight" +command = "pavucontrol" +class = "org.pulseaudio.pavucontrol" +size = "40% 90%" +unfocus = "hide" +lazy = true +``` + +Shortcuts are generally needed: + +```ini +bind = $mainMod,V,exec,pypr toggle volume +bind = $mainMod,A,exec,pypr toggle term +bind = $mainMod,Y,exec,pypr attach +``` +
+ +- If you wish to have a more generic space for any application you may run, check [toggle_special](./toggle_special). +- When you create a scratchpad called "name", it will be hidden in `special:scratch_`. +- Providing `class` allows a glitch free experience, mostly noticeable when using animations + + +## Commands + + + +> [!tip] +> You can use `"*"` as a _scratchpad name_ to target every scratchpad when using `show` or `hide`. +> You'll need to quote or escape the `*` character to avoid interpretation from your shell. + +## Configuration + +### `command` (REQUIRED) + +This is the command you wish to run in the scratchpad. + +It supports [Variables](./Variables) + +### `animation` + +Type of animation to use, default value is "fromTop": + +- `null` / `""` (no animation) +- `fromTop` (stays close to upper screen border) +- `fromBottom` (stays close to lower screen border) +- `fromLeft` (stays close to left screen border) +- `fromRight` (stays close to right screen border) + +### `size` (recommended) + +No default value. + +Each time scratchpad is shown, window will be resized according to the provided values. + +For example on monitor of size `800x600` and `size= "80% 80%"` in config scratchpad always have size `640x480`, +regardless of which monitor it was first launched on. + +> #### Format +> +> String with "x y" (or "width height") values using some units suffix: +> +> - **percents** relative to the focused screen size (`%` suffix), eg: `60% 30%` +> - **pixels** for absolute values (`px` suffix), eg: `800px 600px` +> - a mix is possible, eg: `800px 40%` + +### `class` (recommended) + +No default value. + +Allows _Pyprland_ prepare the window for a correct animation and initial positioning. + +### `position` + +No default value, overrides the automatic margin-based position. + +Sets the scratchpad client window position relative to the top-left corner. + +Same format as `size` (see above) + +Example of scratchpad that always seat on the top-right corner of the screen: + +```toml +[scratchpads.term_quake] +command = "wezterm start --class term_quake" +position = "50% 0%" +size = "50% 50%" +class = "term_quake" +``` + +> [!note] +> If `position` is not provided, the window is placed according to `margin` on one axis and centered on the other. + +### `multi` + +Defaults to `true`. + +When set to `false`, only one client window is supported for this scratchpad. +Otherwise other matching windows will be **attach**ed to the scratchpad. + +## Advanced configuration + +To go beyond the basic setup and have a look at every configuration item, you can read the following pages: + +- [Advanced](./scratchpads_advanced) contains options for fine-tuners or specific tastes (eg: i3 compatibility) +- [Non-Standard](./scratchpads_nonstandard) contains options for "broken" applications +like progressive web apps (PWA) or emacsclient, use only if you can't get it to work otherwise + +## Monitor specific overrides + +You can use different settings for a specific screen. +Most attributes related to the display can be changed (not `command`, `class` or `process_tracking` for instance). + +Use the `monitor.` configuration item to override values, eg: + +```toml +[scratchpads.music.monitor.eDP-1] +position = "30% 50%" +animation = "fromBottom" +``` + +You may want to inline it for simple cases: + +```toml +[scratchpads.music] +monitor = {HDMI-A-1={size = "30% 50%"}} +``` diff --git a/site/versions/2.4.0/scratchpads_advanced.md b/site/versions/2.4.0/scratchpads_advanced.md new file mode 100644 index 0000000..f59d251 --- /dev/null +++ b/site/versions/2.4.0/scratchpads_advanced.md @@ -0,0 +1,134 @@ +# Fine tuning scratchpads + +Advanced configuration options + +## `pinned` + +`true` by default + +Makes the scratchpad "sticky" to the monitor, following any workspace change. + +## `excludes` + +No default value. + +List of scratchpads to hide when this one is displayed, eg: `excludes = ["term", "volume"]`. +If you want to hide every displayed scratch you can set this to the string `"*"` instead of a list: `excludes = "*"`. + +## `restore_excluded` + +`false` by default. + +When enabled, will remember the scratchpads which have been closed due to `excludes` rules, so when the scratchpad is hidden, those previously hidden scratchpads will be shown again. + +## `unfocus` + +No default value. + +When set to `"hide"`, allow to hide the window when the focus is lost. + +Use `hysteresis` to change the reactivity + +## `hysteresis` + +Defaults to `0.4` (seconds) + +Controls how fast a scratchpad hiding on unfocus will react. Check `unfocus` option. +Set to `0` to disable. + +> [!important] +> Only relevant when `unfocus="hide"` is used. + +## `margin` + +default value is `60`. + +number of pixels separating the scratchpad from the screen border, depends on the [animation](./scratchpads#animation) set. + +> [!tip] +> It is also possible to set a string to express percentages of the screen (eg: '`3%`'). + +## `max_size` + +No default value. + +Same format as `size` (see above), only used if `size` is also set. + +Limits the `size` of the window accordingly. +To ensure a window will not be too large on a wide screen for instance: + +```toml +size = "60% 30%" +max_size = "1200px 100%" +``` + +## `lazy` + +default to `false`. + +when set to `true`, prevents the command from being started when pypr starts, it will be started when the scratchpad is first used instead. + +- Good: saves resources when the scratchpad isn't needed +- Bad: slows down the first display (app has to launch before showing) + +## `preserve_aspect` + +Not set by default. +When set to `true`, will preserve the size and position of the scratchpad when called repeatedly from the same monitor and workspace even though an `animation` , `position` or `size` is used (those will be used for the initial setting only). + +Forces the `lazy` option. + +## `offset` + +In pixels, default to `0` (client's window size + margin). + +Number of pixels for the **hide** sliding animation (how far the window will go). + +> [!tip] +> - It is also possible to set a string to express percentages of the client window +> - `margin` is automatically added to the offset +> - automatic (value not set) is same as `"100%"` + +## `hide_delay` + +Defaults to `0.2` + +Delay (in seconds) after which the hide animation happens, before hiding the scratchpad. + +Rule of thumb, if you have an animation with speed "7", as in: +```bash + animation = windowsOut, 1, 7, easeInOut, popin 80% +``` +You can divide the value by two and round to the lowest value, here `3`, then divide by 10, leading to `hide_delay = 0.3`. + +## `restore_focus` + +Enabled by default, set to `false` if you don't want the focused state to be restored when a scratchpad is hidden. + +## `force_monitor` + +If set to some monitor name (eg: `"DP-1"`), it will always use this monitor to show the scratchpad. + +## `alt_toggle` + +Default value is `false` + +When enabled, use an alternative `toggle` command logic for multi-screen setups. +It applies when the `toggle` command is triggered and the toggled scratchpad is visible on a screen which is not the focused one. + +Instead of moving the scratchpad to the focused screen, it will hide the scratchpad. + +## `allow_special_workspaces` + +Default value is `false` (can't be enabled when using *Hyprland* < 0.39 where this behavior can't be controlled and is disabled). + +When enabled, you can toggle a scratchpad over a special workspace. +It will always use the "normal" workspace otherwise. + +## `smart_focus` + +Default value is `true`. + +When enabled, the focus will be restored in a best effort way as en attempt to improve the user experience. +If you face issues such as spontaneous workspace changes, you can disable this feature. + diff --git a/site/versions/2.4.0/scratchpads_nonstandard.md b/site/versions/2.4.0/scratchpads_nonstandard.md new file mode 100644 index 0000000..a2cae9e --- /dev/null +++ b/site/versions/2.4.0/scratchpads_nonstandard.md @@ -0,0 +1,99 @@ +# Troubleshooting scratchpads + +Options that should only be used for applications that are not behaving in a "standard" way, such as `emacsclient` or progressive web apps. + +## `match_by` + +Default value is `"pid"` +When set to a sensitive client property value (eg: `class`, `initialClass`, `title`, `initialTitle`), will match the client window using the provided property instead of the PID of the process. + +This property must be set accordingly, eg: + +```toml +match_by = "class" +class = "my-web-app" +``` + +or + +```toml +match_by = "initialClass" +initialClass = "my-web-app" +``` + +You can add the "re:" prefix to use a regular expression, eg: + +```toml +match_by = "title" +title = "re:.*some string.*" +``` + +> [!note] +> Some apps may open the graphical client window in a "complicated" way, to work around this, it is possible to disable the process PID matching algorithm and simply rely on window's class. +> +> The `match_by` attribute can be used to achieve this, eg. for emacsclient: +> ```toml +> [scratchpads.emacs] +> command = "/usr/local/bin/emacsStart.sh" +> class = "Emacs" +> match_by = "class" +> ``` + +## `process_tracking` + +Default value is `true` + +Allows disabling the process management. Use only if running a progressive web app (Chrome based apps) or similar. + +This will automatically force `lazy = true` and set `match_by="class"` if no `match_by` rule is provided, to help with the fuzzy client window matching. + +It requires defining a `class` option (or the option matching your `match_by` value). + +```toml +## Chat GPT on Brave +[scratchpads.gpt] +animation = "fromTop" +command = "brave --profile-directory=Default --app=https://chat.openai.com" +class = "brave-chat.openai.com__-Default" +size = "75% 60%" +process_tracking = false + +## Some chrome app +[scratchpads.music] +command = "google-chrome --profile-directory=Default --app-id=cinhimbnkkaeohfgghhklpknlkffjgod" +class = "chrome-cinhimbnkkaeohfgghhklpknlkffjgod-Default" +size = "50% 50%" +process_tracking = false +``` + +> [!tip] +> To list windows by class and title you can use: +> - `hyprctl -j clients | jq '.[]|[.class,.title]'` +> - or if you prefer a graphical tool: `rofi -show window` + +> [!note] +> Progressive web apps will share a single process for every window. +> On top of requiring the class based window tracking (using `match_by`), +> the process can not be managed the same way as usual apps and the correlation +> between the process and the client window isn't as straightforward and can lead to false matches in extreme cases. + +## `skip_windowrules` + +Default value is `[]` +Allows you to skip the window rules for a specific scratchpad. +Available rules are: + +- "aspect" controlling size and position +- "float" controlling the floating state +- "workspace" which moves the window to its own workspace + +If you are using an application which can spawn multiple windows and you can't see them, you can skip rules made to improve the initial display of the window. + +```toml +[scratchpads.filemanager] +animation = "fromBottom" +command = "nemo" +class = "nemo" +size = "60% 60%" +skip_windowrules = ["aspect", "workspace"] +``` diff --git a/site/versions/2.4.0/shift_monitors.md b/site/versions/2.4.0/shift_monitors.md new file mode 100644 index 0000000..0d4e616 --- /dev/null +++ b/site/versions/2.4.0/shift_monitors.md @@ -0,0 +1,25 @@ +--- +commands: + - name: shift_monitors + description: Swaps the workspaces of every screen in the given direction. +--- + +# shift_monitors + +Swaps the workspaces of every screen in the given direction. + +> [!Note] +> the behavior can be hard to predict if you have more than 2 monitors (depending on your layout). +> If you use this plugin with many monitors and have some ideas about a convenient configuration, you are welcome ;) + +Example usage in `hyprland.conf`: + +``` +bind = $mainMod, O, exec, pypr shift_monitors +1 +bind = $mainMod SHIFT, O, exec, pypr shift_monitors -1 +``` + +## Command + + + diff --git a/site/versions/2.4.0/shortcuts_menu.md b/site/versions/2.4.0/shortcuts_menu.md new file mode 100644 index 0000000..7a31335 --- /dev/null +++ b/site/versions/2.4.0/shortcuts_menu.md @@ -0,0 +1,171 @@ +--- +commands: + - name: menu [name] + description: Displays the full menu or part of it if "name" is provided +--- + +# shortcuts_menu + +Presents some menu to run shortcut commands. Supports nested menus (aka categories / sub-menus). + +
+ Configuration examples + +```toml +[shortcuts_menu.entries] + +"Open Jira ticket" = 'open-jira-ticket "$(wl-paste)"' +Relayout = "pypr relayout" +"Fetch window" = "pypr fetch_client_menu" +"Hyprland socket" = 'kitty socat - "UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"' +"Hyprland logs" = 'kitty tail -f $XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/hyprland.log' + +"Serial USB Term" = [ + {name="device", command="ls -1 /dev/ttyUSB*; ls -1 /dev/ttyACM*"}, + {name="speed", options=["115200", "9600", "38400", "115200", "256000", "512000"]}, + "kitty miniterm --raw --eol LF [device] [speed]" +] + +"Color picker" = [ + {name="format", options=["hex", "rgb", "hsv", "hsl", "cmyk"]}, + "sleep 0.2; hyprpicker --format [format] | wl-copy" # sleep to let the menu close before the picker opens +] + +screenshot = [ + {name="what", options=["output", "window", "region", "active"]}, + "hyprshot -m [what] -o /tmp -f shot_[what].png" +] + +annotate = [ + {name="fname", command="ls /tmp/shot_*.png"}, + "satty --filename '[fname]' --output-filename '/tmp/annotated.png'" +] + +"Clipboard history" = [ + {name="entry", command="cliphist list", filter="s/\t.*//"}, + "cliphist decode '[entry]' | wl-copy" +] + +"Copy password" = [ + {name="what", command="gopass ls --flat"}, + "gopass show -c [what]" +] + +"Update/Change password" = [ + {name="what", command="gopass ls --flat"}, + "kitty -- gopass generate -s --strict -t '[what]' && gopass show -c '[what]'" +] +``` + +
+ + +## Command + + + +> [!tip] +> - If "name" is provided it will show the given sub-menu. +> - You can use "." to reach any level of the configured menus. +> +> Example to reach `shortcuts_menu.entries.utils."local commands"`, use: +> ```sh +> pypr menu "utils.local commands" +> ``` + +## Configuration + +All the [Menu](./Menu) configuration items are also available. + +### `entries` (REQUIRED) + +Defines the menu entries. Supports [Variables](./Variables) + +```toml +[shortcuts_menu.entries] +"entry 1" = "command to run" +"entry 2" = "command to run" +``` +Submenus can be defined too (there is no depth limit): + +```toml +[shortcuts_menu.entries."My submenu"] +"entry X" = "command" + +[shortcuts_menu.entries.one.two.three.four.five] +foobar = "ls" +``` + +#### Advanced usage + +Instead of navigating a configured list of menu options and running a pre-defined command, you can collect various *variables* (either static list of options selected by the user, or generated from a shell command) and then run a command using those variables. Eg: + +```toml +"Play Video" = [ + {name="video_device", command="ls -1 /dev/video*"}, + {name="player", + options=["mpv", "guvcview"] + }, + "[player] [video_device]" +] + +"Ssh" = [ + {name="action", options=["htop", "uptime", "sudo halt -p"]}, + {name="host", options=["gamix", "gate", "idp"]}, + "kitty --hold ssh [host] [action]" +] +``` + +You must define a list of objects, containing: +- `name`: the variable name +- then the list of options, must be one of: + - `options` for a static list of options + - `command` to get the list of options from a shell command's output + +> [!tip] +> You can apply post-filters to the `command` output, eg: +> ```toml +> { +> name = "entry", +> command = "cliphist list", +> filter = "s/\t.*//" # will remove everything after the TAB character +> } +> ``` +> check the [filters](./filters) page for more details + +The last item of the list must be a string which is the command to run. Variables can be used enclosed in `[]`. + +### `command_start` +### `command_end` +### `submenu_start` +### `submenu_end` + +Allow adding some text (eg: icon) before / after a menu entry. + +command_* is for final commands, while submenu_* is for entries leading to another menu. + +By default `submenu_end` is set to a right arrow sign, while other attributes are not set. + +### `skip_single` + +Defaults to `true`. +When disabled, shows the menu even for single options + +## Hints + +### Multiple menus + +To manage multiple distinct menus, always use a name when using the `pypr menu ` command. + +Example of a multi-menu configuration: + +```toml +[shortcuts_menu.entries."Basic commands"] +"entry X" = "command" +"entry Y" = "command2" + +[shortcuts_menu.entries.menu2] +## ... +``` + +You can then show the first menu using `pypr menu "Basic commands"` diff --git a/site/versions/2.4.0/system_notifier.md b/site/versions/2.4.0/system_notifier.md new file mode 100644 index 0000000..8bbcab0 --- /dev/null +++ b/site/versions/2.4.0/system_notifier.md @@ -0,0 +1,106 @@ +# system_notifier + +This plugin adds system notifications based on journal logs (or any program's output). +It monitors specified **sources** for log entries matching predefined **patterns** and generates notifications accordingly (after applying an optional **filter**). + +Sources are commands that return a stream of text (eg: journal, mqtt, tail -f, ...) which is sent to a parser that will use a [regular expression pattern](https://en.wikipedia.org/wiki/Regular_expression) to detect lines of interest and optionally transform them before sending the notification. + +
+ Minimal configuration + +```toml +[system_notifier.sources] +command = "sudo journalctl -fx" +parser = "journal" +``` + +In general you will also need to define some **parsers**. +By default a **"journal"** parser is provided, otherwise you need to define your own rules. +This built-in configuration is close to this one, provided as an example: + +```toml +[system_notifier.parsers.journal] +pattern = "([a-z0-9]+): Link UP$" +filter = "s/.*\[\d+\]: ([a-z0-9]+): Link.*/\1 is active/" +color= "#00aa00" + +[system_notifier.parsers.journal] +pattern = "([a-z0-9]+): Link DOWN$" +filter = "s/.*\[\d+\]: ([a-z0-9]+): Link.*/\1 is inactive/" +color= "#ff8800" + +[system_notifier.parsers.journal] +pattern = "Process \d+ \(.*\) of .* dumped core." +filter = "s/.*Process \d+ \((.*)\) of .* dumped core./\1 dumped core/" +color= "#aa0000" + +[system_notifier.parsers.journal] +pattern = "usb \d+-[0-9.]+: Product: " +filter = "s/.*usb \d+-[0-9.]+: Product: (.*)/USB plugged: \1/" +``` +
+ + +## Configuration + +### `sources` (recommended) + +List of sources to enable (by default nothing is enabled) + +Each source must contain a `command` to run and a `parser` to use. + +You can also use a list of parsers, eg: + +```toml +[system_notifier.sources](system_notifier.sources) +command = "sudo journalctl -fkn" +parser = ["journal", "custom_parser"] +``` + +#### command (recommended) + +This is the long-running command (eg: `tail -f `) returning the stream of text that will be updated. Aa common option is the system journal output (eg: `journalctl -u nginx`) + +#### parser + +Sets the list of rules / parser to be used to extract lines of interest. +Must match a list of rules defined as `system_notifier.parsers.`. + +### `parsers` (recommended) + +A list of available parsers that can be used to detect lines of interest in the **sources** and re-format it before issuing a notification. + +Each parser definition must contain a **pattern** and optionally a **filter** and a **color**. + +#### pattern + +```toml +[system_notifier.parsers.custom_parser](system_notifier.parsers.custom_parser) + +pattern = 'special value:' +``` + +The pattern is any regular expression. + +#### filter + +The [filters](./filters) allows to change the text before the notification, eg: +`filter="s/.*special value: (\d+)/Value=\1/"` +will set a filter so a string "special value: 42" will lead to the notification "Value=42" + +#### color + +You can also provide an optional **color** in `"hex"` or `"rgb()"` format + +```toml +color = "#FF5500" +``` + +### default_color + +Sets the notification color that will be used when none is provided in a *parser* definition. + +```toml +[system_notifier] +default_color = "#bbccbb" +``` diff --git a/site/versions/2.4.0/toggle_dpms.md b/site/versions/2.4.0/toggle_dpms.md new file mode 100644 index 0000000..4b4a86f --- /dev/null +++ b/site/versions/2.4.0/toggle_dpms.md @@ -0,0 +1,12 @@ +--- +commands: + - name: toggle_dpms + description: if any screen is powered on, turn them all off, else turn them all on +--- + +# toggle_dpms + +## Command + + + diff --git a/site/versions/2.4.0/toggle_special.md b/site/versions/2.4.0/toggle_special.md new file mode 100644 index 0000000..50b6b16 --- /dev/null +++ b/site/versions/2.4.0/toggle_special.md @@ -0,0 +1,24 @@ +--- +commands: + - name: toggle_special [name] + description: moves the focused window to the special workspace name, or move it back to the active workspace +--- + +# toggle_special + +Allows moving the focused window to a special workspace and back (based on the visibility status of that workspace). + +It's a companion of the `togglespecialworkspace` Hyprland's command which toggles a special workspace's visibility. + +You most likely will need to configure the two commands for a complete user experience, eg: + +```bash +bind = $mainMod SHIFT, N, togglespecialworkspace, stash # toggles "stash" special workspace visibility +bind = $mainMod, N, exec, pypr toggle_special stash # moves window to/from the "stash" workspace +``` + +No other configuration needed, here `MOD+SHIFT+N` will show every window in "stash" while `MOD+N` will move the focused window out of it/ to it. + +## Command + + diff --git a/site/versions/2.4.0/wallpapers.md b/site/versions/2.4.0/wallpapers.md new file mode 100644 index 0000000..cd7587c --- /dev/null +++ b/site/versions/2.4.0/wallpapers.md @@ -0,0 +1,115 @@ +--- +commands: + - name: wall next + description: Changes the current background image + - name: wall clear + description: Removes the current background image +--- + +# wallpapers + +Search folders for images and sets the background image at a regular interval. +Images are selected randomly from the full list of images found. + +It serves two purposes: + +- adding support for random images to any background setting tool +- quickly testing different tools with a minimal effort + +It allows "zapping" current backgrounds, clearing it to go distraction free and optionally make them different for each screen. + +> [!tip] +> Uses **swaybg** by default, but can be configured to use any other application. + +
+ Minimal example using defaults(requires swaybg) + +```toml +[wallpapers] +path = "~/Images/wallpapers/" # path to the folder with background images +``` + +
+ +
+More complete, using the custom swww command (not recommended because of its stability) + +```toml +[wallpapers] +unique = true # set a different wallpaper for each screen +path = "~/Images/wallpapers/" +interval = 60 # change every hour +extensions = ["jpg", "jpeg"] +recurse = true +## Using swww +command = 'swww img --transition-type any "[file]"' +clear_command = "swww clear" +``` + +Note that for applications like `swww`, you'll need to start a daemon separately (eg: from `hyprland.conf`). +
+ + +## Commands + + + +## Configuration + + +### `path` (REQUIRED) + +path to a folder or list of folders that will be searched. Can also be a list, eg: + +```toml +path = ["~/Images/Portraits/", "~/Images/Landscapes/"] +``` + +### `interval` + +defaults to `10` + +How long (in minutes) a background should stay in place + + +### `command` + +Overrides the default command to set the background image. + +[variables](./Variables) are replaced with the appropriate values, you must use a `"[file]"` placeholder for the image path. eg: + +``` +swaybg -m fill -i "[file]" +``` + +### `clear_command` + +By default `clear` command kills the `command` program. + +Instead of that, you can provide a command to clear the background. eg: + +``` +clear_command = "swaybg clear" +`````` + +### `extensions` + +defaults to `["png", "jpg", "jpeg"]` + +List of valid wallpaper image extensions. + +### `recurse` + +defaults to `false` + +When enabled, will also search sub-directories recursively. + +### `unique` + +defaults to `false` + +When enabled, will set a different wallpaper for each screen. + +If you are not using the default application, ensure you are using `"[output]"` in the [command](#command) template. + +Example for swaybg: `swaybg -o "[output]" -m fill -i "[file]"` diff --git a/site/versions/2.4.0/workspaces_follow_focus.md b/site/versions/2.4.0/workspaces_follow_focus.md new file mode 100644 index 0000000..5b44389 --- /dev/null +++ b/site/versions/2.4.0/workspaces_follow_focus.md @@ -0,0 +1,32 @@ +--- +commands: + - name: change_workspace [direction] + description: Changes the workspace of the focused monitor in the given direction. +--- + +# workspaces_follow_focus + +Make non-visible workspaces follow the focused monitor. +Also provides commands to switch between workspaces while preserving the current monitor assignments: + +Syntax: +```toml +[workspaces_follow_focus] +max_workspaces = 4 # number of workspaces before cycling +``` +Example usage in `hyprland.conf`: + +```ini +bind = $mainMod, K, exec, pypr change_workspace +1 +bind = $mainMod, J, exec, pypr change_workspace -1 + ``` + +## Command + + + +## Configuration + +### `max_workspaces` + +Limits the number of workspaces when switching, defaults value is `10`.