[doc] Improve HOWTO_MODULE
This commit is contained in:
parent
f262080e78
commit
232dcb733e
1 changed files with 76 additions and 4 deletions
|
@ -17,10 +17,16 @@ modules, etc.
|
||||||
When you feel comfortable with what you've developed, please just open
|
When you feel comfortable with what you've developed, please just open
|
||||||
a PR, somebody will look at it eventually :) Thanks!
|
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
|
## Hello world
|
||||||
This example will show "hello world" in the status bar:
|
This example will show "hello world" in the status bar:
|
||||||
|
|
||||||
```
|
```python
|
||||||
"""Short description"""
|
"""Short description"""
|
||||||
|
|
||||||
import core.module
|
import core.module
|
||||||
|
@ -31,13 +37,79 @@ class Module(core.module.Module):
|
||||||
super().__init__(config, core.widget.Widget(self.full_text))
|
super().__init__(config, core.widget.Widget(self.full_text))
|
||||||
|
|
||||||
def full_text(self, widgets):
|
def full_text(self, widgets):
|
||||||
return "hello world"
|
return 'hello world'
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
```
|
```
|
||||||
|
|
||||||
## `update` vs. `full_text`
|
## Of modules and widgets
|
||||||
TODO
|
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(<new list>)`
|
||||||
|
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=<widgets>)
|
||||||
|
|
||||||
|
core.input.register(widget, button=core.input.LEFT_MOUSE, cmd=<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 <name>(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=<widgets>)
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE**: This makes the update interval of the module independent of what the
|
||||||
|
user configures via `-i <interval>`! It is still possible to override the module's
|
||||||
|
interval using `-p <module>.interval=<value>`, however.
|
||||||
|
|
||||||
## TODOs
|
## TODOs
|
||||||
- default update interval
|
- default update interval
|
||||||
|
|
Loading…
Reference in a new issue