lf/app.go
2017-08-05 19:23:55 +03:00

160 lines
2.9 KiB
Go

package main
import (
"fmt"
"log"
"os"
"strconv"
"strings"
)
type cmdItem struct {
pref string
s string
}
type app struct {
ui *ui
nav *nav
quit chan bool
cmdHist []cmdItem
cmdHind int
}
func newApp() *app {
ui := newUI()
nav := newNav(ui.wins[0].h)
quit := make(chan bool, 1)
return &app{
ui: ui,
nav: nav,
quit: quit,
}
}
func waitKey() error {
// TODO: this should be done with termbox somehow
cmd := pauseCommand()
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("waiting key: %s", err)
}
return nil
}
// This is the main event loop of the application. There are two channels to
// read expressions from client and server. Reading and evaluation are done on
// separate goroutines.
func (app *app) handleInp(serverChan <-chan expr) {
clientChan := app.ui.readExpr()
for {
select {
case <-app.quit:
log.Print("bye!")
if gLastDirPath != "" {
f, err := os.Create(gLastDirPath)
if err != nil {
log.Printf("opening last dir file: %s", err)
}
defer f.Close()
dir := app.nav.currDir()
_, err = f.WriteString(dir.path)
if err != nil {
log.Printf("writing last dir file: %s", err)
}
}
return
case e := <-clientChan:
for i := 0; i < e.count; i++ {
e.expr.eval(app, nil)
}
app.ui.draw(app.nav)
case e := <-serverChan:
e.eval(app, nil)
app.ui.draw(app.nav)
}
}
}
func (app *app) exportVars() {
var envFile string
if f, err := app.nav.currFile(); err == nil {
envFile = f.Path
}
marks := app.nav.currMarks()
envFiles := strings.Join(marks, gOpts.filesep)
os.Setenv("f", envFile)
os.Setenv("fs", envFiles)
if len(marks) == 0 {
os.Setenv("fx", envFile)
} else {
os.Setenv("fx", envFiles)
}
os.Setenv("id", strconv.Itoa(gClientID))
}
// This function is used to run a command in shell. Following modes are used:
//
// Prefix Wait Async Stdin/Stdout/Stderr UI action
// $ No No Yes Pause and then resume
// ! Yes No Yes Pause and then resume
// & No Yes No Do nothing
//
// Waiting async commands are not used for now.
func (app *app) runShell(s string, args []string, wait bool, async bool) {
app.exportVars()
cmd := shellCommand(s, args)
if !async {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
app.ui.pause()
defer app.ui.resume()
defer app.nav.renew(app.ui.wins[0].h)
}
var err error
if async {
err = cmd.Start()
} else {
err = cmd.Run()
}
if err != nil {
msg := fmt.Sprintf("running shell: %s", err)
app.ui.message = msg
log.Print(msg)
}
if wait {
if err := waitKey(); err != nil {
msg := fmt.Sprintf("waiting shell: %s", err)
app.ui.message = msg
log.Print(msg)
}
}
app.ui.loadFile(app.nav)
app.ui.loadFileInfo(app.nav)
}