Skip to content

Instantly share code, notes, and snippets.

@garvit-exe
Last active October 31, 2024 14:17
Show Gist options
  • Save garvit-exe/f2a87129b521434668716a3880b3b15d to your computer and use it in GitHub Desktop.
Save garvit-exe/f2a87129b521434668716a3880b3b15d to your computer and use it in GitHub Desktop.
Terminal Emulator using Go (Pseudo Teletype)
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()
}

TERMINAL EMULATOR WRITTEN IN GOLANG

SUMMARY

DEMO

ScreenRecording2024-10-31at19 20 38-ezgif com-speed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment