diff --git a/readline/comp-group.go b/readline/comp-group.go index 6a6e7bc..648b7ca 100644 --- a/readline/comp-group.go +++ b/readline/comp-group.go @@ -64,14 +64,8 @@ func (g *CompletionGroup) init(rl *Instance) { } } -// updateTabFind - When searching through all completion groups (whether it be command history or not), -// we ask each of them to filter its own items and return the results to the shell for aggregating them. -// The rx parameter is passed, as the shell already checked that the search pattern is valid. -func (g *CompletionGroup) updateTabFind(rl *Instance) { - +func (g *CompletionGroup) filterSuggestions(rl *Instance) []string { suggs := make([]string, 0) - - // We perform filter right here, so we create a new completion group, and populate it with our results. for i := range g.Suggestions { if rl.regexSearch == nil { continue } if rl.regexSearch.MatchString(g.Suggestions[i]) { @@ -82,8 +76,20 @@ func (g *CompletionGroup) updateTabFind(rl *Instance) { } } - // We overwrite the group's items, (will be refreshed as soon as something is typed in the search) - g.Suggestions = suggs + return suggs +} + +// updateTabFind - When searching through all completion groups (whether it be command history or not), +// we ask each of them to filter its own items and return the results to the shell for aggregating them. +// The rx parameter is passed, as the shell already checked that the search pattern is valid. +func (g *CompletionGroup) updateTabFind(rl *Instance) { + // We perform filter right here, so we create a new completion group, and populate it with our results. + // Then overwrite the group's items, (will be refreshed as soon as something is typed in the search) + if rl.searchMode != HistoryFind { + g.Suggestions = g.filterSuggestions(rl) + } else { + g.Suggestions = rl.HistorySearcher(string(rl.tfLine)) + } // Finally, the group computes its new printing settings g.init(rl) diff --git a/readline/instance.go b/readline/instance.go index fcd8379..97372cd 100644 --- a/readline/instance.go +++ b/readline/instance.go @@ -200,6 +200,8 @@ type Instance struct { ViActionCallback func(ViAction, []string) RawInputCallback func([]rune) // called on all input + + HistorySearcher func(string) []string } // NewInstance is used to create a readline instance and initialise it with sane defaults. @@ -229,6 +231,10 @@ func NewInstance() *Instance { rl.evtKeyPress = make(map[string]func(string, []rune, int) *EventReturn) rl.TempDirectory = os.TempDir() + rl.HistorySearcher = func(filter string) []string { + grps := rl.completeHistory() + return grps[0].filterSuggestions(rl) + } // Registers rl.initRegisters() diff --git a/rl.go b/rl.go index 88adc65..0fa9299 100644 --- a/rl.go +++ b/rl.go @@ -27,6 +27,25 @@ func newLineReader(prompt string, noHist bool) *lineReader { rl.SetHistoryCtrlR("History", fileHist) rl.HistoryAutoWrite = false } + oldSearcher := rl.HistorySearcher + rl.HistorySearcher = func(filter string) []string { + searcherHandler := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("searcher")) + if searcherHandler == rt.NilValue { + return oldSearcher(filter) + } + + ret, err := rt.Call1(l.MainThread(), searcherHandler, rt.StringValue(filter)) + entries := []string{} + if err == nil && ret.Type() == rt.TableType { + util.ForEach(ret.AsTable(), func(k rt.Value, v rt.Value) { + if k.Type() == rt.IntType && v.Type() == rt.StringType { + entries = append(entries, v.AsString()) + } + }) + } + + return entries + } rl.ShowVimMode = false rl.ViModeCallback = func(mode readline.ViMode) { modeStr := ""