This commit is contained in:
2026-03-26 20:23:26 +09:00
parent fc41b5bd43
commit 2480aedd9f
4 changed files with 166 additions and 115 deletions

View File

@@ -2,123 +2,13 @@ package main
import (
"os"
"os/exec"
"os/signal"
"syscall"
"github.com/creack/pty"
"tea.kareha.org/lab/kakiko/internal/console"
"tea.kareha.org/lab/kakiko/internal/fep"
"tea.kareha.org/lab/kakiko/internal/skk"
)
var defaultCommand []string = []string{
"/bin/sh",
}
func main() {
var cmd []string
if len(os.Args) > 1 {
cmd = os.Args[1:]
} else {
cmd = defaultCommand
}
var c *exec.Cmd
if len(cmd) < 2 {
c = exec.Command(cmd[0])
} else {
c = exec.Command(cmd[0], cmd[1:]...)
}
ptmx, err := pty.Start(c)
if err != nil {
panic(err)
}
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGWINCH)
go func() {
for range ch {
rows, cols, err := pty.Getsize(os.Stdin)
if err != nil {
panic(err)
}
pty.Setsize(ptmx, &pty.Winsize{
Rows: uint16(rows - 1),
Cols: uint16(cols),
})
}
}()
rows, cols, err := pty.Getsize(os.Stdin)
if err != nil {
panic(err)
}
pty.Setsize(ptmx, &pty.Winsize{
Rows: uint16(rows - 1),
Cols: uint16(cols),
})
console.ScrollRange(0, rows-1)
defer console.ScrollRange(0, rows)
console.Clear()
console.HomeCursor()
console.Raw()
defer func() {
console.Clear()
console.HomeCursor()
console.Cooked()
console.ShowCursor()
}()
go func() {
for {
b := make([]byte, 1)
n, err := os.Stdin.Read(b)
if err != nil {
return
}
if n == 0 {
continue
}
processed := skkProcess(b)
_, err = ptmx.Write(processed)
if err != nil {
return
}
}
}()
go func() {
c.Wait()
os.Exit(0)
}()
buf := make([]byte, 1024)
for {
n, err := ptmx.Read(buf)
if err != nil {
return
}
os.Stdout.Write(buf[:n])
drawStatus()
}
}
func drawStatus() {
_, h := console.Size()
console.SaveCursor()
console.HideCursor()
console.MoveCursor(0, h-1)
console.Print("Hello, World!")
console.ShowCursor()
console.LoadCursor()
}
func skkProcess(b []byte) []byte {
return b
f := fep.Init(os.Args, skk.Process, skk.Status)
defer f.Finish()
f.Main()
}

View File

@@ -26,6 +26,7 @@ func Cooked() {
panic("invalid state")
}
term.Restore(int(os.Stdin.Fd()), state)
state = nil
}
func Clear() {
@@ -75,3 +76,7 @@ func LoadCursor() {
func ScrollRange(top, bottom int) {
fmt.Printf("\x1b[%d;%dr", top+1, bottom)
}
func ClearLine() {
fmt.Print("\x1b[K")
}

138
internal/fep/fep.go Normal file
View File

@@ -0,0 +1,138 @@
package fep
import (
"os"
"os/exec"
"os/signal"
"syscall"
"github.com/creack/pty"
"tea.kareha.org/lab/kakiko/internal/console"
)
type Process func(b []byte) []byte
type Status func() string
const defaultCommand = "/bin/sh"
const bufferSize = 1024
type FEP struct {
fd *os.File
process Process
status Status
}
func (f *FEP) updateSize() {
rows, cols, err := pty.Getsize(os.Stdin)
if err != nil {
panic(err)
}
pty.Setsize(f.fd, &pty.Winsize{
Rows: uint16(rows - 1),
Cols: uint16(cols),
})
}
func Init(args []string, process Process, status Status) *FEP {
var command string = defaultCommand
var arguments []string
if len(args) > 1 {
command = args[1]
}
if len(args) > 2 {
arguments = args[2:]
}
var c = exec.Command(command, arguments...)
fd, err := pty.Start(c)
if err != nil {
panic(err)
}
f := &FEP{
fd: fd,
process: process,
status: status,
}
f.updateSize()
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGWINCH)
go func() {
for range ch {
f.updateSize()
}
}()
_, h := console.Size()
console.ScrollRange(0, h-1)
console.Clear()
console.HomeCursor()
console.Raw()
go func() {
for {
b := make([]byte, 1)
n, err := os.Stdin.Read(b)
if err != nil {
return
}
if n == 0 {
continue
}
processed := f.process(b)
_, err = fd.Write(processed)
if err != nil {
return
}
}
}()
go func() {
c.Wait()
os.Exit(0)
}()
return f
}
func (f *FEP) Finish() {
_, h := console.Size()
console.ScrollRange(0, h)
console.Clear()
console.HomeCursor()
console.Cooked()
console.ShowCursor()
}
func (f *FEP) drawStatus() {
_, h := console.Size()
console.SaveCursor()
console.HideCursor()
console.MoveCursor(0, h-1)
status := f.status()
console.Print(status)
console.ClearLine()
console.ShowCursor()
console.LoadCursor()
}
func (f *FEP) Main() {
buf := make([]byte, bufferSize)
for {
n, err := f.fd.Read(buf)
if err != nil {
return
}
os.Stdout.Write(buf[:n])
f.drawStatus()
}
}

18
internal/skk/skk.go Normal file
View File

@@ -0,0 +1,18 @@
package skk
import (
"fmt"
)
// XXX dummy
var count int = 0
func Process(b []byte) []byte {
count++ // XXX dummy
return b
}
func Status() string {
// XXX dummy
return fmt.Sprintf("Hello, World! (%d)", count)
}