Skip to content

Commit

Permalink
update history interfaces. and support DisableAutoSaveHistory
Browse files Browse the repository at this point in the history
  • Loading branch information
chzyer committed Feb 16, 2016
1 parent d435bdb commit 07485bb
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 40 deletions.
41 changes: 41 additions & 0 deletions example/readline-multiline/readline-multiline.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"strings"

"github.com/chzyer/readline"
)

func main() {
rl, err := readline.NewEx(&readline.Config{
Prompt: "> ",
HistoryFile: "/tmp/readline-multiline",
DisableAutoSaveHistory: true,
})
if err != nil {
panic(err)
}
defer rl.Close()

var cmds []string
for {
line, err := rl.Readline()
if err != nil {
break
}
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
cmds = append(cmds, line)
if !strings.Contains(line, ";") {
rl.SetPrompt(">>> ")
continue
}
cmd := strings.Join(cmds, " ")
cmds = cmds[:0]
rl.SetPrompt("> ")
rl.SaveHistory(cmd)
println(cmd)
}
}
43 changes: 22 additions & 21 deletions history.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (o *opHistory) IsHistoryClosed() bool {
return o.fd.Fd() == ^(uintptr(0))
}

func (o *opHistory) InitHistory() {
func (o *opHistory) Init() {
if o.IsHistoryClosed() {
o.initHistory()
}
Expand All @@ -66,24 +66,24 @@ func (o *opHistory) historyUpdatePath(path string) {
if err != nil {
break
}
o.PushHistory([]rune(strings.TrimSpace(string(line))))
o.CompactHistory()
o.Push([]rune(strings.TrimSpace(string(line))))
o.Compact()
}
if total > o.cfg.HistoryLimit {
o.HistoryRewrite()
o.Rewrite()
}
o.historyVer++
o.PushHistory(nil)
o.Push(nil)
return
}

func (o *opHistory) CompactHistory() {
func (o *opHistory) Compact() {
for o.history.Len() > o.cfg.HistoryLimit && o.history.Len() > 0 {
o.history.Remove(o.history.Front())
}
}

func (o *opHistory) HistoryRewrite() {
func (o *opHistory) Rewrite() {
if o.cfg.HistoryFile == "" {
return
}
Expand Down Expand Up @@ -113,13 +113,13 @@ func (o *opHistory) HistoryRewrite() {
o.fd = fd
}

func (o *opHistory) CloseHistory() {
func (o *opHistory) Close() {
if o.fd != nil {
o.fd.Close()
}
}

func (o *opHistory) FindHistoryBck(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
func (o *opHistory) FindBck(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
for elem := o.current; elem != nil; elem = elem.Prev() {
item := o.showItem(elem.Value)
if isNewSearch {
Expand All @@ -139,7 +139,7 @@ func (o *opHistory) FindHistoryBck(isNewSearch bool, rs []rune, start int) (int,
return -1, nil
}

func (o *opHistory) FindHistoryFwd(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
func (o *opHistory) FindFwd(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
for elem := o.current; elem != nil; elem = elem.Next() {
item := o.showItem(elem.Value)
if isNewSearch {
Expand Down Expand Up @@ -175,7 +175,7 @@ func (o *opHistory) showItem(obj interface{}) []rune {
return item.Source
}

func (o *opHistory) PrevHistory() []rune {
func (o *opHistory) Prev() []rune {
if o.current == nil {
return nil
}
Expand All @@ -187,7 +187,7 @@ func (o *opHistory) PrevHistory() []rune {
return o.showItem(current.Value)
}

func (o *opHistory) NextHistory() ([]rune, bool) {
func (o *opHistory) Next() ([]rune, bool) {
if o.current == nil {
return nil, false
}
Expand All @@ -200,7 +200,8 @@ func (o *opHistory) NextHistory() ([]rune, bool) {
return o.showItem(current.Value), true
}

func (o *opHistory) NewHistory(current []rune) {
// save history
func (o *opHistory) New(current []rune) {
// if just use last command without modify
// just clean lastest history
if back := o.history.Back(); back != nil {
Expand Down Expand Up @@ -231,22 +232,22 @@ func (o *opHistory) NewHistory(current []rune) {
current = use.Tmp
}

o.UpdateHistory(current, true)
o.Update(current, true)

// push a new one to commit current command
o.historyVer++
o.PushHistory(nil)
o.Push(nil)
}

func (o *opHistory) RevertHistory() {
func (o *opHistory) Revert() {
o.historyVer++
o.current = o.history.Back()
}

func (o *opHistory) UpdateHistory(s []rune, commit bool) {
func (o *opHistory) Update(s []rune, commit bool) {
if o.current == nil {
o.PushHistory(s)
o.CompactHistory()
o.Push(s)
o.Compact()
return
}
r := o.current.Value.(*hisItem)
Expand All @@ -261,10 +262,10 @@ func (o *opHistory) UpdateHistory(s []rune, commit bool) {
r.Tmp = append(r.Tmp[:0], s...)
}
o.current.Value = r
o.CompactHistory()
o.Compact()
}

func (o *opHistory) PushHistory(s []rune) {
func (o *opHistory) Push(s []rune) {
newCopy := make([]rune, len(s))
copy(newCopy, s)
elem := o.history.PushBack(&hisItem{Source: newCopy})
Expand Down
41 changes: 25 additions & 16 deletions operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Operation struct {
errchan chan error
w io.Writer

*opHistory
history *opHistory
*opSearch
*opCompleter
*opPassword
Expand Down Expand Up @@ -95,7 +95,7 @@ func (o *Operation) ioloop() {
o.buf.Refresh(nil)
switch r {
case CharEnter, CharCtrlJ:
o.UpdateHistory(o.buf.Runes(), false)
o.history.Update(o.buf.Runes(), false)
fallthrough
case CharInterrupt:
o.t.KickRead()
Expand Down Expand Up @@ -184,20 +184,24 @@ func (o *Operation) ioloop() {
data = o.buf.Reset()
}
o.outchan <- data
o.NewHistory(data)
if !o.cfg.DisableAutoSaveHistory {
o.history.New(data)
} else {
isUpdateHistory = false
}
case CharBackward:
o.buf.MoveBackward()
case CharForward:
o.buf.MoveForward()
case CharPrev:
buf := o.PrevHistory()
buf := o.history.Prev()
if buf != nil {
o.buf.Set(buf)
} else {
o.t.Bell()
}
case CharNext:
buf, ok := o.NextHistory()
buf, ok := o.history.Next()
if ok {
o.buf.Set(buf)
} else {
Expand All @@ -216,7 +220,7 @@ func (o *Operation) ioloop() {
o.buf.WriteString(o.cfg.EOFPrompt + "\n")
o.buf.Reset()
isUpdateHistory = false
o.RevertHistory()
o.history.Revert()
o.errchan <- io.EOF
case CharInterrupt:
if o.IsSearchMode() {
Expand All @@ -235,7 +239,7 @@ func (o *Operation) ioloop() {
o.buf.WriteString(o.cfg.InterruptPrompt + "\n")
o.buf.Reset()
isUpdateHistory = false
o.RevertHistory()
o.history.Revert()
o.errchan <- ErrInterrupt
default:
if o.IsSearchMode() {
Expand Down Expand Up @@ -270,7 +274,8 @@ func (o *Operation) ioloop() {
}
}
if isUpdateHistory && !o.IsSearchMode() {
o.UpdateHistory(o.buf.Runes(), false)
// it will cause null history
o.history.Update(o.buf.Runes(), false)
}
}
}
Expand Down Expand Up @@ -353,15 +358,15 @@ func (o *Operation) Slice() ([]byte, error) {
}

func (o *Operation) Close() {
o.opHistory.CloseHistory()
o.history.Close()
}

func (o *Operation) SetHistoryPath(path string) {
if o.opHistory != nil {
o.opHistory.CloseHistory()
if o.history != nil {
o.history.Close()
}
o.cfg.HistoryFile = path
o.opHistory = newOpHistory(o.cfg)
o.history = newOpHistory(o.cfg)
}

func (o *Operation) IsNormalMode() bool {
Expand All @@ -382,19 +387,23 @@ func (op *Operation) SetConfig(cfg *Config) (*Config, error) {

if cfg.opHistory == nil {
op.SetHistoryPath(cfg.HistoryFile)
cfg.opHistory = op.opHistory
cfg.opSearch = newOpSearch(op.buf.w, op.buf, op.opHistory)
cfg.opHistory = op.history
cfg.opSearch = newOpSearch(op.buf.w, op.buf, op.history)
}
op.opHistory = cfg.opHistory
op.history = cfg.opHistory

// SetHistoryPath will close opHistory which already exists
// so if we use it next time, we need to reopen it by `InitHistory()`
op.opHistory.InitHistory()
op.history.Init()

op.opSearch = cfg.opSearch
return old, nil
}

func (o *Operation) SaveHistory(content string) {
o.history.New([]rune(content))
}

func (o *Operation) Refresh() {
if o.t.IsReading() {
o.buf.Refresh(nil)
Expand Down
8 changes: 7 additions & 1 deletion readline.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ type Config struct {
// readline will persist historys to file where HistoryFile specified
HistoryFile string
// specify the max length of historys, it's 500 by default, set it to -1 to disable history
HistoryLimit int
HistoryLimit int
DisableAutoSaveHistory bool

// AutoCompleter will called once user press TAB
AutoComplete AutoCompleter
Expand Down Expand Up @@ -154,10 +155,15 @@ func (i *Instance) ReadPassword(prompt string) ([]byte, error) {
return i.Operation.Password(prompt)
}

// err is one of (nil, io.EOF, readline.ErrInterrupt)
func (i *Instance) Readline() (string, error) {
return i.Operation.String()
}

func (i *Instance) SaveHistory(content string) {
i.Operation.SaveHistory(content)
}

// same as readline
func (i *Instance) ReadSlice() ([]byte, error) {
return i.Operation.Slice()
Expand Down
4 changes: 2 additions & 2 deletions search.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ func (o *opSearch) SearchBackspace() {

func (o *opSearch) findHistoryBy(isNewSearch bool) (int, *list.Element) {
if o.dir == S_DIR_BCK {
return o.history.FindHistoryBck(isNewSearch, o.data, o.buf.idx)
return o.history.FindBck(isNewSearch, o.data, o.buf.idx)
}
return o.history.FindHistoryFwd(isNewSearch, o.data, o.buf.idx)
return o.history.FindFwd(isNewSearch, o.data, o.buf.idx)
}

func (o *opSearch) search(isChange bool) bool {
Expand Down

0 comments on commit 07485bb

Please sign in to comment.