2016-08-13 15:49:04 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
2017-09-17 14:48:27 +03:00
|
|
|
"io"
|
2022-02-06 19:43:01 +03:00
|
|
|
"io/ioutil"
|
2016-08-13 15:49:04 +03:00
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"os"
|
2016-10-30 02:20:35 +03:00
|
|
|
"strings"
|
2018-07-26 21:58:09 +03:00
|
|
|
"time"
|
2016-08-13 15:49:04 +03:00
|
|
|
|
2020-12-04 23:59:12 +03:00
|
|
|
"github.com/gdamore/tcell/v2"
|
2016-08-13 15:49:04 +03:00
|
|
|
)
|
|
|
|
|
2017-11-19 21:55:13 +03:00
|
|
|
func run() {
|
2020-09-01 22:42:44 +10:00
|
|
|
var screen tcell.Screen
|
|
|
|
var err error
|
|
|
|
if screen, err = tcell.NewScreen(); err != nil {
|
|
|
|
log.Fatalf("creating screen: %s", err)
|
|
|
|
} else if err = screen.Init(); err != nil {
|
|
|
|
log.Fatalf("initializing screen: %s", err)
|
2019-02-18 14:18:02 +03:00
|
|
|
}
|
2021-01-29 19:36:27 +03:00
|
|
|
if gOpts.mouse {
|
|
|
|
screen.EnableMouse()
|
|
|
|
}
|
2019-02-18 14:18:02 +03:00
|
|
|
|
2022-02-06 19:43:01 +03:00
|
|
|
if gLogPath != "" {
|
|
|
|
f, err := os.OpenFile(gLogPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
log.SetOutput(f)
|
|
|
|
} else {
|
|
|
|
log.SetOutput(ioutil.Discard)
|
2022-01-22 13:47:18 +03:00
|
|
|
}
|
2016-08-13 15:49:04 +03:00
|
|
|
|
|
|
|
log.Print("hi!")
|
|
|
|
|
2021-02-21 17:48:23 +03:00
|
|
|
ui := newUI(screen)
|
|
|
|
nav := newNav(ui.wins[0].h)
|
|
|
|
app := newApp(ui, nav)
|
2016-08-13 15:49:04 +03:00
|
|
|
|
2021-05-19 23:38:05 +03:00
|
|
|
if err := nav.sync(); err != nil {
|
|
|
|
app.ui.echoerrf("sync: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-07-11 20:09:26 +03:00
|
|
|
if err := app.nav.readMarks(); err != nil {
|
2019-02-28 21:58:14 +03:00
|
|
|
app.ui.echoerrf("reading marks file: %s", err)
|
2018-07-11 20:09:26 +03:00
|
|
|
}
|
|
|
|
|
2018-07-11 20:49:55 +03:00
|
|
|
if err := app.readHistory(); err != nil {
|
2019-02-28 21:58:14 +03:00
|
|
|
app.ui.echoerrf("reading history file: %s", err)
|
2018-07-11 20:49:55 +03:00
|
|
|
}
|
|
|
|
|
2017-11-19 21:55:13 +03:00
|
|
|
app.loop()
|
2021-02-21 17:48:23 +03:00
|
|
|
|
2020-09-01 22:42:44 +10:00
|
|
|
app.ui.screen.Fini()
|
2016-08-13 15:49:04 +03:00
|
|
|
}
|
|
|
|
|
2017-11-19 21:55:13 +03:00
|
|
|
func readExpr() <-chan expr {
|
2016-12-18 00:47:37 +03:00
|
|
|
ch := make(chan expr)
|
2016-10-30 02:20:35 +03:00
|
|
|
|
|
|
|
go func() {
|
2018-07-26 21:58:09 +03:00
|
|
|
duration := 1 * time.Second
|
|
|
|
|
2017-11-19 21:55:13 +03:00
|
|
|
c, err := net.Dial(gSocketProt, gSocketPath)
|
2018-07-26 21:58:09 +03:00
|
|
|
for err != nil {
|
2019-08-12 13:52:27 +02:00
|
|
|
log.Printf("connecting server: %s", err)
|
2018-07-26 21:58:09 +03:00
|
|
|
time.Sleep(duration)
|
|
|
|
duration *= 2
|
2018-07-26 22:11:05 +03:00
|
|
|
c, err = net.Dial(gSocketProt, gSocketPath)
|
2017-11-19 21:55:13 +03:00
|
|
|
}
|
|
|
|
|
2016-12-18 00:47:37 +03:00
|
|
|
fmt.Fprintf(c, "conn %d\n", gClientID)
|
2016-10-30 02:20:35 +03:00
|
|
|
|
2018-04-12 18:04:37 +03:00
|
|
|
ch <- &callExpr{"sync", nil, 1}
|
2017-11-19 21:55:13 +03:00
|
|
|
|
2016-10-30 02:20:35 +03:00
|
|
|
s := bufio.NewScanner(c)
|
|
|
|
for s.Scan() {
|
2016-11-06 17:06:25 +03:00
|
|
|
log.Printf("recv: %s", s.Text())
|
2016-10-30 02:20:35 +03:00
|
|
|
p := newParser(strings.NewReader(s.Text()))
|
|
|
|
if p.parse() {
|
|
|
|
ch <- p.expr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
return ch
|
|
|
|
}
|
|
|
|
|
2019-02-26 21:27:04 +03:00
|
|
|
func remote(cmd string) error {
|
2017-07-21 01:26:36 +03:00
|
|
|
c, err := net.Dial(gSocketProt, gSocketPath)
|
2016-11-10 23:25:03 +03:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("dialing to send server: %s", err)
|
|
|
|
}
|
|
|
|
|
2016-11-18 23:38:38 +03:00
|
|
|
fmt.Fprintln(c, cmd)
|
2016-11-10 23:25:03 +03:00
|
|
|
|
2017-09-17 14:48:27 +03:00
|
|
|
// XXX: Standard net.Conn interface does not include a CloseWrite method
|
|
|
|
// but net.UnixConn and net.TCPConn implement it so the following should be
|
|
|
|
// safe as long as we do not use other types of connections. We need
|
|
|
|
// CloseWrite to notify the server that this is not a persistent connection
|
|
|
|
// and it should be closed after the response.
|
|
|
|
if v, ok := c.(interface {
|
|
|
|
CloseWrite() error
|
|
|
|
}); ok {
|
|
|
|
v.CloseWrite()
|
|
|
|
}
|
|
|
|
|
|
|
|
io.Copy(os.Stdout, c)
|
|
|
|
|
|
|
|
c.Close()
|
|
|
|
|
2016-11-10 23:25:03 +03:00
|
|
|
return nil
|
|
|
|
}
|