Source File
undo.go
Belonging Package
github.com/reeflective/readline/internal/history
package historyimport ()// lineHistory contains all state changes for a given input line,// whether it is the current input line or one of the history ones.type lineHistory struct {pos intitems []undoItem}type undoItem struct {line stringpos int}// Save saves the current line and cursor position as an undo state item.// If this was called while the shell was in the middle of its undo history// (eg. the caller has undone one or more times), all undone steps are dropped.func ( *Sources) () {defer .Reset()if .skip {return}// Get the undo states for the current line.:= .getLineHistory()if == nil {return}// When the line is identical to the previous undo, we just update// the cursor position if it's a different one.if len(.items) > 0 && .items[len(.items)-1].line == string(*.line) {.items[len(.items)-1].pos = .cursor.Pos()return}// When we add an item to the undo history, the history// is cut from the current undo hist position onwards.if .pos > len(.items) {.pos = len(.items)}.items = .items[:len(.items)-.pos]// Make a copy of the cursor and ensure its position.:= core.NewCursor(.line).Set(.cursor.Pos()).CheckCommand()// And save the item..items = append(.items, undoItem{line: string(*.line),pos: .Pos(),})}// SkipSave will not save the current line when the target command is done// (more precisely, the next call to h.Save() will have no effect).// This function is not useful is most cases, as call to saves will efficiently// compare the line with the last saved state, and will not add redundant ones.func ( *Sources) () {.skip = true}// SaveWithCommand is only meant to be called in the main readline loop of the shell,// and not from within commands themselves: it does the same job as Save(), but also// keeps the command that has just been executed.func ( *Sources) ( inputrc.Bind) {.last =.Save()}// Undo restores the line and cursor position to their last saved state.func ( *Sources) () {.skip = true.undoing = true// Get the undo states for the current line.:= .getLineHistory()if == nil || len(.items) == 0 {return}var undoItem// When undoing, we loop through preceding undo items// as long as they are identical to the current line.for {.pos++// Exit if we reached the end.if .pos > len(.items) {.pos = len(.items)return}// Break as soon as we find a non-matching line.= .items[len(.items)-.pos]if .line != string(*.line) {break}}// Use the undo we found.line.Set([]rune(.line)...).cursor.Set(.pos)}// Revert goes back to the initial state of the line, which is what it was// like when the shell started reading user input. Note that this state might// be a line that was inferred, accept-and-held from the previous readline run.func ( *Sources) () {:= .getLineHistory()if == nil || len(.items) == 0 {return}// Reuse the first saved state.:= .items[0].line.Set([]rune(.line)...).cursor.Set(.pos)// And reset everything.items = make([]undoItem, 0).Reset()}// Redo cancels an undo action if any has been made, or if// at the begin of the undo history, restores the original// line's contents as their were before starting undoing.func ( *Sources) () {.skip = true.undoing = true:= .getLineHistory()if == nil || len(.items) == 0 {return}.pos--if .pos < 1 {return}:= .items[len(.items)-.pos].line.Set([]rune(.line)...).cursor.Set(.pos)}// Last returns the last command ran by the shell.func ( *Sources) () inputrc.Bind {return .last}// Pos returns the current position in the undo history, which is// equal to its length minus the number of previous undo calls.func ( *Sources) () int {:= .getLineHistory()if == nil {return 0}return .pos}// Reset will reset the current position in the list// of undo items, but will not delete any of them.func ( *Sources) () {.skip = false:= .getLineHistory()if == nil {return}if !.undoing {.pos = 0}.undoing = false}// Always returns a non-nil map, whether or not a history source is found.func ( *Sources) () map[int]*lineHistory {:= .Current()if == nil {return map[int]*lineHistory{}}// Get the state changes of all history lines// for the current history source.:= .names[.sourcePos]:= .lines[]if == nil {.lines[] = make(map[int]*lineHistory)= .lines[]}return}func ( *Sources) () *lineHistory {:= .getHistoryLineChanges()if == nil {return &lineHistory{}}// Compute the position of the current line in the history.:= -1:= .Current()if .hpos > -1 && != nil {= .Len() - .hpos}if [] == nil {[] = &lineHistory{}}// Return the state changes of the current line.return []}func ( *Sources) () {.hpos = -1:= .getHistoryLineChanges()if == nil {return}// Get the undo states for the line buffer// (the last one, not any of the history ones):= [.hpos]if == nil || len(.items) == 0 {return}:= .items[len(.items)-1]// Restore the line to the last known state..line.Set([]rune(.line)...).cursor.Set(.pos)}
![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |