mirror of
https://github.com/sorenisanerd/gotty.git
synced 2024-11-22 12:24:25 +00:00
Set window title by control message
This commit is contained in:
parent
67b54b7f20
commit
a765d6c660
6
Makefile
6
Makefile
@ -3,7 +3,7 @@ gotty: app/resource.go main.go app/*.go
|
|||||||
|
|
||||||
resource: app/resource.go
|
resource: app/resource.go
|
||||||
|
|
||||||
app/resource.go: bindata/static/hterm.js bindata/static/gotty.js bindata/templates/index.html
|
app/resource.go: bindata/static/hterm.js bindata/static/gotty.js bindata/static/index.html
|
||||||
go-bindata -prefix bindata -pkg app -ignore=\\.gitkeep -o app/resource.go bindata/...
|
go-bindata -prefix bindata -pkg app -ignore=\\.gitkeep -o app/resource.go bindata/...
|
||||||
gofmt -w app/resource.go
|
gofmt -w app/resource.go
|
||||||
|
|
||||||
@ -23,5 +23,5 @@ bindata/static/hterm.js: bindata/static libapps/hterm/js/*.js
|
|||||||
bindata/static/gotty.js: bindata/static resources/gotty.js
|
bindata/static/gotty.js: bindata/static resources/gotty.js
|
||||||
cp resources/gotty.js bindata/static/gotty.js
|
cp resources/gotty.js bindata/static/gotty.js
|
||||||
|
|
||||||
bindata/templates/index.html: bindata/templates resources/index.html
|
bindata/static/index.html: bindata/static resources/index.html
|
||||||
cp resources/index.html bindata/templates/index.html
|
cp resources/index.html bindata/static/index.html
|
||||||
|
53
app/app.go
53
app/app.go
@ -1,19 +1,17 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
htemplate "html/template"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
ttemplate "text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/elazarl/go-bindata-assetfs"
|
"github.com/elazarl/go-bindata-assetfs"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@ -23,7 +21,8 @@ import (
|
|||||||
type App struct {
|
type App struct {
|
||||||
options Options
|
options Options
|
||||||
|
|
||||||
upgrader *websocket.Upgrader
|
upgrader *websocket.Upgrader
|
||||||
|
titleTemplate *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
@ -36,7 +35,12 @@ type Options struct {
|
|||||||
Command []string
|
Command []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(options Options) *App {
|
func New(options Options) (*App, error) {
|
||||||
|
titleTemplate, err := template.New("title").Parse(options.TitleFormat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Title format string syntax error")
|
||||||
|
}
|
||||||
|
|
||||||
return &App{
|
return &App{
|
||||||
options: options,
|
options: options,
|
||||||
|
|
||||||
@ -45,7 +49,8 @@ func New(options Options) *App {
|
|||||||
WriteBufferSize: 1024,
|
WriteBufferSize: 1024,
|
||||||
Subprotocols: []string{"gotty"},
|
Subprotocols: []string{"gotty"},
|
||||||
},
|
},
|
||||||
}
|
titleTemplate: titleTemplate,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) Run() error {
|
func (app *App) Run() error {
|
||||||
@ -56,15 +61,13 @@ func (app *App) Run() error {
|
|||||||
|
|
||||||
endpoint := app.options.Address + ":" + app.options.Port
|
endpoint := app.options.Address + ":" + app.options.Port
|
||||||
|
|
||||||
indexHandler := http.HandlerFunc(app.handleIndex)
|
|
||||||
wsHandler := http.HandlerFunc(app.handleWS)
|
wsHandler := http.HandlerFunc(app.handleWS)
|
||||||
staticHandler := http.FileServer(
|
staticHandler := http.FileServer(
|
||||||
&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "static"},
|
&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "static"},
|
||||||
)
|
)
|
||||||
|
|
||||||
var siteMux = http.NewServeMux()
|
var siteMux = http.NewServeMux()
|
||||||
siteMux.Handle(path+"/", indexHandler)
|
siteMux.Handle(path+"/", http.StripPrefix(path+"/", staticHandler))
|
||||||
siteMux.Handle(path+"/static/", http.StripPrefix(path+"/static/", staticHandler))
|
|
||||||
siteMux.Handle(path+"/ws", wsHandler)
|
siteMux.Handle(path+"/ws", wsHandler)
|
||||||
|
|
||||||
siteHandler := http.Handler(siteMux)
|
siteHandler := http.Handler(siteMux)
|
||||||
@ -94,36 +97,6 @@ func (app *App) Run() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type TitleVars struct {
|
|
||||||
Command string
|
|
||||||
Hostname string
|
|
||||||
}
|
|
||||||
|
|
||||||
type IndexVars struct {
|
|
||||||
Title string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) handleIndex(w http.ResponseWriter, r *http.Request) {
|
|
||||||
title := make([]byte, 0)
|
|
||||||
titleBuf := bytes.NewBuffer(title)
|
|
||||||
hostname, _ := os.Hostname()
|
|
||||||
titleVars := TitleVars{
|
|
||||||
Command: strings.Join(app.options.Command, " "),
|
|
||||||
Hostname: hostname,
|
|
||||||
}
|
|
||||||
titleTmpl, _ := ttemplate.New("title").Parse(app.options.TitleFormat)
|
|
||||||
titleTmpl.Execute(titleBuf, titleVars)
|
|
||||||
|
|
||||||
data, _ := Asset("templates/index.html")
|
|
||||||
tmpl, _ := htemplate.New("index").Parse(string(data))
|
|
||||||
|
|
||||||
vars := IndexVars{
|
|
||||||
Title: titleBuf.String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl.Execute(w, vars)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) handleWS(w http.ResponseWriter, r *http.Request) {
|
func (app *App) handleWS(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("New client connected: %s", r.RemoteAddr)
|
log.Printf("New client connected: %s", r.RemoteAddr)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@ -26,11 +27,23 @@ const (
|
|||||||
ResizeTerminal = '1'
|
ResizeTerminal = '1'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Output = '0'
|
||||||
|
SetWindowTitle = '1'
|
||||||
|
)
|
||||||
|
|
||||||
type argResizeTerminal struct {
|
type argResizeTerminal struct {
|
||||||
Columns float64
|
Columns float64
|
||||||
Rows float64
|
Rows float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ContextVars struct {
|
||||||
|
Command string
|
||||||
|
Pid int
|
||||||
|
Hostname string
|
||||||
|
RemoteAddr string
|
||||||
|
}
|
||||||
|
|
||||||
func (context *clientContext) goHandleClient() {
|
func (context *clientContext) goHandleClient() {
|
||||||
exit := make(chan bool, 2)
|
exit := make(chan bool, 2)
|
||||||
|
|
||||||
@ -56,6 +69,11 @@ func (context *clientContext) goHandleClient() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (context *clientContext) processSend() {
|
func (context *clientContext) processSend() {
|
||||||
|
if err := context.sendInitialize(); err != nil {
|
||||||
|
log.Printf(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
utf8f := utf8reader.New(context.pty)
|
utf8f := utf8reader.New(context.pty)
|
||||||
|
|
||||||
@ -71,11 +89,34 @@ func (context *clientContext) processSend() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer.Write([]byte{Output})
|
||||||
writer.Write(buf[:size])
|
writer.Write(buf[:size])
|
||||||
writer.Close()
|
writer.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (context *clientContext) sendInitialize() error {
|
||||||
|
hostname, _ := os.Hostname()
|
||||||
|
titleVars := ContextVars{
|
||||||
|
Command: strings.Join(context.app.options.Command, " "),
|
||||||
|
Pid: context.command.Process.Pid,
|
||||||
|
Hostname: hostname,
|
||||||
|
RemoteAddr: context.request.RemoteAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
writer, err := context.connection.NextWriter(websocket.TextMessage)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
writer.Write([]byte{SetWindowTitle})
|
||||||
|
if err = context.app.titleTemplate.Execute(writer, titleVars); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
writer.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (context *clientContext) processReceive() {
|
func (context *clientContext) processReceive() {
|
||||||
for {
|
for {
|
||||||
_, data, err := context.connection.ReadMessage()
|
_, data, err := context.connection.ReadMessage()
|
||||||
|
File diff suppressed because one or more lines are too long
10
main.go
10
main.go
@ -56,7 +56,8 @@ func main() {
|
|||||||
cli.ShowAppHelp(c)
|
cli.ShowAppHelp(c)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
app := app.New(
|
|
||||||
|
app, err := app.New(
|
||||||
app.Options{
|
app.Options{
|
||||||
c.String("addr"),
|
c.String("addr"),
|
||||||
c.String("port"),
|
c.String("port"),
|
||||||
@ -67,11 +68,16 @@ func main() {
|
|||||||
c.Args(),
|
c.Args(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
err := app.Run()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = app.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cli.AppHelpTemplate = helpTemplate
|
cli.AppHelpTemplate = helpTemplate
|
||||||
|
@ -38,7 +38,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ws.onmessage = function(event) {
|
ws.onmessage = function(event) {
|
||||||
term.io.writeUTF16(event.data);
|
data = event.data.slice(1);
|
||||||
|
switch(event.data[0]) {
|
||||||
|
case '0':
|
||||||
|
term.io.writeUTF16(data);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
term.setWindowTitle(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.onclose = function(event) {
|
ws.onclose = function(event) {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>{{ .Title }}</title>
|
<title>GoTTY</title>
|
||||||
<style>body {position: absolute; height: 100%; width: 100%; margin: 0px;}</style>
|
<style>body {position: absolute; height: 100%; width: 100%; margin: 0px;}</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="static/hterm.js"></script>
|
<script src="hterm.js"></script>
|
||||||
<script src="static/gotty.js"></script>
|
<script src="gotty.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user