github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/events/handler.go (about)

     1  package events
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/lmorg/murex/debug"
     9  	"github.com/lmorg/murex/lang"
    10  	"github.com/lmorg/murex/lang/ref"
    11  	"github.com/lmorg/murex/lang/stdio"
    12  	"github.com/lmorg/murex/lang/types"
    13  	"github.com/lmorg/murex/utils/json"
    14  )
    15  
    16  type eventType interface {
    17  	Add(name, interrupt string, block []rune, fileRef *ref.File) (err error)
    18  	Remove(interrupt string) (err error)
    19  	Dump() (dump map[string]DumpT)
    20  }
    21  
    22  var events = make(map[string]eventType)
    23  
    24  // AddEventType registers your event type handlers
    25  func AddEventType(eventTypeName string, handlerInterface eventType, err error) error {
    26  	if err != nil {
    27  		os.Stderr.WriteString(
    28  			fmt.Sprintf("cannot add event module %s: %s", eventTypeName, err),
    29  		)
    30  	}
    31  	events[eventTypeName] = handlerInterface
    32  	return nil
    33  }
    34  
    35  type j struct {
    36  	Name      string
    37  	Interrupt interface{}
    38  }
    39  
    40  // Callback is a generic function your event handlers types should hook into so
    41  // murex functions can remain consistent.
    42  func Callback(name string, interrupt interface{}, block []rune, fileRef *ref.File, stdout stdio.Io, background bool) {
    43  	if fileRef == nil {
    44  		if debug.Enabled {
    45  			panic("fileRef should not be nil value")
    46  		}
    47  		os.Stderr.WriteString("Murex error with `event`: '" + name + "'. fileRef should not be nil value. Creating empty object to continue. Please report this https://github.com/lmorg/murex/issues\n")
    48  		fileRef = &ref.File{
    49  			Source: &ref.Source{
    50  				Filename: "UNKNOWN: forked from `event` " + name,
    51  				Module:   "UNKNOWN: forked from `event` " + name,
    52  				DateTime: time.Now(),
    53  			},
    54  		}
    55  	}
    56  
    57  	json, err := json.Marshal(&j{
    58  		Name:      name,
    59  		Interrupt: interrupt,
    60  	}, false)
    61  	if err != nil {
    62  		lang.ShellProcess.Stderr.Writeln([]byte("error building event input: " + err.Error()))
    63  		return
    64  	}
    65  
    66  	var bgProc int
    67  	if background {
    68  		bgProc = lang.F_BACKGROUND
    69  	}
    70  
    71  	fork := lang.ShellProcess.Fork(lang.F_FUNCTION | bgProc | lang.F_CREATE_STDIN)
    72  	fork.Stdin.SetDataType(types.Json)
    73  	fork.Name.Set("(event)")
    74  	fork.FileRef = fileRef
    75  	fork.CCEvent = nil
    76  	fork.CCExists = nil
    77  	_, err = fork.Stdin.Write(json)
    78  	if err != nil {
    79  		lang.ShellProcess.Stderr.Writeln([]byte("error writing event input: " + err.Error()))
    80  		return
    81  	}
    82  
    83  	debug.Log("Event callback:", string(json), string(block))
    84  
    85  	fork.Stdout = stdout
    86  
    87  	_, err = fork.Execute(block)
    88  	if err != nil {
    89  		lang.ShellProcess.Stderr.Writeln([]byte("error compiling event callback: " + err.Error()))
    90  	}
    91  }
    92  
    93  // DumpEvents is used for `runtime` to output all the saved events
    94  func DumpEvents() (dump map[string]interface{}) {
    95  	dump = make(map[string]interface{})
    96  
    97  	for et := range events {
    98  		dump[et] = events[et].Dump()
    99  	}
   100  
   101  	return
   102  }
   103  
   104  type DumpT struct {
   105  	Interrupt string
   106  	Block     string
   107  	FileRef   *ref.File
   108  }