add raw mode

pull/123/head
Simon Let 6 years ago
parent 282f3bd759
commit 78d9d51484
  1. 79
      cmd/cli/highlight.go
  2. 278
      cmd/cli/item.go
  3. 534
      cmd/cli/main.go
  4. 83
      cmd/cli/query.go

@ -0,0 +1,79 @@
package main
import (
"strconv"
"strings"
)
func cleanHighlight(str string) string {
prefix := "\033["
invert := "\033[7;1m"
invertGreen := "\033[32;7;1m"
end := "\033[0m"
replace := []string{invert, invertGreen, end}
for i := 30; i < 48; i++ {
base := prefix + strconv.Itoa(i)
normal := base + "m"
bold := base + ";1m"
replace = append(replace, normal, bold)
}
if strings.Contains(str, prefix) == false {
return str
}
for _, escSeq := range replace {
str = strings.ReplaceAll(str, escSeq, "")
}
return str
}
func highlightSelected(str string) string {
// template "\033[3%d;%dm"
// invertGreen := "\033[32;7;1m"
invert := "\033[7;1m"
end := "\033[0m"
return invert + cleanHighlight(str) + end
}
func highlightHost(str string) string {
// template "\033[3%d;%dm"
redNormal := "\033[31m"
end := "\033[0m"
return redNormal + cleanHighlight(str) + end
}
func highlightPwd(str string) string {
// template "\033[3%d;%dm"
blueBold := "\033[34;1m"
end := "\033[0m"
return blueBold + cleanHighlight(str) + end
}
func highlightMatch(str string) string {
// template "\033[3%d;%dm"
magentaBold := "\033[35;1m"
end := "\033[0m"
return magentaBold + cleanHighlight(str) + end
}
func highlightWarn(str string) string {
// template "\033[3%d;%dm"
// orangeBold := "\033[33;1m"
redBold := "\033[31;1m"
end := "\033[0m"
return redBold + cleanHighlight(str) + end
}
func highlightGit(str string) string {
// template "\033[3%d;%dm"
greenBold := "\033[32;1m"
end := "\033[0m"
return greenBold + cleanHighlight(str) + end
}
func doHighlightString(str string, minLength int) string {
if len(str) < minLength {
str = str + strings.Repeat(" ", minLength-len(str))
}
return highlightSelected(str)
}

