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  }