mirror of
https://github.com/quitesimpleorg/hs9001.git
synced 2025-01-07 10:13:44 +01:00
Compare commits
No commits in common. "ebcdfa5ff4a62a485cd761fdd7335dd2c95ad5ef" and "3a6a1b2aa949ab97c165b116aab190f2eb77fdc3" have entirely different histories.
ebcdfa5ff4
...
3a6a1b2aa9
39
history.go
39
history.go
@ -2,10 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"hs9001/liner"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,32 +11,14 @@ type history struct {
|
|||||||
conn *sql.DB
|
conn *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSearchOpts(query string, mode int) searchopts {
|
func (h *history) GetHistoryByPrefix(prefix string) (ph []string) {
|
||||||
opts := searchopts{}
|
opts := searchopts{}
|
||||||
o := "DESC"
|
o := "DESC"
|
||||||
opts.order = &o
|
opts.order = &o
|
||||||
lim := 100
|
lim := 100
|
||||||
opts.limit = &lim
|
opts.limit = &lim
|
||||||
opts.command = &query
|
cmdqry := prefix + "%"
|
||||||
|
opts.command = &cmdqry
|
||||||
switch mode {
|
|
||||||
case liner.ModeGlobal:
|
|
||||||
break
|
|
||||||
case liner.ModeWorkdir:
|
|
||||||
workdir, err := filepath.Abs(".")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
opts.workdir = &workdir
|
|
||||||
default:
|
|
||||||
panic("Invalid mode supplied")
|
|
||||||
}
|
|
||||||
return opts
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *history) GetHistoryByPrefix(prefix string, mode int) (ph []string) {
|
|
||||||
cmdquery := prefix + "%"
|
|
||||||
opts := createSearchOpts(cmdquery, mode)
|
|
||||||
results := search(h.conn, opts)
|
results := search(h.conn, opts)
|
||||||
for e := results.Back(); e != nil; e = e.Prev() {
|
for e := results.Back(); e != nil; e = e.Prev() {
|
||||||
entry, ok := e.Value.(*HistoryEntry)
|
entry, ok := e.Value.(*HistoryEntry)
|
||||||
@ -49,11 +29,14 @@ func (h *history) GetHistoryByPrefix(prefix string, mode int) (ph []string) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func (h *history) GetHistoryByPattern(pattern string) (ph []string, pos []int) {
|
||||||
func (h *history) GetHistoryByPattern(pattern string, mode int) (ph []string, pos []int) {
|
opts := searchopts{}
|
||||||
cmdquery := "%" + pattern + "%"
|
o := "DESC"
|
||||||
opts := createSearchOpts(cmdquery, mode)
|
opts.order = &o
|
||||||
|
lim := 100
|
||||||
|
opts.limit = &lim
|
||||||
|
cmdqry := "%" + pattern + "%"
|
||||||
|
opts.command = &cmdqry
|
||||||
results := search(h.conn, opts)
|
results := search(h.conn, opts)
|
||||||
for e := results.Back(); e != nil; e = e.Prev() {
|
for e := results.Back(); e != nil; e = e.Prev() {
|
||||||
entry, ok := e.Value.(*HistoryEntry)
|
entry, ok := e.Value.(*HistoryEntry)
|
||||||
|
@ -37,8 +37,8 @@ type HistoryProvider interface {
|
|||||||
WriteHistory(w io.Writer) (num int, err error)
|
WriteHistory(w io.Writer) (num int, err error)
|
||||||
AppendHistory(item string)
|
AppendHistory(item string)
|
||||||
ClearHistory()
|
ClearHistory()
|
||||||
GetHistoryByPrefix(prefix string, mode int) (ph []string)
|
GetHistoryByPrefix(prefix string) (ph []string)
|
||||||
GetHistoryByPattern(pattern string, mode int) (ph []string, pos []int)
|
GetHistoryByPattern(pattern string) (ph []string, pos []int)
|
||||||
RLock()
|
RLock()
|
||||||
RUnlock()
|
RUnlock()
|
||||||
}
|
}
|
||||||
@ -95,11 +95,11 @@ func (s *State) AppendHistory(item string) {
|
|||||||
func (s *State) ClearHistory() {
|
func (s *State) ClearHistory() {
|
||||||
s.historyProvider.ClearHistory()
|
s.historyProvider.ClearHistory()
|
||||||
}
|
}
|
||||||
func (s *State) getHistoryByPrefix(prefix string, mode int) (ph []string) {
|
func (s *State) getHistoryByPrefix(prefix string) (ph []string) {
|
||||||
return s.historyProvider.GetHistoryByPrefix(prefix, mode)
|
return s.historyProvider.GetHistoryByPrefix(prefix)
|
||||||
}
|
}
|
||||||
func (s *State) getHistoryByPattern(pattern string, mode int) (ph []string, pos []int) {
|
func (s *State) getHistoryByPattern(pattern string) (ph []string, pos []int) {
|
||||||
return s.historyProvider.GetHistoryByPattern(pattern, mode)
|
return s.historyProvider.GetHistoryByPattern(pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHistoryProvider allows you to set a custom provider
|
// SetHistoryProvider allows you to set a custom provider
|
||||||
|
@ -90,11 +90,6 @@ const (
|
|||||||
tabReverse
|
tabReverse
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
ModeGlobal = iota
|
|
||||||
ModeWorkdir
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *State) refresh(prompt []rune, buf []rune, pos int) error {
|
func (s *State) refresh(prompt []rune, buf []rune, pos int) error {
|
||||||
if s.columns == 0 {
|
if s.columns == 0 {
|
||||||
return ErrInternal
|
return ErrInternal
|
||||||
@ -416,26 +411,8 @@ func (s *State) tabComplete(p []rune, line []rune, pos int) ([]rune, int, interf
|
|||||||
|
|
||||||
// reverse intelligent search, implements a bash-like history search.
|
// reverse intelligent search, implements a bash-like history search.
|
||||||
func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, interface{}, error) {
|
func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, interface{}, error) {
|
||||||
modeSelect := false
|
p := "(reverse-i-search)`': "
|
||||||
currentMode := ModeGlobal
|
err := s.refresh([]rune(p), origLine, origPos)
|
||||||
|
|
||||||
getPrompt := func(arg string) string {
|
|
||||||
prompt := ""
|
|
||||||
switch currentMode {
|
|
||||||
case ModeWorkdir:
|
|
||||||
prompt = "(reverse:cwd)`%s': "
|
|
||||||
case ModeGlobal:
|
|
||||||
prompt = "(reverse:global)`%s': "
|
|
||||||
default:
|
|
||||||
panic("Invalid mode")
|
|
||||||
}
|
|
||||||
if modeSelect {
|
|
||||||
prompt = "(select mode)`%s': "
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(prompt, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := s.refresh([]rune(getPrompt("")), origLine, origPos)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return origLine, origPos, rune(esc), err
|
return origLine, origPos, rune(esc), err
|
||||||
}
|
}
|
||||||
@ -449,10 +426,11 @@ func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, inter
|
|||||||
|
|
||||||
getLine := func() ([]rune, []rune, int) {
|
getLine := func() ([]rune, []rune, int) {
|
||||||
search := string(line)
|
search := string(line)
|
||||||
return []rune(getPrompt(search)), []rune(foundLine), foundPos
|
prompt := "(reverse-i-search)`%s': "
|
||||||
|
return []rune(fmt.Sprintf(prompt, search)), []rune(foundLine), foundPos
|
||||||
}
|
}
|
||||||
|
|
||||||
history, positions := s.getHistoryByPattern(string(line), currentMode)
|
history, positions := s.getHistoryByPattern(string(line))
|
||||||
historyPos := len(history) - 1
|
historyPos := len(history) - 1
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -472,8 +450,6 @@ func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, inter
|
|||||||
} else {
|
} else {
|
||||||
s.doBeep()
|
s.doBeep()
|
||||||
}
|
}
|
||||||
case ctrlA:
|
|
||||||
modeSelect = true
|
|
||||||
case ctrlS: // Search forward
|
case ctrlS: // Search forward
|
||||||
if historyPos < len(history)-1 && historyPos >= 0 {
|
if historyPos < len(history)-1 && historyPos >= 0 {
|
||||||
historyPos++
|
historyPos++
|
||||||
@ -491,7 +467,7 @@ func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, inter
|
|||||||
pos -= n
|
pos -= n
|
||||||
|
|
||||||
// For each char deleted, display the last matching line of history
|
// For each char deleted, display the last matching line of history
|
||||||
history, positions := s.getHistoryByPattern(string(line), currentMode)
|
history, positions := s.getHistoryByPattern(string(line))
|
||||||
historyPos = len(history) - 1
|
historyPos = len(history) - 1
|
||||||
if len(history) > 0 {
|
if len(history) > 0 {
|
||||||
foundLine = history[historyPos]
|
foundLine = history[historyPos]
|
||||||
@ -504,28 +480,17 @@ func (s *State) reverseISearch(origLine []rune, origPos int) ([]rune, int, inter
|
|||||||
case ctrlG: // Cancel
|
case ctrlG: // Cancel
|
||||||
return origLine, origPos, rune(esc), err
|
return origLine, origPos, rune(esc), err
|
||||||
|
|
||||||
case tab, cr, lf, ctrlB, ctrlD, ctrlE, ctrlF, ctrlK,
|
case tab, cr, lf, ctrlA, ctrlB, ctrlD, ctrlE, ctrlF, ctrlK,
|
||||||
ctrlL, ctrlN, ctrlO, ctrlP, ctrlQ, ctrlT, ctrlU, ctrlV, ctrlW, ctrlX, ctrlY, ctrlZ:
|
ctrlL, ctrlN, ctrlO, ctrlP, ctrlQ, ctrlT, ctrlU, ctrlV, ctrlW, ctrlX, ctrlY, ctrlZ:
|
||||||
fallthrough
|
fallthrough
|
||||||
case 0, ctrlC, esc, 28, 29, 30, 31:
|
case 0, ctrlC, esc, 28, 29, 30, 31:
|
||||||
return []rune(foundLine), foundPos, next, err
|
return []rune(foundLine), foundPos, next, err
|
||||||
default:
|
default:
|
||||||
if modeSelect {
|
|
||||||
switch v {
|
|
||||||
case 'g':
|
|
||||||
currentMode = ModeGlobal
|
|
||||||
case 'w':
|
|
||||||
currentMode = ModeWorkdir
|
|
||||||
}
|
|
||||||
modeSelect = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
line = append(line[:pos], append([]rune{v}, line[pos:]...)...)
|
line = append(line[:pos], append([]rune{v}, line[pos:]...)...)
|
||||||
pos++
|
pos++
|
||||||
|
|
||||||
// For each keystroke typed, display the last matching line of history
|
// For each keystroke typed, display the last matching line of history
|
||||||
history, positions = s.getHistoryByPattern(string(line), currentMode)
|
history, positions = s.getHistoryByPattern(string(line))
|
||||||
historyPos = len(history) - 1
|
historyPos = len(history) - 1
|
||||||
if len(history) > 0 {
|
if len(history) > 0 {
|
||||||
foundLine = history[historyPos]
|
foundLine = history[historyPos]
|
||||||
@ -761,7 +726,7 @@ mainLoop:
|
|||||||
case ctrlP: // up
|
case ctrlP: // up
|
||||||
historyAction = true
|
historyAction = true
|
||||||
if historyStale {
|
if historyStale {
|
||||||
historyPrefix = s.getHistoryByPrefix(string(line), ModeGlobal)
|
historyPrefix = s.getHistoryByPrefix(string(line))
|
||||||
historyPos = len(historyPrefix)
|
historyPos = len(historyPrefix)
|
||||||
historyStale = false
|
historyStale = false
|
||||||
}
|
}
|
||||||
@ -779,7 +744,7 @@ mainLoop:
|
|||||||
case ctrlN: // down
|
case ctrlN: // down
|
||||||
historyAction = true
|
historyAction = true
|
||||||
if historyStale {
|
if historyStale {
|
||||||
historyPrefix = s.getHistoryByPrefix(string(line), ModeGlobal)
|
historyPrefix = s.getHistoryByPrefix(string(line))
|
||||||
historyPos = len(historyPrefix)
|
historyPos = len(historyPrefix)
|
||||||
historyStale = false
|
historyStale = false
|
||||||
}
|
}
|
||||||
@ -947,7 +912,7 @@ mainLoop:
|
|||||||
case up:
|
case up:
|
||||||
historyAction = true
|
historyAction = true
|
||||||
if historyStale {
|
if historyStale {
|
||||||
historyPrefix = s.getHistoryByPrefix(string(line), ModeGlobal)
|
historyPrefix = s.getHistoryByPrefix(string(line))
|
||||||
historyPos = len(historyPrefix)
|
historyPos = len(historyPrefix)
|
||||||
historyStale = false
|
historyStale = false
|
||||||
}
|
}
|
||||||
@ -964,7 +929,7 @@ mainLoop:
|
|||||||
case down:
|
case down:
|
||||||
historyAction = true
|
historyAction = true
|
||||||
if historyStale {
|
if historyStale {
|
||||||
historyPrefix = s.getHistoryByPrefix(string(line), ModeGlobal)
|
historyPrefix = s.getHistoryByPrefix(string(line))
|
||||||
historyPos = len(historyPrefix)
|
historyPos = len(historyPrefix)
|
||||||
historyStale = false
|
historyStale = false
|
||||||
}
|
}
|
||||||
|
20
main.go
20
main.go
@ -398,31 +398,13 @@ func main() {
|
|||||||
results := search(conn, opts)
|
results := search(conn, opts)
|
||||||
|
|
||||||
previousCmd := ""
|
previousCmd := ""
|
||||||
|
|
||||||
fi, err := os.Stdout.Stat()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Don't print colors if output is piped
|
|
||||||
printColors := true
|
|
||||||
if (fi.Mode() & os.ModeCharDevice) == 0 {
|
|
||||||
printColors = false
|
|
||||||
}
|
|
||||||
|
|
||||||
for e := results.Front(); e != nil; e = e.Next() {
|
for e := results.Front(); e != nil; e = e.Next() {
|
||||||
entry, ok := e.Value.(*HistoryEntry)
|
entry, ok := e.Value.(*HistoryEntry)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Panic("Failed to retrieve entries")
|
log.Panic("Failed to retrieve entries")
|
||||||
}
|
}
|
||||||
if !distinct || previousCmd != entry.cmd {
|
if !distinct || previousCmd != entry.cmd {
|
||||||
prefix := ""
|
fmt.Printf("%s\n", entry.cmd)
|
||||||
postfix := ""
|
|
||||||
if printColors && entry.retval != 0 {
|
|
||||||
prefix = "\033[38;5;88m"
|
|
||||||
postfix = "\033[0m"
|
|
||||||
}
|
|
||||||
fmt.Printf("%s%s%s\n", prefix, entry.cmd, postfix)
|
|
||||||
}
|
}
|
||||||
previousCmd = entry.cmd
|
previousCmd = entry.cmd
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user