@ -0,0 +1,278 @@
package main
import (
"errors"
"fmt"
"log"
"strconv"
"strings"
"github.com/curusarn/resh/pkg/records"
)
type item struct {
// dateWithColor string
// date string
// [host:]pwd
locationWithColor string
location string
// [G] [E#]
flagsWithColor string
flags string
cmdLineWithColor string
cmdLine string
hits float64
key string
// cmdLineRaw string
}
func (i item) less(i2 item) bool {
// reversed order
return i.hits > i2.hits
}
func (i item) produceLine(flagLength int) (string, int) {
line := ""
line += i.locationWithColor
line += i.flagsWithColor
flags := i.flags
if flagLength < len(i.flags) {
log.Printf("produceLine can't specify line w/ flags shorter than the actual size. - len(flags) %v, requested %v\n", len(i.flags), flagLength)
}
for len(flags) < flagLength {
line += " "
flags += " "
}
spacer := " "
if flagLength > 5 {
// use shorter spacer
// because there is likely a long flag like E130 in the view
spacer = " "
}
line += spacer + i.cmdLineWithColor
length := len(i.location) + flagLength + len(spacer) + len(i.cmdLine)
return line, length
}
func leftCutPadString(str string, newLen int) string {
dots := "…"
strLen := len(str)
if newLen > strLen {
return strings.Repeat(" ", newLen-strLen) + str
} else if newLen < strLen {
return dots + str[strLen-newLen+1:]
}
return str
}
func rightCutPadString(str string, newLen int) string {
dots := "…"
strLen := len(str)
if newLen > strLen {
return str + strings.Repeat(" ", newLen-strLen)
} else if newLen < strLen {
return str[:newLen-1] + dots
}
return str
}
// proper match for path is when whole directory is matched
// proper match for command is when term matches word delimeted by whitespace
func properMatch(str, term, padChar string) bool {
if strings.Contains(padChar+str+padChar, padChar+term+padChar) {
return true
}
return false
}
// newItemFromRecordForQuery creates new item from record based on given query
// returns error if the query doesn't match the record
func newItemFromRecordForQuery(record records.EnrichedRecord, query query, debug bool) (item, error) {
const hitScore = 1.0
const hitScoreConsecutive = 0.1
const properMatchScore = 0.3
const actualPwdScore = 0.9
const nonZeroExitCodeScorePenalty = 0.5
const sameGitRepoScore = 0.7
// const sameGitRepoScoreExtra = 0.0
const differentHostScorePenalty = 0.2
// nonZeroExitCodeScorePenalty + differentHostScorePenalty
hits := 0.0
anyHit := false
cmd := record.CmdLine
for _, term := range query.terms {
termHit := false
if strings.Contains(record.CmdLine, term) {
anyHit = true
if termHit == false {
hits += hitScore
} else {
hits += hitScoreConsecutive
}
termHit = true
if properMatch(cmd, term, " ") {
hits += properMatchScore
}
cmd = strings.ReplaceAll(cmd, term, highlightMatch(term))
// NO continue
}
}
// actual pwd matches
// N terms can only produce:
// -> N matches against the command
// -> 1 extra match for the actual directory match
sameGitRepo := false
if query.gitOriginRemote != "" && query.gitOriginRemote == record.GitOriginRemote {
sameGitRepo = true
}
samePwd := false
if record.Pwd == query.pwd {
anyHit = true
samePwd = true
hits += actualPwdScore
} else if sameGitRepo {
anyHit = true
hits += sameGitRepoScore
}
differentHost := false
if record.Host != query.host {
differentHost = true
hits -= differentHostScorePenalty
}
errorExitStatus := false
if record.ExitCode != 0 {
errorExitStatus = true
hits -= nonZeroExitCodeScorePenalty
}
if hits <= 0 && !anyHit {
return item{}, errors.New("no match for given record and query")
}
// KEY for deduplication
unlikelySeparator := "|||||"
key := record.CmdLine + unlikelySeparator + record.Pwd +
unlikelySeparator + strconv.Itoa(record.ExitCode) + unlikelySeparator +
record.GitOriginRemote + unlikelySeparator + record.Host
// DISPLAY
// DISPLAY > date
// TODO
// DISPLAY > location
location := ""
locationWithColor := ""
if differentHost {
location += record.Host + ":"
locationWithColor += highlightHost(record.Host) + ":"
}
const locationLenght = 30
pwdLength := locationLenght - len(location)
pwdTilde := strings.Replace(record.Pwd, record.Home, "~", 1)
location += leftCutPadString(pwdTilde, pwdLength)
if samePwd {
locationWithColor += highlightPwd(leftCutPadString(pwdTilde, pwdLength))
} else {
locationWithColor += leftCutPadString(pwdTilde, pwdLength)
}
// DISPLAY > flags
flags := ""
flagsWithColor := ""
if debug {
hitsStr := fmt.Sprintf("%.1f", hits)
flags += " S" + hitsStr
}
if sameGitRepo {
flags += " G"
flagsWithColor += " " + highlightGit("G")
}
if errorExitStatus {
flags += " E" + strconv.Itoa(record.ExitCode)
flagsWithColor += " " + highlightWarn("E"+strconv.Itoa(record.ExitCode))
}
// DISPLAY > cmdline
// cmd := "<" + strings.ReplaceAll(record.CmdLine, "\n", ";") + ">"
cmdLine := strings.ReplaceAll(record.CmdLine, "\n", ";")
cmdLineWithColor := strings.ReplaceAll(cmd, "\n", ";")
it := item{
location: location,
locationWithColor: locationWithColor,
flags: flags,
flagsWithColor: flagsWithColor,
cmdLine: cmdLine,
cmdLineWithColor: cmdLineWithColor,
hits: hits,
key: key,
}
return it, nil
}
type rawItem struct {
cmdLineWithColor string
cmdLine string
hits float64
key string
// cmdLineRaw string
}
// newRawItemFromRecordForQuery creates new item from record based on given query
// returns error if the query doesn't match the record
func newRawItemFromRecordForQuery(record records.EnrichedRecord, terms []string, debug bool) (rawItem, error) {
const hitScore = 1.0
const hitScoreConsecutive = 0.1
const properMatchScore = 0.3
hits := 0.0
anyHit := false
cmd := record.CmdLine
for _, term := range terms {
termHit := false
if strings.Contains(record.CmdLine, term) {
anyHit = true
if termHit == false {
hits += hitScore
} else {
hits += hitScoreConsecutive
}
termHit = true
if properMatch(cmd, term, " ") {
hits += properMatchScore
}
cmd = strings.ReplaceAll(cmd, term, highlightMatch(term))
// NO continue
}
}
_ = anyHit
// KEY for deduplication
key := record.CmdLine
// DISPLAY > cmdline
// cmd := "<" + strings.ReplaceAll(record.CmdLine, "\n", ";") + ">"
cmdLine := strings.ReplaceAll(record.CmdLine, "\n", ";")
cmdLineWithColor := strings.ReplaceAll(cmd, "\n", ";")
it := rawItem{
cmdLine: cmdLine,
cmdLineWithColor: cmdLineWithColor,
hits: hits,
key: key,
}
return it, nil
}

