github.com/jmigpin/editor@v1.6.0/core/contentcmd.go (about) 1 package core 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 ) 8 9 type ContentCmd struct { 10 Name string // for removal and error msgs 11 Fn ContentCmdFn 12 } 13 14 type ContentCmdFn func(ctx context.Context, erow *ERow, index int) (_ error, handled bool) 15 16 //---------- 17 18 type contentCmds []*ContentCmd 19 20 func (ccs *contentCmds) Append(name string, fn ContentCmdFn) { 21 cc := &ContentCmd{name, fn} 22 *ccs = append(*ccs, cc) 23 } 24 25 func (ccs *contentCmds) Prepend(name string, fn ContentCmdFn) { 26 cc := &ContentCmd{name, fn} 27 *ccs = append([]*ContentCmd{cc}, *ccs...) 28 } 29 30 func (ccs *contentCmds) Remove(name string) (removed bool) { 31 var a []*ContentCmd 32 for _, cc := range *ccs { 33 if cc.Name == name { 34 removed = true 35 } else { 36 a = append(a, cc) 37 } 38 } 39 *ccs = a 40 return 41 } 42 43 //---------- 44 45 // global cmds added via init() from "contentcmds" pkg 46 var ContentCmds contentCmds 47 48 func runContentCmds(ctx context.Context, erow *ERow, index int) { 49 errs := []string{} 50 for _, cc := range ContentCmds { 51 err, handled := cc.Fn(ctx, erow, index) 52 if handled { 53 if err != nil { 54 s := fmt.Sprintf("%v: %v", cc.Name, err) 55 errs = append(errs, s) 56 } else { 57 // stop on first handled without error 58 return 59 } 60 } 61 } 62 63 u := strings.Join(errs, "\n\t") 64 if len(u) > 0 { 65 u = "\n\t" + u 66 } 67 erow.Ed.Errorf("no content cmd ran successfully%v", u) 68 } 69 70 func ContentCmdFromTextArea(erow *ERow, index int) { 71 erow.Ed.RunAsyncBusyCursor(erow.Row, func(done func()) { 72 defer done() 73 ctx, cancel := erow.newContentCmdCtx() 74 defer cancel() 75 runContentCmds(ctx, erow, index) 76 }) 77 }