github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/edit/history.go (about)

     1  package edit
     2  
     3  import "fmt"
     4  
     5  // Command history subsystem.
     6  
     7  // Interface.
     8  
     9  type hist struct {
    10  	current int
    11  	prefix  string
    12  	line    string
    13  }
    14  
    15  func (hist) Mode() ModeType {
    16  	return modeHistory
    17  }
    18  
    19  func (h *hist) ModeLine(width int) *buffer {
    20  	return makeModeLine(fmt.Sprintf(" HISTORY #%d ", h.current), width)
    21  }
    22  
    23  func startHistory(ed *Editor) {
    24  	ed.hist.prefix = ed.line[:ed.dot]
    25  	ed.hist.current = -1
    26  	if ed.prevHistory() {
    27  		ed.mode = &ed.hist
    28  	} else {
    29  		ed.addTip("no matching history item")
    30  	}
    31  }
    32  
    33  func historyUp(ed *Editor) {
    34  	ed.prevHistory()
    35  }
    36  
    37  func historyDown(ed *Editor) {
    38  	ed.nextHistory()
    39  }
    40  
    41  func historyDownOrQuit(ed *Editor) {
    42  	if !ed.nextHistory() {
    43  		ed.mode = &ed.insert
    44  	}
    45  }
    46  
    47  func historySwitchToHistlist(ed *Editor) {
    48  	startHistlist(ed)
    49  	if ed.mode == ed.histlist {
    50  		ed.line = ""
    51  		ed.dot = 0
    52  		ed.histlist.changeFilter(ed.hist.prefix)
    53  	}
    54  }
    55  
    56  func historyDefault(ed *Editor) {
    57  	ed.acceptHistory()
    58  	ed.mode = &ed.insert
    59  	ed.nextAction = action{typ: reprocessKey}
    60  }
    61  
    62  // Implementation.
    63  
    64  func (h *hist) jump(i int, line string) {
    65  	h.current = i
    66  	h.line = line
    67  }
    68  
    69  func (ed *Editor) appendHistory(line string) {
    70  	if ed.store != nil {
    71  		go func() {
    72  			ed.store.Waits.Add(1)
    73  			// TODO(xiaq): Report possible error
    74  			ed.store.AddCmd(line)
    75  			ed.store.Waits.Done()
    76  			Logger.Println("added cmd to store:", line)
    77  		}()
    78  	}
    79  }
    80  
    81  func (ed *Editor) prevHistory() bool {
    82  	if ed.store != nil {
    83  		i, line, err := ed.store.LastCmd(ed.hist.current, ed.hist.prefix, true)
    84  		if err == nil {
    85  			ed.hist.jump(i, line)
    86  			return true
    87  		}
    88  		// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
    89  	}
    90  	return false
    91  }
    92  
    93  func (ed *Editor) nextHistory() bool {
    94  	if ed.store != nil {
    95  		// Persistent history
    96  		i, line, err := ed.store.FirstCmd(ed.hist.current+1, ed.hist.prefix, true)
    97  		if err == nil {
    98  			ed.hist.jump(i, line)
    99  			return true
   100  		}
   101  		// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
   102  	}
   103  
   104  	return false
   105  }
   106  
   107  // acceptHistory accepts the currently selected history.
   108  func (ed *Editor) acceptHistory() {
   109  	ed.line = ed.hist.line
   110  	ed.dot = len(ed.line)
   111  }