@ -3,7 +3,6 @@ package main
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -143,8 +142,12 @@ func runReshCli() (string, int) {
if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone, layout.SelectPaste); err != nil { if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone, layout.SelectPaste); err != nil {
log.Panicln(err) log.Panicln(err)
} }
if err := g.SetKeybinding("", gocui.KeyCtrlR, gocui.ModNone, layout.SwitchModes); err != nil {
log.Panicln(err)
}
layout.UpdateData(*query) layout.UpdateData(*query)
layout.UpdateRawData(*query)
err = g.MainLoop() err = g.MainLoop()
if err != nil && gocui.IsQuit(err) == false { if err != nil && gocui.IsQuit(err) == false {
log.Panicln(err) log.Panicln(err)
@ -152,361 +155,15 @@ func runReshCli() (string, int) {
return layout.s.output, layout.s.exitCode return layout.s.output, layout.s.exitCode
} }
func leftCutPadString(str string, newLen int) string {
dots := "…"
strLen := len(str)
if newLen > strLen {
return strings.Repeat(" ", newLen-strLen) + str
} else if newLen < strLen {
return dots + str[strLen-newLen+1:]
}
return str
}
func rightCutPadString(str string, newLen int) string {
dots := "…"
strLen := len(str)
if newLen > strLen {
return str + strings.Repeat(" ", newLen-strLen)
} else if newLen < strLen {
return str[:newLen-1] + dots
}
return str
}
func cleanHighlight(str string) string {
prefix := "\033["
invert := "\033[32;7;1m"
end := "\033[0m"
replace := []string{invert, end}
for i := 30; i < 48; i++ {
base := prefix + strconv.Itoa(i)
normal := base + "m"
bold := base + ";1m"
replace = append(replace, normal, bold)
}
if strings.Contains(str, prefix) == false {
return str
}
for _, escSeq := range replace {
str = strings.ReplaceAll(str, escSeq, "")
}
return str
}
func highlightSelected(str string) string {
// template "\033[3%d;%dm"
invert := "\033[32;7;1m"
end := "\033[0m"
return invert + cleanHighlight(str) + end
}
func highlightHost(str string) string {
// template "\033[3%d;%dm"
redNormal := "\033[31m"
end := "\033[0m"
return redNormal + cleanHighlight(str) + end
}
func highlightPwd(str string) string {
// template "\033[3%d;%dm"
blueBold := "\033[34;1m"
end := "\033[0m"
return blueBold + cleanHighlight(str) + end
}
func highlightMatch(str string) string {
// template "\033[3%d;%dm"
magentaBold := "\033[35;1m"
end := "\033[0m"
return magentaBold + cleanHighlight(str) + end
}
func highlightWarn(str string) string {
// template "\033[3%d;%dm"
// orangeBold := "\033[33;1m"
redBold := "\033[31;1m"
end := "\033[0m"
return redBold + cleanHighlight(str) + end
}
func highlightGit(str string) string {
// template "\033[3%d;%dm"
greenBold := "\033[32;1m"
end := "\033[0m"
return greenBold + cleanHighlight(str) + end
}
func toString(record records.EnrichedRecord, lineLength int) string {
dirColWidth := 24 // make this dynamic somehow
return leftCutPadString(strings.Replace(record.Pwd, record.Home, "~", 1), dirColWidth) + " " +
rightCutPadString(strings.ReplaceAll(record.CmdLine, "\n", "; "), lineLength-dirColWidth-3) + "\n"
}
type query struct {
terms []string
host string
pwd string
gitOriginRemote string
// pwdTilde string
}
func isValidTerm(term string) bool {
if len(term) == 0 {
return false
}
if strings.Contains(term, " ") {
return false
}
return true
}
func filterTerms(terms []string) []string {
var newTerms []string
for _, term := range terms {
if isValidTerm(term) {
newTerms = append(newTerms, term)
}
}
return newTerms
}
func newQueryFromString(queryInput string, host string, pwd string, gitOriginRemote string) query {
if debug {
log.Println("QUERY input = <" + queryInput + ">")
}
terms := strings.Fields(queryInput)
var logStr string
for _, term := range terms {
logStr += " <" + term + ">"
}
if debug {
log.Println("QUERY raw terms =" + logStr)
}
terms = filterTerms(terms)
logStr = ""
for _, term := range terms {
logStr += " <" + term + ">"
}
if debug {
log.Println("QUERY filtered terms =" + logStr)
log.Println("QUERY pwd =" + pwd)
}
return query{
terms: terms,
host: host,
pwd: pwd,
gitOriginRemote: gitOriginRemote,
}
}
type item struct {
// dateWithColor string
// date string
// [host:]pwd
locationWithColor string
location string
// [G] [E#]
flagsWithColor string
flags string
cmdLineWithColor string
cmdLine string
hits float64
key string
// cmdLineRaw string
}
func (i item) less(i2 item) bool {
// reversed order
return i.hits > i2.hits
}
func (i item) produceLine(flagLength int) (string, int) {
line := ""
line += i.locationWithColor
line += i.flagsWithColor
flags := i.flags
if flagLength < len(i.flags) {
log.Printf("produceLine can't specify line w/ flags shorter than the actual size. - len(flags) %v, requested %v\n", len(i.flags), flagLength)
}
for len(flags) < flagLength {
line += " "
flags += " "
}
spacer := " "
if flagLength > 5 {
// use shorter spacer
// because there is likely a long flag like E130 in the view
spacer = " "
}
line += spacer + i.cmdLineWithColor
length := len(i.location) + flagLength + len(spacer) + len(i.cmdLine)
return line, length
}
// func (i item) equals(i2 item) bool {
// return i.cmdLine == i2.cmdLine && i.pwd == i2.pwd
// }
// proper match for path is when whole directory is matched
// proper match for command is when term matches word delimeted by whitespace
func properMatch(str, term, padChar string) bool {
if strings.Contains(padChar+str+padChar, padChar+term+padChar) {
return true
}
return false
}
// newItemFromRecordForQuery creates new item from record based on given query
// returns error if the query doesn't match the record
func newItemFromRecordForQuery(record records.EnrichedRecord, query query, debug bool) (item, error) {
const hitScore = 1.0
const hitScoreConsecutive = 0.1
const properMatchScore = 0.3
const actualPwdScore = 0.9
const nonZeroExitCodeScorePenalty = 0.5
const sameGitRepoScore = 0.7
// const sameGitRepoScoreExtra = 0.0
const differentHostScorePenalty = 0.2
// nonZeroExitCodeScorePenalty + differentHostScorePenalty
hits := 0.0
anyHit := false
cmd := record.CmdLine
for _, term := range query.terms {
termHit := false
if strings.Contains(record.CmdLine, term) {
anyHit = true
if termHit == false {
hits += hitScore
} else {
hits += hitScoreConsecutive
}
termHit = true
if properMatch(cmd, term, " ") {
hits += properMatchScore
}
cmd = strings.ReplaceAll(cmd, term, highlightMatch(term))
// NO continue
}
}
// actual pwd matches
// N terms can only produce:
// -> N matches against the command
// -> 1 extra match for the actual directory match
sameGitRepo := false
if query.gitOriginRemote != "" && query.gitOriginRemote == record.GitOriginRemote {
sameGitRepo = true
}
samePwd := false
if record.Pwd == query.pwd {
anyHit = true
samePwd = true
hits += actualPwdScore
} else if sameGitRepo {
anyHit = true
hits += sameGitRepoScore
}
differentHost := false
if record.Host != query.host {
differentHost = true
hits -= differentHostScorePenalty
}
errorExitStatus := false
if record.ExitCode != 0 {
errorExitStatus = true
hits -= nonZeroExitCodeScorePenalty
}
if hits <= 0 && !anyHit {
return item{}, errors.New("no match for given record and query")
}
// KEY for deduplication
unlikelySeparator := "|||||"
key := record.CmdLine + unlikelySeparator + record.Pwd +
unlikelySeparator + strconv.Itoa(record.ExitCode) + unlikelySeparator +
record.GitOriginRemote + unlikelySeparator + record.Host
// DISPLAY
// DISPLAY > date
// TODO
// DISPLAY > location
location := ""
locationWithColor := ""
if differentHost {
location += record.Host + ":"
locationWithColor += highlightHost(record.Host) + ":"
}
const locationLenght = 30
pwdLength := locationLenght - len(location)
pwdTilde := strings.Replace(record.Pwd, record.Home, "~", 1)
location += leftCutPadString(pwdTilde, pwdLength)
if samePwd {
locationWithColor += highlightPwd(leftCutPadString(pwdTilde, pwdLength))
} else {
locationWithColor += leftCutPadString(pwdTilde, pwdLength)
}
// DISPLAY > flags
flags := ""
flagsWithColor := ""
if debug {
hitsStr := fmt.Sprintf("%.1f", hits)
flags += " S" + hitsStr
}
if sameGitRepo {
flags += " G"
flagsWithColor += " " + highlightGit("G")
}
if errorExitStatus {
flags += " E" + strconv.Itoa(record.ExitCode)
flagsWithColor += " " + highlightWarn("E"+strconv.Itoa(record.ExitCode))
}
// DISPLAY > cmdline
// cmd := "<" + strings.ReplaceAll(record.CmdLine, "\n", ";") + ">"
cmdLine := strings.ReplaceAll(record.CmdLine, "\n", ";")
cmdLineWithColor := strings.ReplaceAll(cmd, "\n", ";")
it := item{
location: location,
locationWithColor: locationWithColor,
flags: flags,
flagsWithColor: flagsWithColor,
cmdLine: cmdLine,
cmdLineWithColor: cmdLineWithColor,
hits: hits,
key: key,
}
return it, nil
}
func doHighlightString(str string, minLength int) string {
if len(str) < minLength {
str = str + strings.Repeat(" ", minLength-len(str))
}
return highlightSelected(str)
}
type state struct { type state struct {
lock sync.Mutex lock sync.Mutex
fullRecords []records.EnrichedRecord fullRecords []records.EnrichedRecord
data []item data []item
rawData []rawItem
highlightedItem int highlightedItem int
rawMode bool
initialQuery string initialQuery string
output string output string
@ -592,8 +249,58 @@ func (m manager) UpdateData(input string) {
} }
} }
func (m manager) UpdateRawData(input string) {
if debug {
log.Println("EDIT start")
log.Println("len(fullRecords) =", len(m.s.fullRecords))
log.Println("len(data) =", len(m.s.data))
}
query := getRawTermsFromString(input)
var data []rawItem
itemSet := make(map[string]bool)
m.s.lock.Lock()
defer m.s.lock.Unlock()
for _, rec := range m.s.fullRecords {
itm, err := newRawItemFromRecordForQuery(rec, query, m.config.Debug)
if err != nil {
// records didn't match the query
// log.Println(" * continue (no match)", rec.Pwd)
continue
}
if itemSet[itm.key] {
// log.Println(" * continue (already present)", itm.key(), itm.pwd)
continue
}
itemSet[itm.key] = true
data = append(data, itm)
// log.Println("DATA =", itm.display)
}
if debug {
log.Println("len(tmpdata) =", len(data))
}
sort.SliceStable(data, func(p, q int) bool {
return data[p].hits > data[q].hits
})
m.s.rawData = nil
for _, itm := range data {
if len(m.s.rawData) > 420 {
break
}
m.s.rawData = append(m.s.rawData, itm)
}
m.s.highlightedItem = 0
if debug {
log.Println("len(fullRecords) =", len(m.s.fullRecords))
log.Println("len(data) =", len(m.s.data))
log.Println("EDIT end")
}
}
func (m manager) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) { func (m manager) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
gocui.DefaultEditor.Edit(v, key, ch, mod) gocui.DefaultEditor.Edit(v, key, ch, mod)
if m.s.rawMode {
m.UpdateRawData(v.Buffer())
return
}
m.UpdateData(v.Buffer()) m.UpdateData(v.Buffer())
} }
@ -616,6 +323,19 @@ func (m manager) Prev(g *gocui.Gui, v *gocui.View) error {
return nil return nil
} }
func (m manager) SwitchModes(g *gocui.Gui, v *gocui.View) error {
m.s.lock.Lock()
m.s.rawMode = !m.s.rawMode
m.s.lock.Unlock()
if m.s.rawMode {
m.UpdateRawData(v.Buffer())
return nil
}
m.UpdateData(v.Buffer())
return nil
}
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()
@ -627,7 +347,11 @@ func (m manager) Layout(g *gocui.Gui) error {
v.Editable = true v.Editable = true
v.Editor = m v.Editor = m
v.Title = "resh cli" if m.s.rawMode {
v.Title = " RESH CLI - NON-CONTEXTUAL \"RAW\" MODE "
} else {
v.Title = " RESH CLI - CONTEXTUAL MODE "
}
g.SetCurrentView("input") g.SetCurrentView("input")
@ -648,6 +372,53 @@ func (m manager) Layout(g *gocui.Gui) error {
v.Clear() v.Clear()
v.Rewind() v.Rewind()
if m.s.rawMode {
return m.rawMode(g, v)
}
return m.normalMode(g, v)
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
// SendDumpMsg to daemon
func SendDumpMsg(m msg.DumpMsg, port string) msg.DumpResponse {
recJSON, err := json.Marshal(m)
if err != nil {
log.Fatal("send err 1", err)
}
req, err := http.NewRequest("POST", "http://localhost:"+port+"/dump",
bytes.NewBuffer(recJSON))
if err != nil {
log.Fatal("send err 2", err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal("resh-daemon is not running :(")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal("read response error")
}
// log.Println(string(body))
response := msg.DumpResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
log.Fatal("unmarshal resp error: ", err)
}
return response
}
func (m manager) normalMode(g *gocui.Gui, v *gocui.View) error {
maxX, maxY := g.Size()
longestFlagsLen := 2 // at least 2 longestFlagsLen := 2 // at least 2
for i, itm := range m.s.data { for i, itm := range m.s.data {
if i == maxY { if i == maxY {
@ -694,40 +465,41 @@ func (m manager) Layout(g *gocui.Gui) error {
return nil return nil
} }
func quit(g *gocui.Gui, v *gocui.View) error { func (m manager) rawMode(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit maxX, maxY := g.Size()
}
// SendDumpMsg to daemon for i, itm := range m.s.rawData {
func SendDumpMsg(m msg.DumpMsg, port string) msg.DumpResponse { if i == maxY {
recJSON, err := json.Marshal(m) if debug {
if err != nil { log.Println(maxY)
log.Fatal("send err 1", err)
} }
break
req, err := http.NewRequest("POST", "http://localhost:"+port+"/dump",
bytes.NewBuffer(recJSON))
if err != nil {
log.Fatal("send err 2", err)
} }
req.Header.Set("Content-Type", "application/json") displayStr := itm.cmdLineWithColor
if m.s.highlightedItem == i {
client := &http.Client{} // use actual min requried length instead of 420 constant
resp, err := client.Do(req) displayStr = doHighlightString(displayStr, maxX*2)
if err != nil { if debug {
log.Fatal("resh-daemon is not running :(") log.Println("### HightlightedItem string :", displayStr)
} }
} else if debug {
defer resp.Body.Close() log.Println(displayStr)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal("read response error")
} }
// log.Println(string(body)) if strings.Contains(displayStr, "\n") {
response := msg.DumpResponse{} log.Println("display string contained \\n")
err = json.Unmarshal(body, &response) displayStr = strings.ReplaceAll(displayStr, "\n", "#")
if err != nil { if debug {
log.Fatal("unmarshal resp error: ", err) log.Println("display string contained \\n")
} }
return response }
v.WriteString(displayStr + "\n")
// if m.s.highlightedItem == i {
// v.SetHighlight(m.s.highlightedItem, true)
// }
}
if debug {
log.Println("len(data) =", len(m.s.data))
log.Println("highlightedItem =", m.s.highlightedItem)
}
return nil
} }

@ -0,0 +1,83 @@
package main
import (
"log"
"strings"
)
type query struct {
terms []string
host string
pwd string
gitOriginRemote string
// pwdTilde string
}
func isValidTerm(term string) bool {
if len(term) == 0 {
return false
}
if strings.Contains(term, " ") {
return false
}
return true
}
func filterTerms(terms []string) []string {
var newTerms []string
for _, term := range terms {
if isValidTerm(term) {
newTerms = append(newTerms, term)
}
}
return newTerms
}
func newQueryFromString(queryInput string, host string, pwd string, gitOriginRemote string) query {
if debug {
log.Println("QUERY input = <" + queryInput + ">")
}
terms := strings.Fields(queryInput)
var logStr string
for _, term := range terms {
logStr += " <" + term + ">"
}
if debug {
log.Println("QUERY raw terms =" + logStr)
}
terms = filterTerms(terms)
logStr = ""
for _, term := range terms {
logStr += " <" + term + ">"
}
if debug {
log.Println("QUERY filtered terms =" + logStr)
log.Println("QUERY pwd =" + pwd)
}
return query{
terms: terms,
host: host,
pwd: pwd,
gitOriginRemote: gitOriginRemote,
}
}
func getRawTermsFromString(queryInput string) []string {
if debug {
log.Println("QUERY input = <" + queryInput + ">")
}
terms := strings.Fields(queryInput)
var logStr string
for _, term := range terms {
logStr += " <" + term + ">"
}
if debug {
log.Println("QUERY raw terms =" + logStr)
}
terms = filterTerms(terms)
logStr = ""
for _, term := range terms {
logStr += " <" + term + ">"
}
return terms
}
Loading…
Cancel
Save