Search code examples
gofyne

connect fyne.Terminal to a command


Here is a minimal working example:

package main

import (
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/layout"
    "github.com/fyne-io/terminal"
    "log/slog"
    "os"
    "os/exec"
    "sync"
)

func main() {
    err := runMain()
    if err != nil {
        slog.Error(err.Error())
        os.Exit(1)
    }
}

func runMain() error {
    wg := sync.WaitGroup{}
    wg.Add(1)

    term := terminal.New()
    go func() {
        var err error

        // This works
        // err = term.RunLocalShell()

        // This does not work, blank screen...
        cmd := exec.Command("/usr/bin/bash")
        si, err := cmd.StdinPipe()
        if err != nil {
            slog.Error(err.Error())
            os.Exit(1)
        }
        so, err := cmd.StdoutPipe()
        if err != nil {
            slog.Error(err.Error())
            os.Exit(1)
        }
        err = cmd.Start()
        if err != nil {
            slog.Error(err.Error())
            os.Exit(1)
        }
        slog.Info("started", "pid", cmd.Process.Pid)
        err = term.RunWithConnection(si, so)

        if err != nil {
            slog.Error(err.Error())
        }

        wg.Done()
    }()

    a := app.New()
    go func() {
        wg.Wait()
        a.Quit()
    }()
    w := a.NewWindow("Test")
    w.SetContent(container.New(layout.NewStackLayout(), term))
    w.ShowAndRun()
    return nil
}

So term.RunLocalShell() works, but manually connection stdout and stdin of an os.Exec call to term.RunWithConnection(in, out) does not work. It displays a blank screen, and there is no error message at all.

What is wrong here?

I can see that terminal.RunLocalShell calls terminal.open() and that uses github.com/creack/pty to create a pty. However, terminal.pty is not a public field, it cannot be accessed from outside. My goal is to run a shell command remotely, and display it in a local terminal emulator. E.g. the given example is really minimal, in reality stdin and stdout are pipes connected with TCP to a remote process.


Solution

  • If a remote system is the aim I’d recommend checking out an SSH app I wrote using the fyne terminal library - it probably does what you need.

    https://github.com/andydotxyz/sshterm/blob/57557c8e6ab083370f00acd21d228b0bbd692518/main.go#L170