mirror of
https://github.com/paradoxxxzero/butterfly.git
synced 2026-05-31 09:29:40 +00:00
And... done
This commit is contained in:
@@ -3,7 +3,6 @@ import os
|
||||
import io
|
||||
import sys
|
||||
import struct
|
||||
import signal
|
||||
import fcntl
|
||||
import termios
|
||||
import tornado.websocket
|
||||
@@ -24,9 +23,7 @@ class Index(Route):
|
||||
@url(r'/ws')
|
||||
class TermWebSocket(Route, tornado.websocket.WebSocketHandler):
|
||||
|
||||
def open(self):
|
||||
self.log.info('Websocket opened')
|
||||
|
||||
def pty(self):
|
||||
pid, fd = pty.fork()
|
||||
if pid == 0:
|
||||
# Child
|
||||
@@ -79,10 +76,22 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler):
|
||||
)
|
||||
ioloop.add_handler(fd, self.shell, ioloop.READ)
|
||||
|
||||
def open(self):
|
||||
self.log.info('Websocket opened')
|
||||
self.pty()
|
||||
|
||||
def on_message(self, message):
|
||||
self.log.info('WRIT<%s' % message)
|
||||
self.writer.write(message)
|
||||
self.writer.flush()
|
||||
if message.startswith('RS|'):
|
||||
message = message[3:]
|
||||
cols, rows = map(int, message.split(','))
|
||||
s = struct.pack("HHHH", rows, cols, 0, 0)
|
||||
fcntl.ioctl(self.fd, termios.TIOCSWINSZ, s)
|
||||
self.log.info('SIZE (%d, %d)' % (cols, rows))
|
||||
elif message.startswith('SH|'):
|
||||
message = message[3:]
|
||||
self.log.info('WRIT<%r' % message)
|
||||
self.writer.write(message)
|
||||
self.writer.flush()
|
||||
|
||||
def shell(self, fd, events):
|
||||
if events & ioloop.READ:
|
||||
@@ -90,15 +99,16 @@ class TermWebSocket(Route, tornado.websocket.WebSocketHandler):
|
||||
try:
|
||||
read = self.reader.read()
|
||||
except IOError:
|
||||
self.log.info('READ>%s' % read)
|
||||
self.log.info('READ>%r' % read)
|
||||
self.write_message('Exited')
|
||||
return
|
||||
|
||||
self.log.info('READ>%s' % read)
|
||||
self.log.info('READ>%r' % read)
|
||||
self.write_message(read)
|
||||
|
||||
def on_close(self):
|
||||
self.writer.write('')
|
||||
self.writer.flush()
|
||||
os.close(self.fd)
|
||||
os.waitpid(self.pid, 0)
|
||||
self.log.info('Websocket closed')
|
||||
|
||||
@@ -1,27 +1,48 @@
|
||||
ws = null
|
||||
term = ws = null
|
||||
cols = rows = null
|
||||
|
||||
$ ->
|
||||
|
||||
ws = new WebSocket 'ws://' + document.location.host + '/ws'
|
||||
ws.onopen = -> console.log "WebSocket open", arguments
|
||||
ws.onclose = -> console.log "WebSocket closed", arguments
|
||||
ws.onopen = ->
|
||||
console.log "WebSocket open", arguments
|
||||
term = new Terminal(
|
||||
visualBell: true
|
||||
screenKeys: true
|
||||
)
|
||||
term.on "data", (data) ->
|
||||
ws.send 'SH|' + data
|
||||
|
||||
term.on "title", (title) ->
|
||||
document.title = title
|
||||
|
||||
term.open $('main').get(0)
|
||||
$('.terminal').attr('style', '')
|
||||
$(window).trigger 'resize'
|
||||
|
||||
|
||||
ws.onclose = ->
|
||||
if term
|
||||
term.destroy()
|
||||
console.log "WebSocket closed", arguments
|
||||
|
||||
ws.onerror = -> console.log "WebSocket error", arguments
|
||||
ws.onmessage = (event) ->
|
||||
$('.term code').html($('.term code').html() + event.data)
|
||||
term.write event.data
|
||||
|
||||
$('html,body').on('keypress', (event) ->
|
||||
code = event.keyCode
|
||||
ws.send(String.fromCharCode(code))
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
return false
|
||||
).on('keydown', (event) ->
|
||||
code = event.keyCode
|
||||
return if code == 17
|
||||
if event.ctrlKey
|
||||
code -= 64
|
||||
ws.send(String.fromCharCode(code))
|
||||
$(window).resize ->
|
||||
$main = $('main')
|
||||
$termtest = $('<div>').addClass('terminal')
|
||||
$test = $('<div>').css(display: 'inline-block').text('0123456789')
|
||||
$termtest.append($test)
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
return false
|
||||
)
|
||||
$main.append($termtest)
|
||||
ew = $test.outerWidth() / 10
|
||||
eh = $test.outerHeight()
|
||||
$termtest.remove()
|
||||
w = $main.outerWidth()
|
||||
h = $main.outerHeight()
|
||||
cols = Math.floor(w / ew)
|
||||
rows = Math.floor(h / eh)
|
||||
term.resize cols, rows
|
||||
ws.send "RS|#{cols},#{rows}"
|
||||
|
||||
@@ -1,41 +1,57 @@
|
||||
// Generated by CoffeeScript 1.6.3
|
||||
var ws;
|
||||
var cols, rows, term, ws;
|
||||
|
||||
ws = null;
|
||||
term = ws = null;
|
||||
|
||||
cols = rows = null;
|
||||
|
||||
$(function() {
|
||||
ws = new WebSocket('ws://' + document.location.host + '/ws');
|
||||
ws.onopen = function() {
|
||||
return console.log("WebSocket open", arguments);
|
||||
console.log("WebSocket open", arguments);
|
||||
term = new Terminal({
|
||||
visualBell: true,
|
||||
screenKeys: true
|
||||
});
|
||||
term.on("data", function(data) {
|
||||
return ws.send('SH|' + data);
|
||||
});
|
||||
term.on("title", function(title) {
|
||||
return document.title = title;
|
||||
});
|
||||
term.open($('main').get(0));
|
||||
$('.terminal').attr('style', '');
|
||||
return $(window).trigger('resize');
|
||||
};
|
||||
ws.onclose = function() {
|
||||
if (term) {
|
||||
term.destroy();
|
||||
}
|
||||
return console.log("WebSocket closed", arguments);
|
||||
};
|
||||
ws.onerror = function() {
|
||||
return console.log("WebSocket error", arguments);
|
||||
};
|
||||
ws.onmessage = function(event) {
|
||||
return $('.term code').html($('.term code').html() + event.data);
|
||||
return term.write(event.data);
|
||||
};
|
||||
return $('html,body').on('keypress', function(event) {
|
||||
var code;
|
||||
code = event.keyCode;
|
||||
ws.send(String.fromCharCode(code));
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}).on('keydown', function(event) {
|
||||
var code;
|
||||
code = event.keyCode;
|
||||
if (code === 17) {
|
||||
return;
|
||||
}
|
||||
if (event.ctrlKey) {
|
||||
code -= 64;
|
||||
ws.send(String.fromCharCode(code));
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
return $(window).resize(function() {
|
||||
var $main, $termtest, $test, eh, ew, h, w;
|
||||
$main = $('main');
|
||||
$termtest = $('<div>').addClass('terminal');
|
||||
$test = $('<div>').css({
|
||||
display: 'inline-block'
|
||||
}).text('0123456789');
|
||||
$termtest.append($test);
|
||||
$main.append($termtest);
|
||||
ew = $test.outerWidth() / 10;
|
||||
eh = $test.outerHeight();
|
||||
$termtest.remove();
|
||||
w = $main.outerWidth();
|
||||
h = $main.outerHeight();
|
||||
cols = Math.floor(w / ew);
|
||||
rows = Math.floor(h / eh);
|
||||
term.resize(cols, rows);
|
||||
return ws.send("RS|" + cols + "," + rows);
|
||||
});
|
||||
});
|
||||
|
||||
5756
app/static/javascripts/term.js
Normal file
5756
app/static/javascripts/term.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,20 @@
|
||||
$bg: #222
|
||||
$fg: #ccc
|
||||
|
||||
html, body
|
||||
height: 100%
|
||||
|
||||
body
|
||||
color: #5a5a5a
|
||||
background-color: $bg
|
||||
|
||||
main
|
||||
display: flex
|
||||
height: 100%
|
||||
flex-direction: column
|
||||
|
||||
.term
|
||||
.terminal
|
||||
/* margin: .5em
|
||||
flex: 1
|
||||
code
|
||||
white-space: pre-line
|
||||
|
||||
#prompt
|
||||
border: 1px solid #777
|
||||
font-family: monospace
|
||||
outline: none
|
||||
color: $fg
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
/* line 2, ../sass/main.sass */
|
||||
/* line 4, ../sass/main.sass */
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* line 5, ../sass/main.sass */
|
||||
/* line 7, ../sass/main.sass */
|
||||
body {
|
||||
color: #5a5a5a;
|
||||
background-color: #222222;
|
||||
}
|
||||
/* line 8, ../sass/main.sass */
|
||||
/* line 10, ../sass/main.sass */
|
||||
body main {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
/* line 12, ../sass/main.sass */
|
||||
body main .term {
|
||||
/* line 15, ../sass/main.sass */
|
||||
body main .terminal {
|
||||
/* margin: .5em */
|
||||
flex: 1;
|
||||
}
|
||||
/* line 14, ../sass/main.sass */
|
||||
body main .term code {
|
||||
white-space: pre-line;
|
||||
}
|
||||
/* line 17, ../sass/main.sass */
|
||||
body main #prompt {
|
||||
border: 1px solid #777777;
|
||||
font-family: monospace;
|
||||
outline: none;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
@@ -14,15 +14,12 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<main>
|
||||
<section class="term">
|
||||
<code></code>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
|
||||
<script src="{{ static_url('javascripts/bootstrap.min.js') }}"></script>
|
||||
<script src="{{ static_url('javascripts/term.js') }}"></script>
|
||||
<script src="{{ static_url('javascripts/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user