Last active
October 31, 2024 14:17
-
-
Save garvit-exe/f2a87129b521434668716a3880b3b15d to your computer and use it in GitHub Desktop.
Terminal Emulator using Go (Pseudo Teletype)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"io" | |
"os" | |
"os/exec" | |
"time" | |
"fyne.io/fyne/v2" | |
"fyne.io/fyne/v2/app" | |
"fyne.io/fyne/v2/container" | |
"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("garvit's terminal") | |
ui := widget.NewTextGrid() // Create a new TextGrid | |
os.Setenv("TERM", "dumb") // Set the TERM environment variable | |
c := exec.Command("/bin/bash") | |
p, err := pty.Start(c) | |
if err != nil { | |
fyne.LogError("Failed to open pty", err) | |
os.Exit(1) | |
} | |
defer c.Process.Kill() | |
// Callback function that handles special keypresses | |
onTypedKey := func(e *fyne.KeyEvent) { | |
if e.Name == fyne.KeyEnter || e.Name == fyne.KeyReturn { | |
_, _ = p.Write([]byte{'\r'}) | |
} | |
} | |
// Callback function that handles character keypresses | |
onTypedRune := func(r rune) { | |
_, _ = p.WriteString(string(r)) | |
} | |
w.Canvas().SetOnTypedKey(onTypedKey) | |
w.Canvas().SetOnTypedRune(onTypedRune) | |
buffer := [][]rune{} | |
reader := bufio.NewReader(p) | |
// Goroutine that reads from pty | |
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) | |
} | |
} | |
}() | |
// Goroutine that renders to UI | |
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)) | |
} | |
}() | |
// Create a new container with a wrapped layout | |
// set the layout width to 900, height to 325 | |
w.SetContent( | |
container.New( | |
layout.NewGridWrapLayout(fyne.NewSize(1024, 480)), | |
ui, | |
), | |
) | |
w.ShowAndRun() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment