github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/events/onPrompt/onprompt.go (about) 1 package onprompt 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/lmorg/murex/builtins/events" 8 "github.com/lmorg/murex/lang" 9 "github.com/lmorg/murex/lang/ref" 10 "github.com/lmorg/murex/shell" 11 "github.com/lmorg/murex/utils/lists" 12 ) 13 14 var eventType = "onPrompt" 15 16 func init() { 17 event := newOnPrompt() 18 events.AddEventType(eventType, event, nil) 19 shell.Events = event.callback 20 } 21 22 // Interrupt is a JSONable structure passed to the murex function 23 type Interrupt struct { 24 Name string 25 Operation string 26 CmdLine string 27 } 28 29 type promptEvent struct { 30 Key string 31 Block []rune 32 FileRef *ref.File 33 } 34 35 type promptEvents struct { 36 events []promptEvent 37 //mutex sync.Mutex 38 } 39 40 func newOnPrompt() *promptEvents { 41 return new(promptEvents) 42 } 43 44 // Add a command to the onPrompt 45 func (evt *promptEvents) Add(name, interrupt string, block []rune, fileRef *ref.File) error { 46 if err := isValidInterrupt(interrupt); err != nil { 47 return err 48 } 49 50 //evt.mutex.Lock() 51 52 key := compileInterruptKey(interrupt, name) 53 event := promptEvent{ 54 Key: key, 55 Block: block, 56 FileRef: fileRef, 57 } 58 59 i := evt.exists(key) 60 if i == doesNotExist { 61 evt.events = append(evt.events, event) 62 sort.SliceStable(evt.events, func(i, j int) bool { 63 return evt.events[i].Key < evt.events[j].Key 64 }) 65 } else { 66 evt.events[i] = event 67 } 68 69 //evt.mutex.Unlock() 70 71 return nil 72 } 73 74 func (evt *promptEvents) Remove(key string) error { 75 //evt.mutex.Lock() 76 //defer evt.mutex.Unlock() 77 78 i := evt.exists(key) 79 if i != doesNotExist { 80 events, err := lists.RemoveOrdered(evt.events, i) 81 if err != nil { 82 return fmt.Errorf("unable to remove %s: %s", key, err.Error()) 83 } 84 evt.events = events 85 return nil 86 } 87 88 var success bool 89 for _, interrupt := range interrupts { 90 newKey := compileInterruptKey(interrupt, key) 91 i = evt.exists(newKey) 92 if i != doesNotExist { 93 events, err := lists.RemoveOrdered(evt.events, i) 94 if err != nil { 95 return fmt.Errorf("unable to remove %s: %s", newKey, err.Error()) 96 } 97 evt.events = events 98 success = true 99 } 100 } 101 102 if success { 103 return nil 104 } 105 return fmt.Errorf("no %s event found called `%s`", eventType, key) 106 } 107 108 func (evt *promptEvents) callback(interrupt string, cmdLine []rune) { 109 if err := isValidInterrupt(interrupt); err != nil { 110 panic(err.Error()) 111 } 112 113 //evt.mutex.Lock() 114 115 for i := range evt.events { 116 split := getInterruptFromKey(evt.events[i].Key) 117 if split[0] == interrupt { 118 interruptValue := Interrupt{ 119 Name: split[1], 120 Operation: interrupt, 121 CmdLine: string(cmdLine), 122 } 123 events.Callback(evt.events[i].Key, interruptValue, evt.events[i].Block, evt.events[i].FileRef, lang.ShellProcess.Stdout, false) 124 } 125 } 126 127 //evt.mutex.Unlock() 128 } 129 130 const doesNotExist = -1 131 132 func (evt *promptEvents) exists(key string) int { 133 //evt.mutex.Lock() 134 135 for i := range evt.events { 136 if evt.events[i].Key == key { 137 return i 138 } 139 } 140 141 //evt.mutex.Unlock() 142 143 return doesNotExist 144 } 145 146 func (evt *promptEvents) Dump() map[string]events.DumpT { 147 dump := make(map[string]events.DumpT) 148 149 //evt.mutex.Lock() 150 151 for i := range evt.events { 152 dump[evt.events[i].Key] = events.DumpT{ 153 Interrupt: getInterruptFromKey(evt.events[i].Key)[0], 154 Block: string(evt.events[i].Block), 155 FileRef: evt.events[i].FileRef, 156 } 157 } 158 159 //evt.mutex.Unlock() 160 161 return dump 162 }