diff --git a/doc/HOWTO_MODULE.md b/doc/HOWTO_MODULE.md index dde0210..d93ec20 100644 --- a/doc/HOWTO_MODULE.md +++ b/doc/HOWTO_MODULE.md @@ -17,10 +17,16 @@ modules, etc. When you feel comfortable with what you've developed, please just open a PR, somebody will look at it eventually :) Thanks! +## Coding guidelines +I'm pretty open to whatever style you use, but if it's all the same to you +(and yes, I know that the current codebase is only slowly adapting to this): +- Please favour single quotes for strings (except for docstrings, which are always """) +- For private methods/variables, please use a leading `__` (e.g. `__output` rather than `_output`) + ## Hello world This example will show "hello world" in the status bar: -``` +```python """Short description""" import core.module @@ -31,13 +37,79 @@ class Module(core.module.Module): super().__init__(config, core.widget.Widget(self.full_text)) def full_text(self, widgets): - return "hello world" + return 'hello world' # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 ``` -## `update` vs. `full_text` -TODO +## Of modules and widgets +There are two important concepts for module writers: +- A module is something that offers a single set of coherent functionality +- A module has 1 to n "widgets", which translates to individual blocks in the i3bar + +Very often, this is a 1:1 relationship, and a single module has a single widget. If that's the +case for you, you can stop reading now :) + +Otherwise, you have a number of ways to handle widgets: +- During the `super().init__(...)` inside the module's constructor, you can specify a **list** + of widgets, and those will comprise the widgets (in ordered fashion) +- During runtime, you can set a new list of widgets by using the `self.widgets()` + method of the module + +TODO: expand on this + +## Periodic updates +`bumblebee-status` modules have two different ways to update their data: +1. Each interval, the callback registered when the widget was created is called. You can do arbitrarily complex things there +2. Each interval, **before** the widget's callback is invoked, a generic `update(self, widgets)` method is called on the **module** + +Largely, where you want to put your update code is up to you. My observations: +- If you want to change the widgets a module has, you **have** to stick with `update()` +- For simple modules, doing the data update in the widget callback is simplest (see `kernel`, for example) + +## Advanced topics +### Event handlers +The `core.input` module can be used to execute callbacks during mouse events: +```python +import core.module +import core.widget +import core.input + +class Module(core.module.Module): + @core.decorators.every(minutes=60, seconds=20) + def __init__(self, config): + super().__init__(config=config, widgets=) + + core.input.register(widget, button=core.input.LEFT_MOUSE, cmd=) +``` + +The command can be either a CLI tool that will be directly executed (e.g. `cmd='shutdown -h now'`) +or a method that will be executed. The method's signature needs to be: `def (self, event)`, +where "event" is the event data provided by i3wm. + +The full list of possible bindings: +- LEFT_MOUSE +- RIGHT_MOUSE +- MIDDLE_MOUSE +- WHEEL_UP +- WHEEL_UP + +### Setting a default update interval +To change the default update interval, you can use a simple decorator: +```python +import core.module +import core.widget +import core.decorators + +class Module(core.module.Module): + @core.decorators.every(minutes=60, seconds=20) + def __init__(self, config): + super().__init__(config=config, widgets=) +``` + +**NOTE**: This makes the update interval of the module independent of what the +user configures via `-i `! It is still possible to override the module's +interval using `-p .interval=`, however. ## TODOs - default update interval