Development
It's easy to write your own plugin by making a python package and then indicating it's name as the plugin name.
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 <log file path>
, 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's package
The Extension
interface provides a couple of built-in attributes:
config
: object exposing the plugin section inpyprland.toml
notify
,notify_error
,notify_info
: access to Hyprland's notification systemhyprctl
,hyprctl_json
: invoke Hyprland's IPC system
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 queryhyprctl
to trigger general IPC commandson_reload
to be implemented, called when the config is (re)loadedrun_<command_name>
to implement a commandevent_<event_name>
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 thehelp
command self.config
in your Extension contains the entry corresponding to your plugin name in the TOML filestate
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:
pypr exit ; pypr --debug /tmp/output.log
Creating a plugin
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_<name of your command>
to your Extension
class, eg with "togglezoom" command:
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_<the event you are interested in>
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
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 operationsMixins
are providing common code, for instance theCastBoolMixin
provides thecast_bool
method to yourExtension
.
If you want to use menus, then the MenuMixin
will provide:
menu
to show a menuensure_menu_configured
to call before you require a menu in your plugin
Example
You'll find a basic external plugin in the examples folder.
It provides one command: pypr dummy
.
Read the plugin code
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:
[pyprland]
plugins = [
"pypr_examples.focus_counter"
]
Optionally you can customize one color:
["pypr_examples.focus_counter"]
color = "FFFF00"