~stacyharper/bonsai

e9d4902a96d238d31e8c7eb924116ba209c60dc2 — Stacy Harper 4 months ago 45074e3 develop
Add initial readme
1 files changed, 188 insertions(+), 0 deletions(-)

A README.md
A README.md => README.md +188 -0
@@ 0,0 1,188 @@
# Bonsai

### Definitions

Bonsai allow you to define "branches" that a "voyager" will travel. This is a
client / server software and you interract with the voyager using a command
line client. Every branch got child branches attached to it. There is 4 kind
of branches and the voyager will go to the branch childs if they match the
branch condition :

- event branch: The received event name match the branch event name
- context branch: The voyager context match the branch context
- exec branch: The branch command is run and succeed
- delay branch: The voyager wait for the duration. No relevant event is
received while waiting.

After you sent to the voyager an event or changed their context, the voyager will
follow every available branch they can, respecting the order, and recursively. If
there is no more available branch in front of the voyager, they returns to the
initial position.

### Reference

```json
[
  {
    "type": "event",
    "event_name": "event_foo"
  },
  {
    "type": "context",
    "contexts": {
      "toto": "titi",
      "tata": "tutu"
    }
  },
  {
    "type": "delay",
    "delay_duration": 500000000
  },
  {
    "type": "exec",
    "command": [
      "echo",
      "boooh"
    ]
  },
  {
    "type": "…",
    …,
    "branches": [
      {
      },
    ]
  }
]
```

#### Events arent recursives

The voyager will not follow recursively every event branch that match. Only
the first one is triggered then only execs, contexts and delays are recursive.

#### Soft locks

It is easy to soft lock you voyager if you dont handle every situation. The
following example show two trees. The first one can cause soft locks :

```json
[
  {
    "type": "event",
    "event_name": "foo",
    "branches": [
      {
        "type": "event",
        "event_name": "bar",
        "branches": [
          {
            "type": "exec",
            "mmmmmnd": [
              "yataaa"
            ]
          }
        ]
      }
    ]
  }
]
```

If you receive "foo" but never "bar", your voyager is soft locked. The voyager
will ignore irrelevant events so you cant go to a brother event branch of
"foo". Maybe this is intended, maybe not. Here how to handle this :

```json
[
  {
    "type": "event",
    "event_name": "foo",
    "branches": [
      {
        "type": "event",
        "event_name": "bar",
        "branches": [
          {
            "type": "exec",
            "command": [
              "yataaa"
            ]
          }
        ]
      },
      {
        "type": "delay",
        "delay_duration": 500000000
      }
    ]
  }
]
```

Now if the voyager receive "foo" but no "bar" in less than 0.5 seconds, it
return to initial position. This is how [sxmo] use bonsai to support complex
keybinds.

[sxmo]: https://sxmo.org

#### Exec branches

Exec branch commands are run synchronously. If you dont care about the command
status or use the command as final trigger and dont want to hold the bonsai daemon,
you should use `["setsid", "-f", …]`.

#### Hole branches

Context branches can be used as "holes" if you dont specify context values
cause it will always match. This is particulary usefull just after exec branch
that can fail. In that example, if the command fails the voyager go back to
initial position. You can also add childs to the context branch to exec another
command :

```json
[
  {
    "type": "event",
    "event_name": "foo",
    "branches": [
      {
        "type": "exec",
        "command": [
          "this",
          "command",
          "can",
          "fail"
        ]
      },
      {
        "type": "context"
      }
    ]
  }
]
```

#### How delay are cancelled

If the voyager is waiting while receiving an event or a context update, it
check if there is a matching event or context branch available in front of
them. Otherwise it continue to wait.

## Usage

```sh
$ bonsaid -t my/bonsaid/tree.json -D # as daemon
$ bonsaictl -e my_event_name # trigger event
$ bonsaictl -c foo=bar toto=titi # change context
```

## Build

```sh
$ make check
$ make
$ doas make install
```