src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/edit/state_api.go (about) 1 package edit 2 3 import ( 4 "errors" 5 6 "src.elv.sh/pkg/cli" 7 "src.elv.sh/pkg/cli/tk" 8 "src.elv.sh/pkg/eval" 9 "src.elv.sh/pkg/eval/vals" 10 "src.elv.sh/pkg/eval/vars" 11 ) 12 13 var errDotOutOfBoundary = errors.New("dot out of command boundary") 14 15 func insertAtDot(app cli.App, text string) { 16 codeArea, ok := focusedCodeArea(app) 17 if !ok { 18 return 19 } 20 codeArea.MutateState(func(s *tk.CodeAreaState) { 21 s.Buffer.InsertAtDot(text) 22 }) 23 } 24 25 func replaceInput(app cli.App, text string) { 26 codeArea, ok := focusedCodeArea(app) 27 if !ok { 28 return 29 } 30 codeArea.MutateState(func(s *tk.CodeAreaState) { 31 s.Buffer = tk.CodeBuffer{Content: text, Dot: len(text)} 32 }) 33 } 34 35 func initStateAPI(app cli.App, nb eval.NsBuilder) { 36 // State API always operates on the root CodeArea widget 37 codeArea := app.ActiveWidget().(tk.CodeArea) 38 39 nb.AddGoFns(map[string]any{ 40 "insert-at-dot": func(s string) { insertAtDot(app, s) }, 41 "replace-input": func(s string) { replaceInput(app, s) }, 42 }) 43 44 setDot := func(v any) error { 45 var dot int 46 err := vals.ScanToGo(v, &dot) 47 if err != nil { 48 return err 49 } 50 codeArea.MutateState(func(s *tk.CodeAreaState) { 51 if dot < 0 || dot > len(s.Buffer.Content) { 52 err = errDotOutOfBoundary 53 } else { 54 s.Buffer.Dot = dot 55 } 56 }) 57 return err 58 } 59 getDot := func() any { 60 return vals.FromGo(codeArea.CopyState().Buffer.Dot) 61 } 62 nb.AddVar("-dot", vars.FromSetGet(setDot, getDot)) 63 64 setCurrentCommand := func(v any) error { 65 var content string 66 err := vals.ScanToGo(v, &content) 67 if err != nil { 68 return err 69 } 70 replaceInput(app, content) 71 return nil 72 } 73 getCurrentCommand := func() any { 74 return vals.FromGo(codeArea.CopyState().Buffer.Content) 75 } 76 nb.AddVar("current-command", vars.FromSetGet(setCurrentCommand, getCurrentCommand)) 77 }