Created
July 30, 2014 07:45
-
-
Save ggilder/ccd4577dd6dfabac1da2 to your computer and use it in GitHub Desktop.
selecta (go)
This file contains 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" | |
"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