Skip to content

Instantly share code, notes, and snippets.

@ggilder
Created July 30, 2014 07:45
Show Gist options
  • Save ggilder/ccd4577dd6dfabac1da2 to your computer and use it in GitHub Desktop.
Save ggilder/ccd4577dd6dfabac1da2 to your computer and use it in GitHub Desktop.
selecta (go)
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
)
const (
KEY_CTRL_C = "\u0003"
KEY_CTRL_N = "\u000E"
KEY_CTRL_P = "\u0010"
KEY_CTRL_U = "\u0015"
KEY_CTRL_H = "\b"
KEY_CTRL_W = "\u0017"
KEY_CTRL_J = "\n"
KEY_CTRL_M = "\r"
KEY_DELETE = "\x7F"
)
type choiceWindow struct {
choices []string
visibleChoices int
}
type ttyDevice struct {
inFile *os.File
outFile *os.File
}
type Screen struct {
tty ttyDevice
ansi ansiThingy
originalSttyState string
}
type ansiThingy struct {
outFile *os.File
}
func main() {
// c1 := exec.Command("ls")
// c2 := exec.Command("wc", "-l")
// c2.Stdin, _ = c1.StdoutPipe()
// c2.Stdout = os.Stdout
// _ = c2.Start()
// _ = c1.Run()
// _ = c2.Wait()
// TODO make real
screenHeight := 80
screen, tty := startScreen()
choiceWindow := choiceWindowFromStdin(screenHeight)
runInScreen(choiceWindow, screen, tty)
search := stopScreen(screen, tty)
if len(search) > 0 {
fmt.Println(search)
}
}
func check(e error) {
if e != nil {
panic(e)
}
}
func startScreen() (screen Screen, tty ttyDevice) {
inFile, err := os.Open("/dev/tty")
check(err)
outFile, err := os.Create("/dev/tty")
check(err)
tty = ttyDevice{inFile, outFile}
screen = Screen{tty: tty}
screen.configureTty()
// ScreenValidator.raise_unless_screen_is_valid(screen.height)
return screen, tty
}
// TODO finish this function
func stopScreen(screen Screen, tty ttyDevice) (search string) {
screen.restoreTty()
tty.puts
tty.inFile.Close()
tty.outFile.Close()
}
// TODO this one too
func runInScreen(window choiceWindow, screen Screen, tty ttyDevice) {
}
func choiceWindowFromStdin(screenHeight int) choiceWindow {
choices := []string{}
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
choices = append(choices, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
visible := 20
if visible > (screenHeight - 1) {
visible = screenHeight - 1
}
return choiceWindow{choices, visible}
}
func (s *Screen) configureTty() {
s.ansi = ansiThingy{s.tty.outFile}
s.originalSttyState = s.tty.stty("-g")
// -echo: terminal doesn't echo typed characters back to the terminal
// -icanon: terminal doesn't interpret special characters (like backspace)
s.tty.stty("-echo -icanon")
}
func (s *Screen) restoreTty() {
s.tty.stty(s.originalSttyState)
}
// TODO this needs to return a string somehow wtf huh?
func (t *ttyDevice) stty(text string) {
cmd := exec.Command("stty", text)
r, w := io.Pipe()
defer w.Close()
defer r.Close()
var err error
cmd.Stdin, err = os.Open("/dev/tty")
check(err)
cmd.Stdout = w
err = cmd.Start()
cmd.Wait()
if !cmd.ProcessState.Success() {
panic("Command failed: stty " + text)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment