added variables interpolation

This commit is contained in:
sqshq 2019-03-20 22:23:08 -04:00
parent 9f0856466e
commit ee914fade3
5 changed files with 32 additions and 18 deletions

View File

@ -2,6 +2,6 @@ package config
type Options struct { type Options struct {
ConfigFile string `short:"c" long:"config" required:"true" description:"path to YAML config file"` ConfigFile string `short:"c" long:"config" required:"true" description:"path to YAML config file"`
Variables []string `short:"v" long:"variable" required:"false" description:"variable for script ${var-name} placeholder" long-description:"one or more variables can be specified as flags, in order to replace repeated patterns in the scripts, which can be replaced with {$variable-name} placeholder" ` Variables []string `short:"v" long:"variable" required:"false" description:"specify name=value variable to use in script placeholder as $name" long-description:"one or more variables can be specified as flags, in order to replace repeated patterns in the scripts, which can be replaced with {$variable-name} placeholder" `
Examples []string `short:"e" long:"example" required:"false" choice:"runchart" choice:"barchart" choice:"asciibox" choice:"textbox" choice:"gauge" choice:"sparkline" description:"add an example component to the specified config file" long-description:"one or more example component types can be added to the specified config file, in order to jump-start the configuration"` Examples []string `short:"e" long:"example" required:"false" choice:"runchart" choice:"barchart" choice:"asciibox" choice:"textbox" choice:"gauge" choice:"sparkline" description:"add an example component to the specified config file" long-description:"one or more example component types can be added to the specified config file, in order to jump-start the configuration"`
} }

View File

