|
|
|
@ -8,7 +8,6 @@ import ( |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"io/ioutil" |
|
|
|
"io/ioutil" |
|
|
|
"log" |
|
|
|
"log" |
|
|
|
"math" |
|
|
|
|
|
|
|
"net/http" |
|
|
|
"net/http" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"sort" |
|
|
|
"sort" |
|
|
|
@ -60,7 +59,6 @@ func runReshCli() (string, int) { |
|
|
|
log.Fatal("Error reading config:", err) |
|
|
|
log.Fatal("Error reading config:", err) |
|
|
|
} |
|
|
|
} |
|
|
|
if config.Debug { |
|
|
|
if config.Debug { |
|
|
|
// Debug = true
|
|
|
|
|
|
|
|
log.SetFlags(log.LstdFlags | log.Lmicroseconds) |
|
|
|
log.SetFlags(log.LstdFlags | log.Lmicroseconds) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -95,7 +93,8 @@ func runReshCli() (string, int) { |
|
|
|
|
|
|
|
|
|
|
|
st := state{ |
|
|
|
st := state{ |
|
|
|
// lock sync.Mutex
|
|
|
|
// lock sync.Mutex
|
|
|
|
fullRecords: resp.FullRecords, |
|
|
|
fullRecords: resp.FullRecords, |
|
|
|
|
|
|
|
initialQuery: *query, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
layout := manager{ |
|
|
|
layout := manager{ |
|
|
|
@ -279,24 +278,33 @@ func properMatch(str, term, padChar string) bool { |
|
|
|
|
|
|
|
|
|
|
|
// newItemFromRecordForQuery creates new item from record based on given query
|
|
|
|
// newItemFromRecordForQuery creates new item from record based on given query
|
|
|
|
// returns error if the query doesn't match the record
|
|
|
|
// returns error if the query doesn't match the record
|
|
|
|
func newItemFromRecordForQuery(record records.EnrichedRecord, query query) (item, error) { |
|
|
|
func newItemFromRecordForQuery(record records.EnrichedRecord, query query, debug bool) (item, error) { |
|
|
|
// TODO: use color to highlight matches
|
|
|
|
// TODO: use color to highlight matches
|
|
|
|
|
|
|
|
const hitScore = 1.0 |
|
|
|
|
|
|
|
const hitScoreConsecutive = 0.1 |
|
|
|
const properMatchScore = 0.3 |
|
|
|
const properMatchScore = 0.3 |
|
|
|
const actualPwdScore = 0.9 |
|
|
|
const actualPwdScore = 0.9 |
|
|
|
|
|
|
|
const actualPwdScoreExtra = 0.2 |
|
|
|
|
|
|
|
|
|
|
|
hits := 0.0 |
|
|
|
hits := 0.0 |
|
|
|
|
|
|
|
if record.ExitCode != 0 { |
|
|
|
|
|
|
|
hits-- |
|
|
|
|
|
|
|
} |
|
|
|
cmd := record.CmdLine |
|
|
|
cmd := record.CmdLine |
|
|
|
pwdTilde := strings.Replace(record.Pwd, record.Home, "~", 1) |
|
|
|
pwdTilde := strings.Replace(record.Pwd, record.Home, "~", 1) |
|
|
|
pwdDisp := leftCutPadString(pwdTilde, 25) |
|
|
|
pwdDisp := leftCutPadString(pwdTilde, 25) |
|
|
|
pwdRawDisp := leftCutPadString(record.Pwd, 25) |
|
|
|
pwdRawDisp := leftCutPadString(record.Pwd, 25) |
|
|
|
var useRawPwd bool |
|
|
|
var useRawPwd bool |
|
|
|
|
|
|
|
var dirHit bool |
|
|
|
for _, term := range query.terms { |
|
|
|
for _, term := range query.terms { |
|
|
|
alreadyHit := false |
|
|
|
termHit := false |
|
|
|
if strings.Contains(record.CmdLine, term) { |
|
|
|
if strings.Contains(record.CmdLine, term) { |
|
|
|
if alreadyHit == false { |
|
|
|
if termHit == false { |
|
|
|
hits++ |
|
|
|
hits += hitScore |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
hits += hitScoreConsecutive |
|
|
|
} |
|
|
|
} |
|
|
|
alreadyHit = true |
|
|
|
termHit = true |
|
|
|
if properMatch(cmd, term, " ") { |
|
|
|
if properMatch(cmd, term, " ") { |
|
|
|
hits += properMatchScore |
|
|
|
hits += properMatchScore |
|
|
|
} |
|
|
|
} |
|
|
|
@ -304,36 +312,48 @@ func newItemFromRecordForQuery(record records.EnrichedRecord, query query) (item |
|
|
|
// NO continue
|
|
|
|
// NO continue
|
|
|
|
} |
|
|
|
} |
|
|
|
if strings.Contains(pwdTilde, term) { |
|
|
|
if strings.Contains(pwdTilde, term) { |
|
|
|
if alreadyHit == false { |
|
|
|
if termHit == false { |
|
|
|
hits++ |
|
|
|
hits += hitScore |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
hits += hitScoreConsecutive |
|
|
|
} |
|
|
|
} |
|
|
|
alreadyHit = true |
|
|
|
termHit = true |
|
|
|
if properMatch(pwdTilde, term, " ") { |
|
|
|
if properMatch(pwdTilde, term, "/") { |
|
|
|
hits += properMatchScore |
|
|
|
hits += properMatchScore |
|
|
|
} |
|
|
|
} |
|
|
|
pwdDisp = strings.ReplaceAll(pwdDisp, term, highlightMatch(term)) |
|
|
|
pwdDisp = strings.ReplaceAll(pwdDisp, term, highlightMatch(term)) |
|
|
|
useRawPwd = false |
|
|
|
pwdRawDisp = strings.ReplaceAll(pwdRawDisp, term, highlightMatch(term)) |
|
|
|
continue // IMPORTANT
|
|
|
|
dirHit = true |
|
|
|
} |
|
|
|
} else if strings.Contains(record.Pwd, term) { |
|
|
|
if strings.Contains(record.Pwd, term) { |
|
|
|
if termHit == false { |
|
|
|
if alreadyHit == false { |
|
|
|
hits += hitScore |
|
|
|
hits++ |
|
|
|
} else { |
|
|
|
|
|
|
|
hits += hitScoreConsecutive |
|
|
|
} |
|
|
|
} |
|
|
|
alreadyHit = true |
|
|
|
termHit = true |
|
|
|
if properMatch(pwdTilde, term, " ") { |
|
|
|
if properMatch(pwdTilde, term, "/") { |
|
|
|
hits += properMatchScore |
|
|
|
hits += properMatchScore |
|
|
|
} |
|
|
|
} |
|
|
|
pwdRawDisp = strings.ReplaceAll(pwdRawDisp, term, highlightMatch(term)) |
|
|
|
pwdRawDisp = strings.ReplaceAll(pwdRawDisp, term, highlightMatch(term)) |
|
|
|
|
|
|
|
dirHit = true |
|
|
|
useRawPwd = true |
|
|
|
useRawPwd = true |
|
|
|
continue // IMPORTANT
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
// if strings.Contains(record.GitOriginRemote, term) {
|
|
|
|
// if strings.Contains(record.GitOriginRemote, term) {
|
|
|
|
// hits++
|
|
|
|
// hits++
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
} |
|
|
|
} |
|
|
|
// actual pwd matches
|
|
|
|
// actual pwd matches
|
|
|
|
|
|
|
|
// only use if there was no directory match on any of the terms
|
|
|
|
|
|
|
|
// N terms can only produce:
|
|
|
|
|
|
|
|
// -> N matches against the command
|
|
|
|
|
|
|
|
// -> N matches against the directory
|
|
|
|
|
|
|
|
// -> 1 extra match for the actual directory match
|
|
|
|
if record.Pwd == query.pwd { |
|
|
|
if record.Pwd == query.pwd { |
|
|
|
hits += actualPwdScore |
|
|
|
if dirHit { |
|
|
|
|
|
|
|
hits += actualPwdScoreExtra |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
hits += actualPwdScore |
|
|
|
|
|
|
|
} |
|
|
|
pwdDisp = highlightMatchAlternative(pwdDisp) |
|
|
|
pwdDisp = highlightMatchAlternative(pwdDisp) |
|
|
|
// pwdRawDisp = highlightMatchAlternative(pwdRawDisp)
|
|
|
|
// pwdRawDisp = highlightMatchAlternative(pwdRawDisp)
|
|
|
|
useRawPwd = false |
|
|
|
useRawPwd = false |
|
|
|
@ -348,8 +368,13 @@ func newItemFromRecordForQuery(record records.EnrichedRecord, query query) (item |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
display += pwdDisp |
|
|
|
display += pwdDisp |
|
|
|
} |
|
|
|
} |
|
|
|
hitsDisp := " " + rightCutPadString(strconv.Itoa(int(math.Floor(hits))), 2) |
|
|
|
if debug { |
|
|
|
display += hitsDisp |
|
|
|
hitsStr := fmt.Sprintf("%.1f", hits) |
|
|
|
|
|
|
|
hitsDisp := " " + hitsStr + " " |
|
|
|
|
|
|
|
display += hitsDisp |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
display += " " |
|
|
|
|
|
|
|
} |
|
|
|
// cmd := "<" + strings.ReplaceAll(record.CmdLine, "\n", ";") + ">"
|
|
|
|
// cmd := "<" + strings.ReplaceAll(record.CmdLine, "\n", ";") + ">"
|
|
|
|
cmd = strings.ReplaceAll(cmd, "\n", ";") |
|
|
|
cmd = strings.ReplaceAll(cmd, "\n", ";") |
|
|
|
display += cmd |
|
|
|
display += cmd |
|
|
|
@ -383,6 +408,8 @@ type state struct { |
|
|
|
data []item |
|
|
|
data []item |
|
|
|
highlightedItem int |
|
|
|
highlightedItem int |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initialQuery string |
|
|
|
|
|
|
|
|
|
|
|
output string |
|
|
|
output string |
|
|
|
exitCode int |
|
|
|
exitCode int |
|
|
|
} |
|
|
|
} |
|
|
|
@ -427,7 +454,7 @@ func (m manager) UpdateData(input string) { |
|
|
|
m.s.lock.Lock() |
|
|
|
m.s.lock.Lock() |
|
|
|
defer m.s.lock.Unlock() |
|
|
|
defer m.s.lock.Unlock() |
|
|
|
for _, rec := range m.s.fullRecords { |
|
|
|
for _, rec := range m.s.fullRecords { |
|
|
|
itm, err := newItemFromRecordForQuery(rec, query) |
|
|
|
itm, err := newItemFromRecordForQuery(rec, query, m.config.Debug) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
// records didn't match the query
|
|
|
|
// records didn't match the query
|
|
|
|
// log.Println(" * continue (no match)", rec.Pwd)
|
|
|
|
// log.Println(" * continue (no match)", rec.Pwd)
|
|
|
|
@ -482,8 +509,6 @@ func (m manager) Prev(g *gocui.Gui, v *gocui.View) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// you can have Layout with pointer reciever if you pass the layout function to the setmanger
|
|
|
|
|
|
|
|
// I dont think we need that tho
|
|
|
|
|
|
|
|
func (m manager) Layout(g *gocui.Gui) error { |
|
|
|
func (m manager) Layout(g *gocui.Gui) error { |
|
|
|
var b byte |
|
|
|
var b byte |
|
|
|
maxX, maxY := g.Size() |
|
|
|
maxX, maxY := g.Size() |
|
|
|
@ -494,12 +519,19 @@ func (m manager) Layout(g *gocui.Gui) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
v.Editable = true |
|
|
|
v.Editable = true |
|
|
|
// v.Editor = gocui.EditorFunc(m.editor.Edit)
|
|
|
|
|
|
|
|
v.Editor = m |
|
|
|
v.Editor = m |
|
|
|
v.Title = "resh cli" |
|
|
|
v.Title = "resh cli" |
|
|
|
|
|
|
|
|
|
|
|
g.SetCurrentView("input") |
|
|
|
g.SetCurrentView("input") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.s.lock.Lock() |
|
|
|
|
|
|
|
defer m.s.lock.Unlock() |
|
|
|
|
|
|
|
if len(m.s.initialQuery) > 0 { |
|
|
|
|
|
|
|
v.WriteString(m.s.initialQuery) |
|
|
|
|
|
|
|
v.SetCursor(len(m.s.initialQuery), 0) |
|
|
|
|
|
|
|
m.s.initialQuery = "" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
v, err = g.SetView("body", 0, 2, maxX-1, maxY, b) |
|
|
|
v, err = g.SetView("body", 0, 2, maxX-1, maxY, b) |
|
|
|
if err != nil && gocui.IsUnknownView(err) == false { |
|
|
|
if err != nil && gocui.IsUnknownView(err) == false { |
|
|
|
log.Panicln(err.Error()) |
|
|
|
log.Panicln(err.Error()) |
|
|
|
@ -509,8 +541,6 @@ func (m manager) Layout(g *gocui.Gui) error { |
|
|
|
v.Clear() |
|
|
|
v.Clear() |
|
|
|
v.Rewind() |
|
|
|
v.Rewind() |
|
|
|
|
|
|
|
|
|
|
|
m.s.lock.Lock() |
|
|
|
|
|
|
|
defer m.s.lock.Unlock() |
|
|
|
|
|
|
|
for i, itm := range m.s.data { |
|
|
|
for i, itm := range m.s.data { |
|
|
|
if i == maxY { |
|
|
|
if i == maxY { |
|
|
|
log.Println(maxY) |
|
|
|
log.Println(maxY) |
|
|
|
|