mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-15 20:17:50 +08:00
114 lines
2.1 KiB
Go
114 lines
2.1 KiB
Go
package edit
|
|
|
|
import "fmt"
|
|
|
|
// Command history subsystem.
|
|
|
|
// Interface.
|
|
|
|
type hist struct {
|
|
current int
|
|
prefix string
|
|
line string
|
|
}
|
|
|
|
func (hist) Mode() ModeType {
|
|
return modeHistory
|
|
}
|
|
|
|
func (h *hist) ModeLine(width int) *buffer {
|
|
return makeModeLine(fmt.Sprintf(" HISTORY #%d ", h.current), width)
|
|
}
|
|
|
|
func startHistory(ed *Editor) {
|
|
ed.hist.prefix = ed.line[:ed.dot]
|
|
ed.hist.current = -1
|
|
if ed.prevHistory() {
|
|
ed.mode = &ed.hist
|
|
} else {
|
|
ed.addTip("no matching history item")
|
|
}
|
|
}
|
|
|
|
func historyUp(ed *Editor) {
|
|
ed.prevHistory()
|
|
}
|
|
|
|
func historyDown(ed *Editor) {
|
|
ed.nextHistory()
|
|
}
|
|
|
|
func historyDownOrQuit(ed *Editor) {
|
|
if !ed.nextHistory() {
|
|
ed.mode = &ed.insert
|
|
}
|
|
}
|
|
|
|
func historySwitchToHistlist(ed *Editor) {
|
|
startHistlist(ed)
|
|
if ed.mode == ed.histlist {
|
|
ed.line = ""
|
|
ed.dot = 0
|
|
ed.histlist.changeFilter(ed.hist.prefix)
|
|
}
|
|
}
|
|
|
|
func historyDefault(ed *Editor) {
|
|
ed.acceptHistory()
|
|
ed.mode = &ed.insert
|
|
ed.nextAction = action{typ: reprocessKey}
|
|
}
|
|
|
|
// Implementation.
|
|
|
|
func (h *hist) jump(i int, line string) {
|
|
h.current = i
|
|
h.line = line
|
|
}
|
|
|
|
func (ed *Editor) appendHistory(line string) {
|
|
if ed.store != nil {
|
|
ed.historyMutex.Lock()
|
|
go func() {
|
|
ed.store.Waits.Add(1)
|
|
// TODO(xiaq): Report possible error
|
|
ed.store.AddCmd(line)
|
|
ed.store.Waits.Done()
|
|
ed.historyMutex.Unlock()
|
|
Logger.Println("added cmd to store:", line)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func (ed *Editor) prevHistory() bool {
|
|
if ed.store != nil {
|
|
i, line, err := ed.store.LastCmd(ed.hist.current, ed.hist.prefix, true)
|
|
if err == nil {
|
|
ed.hist.jump(i, line)
|
|
return true
|
|
}
|
|
// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (ed *Editor) nextHistory() bool {
|
|
if ed.store != nil {
|
|
// Persistent history
|
|
i, line, err := ed.store.FirstCmd(ed.hist.current+1, ed.hist.prefix, true)
|
|
if err == nil {
|
|
ed.hist.jump(i, line)
|
|
return true
|
|
}
|
|
// TODO(xiaq): Errors other than ErrNoMatchingCmd should be reported
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// acceptHistory accepts the currently selected history.
|
|
func (ed *Editor) acceptHistory() {
|
|
ed.line = ed.hist.line
|
|
ed.dot = len(ed.line)
|
|
}
|