@ -3,6 +3,7 @@ package data
import ( import (
ui "github.com/gizak/termui/v3" ui "github.com/gizak/termui/v3"
"github.com/sqshq/sampler/config" "github.com/sqshq/sampler/config"
"os"
"os/exec" "os/exec"
"strings" "strings"
) )
@ -25,9 +26,16 @@ func NewItems(cfgs []config.Item) []Item {
return items return items
} }
func (i *Item) nextValue() (value string, err error) { func (i *Item) nextValue(variables []string) (value string, err error) {
output, err := exec.Command("sh", "-c", i.Script).Output() cmd := exec.Command("sh", "-c", i.Script)
cmd.Env = os.Environ()
for _, variable := range variables {
cmd.Env = append(cmd.Env, variable)
}
output, err := cmd.Output()
if err != nil { if err != nil {
return "", err return "", err

View File

@ -1,6 +1,7 @@
package data package data
import ( import (
"github.com/sqshq/sampler/config"
"os/exec" "os/exec"
"time" "time"
) )
@ -12,11 +13,9 @@ type Sampler struct {
triggersChannel chan *Sample triggersChannel chan *Sample
} }
func NewSampler(consumer *Consumer, items []Item, triggers []Trigger, rateMs int) Sampler { func NewSampler(consumer *Consumer, items []Item, triggers []Trigger, options config.Options, rateMs int) Sampler {
ticker := time.NewTicker( ticker := time.NewTicker(time.Duration(rateMs * int(time.Millisecond)))
time.Duration(rateMs * int(time.Millisecond)),
)
sampler := Sampler{ sampler := Sampler{
consumer, consumer,
@ -28,7 +27,7 @@ func NewSampler(consumer *Consumer, items []Item, triggers []Trigger, rateMs int
go func() { go func() {
for ; true; <-ticker.C { for ; true; <-ticker.C {
for _, item := range sampler.items { for _, item := range sampler.items {
go sampler.sample(item) go sampler.sample(item, options)
} }
} }
}() }()
@ -47,9 +46,9 @@ func NewSampler(consumer *Consumer, items []Item, triggers []Trigger, rateMs int
return sampler return sampler
} }
func (s *Sampler) sample(item Item) { func (s *Sampler) sample(item Item, options config.Options) {
val, err := item.nextValue() val, err := item.nextValue(options.Variables)
if err == nil { if err == nil {
sample := &Sample{Label: item.Label, Value: val, Color: item.Color} sample := &Sample{Label: item.Label, Value: val, Color: item.Color}

View File

@ -21,6 +21,7 @@ type Trigger struct {
actions *Actions actions *Actions
consumer *Consumer consumer *Consumer
valuesByLabel map[string]Values valuesByLabel map[string]Values
options config.Options
player *asset.AudioPlayer player *asset.AudioPlayer
digitsRegexp *regexp.Regexp digitsRegexp *regexp.Regexp
} }
@ -37,23 +38,24 @@ type Values struct {
previous string previous string
} }
func NewTriggers(cfgs []config.TriggerConfig, consumer *Consumer, player *asset.AudioPlayer) []Trigger { func NewTriggers(cfgs []config.TriggerConfig, consumer *Consumer, options config.Options, player *asset.AudioPlayer) []Trigger {
triggers := make([]Trigger, 0) triggers := make([]Trigger, 0)
for _, cfg := range cfgs { for _, cfg := range cfgs {
triggers = append(triggers, NewTrigger(cfg, consumer, player)) triggers = append(triggers, NewTrigger(cfg, consumer, options, player))
} }
return triggers return triggers
} }
func NewTrigger(config config.TriggerConfig, consumer *Consumer, player *asset.AudioPlayer) Trigger { func NewTrigger(config config.TriggerConfig, consumer *Consumer, options config.Options, player *asset.AudioPlayer) Trigger {
return Trigger{ return Trigger{
title: config.Title, title: config.Title,
condition: config.Condition, condition: config.Condition,
consumer: consumer, consumer: consumer,
valuesByLabel: make(map[string]Values), valuesByLabel: make(map[string]Values),
options: options,
player: player, player: player,
digitsRegexp: regexp.MustCompile("[^0-9]+"), digitsRegexp: regexp.MustCompile("[^0-9]+"),
actions: &Actions{ actions: &Actions{
@ -85,7 +87,7 @@ func (t *Trigger) Execute(sample *Sample) {
} }
if t.actions.script != nil { if t.actions.script != nil {
_, _ = runScript(*t.actions.script, sample.Label, t.valuesByLabel[sample.Label]) _, _ = t.runScript(*t.actions.script, sample.Label, t.valuesByLabel[sample.Label])
} }
} }
} }
@ -100,7 +102,7 @@ func (t *Trigger) evaluate(sample *Sample) bool {
t.valuesByLabel[sample.Label] = Values{previous: InitialValue, current: sample.Value} t.valuesByLabel[sample.Label] = Values{previous: InitialValue, current: sample.Value}
} }
output, err := runScript(t.condition, sample.Label, t.valuesByLabel[sample.Label]) output, err := t.runScript(t.condition, sample.Label, t.valuesByLabel[sample.Label])
if err != nil { if err != nil {
t.consumer.AlertChannel <- &Alert{ t.consumer.AlertChannel <- &Alert{
@ -112,10 +114,15 @@ func (t *Trigger) evaluate(sample *Sample) bool {
return t.digitsRegexp.ReplaceAllString(string(output), "") == TrueIndicator return t.digitsRegexp.ReplaceAllString(string(output), "") == TrueIndicator
} }
func runScript(script, label string, data Values) ([]byte, error) { func (t *Trigger) runScript(script, label string, data Values) ([]byte, error) {
cmd := exec.Command("sh", "-c", script) cmd := exec.Command("sh", "-c", script)
cmd.Env = os.Environ() cmd.Env = os.Environ()
for _, variable := range t.options.Variables {
cmd.Env = append(cmd.Env, variable)
}
cmd.Env = append(cmd.Env, cmd.Env = append(cmd.Env,
fmt.Sprintf("prev=%v", data.previous), fmt.Sprintf("prev=%v", data.previous),
fmt.Sprintf("cur=%v", data.current), fmt.Sprintf("cur=%v", data.current),

View File

@ -23,8 +23,8 @@ type Starter struct {
func (s *Starter) start(drawable ui.Drawable, consumer *data.Consumer, conponentConfig config.ComponentConfig, itemsConfig []config.Item, triggersConfig []config.TriggerConfig) { func (s *Starter) start(drawable ui.Drawable, consumer *data.Consumer, conponentConfig config.ComponentConfig, itemsConfig []config.Item, triggersConfig []config.TriggerConfig) {
cpt := component.NewComponent(drawable, consumer, conponentConfig) cpt := component.NewComponent(drawable, consumer, conponentConfig)
triggers := data.NewTriggers(triggersConfig, consumer, s.player) triggers := data.NewTriggers(triggersConfig, consumer, s.opt, s.player)
data.NewSampler(consumer, data.NewItems(itemsConfig), triggers, *conponentConfig.RefreshRateMs) data.NewSampler(consumer, data.NewItems(itemsConfig), triggers, s.opt, *conponentConfig.RefreshRateMs)
s.lout.AddComponent(cpt) s.lout.AddComponent(cpt)
} }