src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/hook.go (about) 1 package eval 2 3 import ( 4 "fmt" 5 6 "src.elv.sh/pkg/diag" 7 "src.elv.sh/pkg/eval/vals" 8 ) 9 10 // CallHook runs all the functions in the list "hook", with "args". 11 // 12 // If "evalCfg" is not specified, the standard files will be used for IO. 13 // 14 // TODO: Eventually all callers should supply evalCfg. In general it's not 15 // correct to use standard files: 16 // 17 // - Chdir hooks should use the frame from which the chdir is triggered. 18 // - Editor lifecycle hooks should use the editor's TTY. 19 func CallHook(ev *Evaler, evalCfg *EvalCfg, name string, hook vals.List, args ...any) { 20 if hook.Len() == 0 { 21 return 22 } 23 24 if evalCfg == nil { 25 ports, cleanup := PortsFromStdFiles(ev.ValuePrefix()) 26 defer cleanup() 27 evalCfg = &EvalCfg{Ports: ports} 28 } 29 30 callCfg := CallCfg{Args: args, From: "[hook " + name + "]"} 31 32 i := -1 33 stderr := evalCfg.Ports[2].File 34 for it := hook.Iterator(); it.HasElem(); it.Next() { 35 i++ 36 fn, ok := it.Elem().(Callable) 37 if !ok { 38 diag.ShowError(stderr, fmt.Errorf("hook %s[%d] must be callable", name, i)) 39 continue 40 } 41 42 err := ev.Call(fn, callCfg, *evalCfg) 43 if err != nil { 44 diag.ShowError(stderr, err) 45 } 46 } 47 }