src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/edit/histwalk.go (about)

     1  package edit
     2  
     3  import (
     4  	"errors"
     5  
     6  	"src.elv.sh/pkg/cli"
     7  	"src.elv.sh/pkg/cli/histutil"
     8  	"src.elv.sh/pkg/cli/modes"
     9  	"src.elv.sh/pkg/cli/tk"
    10  	"src.elv.sh/pkg/eval"
    11  )
    12  
    13  func initHistWalk(ed *Editor, ev *eval.Evaler, hs *histStore, nb eval.NsBuilder) {
    14  	bindingVar := newBindingVar(emptyBindingsMap)
    15  	bindings := newMapBindings(ed, ev, bindingVar)
    16  	app := ed.app
    17  	nb.AddNs("history",
    18  		eval.BuildNsNamed("edit:history").
    19  			AddVar("binding", bindingVar).
    20  			AddGoFns(map[string]any{
    21  				"start": func() { notifyError(app, histwalkStart(app, hs, bindings)) },
    22  				"up":    func() { notifyError(app, histwalkDo(app, modes.Histwalk.Prev)) },
    23  				"down":  func() { notifyError(app, histwalkDo(app, modes.Histwalk.Next)) },
    24  				"down-or-quit": func() {
    25  					err := histwalkDo(app, modes.Histwalk.Next)
    26  					if err == histutil.ErrEndOfHistory {
    27  						app.PopAddon()
    28  					} else {
    29  						notifyError(app, err)
    30  					}
    31  				},
    32  				"accept":       func() { notifyError(app, histwalkDo(app, modes.Histwalk.Accept)) },
    33  				"fast-forward": hs.FastForward,
    34  			}))
    35  }
    36  
    37  func histwalkStart(app cli.App, hs *histStore, bindings tk.Bindings) error {
    38  	codeArea, ok := focusedCodeArea(app)
    39  	if !ok {
    40  		return nil
    41  	}
    42  	buf := codeArea.CopyState().Buffer
    43  	w, err := modes.NewHistwalk(app, modes.HistwalkSpec{
    44  		Bindings: bindings, Store: hs, Prefix: buf.Content[:buf.Dot],
    45  	})
    46  	if w != nil {
    47  		app.PushAddon(w)
    48  	}
    49  	return err
    50  }
    51  
    52  var errNotInHistoryMode = errors.New("not in history mode")
    53  
    54  func histwalkDo(app cli.App, f func(modes.Histwalk) error) error {
    55  	w, ok := app.ActiveWidget().(modes.Histwalk)
    56  	if !ok {
    57  		return errNotInHistoryMode
    58  	}
    59  	return f(w)
    60  }
    61  
    62  func notifyError(app cli.App, err error) {
    63  	if err != nil {
    64  		app.Notify(modes.ErrorText(err))
    65  	}
    66  }