github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/elvish/edit/lastcmd/lastcmd.go (about)

     1  package lastcmd
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/u-root/u-root/cmds/core/elvish/edit/eddefs"
     9  	"github.com/u-root/u-root/cmds/core/elvish/edit/ui"
    10  	"github.com/u-root/u-root/cmds/core/elvish/eval"
    11  	"github.com/u-root/u-root/cmds/core/elvish/eval/vars"
    12  	"github.com/u-root/u-root/cmds/core/elvish/parse/parseutil"
    13  )
    14  
    15  type state struct {
    16  	line     string
    17  	words    []string
    18  	filtered []entry
    19  	minus    bool
    20  }
    21  
    22  type entry struct {
    23  	i int
    24  	s string
    25  }
    26  
    27  // Init initializes the lastcmd module for an Editor.
    28  func Init(ed eddefs.Editor, ns eval.Ns) {
    29  	lc := &state{}
    30  	binding := eddefs.EmptyBindingMap
    31  
    32  	subns := eval.Ns{
    33  		"binding": vars.FromPtr(&binding),
    34  	}
    35  	subns.AddBuiltinFns("edit:lastcmd:", map[string]interface{}{
    36  		"start":       func() { lc.start(ed, binding) },
    37  		"accept-line": func() { lc.acceptLine(ed) },
    38  	})
    39  	ns.AddNs("lastcmd", subns)
    40  }
    41  
    42  func newState(line string) *state {
    43  	return &state{line, parseutil.Wordify(line), nil, false}
    44  }
    45  
    46  func (*state) AutoAccept() bool {
    47  	return true
    48  }
    49  
    50  func (*state) ModeTitle(int) string {
    51  	return " LASTCMD "
    52  }
    53  
    54  func (s *state) Len() int {
    55  	return len(s.filtered)
    56  }
    57  
    58  func (s *state) Show(i int) (string, ui.Styled) {
    59  	entry := s.filtered[i]
    60  	var head string
    61  	if entry.i == -1 {
    62  		head = "M-1"
    63  	} else if s.minus {
    64  		head = fmt.Sprintf("%d", entry.i-len(s.words))
    65  	} else {
    66  		head = fmt.Sprintf("%d", entry.i)
    67  	}
    68  	return head, ui.Unstyled(entry.s)
    69  }
    70  
    71  func (s *state) Filter(filter string) int {
    72  	s.filtered = nil
    73  	s.minus = len(filter) > 0 && filter[0] == '-'
    74  	if filter == "" || filter == "-" {
    75  		s.filtered = append(s.filtered, entry{-1, s.line})
    76  	} else if _, err := strconv.Atoi(filter); err != nil {
    77  		return -1
    78  	}
    79  	// Quite inefficient way to filter by prefix of stringified index.
    80  	n := len(s.words)
    81  	for i, word := range s.words {
    82  		if filter == "" ||
    83  			(!s.minus && strings.HasPrefix(strconv.Itoa(i), filter)) ||
    84  			(s.minus && strings.HasPrefix(strconv.Itoa(i-n), filter)) {
    85  			s.filtered = append(s.filtered, entry{i, word})
    86  		}
    87  	}
    88  	if len(s.filtered) == 0 {
    89  		return -1
    90  	}
    91  	return 0
    92  }
    93  
    94  func (s *state) Accept(i int, ed eddefs.Editor) {
    95  	ed.InsertAtDot(s.filtered[i].s)
    96  	ed.SetModeInsert()
    97  }
    98  
    99  func (s *state) start(ed eddefs.Editor, binding eddefs.BindingMap) {
   100  	ed.Notify("store offline, cannot start lastcmd mode")
   101  }
   102  
   103  func (s *state) acceptLine(ed eddefs.Editor) {
   104  	ed.InsertAtDot(s.line)
   105  	ed.SetModeInsert()
   106  }