Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Created March 14, 2019 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterhellberg/8da1f8d13c76d7fbf710cf1af1c9de03 to your computer and use it in GitHub Desktop.
Save peterhellberg/8da1f8d13c76d7fbf710cf1af1c9de03 to your computer and use it in GitHub Desktop.
s3270 package for Go, based on https://github.com/msalcantara/go3270
package s3270
import (
"fmt"
"log"
"os/exec"
"strings"
"time"
)
const (
Enter = "Enter"
Tab = "Tab"
F1 = "PF(1)"
F2 = "PF(2)"
F3 = "PF(3)"
F4 = "PF(4)"
F5 = "PF(5)"
F6 = "PF(6)"
F7 = "PF(7)"
F8 = "PF(8)"
F9 = "PF(9)"
F10 = "PF(10)"
F11 = "PF(11)"
F12 = "PF(12)"
)
var (
ErrNoAddr = fmt.Errorf("no Addr specified")
ErrAlreadyConnected = fmt.Errorf("already connected")
)
func NewEmulator(addr, scriptPort string) Emulator {
return Emulator{
Addr: addr,
ScriptPort: scriptPort,
}
}
type Emulator struct {
Addr string
ScriptPort string
}
func (e *Emulator) Connect() error {
if e.Addr == "" {
return ErrNoAddr
}
if e.IsConnected() {
return ErrAlreadyConnected
}
if e.ScriptPort == "" {
e.ScriptPort = "5000"
}
e.connect()
if !e.IsConnected() {
e.exec("quit")
log.Fatalf("error connecting to %s", e.Addr)
}
return nil
}
func (e *Emulator) Disconnect() error {
if e.IsConnected() {
return e.exec("quit")
}
time.Sleep(time.Second)
return nil
}
func (e *Emulator) ConnectionState() (string, error) {
return e.query("ConnectionState")
}
func (e *Emulator) IsConnected() bool {
if s, err := e.ConnectionState(); err != nil || len(strings.TrimSpace(s)) == 0 {
return false
}
return true
}
func (e *Emulator) FillString(x, y int, value string) error {
if err := e.MoveCursor(x, y); err != nil {
return fmt.Errorf("move cursor error: %v", err)
}
return e.SetString(value)
}
func (e *Emulator) SetString(value string) error {
return e.exec(command("String(%s)", value))
}
func (e *Emulator) Press(key string) error {
if !e.validaKeyboard(key) {
return fmt.Errorf("invalid key %s", key)
}
return e.exec(key)
}
func (e *Emulator) Value(x, y, l int) (string, error) {
return e.execOutput(command("Ascii(%d,%d,%d)", x, y, l))
}
func (e *Emulator) Cursor() (string, error) {
return e.query("cursor")
}
func (e *Emulator) MoveCursor(x, y int) error {
return e.exec(command("MoveCursor(%d,%d)", x, y))
}
func (e *Emulator) validaKeyboard(key string) bool {
switch key {
case Tab:
return true
case Enter:
return true
default:
return false
}
}
func (e *Emulator) query(keyword string) (string, error) {
return e.execOutput(command("query(%s)", keyword))
}
func (e *Emulator) connect() {
cmd := exec.Command("s3270", "-scriptport", e.ScriptPort, e.Addr)
cmd.Start()
go func() {
if err := cmd.Wait(); err != nil {
log.Fatalf("error to create an instance of 3270\n%v\n", err)
}
}()
time.Sleep(4 * time.Second)
}
func (e *Emulator) exec(arg string) error {
if err := exec.Command("x3270if", "-t", e.ScriptPort, arg).Run(); err != nil {
return err
}
return nil
}
func (e *Emulator) execOutput(arg string) (string, error) {
b, err := exec.Command("x3270if", "-t", e.ScriptPort, arg).Output()
if err != nil {
return "", err
}
return string(b), nil
}
func command(format string, a ...interface{}) string {
return fmt.Sprintf(format, a...)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment