mirror of https://github.com/curusarn/resh
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
5.2 KiB
241 lines
5.2 KiB
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
"github.com/awesome-gocui/gocui"
|
|
"github.com/curusarn/resh/pkg/cfg"
|
|
"github.com/curusarn/resh/pkg/msg"
|
|
|
|
"os/user"
|
|
"path/filepath"
|
|
"strconv"
|
|
)
|
|
|
|
// version from git set during build
|
|
var version string
|
|
|
|
// commit from git set during build
|
|
var commit string
|
|
|
|
func main() {
|
|
usr, _ := user.Current()
|
|
dir := usr.HomeDir
|
|
configPath := filepath.Join(dir, "/.config/resh.toml")
|
|
|
|
var config cfg.Config
|
|
if _, err := toml.DecodeFile(configPath, &config); err != nil {
|
|
log.Fatal("Error reading config:", err)
|
|
}
|
|
|
|
sessionID := flag.String("sessionID", "", "resh generated session id")
|
|
flag.Parse()
|
|
|
|
if *sessionID == "" {
|
|
fmt.Println("Error: you need to specify sessionId")
|
|
}
|
|
|
|
g, err := gocui.NewGui(gocui.OutputNormal, false)
|
|
if err != nil {
|
|
log.Panicln(err)
|
|
}
|
|
defer g.Close()
|
|
|
|
g.Cursor = true
|
|
g.SelFgColor = gocui.ColorGreen
|
|
// g.SelBgColor = gocui.ColorGreen
|
|
g.Highlight = false
|
|
|
|
mess := msg.InspectMsg{SessionID: *sessionID, Count: 40}
|
|
resp := SendInspectMsg(mess, strconv.Itoa(config.Port))
|
|
|
|
st := state{
|
|
// lock sync.Mutex
|
|
dataOriginal: resp.CmdLines,
|
|
data: resp.CmdLines,
|
|
}
|
|
layout := manager{
|
|
sessionID: *sessionID,
|
|
config: config,
|
|
s: &st,
|
|
}
|
|
g.SetManager(layout)
|
|
|
|
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, layout.Next); err != nil {
|
|
log.Panicln(err)
|
|
}
|
|
if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, layout.Next); err != nil {
|
|
log.Panicln(err)
|
|
}
|
|
if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, layout.Prev); err != nil {
|
|
log.Panicln(err)
|
|
}
|
|
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
|
log.Panicln(err)
|
|
}
|
|
if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, layout.SelectExecute); err != nil {
|
|
log.Panicln(err)
|
|
}
|
|
|
|
err = g.MainLoop()
|
|
if err != nil && gocui.IsQuit(err) == false {
|
|
log.Panicln(err)
|
|
}
|
|
layout.Output()
|
|
}
|
|
|
|
// returns the number of hits for query
|
|
func queryHits(cmdline string, queryTerms []string) int {
|
|
hits := 0
|
|
for _, term := range queryTerms {
|
|
if strings.Contains(cmdline, term) {
|
|
hits++
|
|
}
|
|
}
|
|
return hits
|
|
}
|
|
|
|
type state struct {
|
|
dataOriginal []string
|
|
data []string
|
|
highlightedItem int
|
|
|
|
outputBuffer string
|
|
}
|
|
|
|
type manager struct {
|
|
sessionID string
|
|
config cfg.Config
|
|
|
|
s *state
|
|
}
|
|
|
|
func (m manager) Output() {
|
|
if len(m.s.outputBuffer) > 0 {
|
|
fmt.Print(m.s.outputBuffer)
|
|
}
|
|
}
|
|
|
|
func (m manager) SelectExecute(g *gocui.Gui, v *gocui.View) error {
|
|
if m.s.highlightedItem < len(m.s.data) {
|
|
m.s.outputBuffer = m.s.data[m.s.highlightedItem]
|
|
return gocui.ErrQuit
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m manager) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
|
|
gocui.DefaultEditor.Edit(v, key, ch, mod)
|
|
query := v.Buffer()
|
|
terms := strings.Split(query, " ")
|
|
var dataHits []int
|
|
m.s.data = nil
|
|
for _, entry := range m.s.dataOriginal {
|
|
hits := queryHits(entry, terms)
|
|
if hits > 0 {
|
|
m.s.data = append(m.s.data, entry)
|
|
dataHits = append(dataHits, hits)
|
|
}
|
|
}
|
|
sort.SliceStable(m.s.data, func(p, q int) bool {
|
|
return dataHits[p] > dataHits[q]
|
|
})
|
|
m.s.highlightedItem = 0
|
|
}
|
|
|
|
func (m manager) Next(g *gocui.Gui, v *gocui.View) error {
|
|
_, y := g.Size()
|
|
if m.s.highlightedItem < y {
|
|
m.s.highlightedItem++
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m manager) Prev(g *gocui.Gui, v *gocui.View) error {
|
|
if m.s.highlightedItem > 0 {
|
|
m.s.highlightedItem--
|
|
}
|
|
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 {
|
|
var b byte
|
|
maxX, maxY := g.Size()
|
|
|
|
v, err := g.SetView("input", 0, 0, maxX-1, 2, b)
|
|
if err != nil && gocui.IsUnknownView(err) == false {
|
|
log.Panicln(err.Error())
|
|
}
|
|
|
|
v.Editable = true
|
|
// v.Editor = gocui.EditorFunc(m.editor.Edit)
|
|
v.Editor = m
|
|
v.Title = "resh cli"
|
|
|
|
g.SetCurrentView("input")
|
|
|
|
v, err = g.SetView("body", 0, 2, maxX-1, maxY, b)
|
|
if err != nil && gocui.IsUnknownView(err) == false {
|
|
log.Panicln(err.Error())
|
|
}
|
|
v.Frame = false
|
|
v.Autoscroll = true
|
|
v.Clear()
|
|
for _, cmdLine := range m.s.data {
|
|
entry := strings.Trim(cmdLine, "\n") + "\n"
|
|
v.WriteString(entry)
|
|
}
|
|
if m.s.highlightedItem < len(m.s.data) {
|
|
v.SetHighlight(m.s.highlightedItem, true)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func quit(g *gocui.Gui, v *gocui.View) error {
|
|
return gocui.ErrQuit
|
|
}
|
|
|
|
// SendInspectMsg to daemon
|
|
func SendInspectMsg(m msg.InspectMsg, port string) msg.MultiResponse {
|
|
recJSON, err := json.Marshal(m)
|
|
if err != nil {
|
|
log.Fatal("send err 1", err)
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", "http://localhost:"+port+"/inspect",
|
|
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.MultiResponse{}
|
|
err = json.Unmarshal(body, &response)
|
|
if err != nil {
|
|
log.Fatal("unmarshal resp error: ", err)
|
|
}
|
|
return response
|
|
}
|
|
|