dsklfsdlkf1232 2018-02-28 11:22
浏览 24
已采纳

Gocui在寻呼机程序后中断

I have a program based on the gocui library, which has a keybinding with a function which generates text and sends it to the pager's stdin. But after closing the pager, all previous gocui interface becomes broken, but program is still working.

So how can I safely return from pager to the gocui mode and continue the program?

Simplified example, here.

package main

import (
    "fmt"
    "log"
    "os/exec"
    "os"
    "strings"
    "github.com/jroimartin/gocui"
    "time"
    "sync"
    "bytes"
)

var (
    done = make(chan struct{})
    wg  sync.WaitGroup
)

func main() {
    g, err := gocui.NewGui(gocui.OutputNormal)
    if err != nil {
        log.Panicln(err)
    }
    defer g.Close()

    g.SetManagerFunc(layout)

    if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
        log.Panicln(err)
    }
    if err := g.SetKeybinding("", gocui.KeySpace, gocui.ModNone, pager); err != nil {
        log.Panicln(err)
    }

    wg.Add(1)
    go showTime(g)

    if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
        log.Panicln(err)
    }

    wg.Wait()
}

func layout(g *gocui.Gui) error {
    maxX, _ := g.Size()
        if v, err := g.SetView("main", -1, -1, maxX/2-1, 4); err != nil {
        if err != gocui.ErrUnknownView {
            return err
        }
        fmt.Fprintln(v, time.Now().Format("2006-01-02 15:04:05.000"))
        v.Frame = false
    }

    return nil
}

func pager(g *gocui.Gui, v *gocui.View) error {
    var buf bytes.Buffer
    for i:=0; i < 10; i++ {
        buf.WriteString(fmt.Sprintf("%d -- %s %s
", i, "example", "text"))
    }

    cmd := exec.Command("less")
    cmd.Stdin = strings.NewReader(buf.String())
    cmd.Stdout = os.Stdout
    err := cmd.Run()

    return err
}

func showTime(g *gocui.Gui) {
    defer wg.Done()

    for {
        select {
        case <-done:
            return
        case <-time.After(1 * time.Second):
            t := time.Now()

            g.Update(func(g *gocui.Gui) error {
                v, err := g.View("main")
                if err != nil {
                    return err
                }
                v.Clear()
                fmt.Fprintln(v, t.Format("2006-01-02 15:04:05.000"))
                return nil
            })
        }
    }
}

func quit(g *gocui.Gui, v *gocui.View) error {
    return gocui.ErrQuit
}
  • 写回答

1条回答 默认 最新

  • dongqu1783 2018-03-11 04:45
    关注

    Final example is below, it has additional things and in some places looks dirty, but it works in general.

    package main
    
    import (
        "fmt"
        "log"
        "os/exec"
        "os"
        "github.com/jroimartin/gocui"
        "time"
        "sync"
    )
    
    var (
        do_quit = make(chan int)
        do_pause = make(chan int)
        show_aux = false
        wg  sync.WaitGroup
    )
    
    func main() {
        for {
            // DEBUG: fmt.Println("start gui")
    
            g, err := gocui.NewGui(gocui.OutputNormal)
            if err != nil {
                log.Panicln(err)
            }
            defer g.Close()
    
            g.SetManagerFunc(layout)
            setKeys(g)
    
            wg.Add(1)
            go showTime(g)
    
            if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
                continue        // restart gui if something goes wrong
            }
            wg.Wait()
        }
    }
    
    
    func layout(g *gocui.Gui) error {
        maxX, _ := g.Size()
    
        if v, err := g.SetView("main", -1, -1, maxX/2-1, 4); err != nil {
            if err != gocui.ErrUnknownView {
                return err
            }
            fmt.Fprintf(v, "sys: %s
    ", time.Now().Format("2006-01-02 15:04:05.000"))
            v.Frame = false
        }
    
        return nil
    }
    
    func runPager(g *gocui.Gui, v *gocui.View) error {
        do_quit <-1
        g.Close()
        cmd := exec.Command("less", "/etc/sysctl.conf")
        cmd.Stdout = os.Stdout
        err := cmd.Run()
    
        return err
    }
    
    func runEditor(g *gocui.Gui, v *gocui.View) error {
        do_quit <-1
        g.Close()
        cmd := exec.Command("vi", "/tmp/strace.out")
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        err := cmd.Run()
    
        return err
    }
    
    func runPsql(g *gocui.Gui, v *gocui.View) error {
        do_quit <-1
        g.Close()
        cmd := exec.Command("psql", "-U", "postgres")
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        err := cmd.Run()
    
        return err
    }
    
    func showAux(g *gocui.Gui, _ *gocui.View) error {
        if !show_aux {
            maxX, maxY := g.Size()
            if v, err := g.SetView("aux", -1, 3*maxY/5-1, maxX-1, maxY-1); err != nil {
                if err != gocui.ErrUnknownView {
                    return err
                }
                fmt.Fprintln(v, "")
                v.Frame = false
            }
        } else {
            g.DeleteView("aux")
        }
        show_aux = !show_aux
        return nil
    }
    
    func showTime(g *gocui.Gui) {
        var pause = false
        defer wg.Done()
    
        for {
            select {
            case <-do_pause:
                pause = !pause
            case <-do_quit:
                return
            case <-time.After(1 * time.Second):
                if pause { continue }
    
                g.Update(func(g *gocui.Gui) error {
                    v, err := g.View("main")
                    if err != nil {
                        return err
                    }
                    v.Clear()
                    fmt.Fprintf(v, "sys: %s
    ", time.Now().Format("2006-01-02 15:04:05.000"))
    
                    if show_aux {
                        v, err := g.View("aux")
                        if err != nil {
                            return err
                        }
                        v.Clear()
                        fmt.Fprintf(v, "aux: %s
    ", time.Now().Format("2006-01-02 15:04:05.000"))
                    }
                    return nil
                })
            }
        }
    }
    
    func doQuit(g *gocui.Gui, v *gocui.View) error {
        do_quit <- 1
        g.Close()
        os.Exit(0)
        return gocui.ErrQuit
    }
    
    func setKeys(g *gocui.Gui) {
        if err := g.SetKeybinding("", gocui.KeyCtrlQ, gocui.ModNone, doQuit); err != nil {
            log.Panicln(err)
        }
        if err := g.SetKeybinding("", 'c', gocui.ModNone, runPager); err != nil {
            log.Panicln(err)
        }
        if err := g.SetKeybinding("", 'e', gocui.ModNone, runEditor); err != nil {
            log.Panicln(err)
        }
        if err := g.SetKeybinding("", 'p', gocui.ModNone, runPsql); err != nil {
            log.Panicln(err)
        }
        if err := g.SetKeybinding("", 'b', gocui.ModNone, showAux); err != nil {
            log.Panicln(err)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图