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 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器