github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/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/mode"
     9  	"src.elv.sh/pkg/cli/tk"
    10  	"src.elv.sh/pkg/eval"
    11  )
    12  
    13  //elvdoc:var history:binding
    14  //
    15  // Binding table for the history mode.
    16  
    17  //elvdoc:fn history:start
    18  //
    19  // Starts the history mode.
    20  
    21  //elvdoc:fn history:up
    22  //
    23  // Walks to the previous entry in history mode.
    24  
    25  //elvdoc:fn history:down
    26  //
    27  // Walks to the next entry in history mode.
    28  
    29  //elvdoc:fn history:down-or-quit
    30  //
    31  // Walks to the next entry in history mode, or quit the history mode if already
    32  // at the newest entry.
    33  
    34  //elvdoc:fn history:fast-forward
    35  //
    36  // Import command history entries that happened after the current session
    37  // started.
    38  
    39  func initHistWalk(ed *Editor, ev *eval.Evaler, hs *histStore, nb eval.NsBuilder) {
    40  	bindingVar := newBindingVar(emptyBindingsMap)
    41  	bindings := newMapBindings(ed, ev, bindingVar)
    42  	app := ed.app
    43  	nb.AddNs("history",
    44  		eval.NsBuilder{
    45  			"binding": bindingVar,
    46  		}.AddGoFns("<edit:history>", map[string]interface{}{
    47  			"start": func() { notifyError(app, histwalkStart(app, hs, bindings)) },
    48  			"up":    func() { notifyError(app, histwalkDo(app, mode.Histwalk.Prev)) },
    49  
    50  			"down": func() { notifyError(app, histwalkDo(app, mode.Histwalk.Next)) },
    51  			"down-or-quit": func() {
    52  				err := histwalkDo(app, mode.Histwalk.Next)
    53  				if err == histutil.ErrEndOfHistory {
    54  					app.SetAddon(nil, false)
    55  				} else {
    56  					notifyError(app, err)
    57  				}
    58  			},
    59  			// TODO: Remove these builtins in favor of two universal accept and
    60  			// close builtins
    61  			"accept": func() { app.SetAddon(nil, true) },
    62  
    63  			"fast-forward": hs.FastForward,
    64  		}).Ns())
    65  }
    66  
    67  func histwalkStart(app cli.App, hs *histStore, bindings tk.Bindings) error {
    68  	buf := app.CodeArea().CopyState().Buffer
    69  	w, err := mode.NewHistwalk(app, mode.HistwalkSpec{
    70  		Bindings: bindings, Store: hs, Prefix: buf.Content[:buf.Dot]})
    71  	if w != nil {
    72  		app.SetAddon(w, false)
    73  	}
    74  	return err
    75  }
    76  
    77  var errNotInHistoryMode = errors.New("not in history mode")
    78  
    79  func histwalkDo(app cli.App, f func(mode.Histwalk) error) error {
    80  	w, ok := app.CopyState().Addon.(mode.Histwalk)
    81  	if !ok {
    82  		return errNotInHistoryMode
    83  	}
    84  	return f(w)
    85  }
    86  
    87  func notifyError(app cli.App, err error) {
    88  	if err != nil {
    89  		app.Notify(err.Error())
    90  	}
    91  }