100 lines
1.7 KiB
Go
100 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/app"
|
|
"fyne.io/fyne/v2/layout"
|
|
"fyne.io/fyne/v2/widget"
|
|
"github.com/creack/pty"
|
|
)
|
|
|
|
// MaxBufferSize sets the size limit
|
|
// for our command output buffer.
|
|
const MaxBufferSize = 16
|
|
|
|
func main() {
|
|
a := app.New()
|
|
w := a.NewWindow("goTerm")
|
|
|
|
ui := widget.NewTextGrid()
|
|
|
|
os.Setenv("TERM", "dumb")
|
|
c := exec.Command("/bin/bash")
|
|
p, err := pty.Start(c)
|
|
|
|
if err != nil {
|
|
fyne.LogError("Failed to open Terminal", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
defer c.Process.Kill()
|
|
|
|
onTypedKey := func(e *fyne.KeyEvent) {
|
|
if e.Name == fyne.KeyEnter || e.Name == fyne.KeyReturn {
|
|
_, _ = p.Write([]byte{'\r'})
|
|
}
|
|
}
|
|
|
|
onTypedRune := func(r rune) {
|
|
_, _ = p.WriteString(string(r))
|
|
}
|
|
|
|
w.Canvas().SetOnTypedKey(onTypedKey)
|
|
w.Canvas().SetOnTypedRune(onTypedRune)
|
|
|
|
buffer := [][]rune{}
|
|
reader := bufio.NewReader(p)
|
|
|
|
go func() {
|
|
line := []rune{}
|
|
buffer = append(buffer, line)
|
|
for {
|
|
r, _, err := reader.ReadRune()
|
|
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
return
|
|
}
|
|
os.Exit(0)
|
|
}
|
|
|
|
line = append(line, r)
|
|
buffer[len(buffer)-1] = line
|
|
if r == '\n' {
|
|
if len(buffer) > MaxBufferSize { // If the buffer is at capacity...
|
|
buffer = buffer[1:] // ...pop the first line in the buffer
|
|
}
|
|
|
|
line = []rune{}
|
|
buffer = append(buffer, line)
|
|
}
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for {
|
|
time.Sleep(100 * time.Millisecond)
|
|
ui.SetText("")
|
|
var lines string
|
|
for _, line := range buffer {
|
|
lines = lines + string(line)
|
|
}
|
|
ui.SetText(string(lines))
|
|
}
|
|
}()
|
|
|
|
w.SetContent(
|
|
fyne.NewContainerWithLayout(
|
|
layout.NewGridWrapLayout(fyne.NewSize(900, 325)),
|
|
ui,
|
|
),
|
|
)
|
|
w.ShowAndRun()
|
|
}
|