From 0f7a51d4514c352411df9dc0c08c026327cd5f1d Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Wed, 7 Oct 2015 16:03:32 +0200 Subject: [PATCH] Add a default conf file. Handle themes in a far more intelligent way by adding a popup and saving conf in localStorage. --- butterfly.server.py | 93 ++++++++++++++++++---- butterfly/bin/btheme | 96 ----------------------- butterfly/bin/butterfly_help | 32 ++++---- butterfly/butterfly.conf.default | 58 ++++++++++++++ butterfly/routes.py | 115 ++++++++++++++++----------- butterfly/sass/_layout.sass | 26 +++++++ butterfly/static/ext.js | 129 ++++++++++++++++++++++++++++++- butterfly/static/ext.min.js | 4 +- butterfly/static/main.css | 25 +++++- butterfly/static/main.js | 15 +--- butterfly/static/main.min.js | 6 +- butterfly/templates/index.html | 4 +- coffees/ext/popup.coffee | 35 +++++++++ coffees/ext/theme.coffee | 70 +++++++++++++++++ coffees/main.coffee | 2 - coffees/term.coffee | 14 +--- setup.py | 4 +- 17 files changed, 516 insertions(+), 212 deletions(-) delete mode 100755 butterfly/bin/btheme create mode 100644 butterfly/butterfly.conf.default create mode 100644 coffees/ext/popup.coffee create mode 100644 coffees/ext/theme.coffee diff --git a/butterfly.server.py b/butterfly.server.py index 3311286..15f2051 100755 --- a/butterfly.server.py +++ b/butterfly.server.py @@ -26,6 +26,7 @@ import uuid import ssl import getpass import os +import shutil import stat import socket import sys @@ -33,6 +34,9 @@ import sys tornado.options.define("debug", default=False, help="Debug mode") tornado.options.define("more", default=False, help="Debug mode with more verbosity") +tornado.options.define("unminified", default=False, + help="Use the unminified js (for development only)") + tornado.options.define("host", default='localhost', help="Server host") tornado.options.define("port", default=57575, type=int, help="Server port") tornado.options.define("shell", help="Shell to execute at login") @@ -41,12 +45,12 @@ tornado.options.define("cmd", help="Command to run instead of shell, f.i.: 'ls -l'") tornado.options.define("unsecure", default=False, help="Don't use ssl not recommended") +tornado.options.define("login", default=True, + help="Use login screen at start") tornado.options.define("force_unicode_width", default=False, help="Force all unicode characters to the same width." "Useful for avoiding layout mess.") -tornado.options.define("login", default=True, - help="Use login screen at start") tornado.options.define("ssl_version", default=None, help="SSL protocol version") tornado.options.define("generate_certs", default=False, @@ -57,19 +61,33 @@ tornado.options.define("generate_current_user_pkcs", default=False, tornado.options.define("generate_user_pkcs", default='', help="Generate user pfx for client authentication " "(Must be root to create for another user)") -tornado.options.define("unminified", default=False, - help="Use the unminified js (for development only)") -tornado.options.define("theme", default=None, - help="Specify a theme for butterfly.") +tornado.options.define("install_themes", default=False, + help="Install or update themes from butterfly-themes") +tornado.options.define("install_themes_from", + default='https://github.com/paradoxxxzero/' + 'butterfly-themes/archive/master.zip', + help="Url to download themes from") if os.getuid() == 0: - conf_file = os.path.join( - os.path.abspath(os.sep), 'etc', 'butterfly', 'butterfly.conf') - ssl_dir = os.path.join(os.path.abspath(os.sep), 'etc', 'butterfly', 'ssl') + ev = os.getenv('XDG_CONFIG_DIRS', '/etc') else: - conf_file = os.path.join( - os.path.expanduser('~'), '.butterfly', 'butterfly.conf') - ssl_dir = os.path.join(os.path.expanduser('~'), '.butterfly', 'ssl') + ev = os.getenv( + 'XDG_CONFIG_HOME', os.path.join(os.getenv('HOME'), '.config')) + +butterfly_dir = os.path.join(ev, 'butterfly') +conf_file = os.path.join(butterfly_dir, 'butterfly.conf') +ssl_dir = os.path.join(butterfly_dir, 'ssl') + +if not os.path.exists(conf_file): + try: + shutil.copy( + os.path.join( + os.path.abspath(os.path.dirname(__file__)), + 'butterfly', + 'butterfly.conf.default'), conf_file) + print('butterfly.conf installed in %s' % conf_file) + except: + pass tornado.options.define("conf", default=conf_file, help="Butterfly configuration file. " @@ -78,11 +96,15 @@ tornado.options.define("conf", default=conf_file, tornado.options.define("ssl_dir", default=ssl_dir, help="Force SSL directory location") +# Do it once to get the conf path tornado.options.parse_command_line() if os.path.exists(tornado.options.options.conf): tornado.options.parse_config_file(tornado.options.options.conf) +# Do it again to overwrite conf with args +tornado.options.parse_command_line() + options = tornado.options.options for logger in ('tornado.access', 'tornado.application', @@ -95,7 +117,49 @@ for logger in ('tornado.access', 'tornado.application', logging.getLogger(logger).setLevel(level) log = logging.getLogger('butterfly') -log.info('Starting server') + +if options.install_themes: + from io import BytesIO + from shutil import move, rmtree + from zipfile import ZipFile + from tempfile import mkdtemp + try: + from urllib.request import urlopen + except ImportError: + from urllib import urlopen + try: + import sass as _ + _.CompileError + except Exception: + print('You must install libsass to use themes ' + '(run: pip install libsass)') + sys.exit(1) + themes_url = options.install_themes_from + print('Downloading %s...' % themes_url) + zip_ = ZipFile(BytesIO(urlopen(themes_url).read())) + + print('Extracting in %s' % butterfly_dir) + zip_.extractall(butterfly_dir) + + zip_dest = os.path.join(butterfly_dir, 'butterfly-themes-master') + theme_dir = os.path.join(butterfly_dir, 'themes') + if not os.path.exists(theme_dir): + os.makedirs(theme_dir) + + tmp_dir = mkdtemp() + for dir_ in os.listdir(zip_dest): + if dir_ == 'README.md': + continue + new_dir = os.path.join(theme_dir, dir_) + if os.path.exists(new_dir): + move(new_dir, tmp_dir) + print('Old theme %s has been backed up in %s' % ( + new_dir, tmp_dir)) + move(os.path.join(zip_dest, dir_), theme_dir) + + rmtree(zip_dest) + print('%s extracted.' % theme_dir) + sys.exit(0) host = options.host port = options.port @@ -272,7 +336,8 @@ else: ssl, 'PROTOCOL_%s' % options.ssl_version) from butterfly import application - +application.butterfly_dir = butterfly_dir +log.info('Starting server') http_server = tornado_systemd.SystemdHTTPServer( application, ssl_options=ssl_opts) http_server.listen(port, address=host) diff --git a/butterfly/bin/btheme b/butterfly/bin/btheme deleted file mode 100755 index d9f867b..0000000 --- a/butterfly/bin/btheme +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -import argparse -import os -import sys -try: - from urllib.request import urlopen -except ImportError: - from urllib import urlopen - -from io import BytesIO -from shutil import move, rmtree -from zipfile import ZipFile -from tempfile import mkdtemp -from butterfly.escapes import sass - -try: - import sass as _ - _.CompileError -except Exception: - print('You must install libsass to use themes ' - '(run: pip install libsass)') - sys.exit(1) - -themes_url = ("https://github.com/paradoxxxzero/" - "butterfly-themes/archive/master.zip") - -parser = argparse.ArgumentParser(description='Butterfly session opener.') -parser.add_argument( - '--install', - action="store_true", - help='Install preset themes from ' - 'https://github.com/paradoxxxzero/butterfly-themes') - -parser.add_argument( - '--refresh', - action="store_true", - help='Refresh the current style') - -parser.add_argument( - '-g', - action="store_true", - help='Install system wide for usage with butterfly as daemon') - -parser.add_argument( - 'theme', - nargs='?', - help='Theme to load. ' - 'Can be a sass file or a directory containing a sass file.') -args = parser.parse_args() - -if args.g: - home_dir = os.path.join('/etc', 'butterfly') -else: - home_dir = os.path.expanduser(os.path.join('~', '.butterfly')) - -if args.install: - print('Downloading %s...' % themes_url) - zip_ = ZipFile(BytesIO(urlopen(themes_url).read())) - - print('Extracting in %s' % home_dir) - zip_.extractall(home_dir) - - zip_dest = os.path.join(home_dir, 'butterfly-themes-master') - theme_dir = os.path.join(home_dir, 'themes') - if not os.path.exists(theme_dir): - os.makedirs(theme_dir) - - tmp_dir = mkdtemp() - for dir_ in os.listdir(zip_dest): - if dir_ == 'README.md': - continue - new_dir = os.path.join(theme_dir, dir_) - if os.path.exists(new_dir): - move(new_dir, tmp_dir) - print('Old theme %s has been backed up in %s' % ( - new_dir, tmp_dir)) - move(os.path.join(zip_dest, dir_), theme_dir) - - rmtree(zip_dest) - print('%s extracted.' % theme_dir) - -elif args.refresh: - with sass(): - pass - -else: - sss = os.path.abspath(args.theme or home_dir) - if not os.path.exists(sss): - sss = os.path.join(home_dir, 'themes', args.theme) - if not os.path.exists(sss): - print('%s not found' % sss) - sys.exit(1) - - print('Loading %s' % sss) - with sass(): - sys.stdout.write(sss) diff --git a/butterfly/bin/butterfly_help b/butterfly/bin/butterfly_help index 190918b..589b551 100755 --- a/butterfly/bin/butterfly_help +++ b/butterfly/bin/butterfly_help @@ -3,6 +3,7 @@ from butterfly.escapes import image from butterfly.utils import ansi_colors import os import base64 +import shutil print(ansi_colors.white + "Welcome to the butterfly help." + ansi_colors.reset) with image('image/png'): @@ -17,9 +18,11 @@ Butterfly is a xterm compliant terminal built with python and javascript. {title}Terminal functionalities:{reset} {strong}[Alt] + [a] : {reset}Set an alarm which sends a notification when a modification is detected. {strong}[Ctrl] + [Shift] + [Up] : {reset}Trigger visual selection mode. Hitting [Enter] inserts the selection in the prompt. + {strong}[Alt] + [s] : {reset}Open theme selection prompt. Use [Alt] + [Shift] + [s] to refresh current theme. {strong}[ScrollLock] : {reset}Lock the scrolling to the current position. Press again to release. - {strong}[Alt] + [z] : {reset}Escape: don't catch the next pressed key. Useful for using native search for example. ([Alt] + [z] then [Ctrl] + [f]). {strong}[Ctrl] + [c] <> : {reset}Cut the output when [Ctrl] + [c] is not enough. + {strong}[Alt] + [z] : {reset}Escape: don't catch the next pressed key. + Useful for using native search for example. ([Alt] + [z] then [Ctrl] + [f]). {title}Butterfly programs:{reset} @@ -29,35 +32,26 @@ Butterfly is a xterm compliant terminal built with python and javascript. {strong}b16M : {reset}Test the 16M colors support in terminal. {strong}bhr : {reset}Put a html hr. This is a test for html output. {strong}bcal : {reset}Display current month using html. This is also a test for html output. - {strong}btheme : {reset}Set a theme as current theme. (Can also install preset themes) {title}Styling butterfly:{reset} To style butterfly in sass, you need to have the libsass python library installed. + Install official themes with {code}butterfly.server.py --install-themes{reset} - First check out existing themes, run: - {code}$ btheme --install{reset} - Then try: - {code}$ btheme solarized-dark {comment}# or C64 or abstract-image{reset} - If you want to set a theme as default add a 'theme="theme"' line in your butterfly.conf + Theming is done by overiding the default sass files located in {code}{main}{reset} in a theme directory. + This directory can include images and custom fonts. + Please take a look at official themes here: https://github.com/paradoxxxzero/butterfly-themes + and submit your best themes as pull request! - If you want to style it yourself do: - {code}$ cp {main} ~/.butterfly/style.sass {comment}# or /etc/butterfly/style.sass for system wide{reset} - and then edit this file. - - You can also copy the imported sass files in the same dir. Run: - {code}$ btheme --refresh{reset} - To update the style in the current terminal. - - Finally you can make a theme in the themes directory and submit it to https://github.com/paradoxxxzero/butterfly-themes - - It is also possible to use a style.css file and re do all the styling in css exclusively.\ + \x1b[{rcol}G\x1b[3m{dark}butterfly @ 2015 Mounier Florian{reset}\ """.format( title=ansi_colors.light_blue, + dark=ansi_colors.light_black, strong=ansi_colors.white, code=ansi_colors.light_yellow, comment=ansi_colors.light_magenta, reset=ansi_colors.reset, + rcol=shutil.get_terminal_size()[0] - 31, main=os.path.normpath(os.path.join( os.path.abspath(os.path.dirname(__file__)), - '../sass/main.sass')))) + '../sass/')))) diff --git a/butterfly/butterfly.conf.default b/butterfly/butterfly.conf.default new file mode 100644 index 0000000..1e37de8 --- /dev/null +++ b/butterfly/butterfly.conf.default @@ -0,0 +1,58 @@ +# Butterfly autogenerated config file + +# Activate debug mode +# +#debug=False + +# In debug mode produce more verbose output +# +#more=False + +# Use unminified version of js for development +# +#unminified=False + +# Server host +# Use 'localhost' for local only +# Use your ip to share over your network +# Use '0.0.0.0' to listen to every network +# +#host='localhost' + +# Server port +# +#port=57575 + +# Shell to launch at start (defaults to user shell) +# +#shell=None # shell='/bin/bash' for instance + +# Motd, path to custom message of the day file +# +#motd='motd' + +# Command to run instead of shell +# +#cmd=None # cmd='ls -l' + + +# Unsecure mode +# This mode use http without ssl and is therefore NOT RECOMMENDED +# Please generate yourself a certificate using the butterfly.server.py command +# +#unsecure=False + +# Force user login in unsecure mode +# +#login=False + +# Force unicode width +# This mode force every character to be the same width +# Which can be useful in some case +# But this breaks unicode display of varying width character +# +#force_unicode_width=False + +# SSL version defaults to auto +# +#ssl_version=None diff --git a/butterfly/routes.py b/butterfly/routes.py index 27f6303..b5db666 100644 --- a/butterfly/routes.py +++ b/butterfly/routes.py @@ -20,6 +20,7 @@ import os import sys import tornado.options import tornado.process +import tornado.escape import tornado.web import tornado.websocket from mimetypes import guess_type @@ -42,61 +43,67 @@ class Index(Route): return self.render('index.html') -@url(r'/style.css') -class Style(Route): - - def get(self): - default_style = os.path.join( - os.path.dirname(__file__), 'static', 'main.css') +@url(r'/theme/([^/]+)/style.css') +class Theme(Route): + def get(self, theme): self.log.info('Getting style') - css = utils.get_style() + try: + import sass + sass.CompileError + except Exception: + self.log.error( + 'You must install libsass to use sass ' + '(pip install libsass)') + return + + themes_dir = os.path.join( + self.application.butterfly_dir, 'themes') + base_dir = os.path.join(themes_dir, theme) + style = None + for ext in ['css', 'scss', 'sass']: + probable_style = os.path.join(base_dir, 'style.%s' % ext) + if os.path.exists(probable_style): + style = probable_style + + if not style: + raise tornado.web.HTTPError(404) + + sass_path = os.path.join( + os.path.dirname(__file__), 'sass') + + css = None + try: + css = sass.compile(filename=style, include_paths=[ + base_dir, sass_path]) + except sass.CompileError: + self.log.error( + 'Unable to compile style (filename: %s, paths: %r) ' % ( + style, [base_dir, sass_path]), exc_info=True) + if not style: + raise tornado.web.HTTPError(500) + self.log.debug('Style ok') - self.set_header("Content-Type", "text/css") - - if css: - self.write(css) - else: - with open(default_style) as s: - while True: - data = s.read(16384) - if data: - self.write(data) - else: - break + self.write(css) self.finish() -@url(r'/theme/font/([^/]+)') -class ThemeFont(Route): +@url(r'/theme/([^/]+)/(.+)') +class ThemeStatic(Route): - def get(self, name): - if not tornado.options.options.theme or not name: - raise tornado.web.HTTPError(404) - fn = os.path.join( - os.path.dirname(utils.get_style_path()), 'font', name) - if os.path.exists(fn): - self.set_header("Content-Type", guess_type(fn)[0]) - with open(fn, 'rb') as s: - while True: - data = s.read(16384) - if data: - self.write(data) - else: - break - self.finish() - raise tornado.web.HTTPError(404) + def get(self, theme, name): + if '..' in name: + raise tornado.web.HTTPError(403) + themes_dir = os.path.join( + self.application.butterfly_dir, 'themes') + base_dir = os.path.join(themes_dir, theme) -@url(r'/theme/image/([^/]+)') -class ThemeImage(Route): + fn = os.path.normpath(os.path.join(base_dir, name)) + if not fn.startswith(base_dir): + raise tornado.web.HTTPError(403) - def get(self, name): - if not tornado.options.options.theme or not name: - raise tornado.web.HTTPError(404) - fn = os.path.join( - os.path.dirname(utils.get_style_path()), 'image', name) if os.path.exists(fn): self.set_header("Content-Type", guess_type(fn)[0]) with open(fn, 'rb') as s: @@ -115,7 +122,7 @@ class ThemeImage(Route): '(?:session/(?P[^/]+))?/?' '(?:/wd/(?P.+))?') class TermWebSocket(Route, tornado.websocket.WebSocketHandler): - session_history_size = 100000 + session_history_size = 50000 # List of websockets per session per user # dict: user -> dict: session -> [TermWebSocket] sessions = defaultdict(dict) @@ -299,3 +306,21 @@ class Sessions(Route): return self.render( 'list.html', sessions=TermWebSocket.sessions.get(user, [])) + + +@url(r'/themes/list.json') +class ThemesList(Route): + """Get the theme list""" + + def get(self): + themes_dir = os.path.join( + self.application.butterfly_dir, 'themes') + self.set_header('Content-Type', 'application/json') + self.write(tornado.escape.json_encode({ + 'themes': sorted( + [theme + for theme in os.listdir(themes_dir) + if os.path.isdir(os.path.join(themes_dir, theme)) and + not theme.startswith('.')]), + 'dir': themes_dir + })) diff --git a/butterfly/sass/_layout.sass b/butterfly/sass/_layout.sass index f810802..a63590c 100644 --- a/butterfly/sass/_layout.sass +++ b/butterfly/sass/_layout.sass @@ -38,5 +38,31 @@ body &::-webkit-scrollbar-thumb:hover background: rgba($fg, .15) + /* Pop ups */ + .hidden + display: none + + #popup + position: fixed + display: flex + align-items: center + justify-content: center + width: 100% + height: 100% + + form + padding: 1.5em + background: rgba(127, 127, 127, .5) + h2 + margin: .5em + select + min-width: 300px + padding: .5em + width: 100% + label + display: block + padding: .5em + font-size: .75em + .terminal outline: none diff --git a/butterfly/static/ext.js b/butterfly/static/ext.js index 24db8a8..0383392 100644 --- a/butterfly/static/ext.js +++ b/butterfly/static/ext.js @@ -1,5 +1,5 @@ (function() { - var Selection, alt, cancel, copy, ctrl, first, nextLeaf, previousLeaf, selection, setAlarm, virtualInput, + var Popup, Selection, _set_theme_href, _theme, alt, cancel, copy, ctrl, first, nextLeaf, popup, previousLeaf, selection, setAlarm, virtualInput, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; setAlarm = function(notification) { @@ -77,6 +77,54 @@ return e.preventDefault(); }); + Popup = (function() { + function Popup() { + this.el = document.getElementById('popup'); + this.bound_click_maybe_close = this.click_maybe_close.bind(this); + this.bound_key_maybe_close = this.key_maybe_close.bind(this); + } + + Popup.prototype.open = function(html) { + this.el.innerHTML = html; + this.el.classList.remove('hidden'); + addEventListener('click', this.bound_click_maybe_close); + return addEventListener('keydown', this.bound_key_maybe_close); + }; + + Popup.prototype.close = function() { + removeEventListener('click', this.bound_click_maybe_close); + removeEventListener('keydown', this.bound_key_maybe_close); + this.el.classList.add('hidden'); + return this.el.innerHTML = ''; + }; + + Popup.prototype.click_maybe_close = function(e) { + var t; + t = e.target; + while (t.parentElement) { + if (Array.prototype.slice.call(this.el.children).indexOf(t) > -1) { + return true; + } + t = t.parentElement; + } + this.close(); + return cancel(e); + }; + + Popup.prototype.key_maybe_close = function(e) { + if (e.keyCode !== 27) { + return true; + } + this.close(); + return cancel(e); + }; + + return Popup; + + })(); + + popup = new Popup(); + selection = null; cancel = function(ev) { @@ -401,6 +449,85 @@ return sel.modify('extend', 'forward', 'character'); }); + _set_theme_href = function(href) { + var img; + document.getElementById('style').setAttribute('href', href); + img = document.createElement('img'); + img.onerror = function() { + return setTimeout((function() { + return typeof butterfly !== "undefined" && butterfly !== null ? butterfly.resize() : void 0; + }), 50); + }; + return img.src = href; + }; + + _theme = typeof localStorage !== "undefined" && localStorage !== null ? localStorage.getItem('theme') : void 0; + + if (_theme) { + _set_theme_href(_theme); + } + + this.set_theme = function(theme) { + _theme = theme; + if (typeof localStorage !== "undefined" && localStorage !== null) { + localStorage.setItem('theme', theme); + } + if (theme) { + return _set_theme_href(theme); + } + }; + + document.addEventListener('keydown', function(e) {}); + + document.addEventListener('keydown', function(e) { + var oReq, style; + if (!(e.altKey && e.keyCode === 83)) { + return true; + } + if (e.shiftKey) { + style = document.getElementById('style').getAttribute('href'); + style = style.split('?')[0]; + document.getElementById('style').setAttribute('href', style + '?' + (new Date().getTime())); + return cancel(e); + } + oReq = new XMLHttpRequest(); + oReq.addEventListener('load', function() { + var inner, j, len1, ref, response, theme, theme_list, themes, url; + response = JSON.parse(this.responseText); + themes = response.themes; + if (themes.length === 0) { + alert("No themes found in " + response.dir + ".\n Please install themes with butterfly.server.py --install-themes"); + return; + } + inner = "
\n

Pick a theme:

\n \n \n
"; + popup.open(inner); + theme_list = document.getElementById('theme_list'); + return theme_list.addEventListener('change', function() { + return set_theme(theme_list.value); + }); + }); + oReq.open("GET", "/themes/list.json"); + oReq.send(); + return cancel(e); + }); + if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { ctrl = false; alt = false; diff --git a/butterfly/static/ext.min.js b/butterfly/static/ext.min.js index 8186508..489f047 100644 --- a/butterfly/static/ext.min.js +++ b/butterfly/static/ext.min.js @@ -1,4 +1,4 @@ -/*! butterfly 2015-10-06 */ +/*! butterfly 2015-10-07 */ -(function(){var a,b,c,d,e,f,g,h,i,j,k,l=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};j=function(a){var b;return b=function(c){var d;return butterfly.body.classList.remove("alarm"),d="New activity on butterfly terminal ["+butterfly.title+"]",a?new Notification(d,{body:c.data,icon:"/static/images/favicon.png"}):alert(d+"\n"+c.data),butterfly.ws.removeEventListener("message",b)},butterfly.ws.addEventListener("message",b),butterfly.body.classList.add("alarm")},c=function(a){return a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0,!1},document.addEventListener("keydown",function(a){return a.altKey&&65===a.keyCode?(Notification&&"default"===Notification.permission?Notification.requestPermission(function(){return j("granted"===Notification.permission)}):j("granted"===Notification.permission),c(a)):!0}),addEventListener("copy",d=function(a){var b,c,d,e,f,g,h;for(butterfly.bell("copied"),a.clipboardData.clearData(),h=getSelection().toString().replace(/\u00A0/g," ").replace(/\u2007/g," "),b="",g=h.split("\n"),d=0,e=g.length;e>d;d++)f=g[d],"⏎"===f.slice(-1)?(c="",f=f.slice(0,-1)):c="\n",b+=f.replace(/\s*$/,"")+c;return a.clipboardData.setData("text/plain",b.slice(0,-1)),a.preventDefault()}),addEventListener("paste",function(a){var b;return butterfly.bell("pasted"),b=a.clipboardData.getData("text/plain"),b=b.replace(/\r\n/g,"\n").replace(/\n/g,"\r"),butterfly.send(b),a.preventDefault()}),i=null,c=function(a){return a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0,!1},h=function(a){var b;for(b=a.previousSibling,b||(b=a.parentNode.previousSibling),b||(b=a.parentNode.parentNode.previousSibling);b.lastChild;)b=b.lastChild;return b},g=function(a){var b;for(b=a.nextSibling,b||(b=a.parentNode.nextSibling),b||(b=a.parentNode.parentNode.nextSibling);null!=b?b.firstChild:void 0;)b=b.firstChild;return b},a=function(){function a(){butterfly.body.classList.add("selection"),this.selection=getSelection()}return a.prototype.reset=function(){var a,b,c;for(this.selection=getSelection(),a=document.createRange(),a.setStart(this.selection.anchorNode,this.selection.anchorOffset),a.setEnd(this.selection.focusNode,this.selection.focusOffset),this.start={node:this.selection.anchorNode,offset:this.selection.anchorOffset},this.end={node:this.selection.focusNode,offset:this.selection.focusOffset},a.collapsed&&(b=[this.end,this.start],this.start=b[0],this.end=b[1]),this.startLine=this.start.node;!this.startLine.classList||l.call(this.startLine.classList,"line")<0;)this.startLine=this.startLine.parentNode;for(this.endLine=this.end.node,c=[];!this.endLine.classList||l.call(this.endLine.classList,"line")<0;)c.push(this.endLine=this.endLine.parentNode);return c},a.prototype.clear=function(){return this.selection.removeAllRanges()},a.prototype.destroy=function(){return butterfly.body.classList.remove("selection"),this.clear()},a.prototype.text=function(){return this.selection.toString().replace(/\u00A0/g," ").replace(/\u2007/g," ")},a.prototype.up=function(){return this.go(-1)},a.prototype.down=function(){return this.go(1)},a.prototype.go=function(a){var b;if(b=butterfly.children.indexOf(this.startLine)+a,b>=0&&b=0&&b0;)if(f[--d].match(b))return{node:e,offset:d+1};e=h(e),f=null!=e?e.textContent:void 0,d=f.length}else for(;e;){for(;d=0)return!0;if(b.shiftKey&&13===b.keyCode&&!i&&!getSelection().isCollapsed)return butterfly.send(getSelection().toString()),getSelection().removeAllRanges(),c(b);if(i){if(i.reset(),!b.ctrlKey&&b.shiftKey&&37<=(e=b.keyCode)&&40>=e)return!0;if(b.shiftKey&&b.ctrlKey)38===b.keyCode?i.up():40===b.keyCode&&i.down();else if(39===b.keyCode)i.shrinkLeft();else if(38===b.keyCode)i.expandLeft();else if(37===b.keyCode)i.shrinkRight();else{if(40!==b.keyCode)return c(b);i.expandRight()}return null!=i&&i.apply(),c(b)}return!i&&b.ctrlKey&&b.shiftKey&&38===b.keyCode?(i=new a,i.selectLine(butterfly.y-1),i.apply(),c(b)):!0}),document.addEventListener("keyup",function(a){var b,d;if(b=a.keyCode,l.call([16,17,18,19],b)>=0)return!0;if(i){if(13===a.keyCode)return butterfly.send(i.text()),i.destroy(),i=null,c(a);if(d=a.keyCode,l.call([37,38,39,40],d)<0)return i.destroy(),i=null,!0}return!0}),document.addEventListener("dblclick",function(a){var b,c,d,e,f;if(!(a.ctrlKey||a.altkey||(f=getSelection(),f.isCollapsed||f.toString().match(/\s/)))){for(e=document.createRange(),e.setStart(f.anchorNode,f.anchorOffset),e.setEnd(f.focusNode,f.focusOffset),e.collapsed&&(f.removeAllRanges(),d=document.createRange(),d.setStart(f.focusNode,f.focusOffset),d.setEnd(f.anchorNode,f.anchorOffset),f.addRange(d));!f.toString().match(/\s/)&&f.toString();)f.modify("extend","forward","character");for(f.modify("extend","backward","character"),b=f.anchorNode,c=f.anchorOffset,f.collapseToEnd(),f.extend(b,c);!f.toString().match(/\s/)&&f.toString();)f.modify("extend","backward","character");return f.modify("extend","forward","character")}}),/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&(e=!1,b=!1,f=!0,k=document.createElement("input"),k.type="password",k.style.position="fixed",k.style.top=0,k.style.left=0,k.style.border="none",k.style.outline="none",k.style.opacity=0,k.value="0",document.body.appendChild(k),k.addEventListener("blur",function(){return setTimeout(function(a){return function(){return a.focus()}}(this),10)}),addEventListener("click",function(){return k.focus()}),addEventListener("touchstart",function(a){return 2===a.touches.length?e=!0:3===a.touches.length?(e=!1,b=!0):4===a.touches.length?(e=!0,b=!0):void 0}),k.addEventListener("keydown",function(a){return butterfly.keyDown(a),!0}),k.addEventListener("input",function(a){var c;return c=this.value.length,0===c?(a.keyCode=8,butterfly.keyDown(a),this.value="0",!0):(a.keyCode=this.value.charAt(1).charCodeAt(0),!e&&!b||f?(butterfly.keyPress(a),f=!1,this.value="0",!0):(a.keyCode=this.value.charAt(1).charCodeAt(0),a.ctrlKey=e,a.altKey=b,a.keyCode>=97&&a.keyCode<=122&&(a.keyCode-=32),butterfly.keyDown(a),this.value="0",e=b=!1,!0))}))}).call(this); +(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};n=function(a){var b;return b=function(c){var d;return butterfly.body.classList.remove("alarm"),d="New activity on butterfly terminal ["+butterfly.title+"]",a?new Notification(d,{body:c.data,icon:"/static/images/favicon.png"}):alert(d+"\n"+c.data),butterfly.ws.removeEventListener("message",b)},butterfly.ws.addEventListener("message",b),butterfly.body.classList.add("alarm")},f=function(a){return a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0,!1},document.addEventListener("keydown",function(a){return a.altKey&&65===a.keyCode?(Notification&&"default"===Notification.permission?Notification.requestPermission(function(){return n("granted"===Notification.permission)}):n("granted"===Notification.permission),f(a)):!0}),addEventListener("copy",g=function(a){var b,c,d,e,f,g,h;for(butterfly.bell("copied"),a.clipboardData.clearData(),h=getSelection().toString().replace(/\u00A0/g," ").replace(/\u2007/g," "),b="",g=h.split("\n"),d=0,e=g.length;e>d;d++)f=g[d],"⏎"===f.slice(-1)?(c="",f=f.slice(0,-1)):c="\n",b+=f.replace(/\s*$/,"")+c;return a.clipboardData.setData("text/plain",b.slice(0,-1)),a.preventDefault()}),addEventListener("paste",function(a){var b;return butterfly.bell("pasted"),b=a.clipboardData.getData("text/plain"),b=b.replace(/\r\n/g,"\n").replace(/\n/g,"\r"),butterfly.send(b),a.preventDefault()}),a=function(){function a(){this.el=document.getElementById("popup"),this.bound_click_maybe_close=this.click_maybe_close.bind(this),this.bound_key_maybe_close=this.key_maybe_close.bind(this)}return a.prototype.open=function(a){return this.el.innerHTML=a,this.el.classList.remove("hidden"),addEventListener("click",this.bound_click_maybe_close),addEventListener("keydown",this.bound_key_maybe_close)},a.prototype.close=function(){return removeEventListener("click",this.bound_click_maybe_close),removeEventListener("keydown",this.bound_key_maybe_close),this.el.classList.add("hidden"),this.el.innerHTML=""},a.prototype.click_maybe_close=function(a){var b;for(b=a.target;b.parentElement;){if(Array.prototype.slice.call(this.el.children).indexOf(b)>-1)return!0;b=b.parentElement}return this.close(),f(a)},a.prototype.key_maybe_close=function(a){return 27!==a.keyCode?!0:(this.close(),f(a))},a}(),k=new a,m=null,f=function(a){return a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0,!1},l=function(a){var b;for(b=a.previousSibling,b||(b=a.parentNode.previousSibling),b||(b=a.parentNode.parentNode.previousSibling);b.lastChild;)b=b.lastChild;return b},j=function(a){var b;for(b=a.nextSibling,b||(b=a.parentNode.nextSibling),b||(b=a.parentNode.parentNode.nextSibling);null!=b?b.firstChild:void 0;)b=b.firstChild;return b},b=function(){function a(){butterfly.body.classList.add("selection"),this.selection=getSelection()}return a.prototype.reset=function(){var a,b,c;for(this.selection=getSelection(),a=document.createRange(),a.setStart(this.selection.anchorNode,this.selection.anchorOffset),a.setEnd(this.selection.focusNode,this.selection.focusOffset),this.start={node:this.selection.anchorNode,offset:this.selection.anchorOffset},this.end={node:this.selection.focusNode,offset:this.selection.focusOffset},a.collapsed&&(b=[this.end,this.start],this.start=b[0],this.end=b[1]),this.startLine=this.start.node;!this.startLine.classList||p.call(this.startLine.classList,"line")<0;)this.startLine=this.startLine.parentNode;for(this.endLine=this.end.node,c=[];!this.endLine.classList||p.call(this.endLine.classList,"line")<0;)c.push(this.endLine=this.endLine.parentNode);return c},a.prototype.clear=function(){return this.selection.removeAllRanges()},a.prototype.destroy=function(){return butterfly.body.classList.remove("selection"),this.clear()},a.prototype.text=function(){return this.selection.toString().replace(/\u00A0/g," ").replace(/\u2007/g," ")},a.prototype.up=function(){return this.go(-1)},a.prototype.down=function(){return this.go(1)},a.prototype.go=function(a){var b;if(b=butterfly.children.indexOf(this.startLine)+a,b>=0&&b=0&&b0;)if(f[--d].match(b))return{node:e,offset:d+1};e=l(e),f=null!=e?e.textContent:void 0,d=f.length}else for(;e;){for(;d=0)return!0;if(a.shiftKey&&13===a.keyCode&&!m&&!getSelection().isCollapsed)return butterfly.send(getSelection().toString()),getSelection().removeAllRanges(),f(a);if(m){if(m.reset(),!a.ctrlKey&&a.shiftKey&&37<=(d=a.keyCode)&&40>=d)return!0;if(a.shiftKey&&a.ctrlKey)38===a.keyCode?m.up():40===a.keyCode&&m.down();else if(39===a.keyCode)m.shrinkLeft();else if(38===a.keyCode)m.expandLeft();else if(37===a.keyCode)m.shrinkRight();else{if(40!==a.keyCode)return f(a);m.expandRight()}return null!=m&&m.apply(),f(a)}return!m&&a.ctrlKey&&a.shiftKey&&38===a.keyCode?(m=new b,m.selectLine(butterfly.y-1),m.apply(),f(a)):!0}),document.addEventListener("keyup",function(a){var b,c;if(b=a.keyCode,p.call([16,17,18,19],b)>=0)return!0;if(m){if(13===a.keyCode)return butterfly.send(m.text()),m.destroy(),m=null,f(a);if(c=a.keyCode,p.call([37,38,39,40],c)<0)return m.destroy(),m=null,!0}return!0}),document.addEventListener("dblclick",function(a){var b,c,d,e,f;if(!(a.ctrlKey||a.altkey||(f=getSelection(),f.isCollapsed||f.toString().match(/\s/)))){for(e=document.createRange(),e.setStart(f.anchorNode,f.anchorOffset),e.setEnd(f.focusNode,f.focusOffset),e.collapsed&&(f.removeAllRanges(),d=document.createRange(),d.setStart(f.focusNode,f.focusOffset),d.setEnd(f.anchorNode,f.anchorOffset),f.addRange(d));!f.toString().match(/\s/)&&f.toString();)f.modify("extend","forward","character");for(f.modify("extend","backward","character"),b=f.anchorNode,c=f.anchorOffset,f.collapseToEnd(),f.extend(b,c);!f.toString().match(/\s/)&&f.toString();)f.modify("extend","backward","character");return f.modify("extend","forward","character")}}),c=function(a){var b;return document.getElementById("style").setAttribute("href",a),b=document.createElement("img"),b.onerror=function(){return setTimeout(function(){return"undefined"!=typeof butterfly&&null!==butterfly?butterfly.resize():void 0},50)},b.src=a},d="undefined"!=typeof localStorage&&null!==localStorage?localStorage.getItem("theme"):void 0,d&&c(d),this.set_theme=function(a){return d=a,"undefined"!=typeof localStorage&&null!==localStorage&&localStorage.setItem("theme",a),a?c(a):void 0},document.addEventListener("keydown",function(a){}),document.addEventListener("keydown",function(a){var b,c;return a.altKey&&83===a.keyCode?a.shiftKey?(c=document.getElementById("style").getAttribute("href"),c=c.split("?")[0],document.getElementById("style").setAttribute("href",c+"?"+(new Date).getTime()),f(a)):(b=new XMLHttpRequest,b.addEventListener("load",function(){var a,b,c,e,f,g,h,i,j;if(f=JSON.parse(this.responseText),i=f.themes,0===i.length)return void alert("No themes found in "+f.dir+".\n Please install themes with butterfly.server.py --install-themes");for(a='
\n

Pick a theme:

\n \n \n
",k.open(a),h=document.getElementById("theme_list"),h.addEventListener("change",function(){return set_theme(h.value)})}),b.open("GET","/themes/list.json"),b.send(),f(a)):!0}),/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&(h=!1,e=!1,i=!0,o=document.createElement("input"),o.type="password",o.style.position="fixed",o.style.top=0,o.style.left=0,o.style.border="none",o.style.outline="none",o.style.opacity=0,o.value="0",document.body.appendChild(o),o.addEventListener("blur",function(){return setTimeout(function(a){return function(){return a.focus()}}(this),10)}),addEventListener("click",function(){return o.focus()}),addEventListener("touchstart",function(a){return 2===a.touches.length?h=!0:3===a.touches.length?(h=!1,e=!0):4===a.touches.length?(h=!0,e=!0):void 0}),o.addEventListener("keydown",function(a){return butterfly.keyDown(a),!0}),o.addEventListener("input",function(a){var b;return b=this.value.length,0===b?(a.keyCode=8,butterfly.keyDown(a),this.value="0",!0):(a.keyCode=this.value.charAt(1).charCodeAt(0),!h&&!e||i?(butterfly.keyPress(a),i=!1,this.value="0",!0):(a.keyCode=this.value.charAt(1).charCodeAt(0),a.ctrlKey=h,a.altKey=e,a.keyCode>=97&&a.keyCode<=122&&(a.keyCode-=32),butterfly.keyDown(a),this.value="0",h=e=!1,!0))}))}).call(this); //# sourceMappingURL=ext.min.js.map \ No newline at end of file diff --git a/butterfly/static/main.css b/butterfly/static/main.css index e653fda..2639b79 100644 --- a/butterfly/static/main.css +++ b/butterfly/static/main.css @@ -3048,7 +3048,8 @@ html, body { body { white-space: nowrap; overflow-x: hidden; - overflow-y: scroll; } + overflow-y: scroll; + /* Pop ups */ } body::-webkit-scrollbar { background: #110f13; width: .75em; } @@ -3056,6 +3057,28 @@ body { background: rgba(255, 255, 255, 0.1); } body::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.15); } + body .hidden { + display: none; } + body #popup { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; } + body #popup form { + padding: 1.5em; + background: rgba(127, 127, 127, 0.5); } + body #popup form h2 { + margin: .5em; } + body #popup form select { + min-width: 300px; + padding: .5em; + width: 100%; } + body #popup form label { + display: block; + padding: .5em; + font-size: .75em; } .terminal { outline: none; } diff --git a/butterfly/static/main.js b/butterfly/static/main.js index 0aa80ec..7c7f939 100644 --- a/butterfly/static/main.js +++ b/butterfly/static/main.js @@ -23,8 +23,6 @@ params = args.join(','); if (type === 'Resize') { return ws.send('R' + params); - } else if (type === 'Theme') { - return ws.send('T' + params); } }; if (location.protocol === 'https:') { @@ -1245,7 +1243,7 @@ } pt = pt.slice(1); ref3 = pt.split('|', 2), type = ref3[0], content = ref3[1]; - if (!content && type !== 'SASS') { + if (!content) { console.error("No type for inline DECUDK: " + pt); break; } @@ -1283,12 +1281,6 @@ l += content.length; data = data.slice(0, i + 1) + content + data.slice(i + 1); break; - case "SASS": - if (content.length) { - this.ctl('Theme', content); - } - setTimeout(this.refreshStyle.bind(this), 50); - break; default: console.error("Unknown type " + type + " for DECUDK"); } @@ -2768,11 +2760,6 @@ return results; }; - Terminal.prototype.refreshStyle = function() { - document.getElementById('style').setAttribute('href', '/style.css?' + new Date().getTime()); - return setTimeout(this.resize.bind(this), 300); - }; - Terminal.prototype.charsets = { SCLD: { "`": "◆", diff --git a/butterfly/static/main.min.js b/butterfly/static/main.min.js index a2d548c..6a19457 100644 --- a/butterfly/static/main.min.js +++ b/butterfly/static/main.min.js @@ -1,5 +1,5 @@ -/*! butterfly 2015-10-06 */ +/*! butterfly 2015-10-07 */ -(function(){var a,b,c,d,e,f,g,h,i,j=[].slice,k=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};e=h=null,g=!1,f=(new Date).getTime(),a=document.querySelectorAll.bind(document),document.addEventListener("DOMContentLoaded",function(){var a,b,d,e,h,i,k,l,m;return i=null,e=function(a){return l.send("S"+a)},a=function(){var a,b,c;return c=arguments[0],a=2<=arguments.length?j.call(arguments,1):[],b=a.join(","),"Resize"===c?l.send("R"+b):"Theme"===c?l.send("T"+b):void 0},m="https:"===location.protocol?"wss://":"ws://",m+=document.location.host+"/ws"+location.pathname,l=new WebSocket(m),l.addEventListener("open",function(){return console.log("WebSocket open",arguments),i=new c(document.body,e,a),i.ws=l,window.butterfly=i,l.send("R"+i.cols+","+i.rows),f=(new Date).getTime()}),l.addEventListener("error",function(){return console.log("WebSocket error",arguments)}),b="",h=null,d="",l.addEventListener("message",function(a){return h&&clearTimeout(h),d+=a.data,i.stop&&(d=d.slice(-10240)),d.length>i.buffSize?k():h=setTimeout(k,1)}),k=function(){return i.write(d),i.stop&&(i.stop=!1,i.body.classList.remove("stopped")),d=""},l.addEventListener("close",function(){return console.log("WebSocket closed",arguments),setTimeout(function(){return i.write("Closed"),i.skipNextKey=!0,i.body.classList.add("dead")},1),g=!0,(new Date).getTime()-f>6e4?open("","_self").close():void 0}),addEventListener("beforeunload",function(){return g?void 0:"This will exit the terminal session"}),window.bench=function(a){var b;for(null==a&&(a=1e8),b="";b.lengthc?b.push(c):(c>2047&&(c=2047),b.push(192|c>>6),b.push(128|63&c)):255===c?b.push(0):(c>127&&(c=127),b.push(c))}}(this),g=function(b){return function(c,d,e){var f;return b.urxvtMouse?(d.x-=32,d.y-=32,d.x++,d.y++,void b.send("["+c+";"+d.x+";"+d.y+"M")):b.sgrMouse?(d.x-=32,d.y-=32,c-=32,void b.send("[<"+c+";"+d.x+";"+d.y+("mouseup"===e?"m":"M"))):(f=[],a(f,c),a(f,d.x),a(f,d.y),b.send(""+String.fromCharCode.apply(String,f)))}}(this),b=function(a){return function(b){var c,d,e,f,g;switch(b.type){case"mousedown":c=null!=b.button?+b.button:null!=b.which?b.which-1:null;break;case"mouseup":c=3;break;case"wheel":c=b.deltaY<0?64:65}return g=b.shiftKey?4:0,e=b.metaKey?8:0,d=b.ctrlKey?16:0,f=g|e|d,a.vt200Mouse?f&=d:a.normalMouse||(f=0),32+(f<<2)+c}}(this),c=function(a){return function(b){var c,d,e,f;return e=b.pageX,f=b.pageY-window.scrollY,d=a.body.clientWidth,c=window.innerHeight,e=Math.ceil(e/d*a.cols),f=Math.ceil(f/c*a.rows),0>e&&(e=0),e>a.cols&&(e=a.cols),0>f&&(f=0),f>a.rows&&(f=a.rows),e+=32,f+=32,{x:e,y:f,type:b.type}}}(this),addEventListener("contextmenu",function(a){return function(b){return a.mouseEvents?d(b):void 0}}(this)),addEventListener("mousedown",function(a){return function(b){var c,e;if(a.mouseEvents)return f(b),c=h.bind(a),addEventListener("mousemove",c),a.x10Mouse||addEventListener("mouseup",e=function(a){return f(a),removeEventListener("mousemove",c),removeEventListener("mouseup",e),d(a)}),d(b)}}(this)),addEventListener("wheel",function(a){return function(b){if(a.mouseEvents){if(a.x10Mouse)return;return f(b),d(b)}}}(this))},a.prototype.linkify=function(a){var b,c,d,e;return e=/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim,d=/(^|[^\/])(www\.[\S]+(\b|$))/gim,b=/[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim,function(){var f,g,h,i;for(h=a.split(" "),i=[],f=0,g=h.length;g>f;f++)c=h[f],i.push(c.replace(e,'$&').replace(d,'$1$2').replace(b,'$&'));return i}().join(" ")},a.prototype.refresh=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E;for(null==a&&(a=!1),w=this.body.querySelectorAll(".cursor"),k=0,l=w.length;l>k;k++)e=w[k],e.parentNode.replaceChild(this.document.createTextNode(e.textContent),e);for(s="",x=this.screen,j=r=0,m=x.length;m>r;j=++r)if(p=x[j],p.dirty||a){for(u="",E=j!==this.y+this.shift||this.cursorHidden?-(1/0):this.x,b=this.cloneAttr(this.defAttr),B=!1,i=t=0,y=this.cols-1;y>=0?y>=t:t>=y;i=y>=0?++t:--t){if(f=p.chars[i],f.html){u+=f.html;break}if(B)B=!1;else{if(c=f.ch,this.equalAttr(f,b)||(this.equalAttr(b,this.defAttr)||(u+=""),this.equalAttr(f,this.defAttr)||(d=[],C=[],u+="g&&(g+=8),d.push("fg-color-"+g)),"string"==typeof f.fg&&C.push("color: "+f.fg),"number"==typeof f.bg&&d.push("bg-color-"+f.bg),"string"==typeof f.bg&&C.push("background-color: "+f.bg),u+='class="',u+=d.join(" "),u+='"',C.length&&(u+=' style="'+C.join("; ")+'"'),u+=">")),i===E&&(u+=''),c.length>1)u+=c;else switch(c){case"&":u+="&";break;case"<":u+="<";break;case">":u+=">";break;default:" "===c?u+='':" ">=c?u+=" ":!this.forceWidth||"~">=c?u+=c:c>"＀"&&"￯">c?(B=!0,u+=''+c+""):u+=''+c+""}i===E&&(u+=""),b=f}}this.equalAttr(b,this.defAttr)||(u+=""),j===this.y+this.shift||f.html||(u=this.linkify(u)),p.wrap&&(u+="⏎"),this.children[j]?this.children[j].innerHTML=u:s+='
'+u+"
",this.screen[j].dirty=!1}if(""!==s){if(h=this.document.createElement("div"),h.className="group",h.innerHTML=s,this.body.appendChild(h),this.screen=this.screen.slice(-this.rows),this.shift=0,q=document.querySelectorAll(".line"),q.length>this.scrollback){for(z=Array.prototype.slice.call(q,0,q.length-this.scrollback),v=0,n=z.length;n>v;v++)p=z[v],p.remove();for(A=document.querySelectorAll(".group:empty"),D=0,o=A.length;o>D;D++)h=A[D],h.remove();q=document.querySelectorAll(".line")}this.children=Array.prototype.slice.call(q,-this.rows)}return this.scrollLock?void 0:this.nativeScrollTo()},a.prototype._cursorBlink=function(){var a;return this.cursorState^=1,(a=this.body.querySelector(".cursor"))?a.classList.contains("reverse-video")?a.classList.remove("reverse-video"):a.classList.add("reverse-video"):void 0},a.prototype.showCursor=function(){return this.cursorState?void 0:(this.cursorState=1,this.screen[this.y+this.shift].dirty=!0,this.refresh())},a.prototype.startBlink=function(){return this.cursorBlink?(this._blinker=function(a){return function(){return a._cursorBlink()}}(this),this.t_blink=setInterval(this._blinker,500)):void 0},a.prototype.refreshBlink=function(){return this.cursorBlink?(clearInterval(this.t_blink),this.t_blink=setInterval(this._blinker,500)):void 0},a.prototype.scroll=function(){var a,b,c,d,e;if(this.normal||0!==this.scrollTop||this.scrollBottom!==this.rows-1){for(this.screen.splice(this.shift+this.scrollBottom+1,0,this.blankLine()),this.screen.splice(this.shift+this.scrollTop,1),e=[],a=b=c=this.scrollTop,d=this.scrollBottom;d>=c?d>=b:b>=d;a=d>=c?++b:--b)e.push(this.screen[a+this.shift].dirty=!0);return e}return this.screen.push(this.blankLine()),this.shift++},a.prototype.unscroll=function(){var a,b,c,d,e;for(this.screen.splice(this.shift+this.scrollTop,0,this.blankLine(!0)),this.screen.splice(this.shift+this.scrollBottom+1,1),e=[],a=b=c=this.scrollTop,d=this.scrollBottom;d>=c?d>=b:b>=d;a=d>=c?++b:--b)e.push(this.screen[a+this.shift].dirty=!0);return e},a.prototype.nativeScrollTo=function(a){return null==a&&(a=2e9),window.scrollTo(0,a)},a.prototype.scrollDisplay=function(a){return this.nativeScrollTo(window.scrollY+a*this.charSize.height)},a.prototype.nextLine=function(){return this.y++,this.y>this.scrollBottom?(this.y--,this.scroll()):void 0},a.prototype.prevLine=function(){return this.y--,this.yj;){switch(g=c.charAt(j),this.state){case b.normal:switch(g){case"":this.bell();break;case"\n":case" ":case"\f":this.screen[this.y+this.shift].dirty=!0,this.nextLine();break;case"\r":this.x=0;break;case"\b":this.x>=this.cols&&this.x--,this.x>0&&this.x--;break;case" ":this.x=this.nextStop();break;case"":this.setgLevel(1);break;case"":this.setgLevel(0);break;case"":this.state=b.escaped;break;default:if(g>="̀"&&"ͯ">=g||g>="᪰"&&"᫿">=g||g>="᷀"&&"᷿">=g||g>="⃐"&&"⃿">=g||g>="︠"&&"︯">=g){if(z=this.x,A=this.y+this.shift,this.x>0)z-=1;else{if(!(this.y>0))break;A-=1,z=this.cols-1}this.screen[A].chars[z].ch+=g;break}if(g>=" "&&((null!=(s=this.charset)?s[g]:void 0)&&(g=this.charset[g]),this.x>=this.cols&&(this.autowrap&&(this.screen[this.y+this.shift].wrap=!0,this.nextLine()),this.x=0),this.putChar(g),this.x++,this.forceWidth&&g>"＀"&&"￯">g)){if(this.cols<2||this.x>=this.cols){this.putChar(" ");break}this.putChar(" "),this.x++}}break;case b.escaped:switch(g){case"[":this.params=[],this.currentParam=0,this.state=b.csi;break;case"]":this.params=[],this.currentParam=0,this.state=b.osc;break;case"P":this.params=[],this.currentParam=0,this.state=b.dcs;break;case"_":this.state=b.ignore;break;case"^":this.state=b.ignore;break;case"c":this.reset();break;case"E":this.x=0,this.index();break;case"D":this.index();break;case"M":this.reverseIndex();break;case"%":this.setgLevel(0),this.setgCharset(0,a.prototype.charsets.US),this.state=b.normal,j++;break;case"(":case")":case"*":case"+":case"-":case".":switch(g){case"(":this.gcharset=0;break;case")":case"-":this.gcharset=1;break;case"*":case".":this.gcharset=2;break;case"+":this.gcharset=3}this.state=b.charset;break;case"/":this.gcharset=3,this.state=b.charset,j--;break;case"n":this.setgLevel(2);break;case"o":this.setgLevel(3);break;case"|":this.setgLevel(3);break;case"}":this.setgLevel(2);break;case"~":this.setgLevel(1);break;case"7":this.saveCursor(),this.state=b.normal;break;case"8":this.restoreCursor(),this.state=b.normal;break;case"#":switch(this.state=b.normal,j++,q=c.charAt(j)){case"3":break;case"4":break;case"5":break;case"6":break;case"8":for(t=this.screen,k=0,m=t.length;m>k;k++)for(n=t[k],n.dirty=!0,f=o=0,u=n.chars.length;u>=0?u>=o:o>=u;f=u>=0?++o:--o)n.chars[f]=this.cloneAttr(this.curAttr,"E");this.x=this.y=0}break;case"H":this.tabSet();break;case"=":this.applicationKeypad=!0,this.state=b.normal;break;case">":this.applicationKeypad=!1,this.state=b.normal;break;default:this.state=b.normal,console.log("Unknown ESC control:",g)}break;case b.charset:switch(g){case"0":i=a.prototype.charsets.SCLD;break;case"A":i=a.prototype.charsets.UK;break;case"B":i=a.prototype.charsets.US;break;case"4":i=a.prototype.charsets.Dutch;break;case"C":case"5":i=a.prototype.charsets.Finnish;break;case"R":i=a.prototype.charsets.French;break;case"Q":i=a.prototype.charsets.FrenchCanadian;break;case"K":i=a.prototype.charsets.German;break;case"Y":i=a.prototype.charsets.Italian;break;case"E":case"6":i=a.prototype.charsets.NorwegianDanish;break;case"Z":i=a.prototype.charsets.Spanish;break;case"H":case"7":i=a.prototype.charsets.Swedish;break;case"=":i=a.prototype.charsets.Swiss;break;case"/":i=a.prototype.charsets.ISOLatin,j++;break;default:i=a.prototype.charsets.US}this.setgCharset(this.gcharset,i),this.gcharset=null,this.state=b.normal;break;case b.osc:if(""===g||""===g){switch(""===g&&j++,this.params.push(this.currentParam),this.params[0]){case 0:case 1:case 2:this.params[1]&&(this.title=this.params[1]+" - ƸӜƷ butterfly",this.handleTitle(this.title))}this.params=[],this.currentParam=0,this.state=b.normal}else this.params.length?this.currentParam+=g:g>="0"&&"9">=g?this.currentParam=10*this.currentParam+g.charCodeAt(0)-48:";"===g&&(this.params.push(this.currentParam),this.currentParam="");break;case b.csi:if("?"===g||">"===g||"!"===g){this.prefix=g;break}if(g>="0"&&"9">=g){this.currentParam=10*this.currentParam+g.charCodeAt(0)-48;break}if("$"===g||'"'===g||" "===g||"'"===g)break;if(" ">=g||g>="~"){"\b"===g&&(this.currentParam=this.currentParam/10&1),"\r"===g&&(this.x=0),["\n"," ","\f"].indexOf(g)>=0&&(this.screen[this.y+this.shift].dirty=!0,this.nextLine());break}if(this.params.push(this.currentParam),this.currentParam=0,";"===g)break;switch(this.state=b.normal,g){case"A":this.cursorUp(this.params);break;case"B":this.cursorDown(this.params);break;case"C":this.cursorForward(this.params);break;case"D":this.cursorBackward(this.params);break;case"H":this.cursorPos(this.params);break;case"J":this.eraseInDisplay(this.params);break;case"K":this.eraseInLine(this.params);break;case"m":this.prefix||this.charAttributes(this.params);break;case"n":this.prefix||this.deviceStatus(this.params);break;case"@":this.insertChars(this.params);break;case"E":this.cursorNextLine(this.params);break;case"F":this.cursorPrecedingLine(this.params);break;case"G":this.cursorCharAbsolute(this.params);break;case"L":this.insertLines(this.params);break;case"M":this.deleteLines(this.params);break;case"P":this.deleteChars(this.params);break;case"X":this.eraseChars(this.params);break;case"`":this.charPosAbsolute(this.params);break;case"a":this.HPositionRelative(this.params);break;case"c":this.sendDeviceAttributes(this.params);break;case"d":this.linePosAbsolute(this.params);break;case"e":this.VPositionRelative(this.params);break;case"f":this.HVPosition(this.params);break;case"h":this.setMode(this.params);break;case"l":this.resetMode(this.params);break;case"r":this.setScrollRegion(this.params);break;case"s":this.saveCursor(this.params);break;case"u":this.restoreCursor(this.params);break;case"I":this.cursorForwardTab(this.params);break;case"S":this.scrollUp(this.params);break;case"T":this.params.length<2&&!this.prefix&&this.scrollDown(this.params);break;case"Z":this.cursorBackwardTab(this.params);break;case"b":this.repeatPrecedingCharacter(this.params);break;case"g":this.tabClear(this.params);break;case"p":"!"===this.prefix&&this.softReset(this.params);break;default:console.error("Unknown CSI code: %s (%d).",g,g.charCodeAt(0))}this.prefix="";break;case b.dcs:if(""===g||""===g){switch(""===g&&j++,this.prefix){case"":if(r=this.currentParam,";"!==r[0]){console.error("Unknown DECUDK: "+r);break}if(r=r.slice(1),v=r.split("|",2),x=v[0],h=v[1],!h&&"SASS"!==x){console.error("No type for inline DECUDK: "+r);break}switch(x){case"HTML":w=html_sanitize(h,function(a){return a}),d=this.cloneAttr(this.curAttr),d.html='
'+w+"
",this.screen[this.y+this.shift].chars[this.x]=d,this.screen[this.y+this.shift].dirty=!0,this.screen[this.y+this.shift].wrap=!1,this.nextLine();break;case"IMAGE":h=encodeURI(h),h.indexOf(";")?(p=h.slice(0,h.indexOf(";")),e=h.slice(h.indexOf(";")+1)):(p="image",e=h),d=this.cloneAttr(this.curAttr),d.html='',this.screen[this.y+this.shift].chars[this.x]=d,this.screen[this.y+this.shift].dirty=!0,this.screen[this.y+this.shift].wrap=!1;break;case"PROMPT":this.send(h);break;case"TEXT":l+=h.length,c=c.slice(0,j+1)+h+c.slice(j+1);break;case"SASS":h.length&&this.ctl("Theme",h),setTimeout(this.refreshStyle.bind(this),50);break;default:console.error("Unknown type "+x+" for DECUDK")}break;case"$q":switch(r=this.currentParam,y=!1,r){case'"q':r='0"q';break;case'"p':r='61"p';break;case"r":r=""+(this.scrollTop+1)+";"+(this.scrollBottom+1)+"r";break;case"m":r="0m";break;default:console.error("Unknown DCS Pt: %s.",r),r=""}this.send("P"+ +y+"$r"+r+"\\");break;case"+q":r=this.currentParam,y=!1,this.send("P"+ +y+"+r"+r+"\\");break;default:console.error("Unknown DCS prefix: %s.",this.prefix)}this.currentParam=0,this.prefix="",this.state=b.normal}else this.currentParam?this.currentParam+=g:this.prefix||"$"===g||"+"===g?2===this.prefix.length?this.currentParam=g:this.prefix+=g:this.currentParam=g;break;case b.ignore:(""===g||""===g)&&(""===g&&j++,this.state=b.normal)}j++}return this.screen[this.y+this.shift].dirty=!0,this.refresh()},a.prototype.writeln=function(a){return this.write(a+"\r\n")},a.prototype.keyDown=function(a){var b,c,e,f;if(a.keyCode>15&&a.keyCode<19)return!0;if((a.shiftKey||a.ctrlKey)&&45===a.keyCode)return!0;if(a.shiftKey&&a.ctrlKey&&(67===(e=a.keyCode)||86===e))return!0;if(a.altKey&&90===a.keyCode&&!this.skipNextKey)return this.skipNextKey=!0,this.body.classList.add("skip"),d(a);if(this.skipNextKey)return this.skipNextKey=!1,this.body.classList.remove("skip"),!0;switch(a.keyCode){case 8:if(c=a.altKey?"":"",a.shiftKey){c+="\b";break}c+="";break;case 9:if(a.shiftKey){c="";break}c=" ";break;case 13:c="\r";break;case 27:c="";break;case 37:if(this.applicationCursor){c="OD";break}c="";break;case 39:if(this.applicationCursor){c="OC";break}c="";break;case 38:if(this.applicationCursor){c="OA";break}if(a.ctrlKey)return this.scrollDisplay(-1),d(a);c="";break;case 40:if(this.applicationCursor){c="OB";break}if(a.ctrlKey)return this.scrollDisplay(1),d(a);c="";break;case 46:c="[3~";break;case 45:c="[2~";break;case 36:if(this.applicationKeypad){c="OH";break}c="OH";break;case 35:if(this.applicationKeypad){c="OF";break}c="OF";break;case 33:if(a.shiftKey){if(a.ctrlKey)break;return this.scrollDisplay(-(this.rows-1)),d(a)}c="[5~";break;case 34:if(a.shiftKey){if(a.ctrlKey)break;return this.scrollDisplay(this.rows-1),d(a)}c="[6~";break;case 112:c="OP";break;case 113:c="OQ";break;case 114:c="OR";break;case 115:c="OS";break;case 116:c="[15~";break;case 117:c="[17~";break;case 118:c="[18~";break;case 119:c="[19~";break;case 120:c="[20~";break;case 121:c="[21~";break;case 122:c="[23~";break;case 123:c="[24~";break;case 145:return this.scrollLock=!this.scrollLock,this.scrollLock?this.body.classList.add("locked"):this.body.classList.remove("locked"),d(a);default:if(a.ctrlKey)if(a.keyCode>=65&&a.keyCode<=90){if(67===a.keyCode){if(f=(new Date).getTime(),f-this.lastcc<500&&!this.stop){for(b=setTimeout(function(){});b--;)b!==this.t_bell&&b!==this.t_queue&&b!==this.t_blink&&clearTimeout(b);return this.body.classList.add("stopped"),this.stop=!0,this.send(" ")}if(this.stop)return!0;this.lastcc=f}c=String.fromCharCode(a.keyCode-64)}else 32===a.keyCode?c=String.fromCharCode(0):a.keyCode>=51&&a.keyCode<=55?c=String.fromCharCode(a.keyCode-51+27):56===a.keyCode?c=String.fromCharCode(127):219===a.keyCode?c=String.fromCharCode(27):221===a.keyCode&&(c=String.fromCharCode(29));else(a.altKey&&k.call(navigator.platform,"Mac")<0||a.metaKey&&k.call(navigator.platform,"Mac")>=0)&&(a.keyCode>=65&&a.keyCode<=90?c=""+String.fromCharCode(a.keyCode+32):192===a.keyCode?c="`":a.keyCode>=48&&a.keyCode<=57&&(c=""+(a.keyCode-48)))}return a.keyCode>=37&&a.keyCode<=40&&(a.ctrlKey?c=c.slice(0,-1)+"1;5"+c.slice(-1):a.altKey?c=c.slice(0,-1)+"1;3"+c.slice(-1):a.shiftKey&&(c=c.slice(0,-1)+"1;4"+c.slice(-1))),c?(this.showCursor(),this.send(c),d(a)):!0},a.prototype.setgLevel=function(a){return this.glevel=a,this.charset=this.charsets[a]},a.prototype.setgCharset=function(a,b){return this.charsets[a]=b,this.glevel===a?this.charset=b:void 0},a.prototype.keyPress=function(a){var b,c;if(this.skipNextKey===!1)return this.skipNextKey=null,!0;if(a.keyCode>15&&a.keyCode<19)return!0;if((a.shiftKey||a.ctrlKey)&&45===a.keyCode)return!0;if(a.shiftKey&&a.ctrlKey&&(67===(c=a.keyCode)||86===c))return!0;if(d(a),a.charCode)b=a.charCode;else if(null==a.which)b=a.keyCode;else{if(0===a.which||0===a.charCode)return!1;b=a.which}return!b||a.ctrlKey||a.altKey||a.metaKey?!1:(b=String.fromCharCode(b),this.showCursor(),this.send(b),!1)},a.prototype.bell=function(a){return null==a&&(a="bell"),this.visualBell?(this.body.classList.add(a),this.t_bell=setTimeout(function(b){return function(){return b.body.classList.remove(a)}}(this),this.visualBell)):void 0},a.prototype.resize=function(a,b){var c,d,e,f,g,h,i;if(null==a&&(a=null),null==b&&(b=null),g=this.cols,h=this.rows,this.computeCharSize(),this.cols=a||Math.floor(this.body.clientWidth/this.charSize.width),this.rows=b||Math.floor(window.innerHeight/this.charSize.height),i=window.innerHeight%this.charSize.height,this.body.style["padding-bottom"]=i+"px",a||b||g!==this.cols||h!==this.rows){if(this.ctl("Resize",this.cols,this.rows),gthis.cols)for(d=this.screen.length;d--;)for(;this.screen[d].chars.length>this.cols;)this.screen[d].chars.pop();if(this.setupStops(g),e=h,ethis.rows)for(;e-->this.rows;)this.screen.length>this.rows&&this.screen.pop(),this.children.length>this.rows&&(c=this.children.pop(),null!=c&&c.parentNode.removeChild(c));if(this.normal){if(gthis.cols)for(d=this.normal.screen.length;d--;)for(;this.normal.screen[d].chars.length>this.cols;)this.normal.screen[d].chars.pop();if(e=h,ethis.rows)for(;e-->this.rows;)this.normal.screen.length>this.rows&&this.normal.screen.pop()}return this.y>=this.rows&&(this.y=this.rows-1),this.x>=this.cols&&(this.x=this.cols-1),this.scrollTop=0,this.scrollBottom=this.rows-1,this.refresh(!0),a||b?this.reset():void 0}},a.prototype.resizeWindowPlease=function(a){var b,c;return b=window.innerWidth-this.body.clientWidth,c=a*this.charSize.width+b,resizeTo(c,window.innerHeight)},a.prototype.setupStops=function(a){var b;for(null!=a?this.tabs[a]||(a=this.prevStop(a)):(this.tabs={},a=0),b=[];a0;);return a>=this.cols?this.cols-1:0>a?0:a},a.prototype.nextStop=function(a){for(null==a&&(a=this.x);!this.tabs[++a]&&a=this.cols?this.cols-1:0>a?0:a},a.prototype.eraseRight=function(a,b){var c;for(c=this.screen[b+this.shift].chars;ab&&(b=1),this.y-=b,this.y<0?this.y=0:void 0},a.prototype.cursorDown=function(a){var b;return b=a[0],1>b&&(b=1),this.y+=b,this.y>=this.rows?this.y=this.rows-1:void 0},a.prototype.cursorForward=function(a){var b;return b=a[0],1>b&&(b=1),this.x+=b,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.cursorBackward=function(a){var b;return b=a[0],1>b&&(b=1),this.x-=b,this.x<0?this.x=0:void 0},a.prototype.cursorPos=function(a){var b,c;return c=a[0]-1,b=a.length>=2?a[1]-1:0,0>c?c=0:c>=this.rows&&(c=this.rows-1),0>b?b=0:b>=this.cols&&(b=this.cols-1),this.x=b,this.y=c+(this.originMode?this.scrollTop:0)},a.prototype.eraseInDisplay=function(a){var b,c,d,e;switch(a[0]){case 0:for(this.eraseRight(this.x,this.y),b=this.y+1,c=[];bb;)d=a[b],d>=30&&37>=d?this.curAttr.fg=d-30:d>=40&&47>=d?this.curAttr.bg=d-40:d>=90&&97>=d?(d+=8,this.curAttr.fg=d-90):d>=100&&107>=d?(d+=8,this.curAttr.bg=d-100):0===d?this.curAttr=this.cloneAttr(this.defAttr):1===d?this.curAttr.bold=!0:2===d?this.curAttr.faint=!0:3===d?this.curAttr.italic=!0:4===d?this.curAttr.underline=!0:5===d?this.curAttr.blink=1:6===d?this.curAttr.blink=2:7===d?this.curAttr.inverse=!0:8===d?this.curAttr.invisible=!0:9===d?this.curAttr.crossed=!0:10===d||(21===d?this.curAttr.bold=!1:22===d?(this.curAttr.bold=!1,this.curAttr.faint=!1):23===d?this.curAttr.italic=!1:24===d?this.curAttr.underline=!1:25===d?this.curAttr.blink=!1:27===d?this.curAttr.inverse=!1:28===d?this.curAttr.invisible=!1:29===d?this.curAttr.crossed=!1:39===d?this.curAttr.fg=257:49===d?this.curAttr.bg=256:38===d?2===a[b+1]?(b+=2,this.curAttr.fg="rgb("+a[b]+", "+a[b+1]+", "+a[b+2]+")",b+=2):5===a[b+1]&&(b+=2,this.curAttr.fg=255&a[b]):48===d?2===a[b+1]?(b+=2,this.curAttr.bg="rgb("+a[b]+", "+a[b+1]+", "+a[b+2]+")",b+=2):5===a[b+1]&&(b+=2,this.curAttr.bg=255&a[b]):100===d?(this.curAttr.fg=257,this.curAttr.bg=256):console.error("Unknown SGR attribute: %d.",d)),e.push(b++);return e},a.prototype.deviceStatus=function(a){if(this.prefix){if("?"===this.prefix&&6===a[0])return this.send("[?"+(this.y+1)+";"+(this.x+1)+"R")}else switch(a[0]){case 5:return this.send("");case 6:return this.send("["+(this.y+1)+";"+(this.x+1)+"R")}},a.prototype.insertChars=function(a){var b,c,d;for(c=a[0],1>c&&(c=1),d=this.y,b=this.x;c--&&bb&&(b=1),this.y+=b,this.y>=this.rows&&(this.y=this.rows-1),this.x=0},a.prototype.cursorPrecedingLine=function(a){var b;return b=a[0],1>b&&(b=1),this.y-=b,this.y<0&&(this.y=0),this.x=0},a.prototype.cursorCharAbsolute=function(a){var b;return b=a[0],1>b&&(b=1),this.x=b-1},a.prototype.insertLines=function(a){var b,c,d,e,f,g;for(d=a[0],1>d&&(d=1);d--;)this.screen.splice(this.y+this.shift,0,this.blankLine(!0)),this.screen.splice(this.scrollBottom+1+this.shift,1);for(g=[],b=c=e=this.y+this.shift,f=this.screen.length-1;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b].dirty=!0);return g},a.prototype.deleteLines=function(a){var b,c,d,e,f,g;for(d=a[0],1>d&&(d=1);d--;)this.screen.splice(this.scrollBottom+this.shift,0,this.blankLine(!0)),this.screen.splice(this.y+this.shift,1),this.normal||0!==this.scrollTop||this.scrollBottom!==this.rows-1||(this.children[this.y+this.shift].remove(), -this.children.splice(this.y+this.shift,1));if(this.normal||0!==this.scrollTop||this.scrollBottom!==this.rows-1){for(g=[],b=c=e=this.y+this.shift,f=this.screen.length-1;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b].dirty=!0);return g}},a.prototype.deleteChars=function(a){var b;for(b=a[0],1>b&&(b=1);b--;)this.screen[this.y+this.shift].chars.splice(this.x,1),this.screen[this.y+this.shift].chars.push(this.eraseAttr());return this.screen[this.y+this.shift].dirty=!0,this.screen[this.y+this.shift].wrap=!1},a.prototype.eraseChars=function(a){var b,c;for(c=a[0],1>c&&(c=1),b=this.x;c--&&bb&&(b=1),this.x=b-1,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.HPositionRelative=function(a){var b;return b=a[0],1>b&&(b=1),this.x+=b,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.sendDeviceAttributes=function(a){if(!(a[0]>0))if(this.prefix){if(">"===this.prefix){if(this.isterm("xterm"))return this.send("[>0;276;0c");if(this.isterm("rxvt-unicode"))return this.send("[>85;95;0c");if(this.isterm("linux"))return this.send(a[0]+"c");if(this.isterm("screen"))return this.send("[>83;40003;0c")}}else{if(this.isterm("xterm")||this.isterm("rxvt-unicode")||this.isterm("screen"))return this.send("[?1;2c");if(this.isterm("linux"))return this.send("[?6c")}},a.prototype.linePosAbsolute=function(a){var b;return b=a[0],1>b&&(b=1),this.y=b-1,this.y>=this.rows?this.y=this.rows-1:void 0},a.prototype.VPositionRelative=function(a){var b;return b=a[0],1>b&&(b=1),this.y+=b,this.y>=this.rows?this.y=this.rows-1:void 0},a.prototype.HVPosition=function(a){return a[0]<1&&(a[0]=1),a[1]<1&&(a[1]=1),this.y=a[0]-1,this.y>=this.rows&&(this.y=this.rows-1),this.x=a[1]-1,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.setMode=function(b){var c,d,e;if("object"!=typeof b)if(this.prefix){if("?"===this.prefix)switch(b){case 1:return this.applicationCursor=!0;case 2:return this.setgCharset(0,a.prototype.charsets.US),this.setgCharset(1,a.prototype.charsets.US),this.setgCharset(2,a.prototype.charsets.US),this.setgCharset(3,a.prototype.charsets.US);case 3:return this.savedCols=this.cols,this.resize(132,this.rows),this.resizeWindowPlease(132),this.reset();case 6:return this.originMode=!0;case 7:return this.autowrap=!0;case 66:return this.applicationKeypad=!0;case 9:case 1e3:case 1002:case 1003:return this.x10Mouse=9===b,this.vt200Mouse=1e3===b,this.normalMouse=b>1e3,this.mouseEvents=!0,this.body.style.cursor="pointer";case 1004:return this.sendFocus=!0;case 1005:return this.utfMouse=!0;case 1006:return this.sgrMouse=!0;case 1015:return this.urxvtMouse=!0;case 25:return this.cursorHidden=!1;case 1049:case 47:case 1047:if(!this.normal)return e={screen:this.screen,x:this.x,y:this.y,shift:this.shift,scrollTop:this.scrollTop,scrollBottom:this.scrollBottom,tabs:this.tabs,curAttr:this.curAttr},this.reset(),this.normal=e,this.showCursor()}}else switch(b){case 4:this.insertMode=!0;break;case 20:this.convertEol=!0}else for(d=b.length,c=0;d>c;)this.setMode(b[c]),c++},a.prototype.resetMode=function(a){var b,c;if("object"!=typeof a)if(this.prefix){if("?"===this.prefix)switch(a){case 1:return this.applicationCursor=!1;case 3:return 132===this.cols&&this.savedCols&&this.resize(this.savedCols,this.rows),this.resizeWindowPlease(80),this.reset(),delete this.savedCols;case 6:return this.originMode=!1;case 7:return this.autowrap=!1;case 66:return this.applicationKeypad=!1;case 9:case 1e3:case 1002:case 1003:return this.x10Mouse=!1,this.vt200Mouse=!1,this.normalMouse=!1,this.mouseEvents=!1,this.body.style.cursor="";case 1004:return this.sendFocus=!1;case 1005:return this.utfMouse=!1;case 1006:return this.sgrMouse=!1;case 1015:return this.urxvtMouse=!1;case 25:return this.cursorHidden=!0;case 1049:case 47:case 1047:if(this.normal)return this.screen=this.normal.screen,this.x=this.normal.x,this.y=this.normal.y,this.shift=this.normal.shift,this.scrollTop=this.normal.scrollTop,this.scrollBottom=this.normal.scrollBottom,this.tabs=this.normal.tabs,this.curAttr=this.normal.curAttr,this.normal=null,this.refresh(!0),this.showCursor()}}else switch(a){case 4:this.insertMode=!1;break;case 20:this.convertEol=!1}else for(c=a.length,b=0;c>b;)this.resetMode(a[b]),b++},a.prototype.setScrollRegion=function(a){return this.prefix?void 0:(this.scrollTop=(a[0]||1)-1,this.scrollBottom=(a[1]||this.rows)-1,this.x=0,this.y=0)},a.prototype.saveCursor=function(a){return this.savedX=this.x,this.savedY=this.y},a.prototype.restoreCursor=function(a){return this.x=this.savedX||0,this.y=this.savedY||0},a.prototype.cursorForwardTab=function(a){var b,c;for(b=a[0]||1,c=[];b--;)c.push(this.x=this.nextStop());return c},a.prototype.scrollUp=function(a){var b,c,d,e,f,g;for(d=a[0]||1;d--;)this.screen.splice(this.scrollTop,1),this.screen.splice(this.scrollBottom,0,this.blankLine());for(g=[],b=c=e=this.scrollTop,f=this.scrollBottom;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b+this.shift].dirty=!0);return g},a.prototype.scrollDown=function(a){var b,c,d,e,f,g;for(d=a[0]||1;d--;)this.screen.splice(this.scrollBottom,1),this.screen.splice(this.scrollTop,0,this.blankLine());for(g=[],b=c=e=this.scrollTop,f=this.scrollBottom;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b+this.shift].dirty=!0);return g},a.prototype.initMouseTracking=function(a){},a.prototype.resetTitleModes=function(a){},a.prototype.cursorBackwardTab=function(a){var b,c;for(b=a[0]||1,c=[];b--;)c.push(this.x=this.prevStop());return c},a.prototype.repeatPrecedingCharacter=function(a){var b,c,d;for(d=a[0]||1,c=this.screen[this.y+this.shift].chars,b=c[this.x-1]||this.defAttr;d--;)c[this.x++]=b;return this.screen[this.y+this.shift].dirty=!0},a.prototype.tabClear=function(a){var b;return b=a[0],0>=b?delete this.tabs[this.x]:3===b?this.tabs={}:void 0},a.prototype.mediaCopy=function(a){},a.prototype.setResources=function(a){},a.prototype.disableModifiers=function(a){},a.prototype.setPointerMode=function(a){},a.prototype.softReset=function(a){return this.cursorHidden=!1,this.insertMode=!1,this.originMode=!1,this.autowrap=!0,this.applicationKeypad=!1,this.applicationCursor=!1,this.scrollTop=0,this.scrollBottom=this.rows-1,this.curAttr=this.defAttr,this.x=this.y=0,this.charset=null,this.glevel=0,this.charsets=[null]},a.prototype.requestAnsiMode=function(a){},a.prototype.requestPrivateMode=function(a){},a.prototype.setConformanceLevel=function(a){},a.prototype.loadLEDs=function(a){},a.prototype.setCursorStyle=function(a){},a.prototype.setCharProtectionAttr=function(a){},a.prototype.restorePrivateValues=function(a){},a.prototype.setAttrInRectangle=function(a){var b,c,d,e,f,g,h,i;for(i=a[0],e=a[1],c=a[2],g=a[3],b=a[4],h=[];c+1>i;){for(f=this.screen[i+this.shift].chars,this.screen[i+this.shift].dirty=!0,d=e;g>d;)f[d]=this.cloneAttr(b,f[d].ch),d++;h.push(i++)}return h},a.prototype.savePrivateValues=function(a){},a.prototype.manipulateWindow=function(a){},a.prototype.reverseAttrInRectangle=function(a){},a.prototype.setTitleModeFeature=function(a){},a.prototype.setWarningBellVolume=function(a){},a.prototype.setMarginBellVolume=function(a){},a.prototype.copyRectangle=function(a){},a.prototype.enableFilterRectangle=function(a){},a.prototype.requestParameters=function(a){},a.prototype.selectChangeExtent=function(a){},a.prototype.fillRectangle=function(a){var b,c,d,e,f,g,h,i;for(c=a[0],i=a[1],e=a[2],b=a[3],g=a[4],h=[];b+1>i;){for(f=this.screen[i+this.shift].chars,this.screen[i+this.shift].dirty=!0,d=e;g>d;)f[d]=this.cloneAttr(f[d][0],String.fromCharCode(c)),d++;h.push(i++)}return h},a.prototype.enableLocatorReporting=function(a){var b;return b=a[0]>0},a.prototype.eraseRectangle=function(a){var b,c,d,e,f,g,h;for(h=a[0],d=a[1],b=a[2],f=a[3],g=[];b+1>h;){for(e=this.screen[h+this.shift].chars,this.screen[h+this.shift].dirty=!0,c=d;f>c;)e[c]=this.eraseAttr(),c++;g.push(h++)}return g},a.prototype.setLocatorEvents=function(a){},a.prototype.selectiveEraseRectangle=function(a){},a.prototype.requestLocatorPosition=function(a){},a.prototype.insertColumns=function(){var a,b,c,d;for(c=params[0],b=this.rows+this.shift,d=[];c--;)a=this.shift,d.push(function(){var c;for(c=[];b>a;)this.screen[a].chars.splice(this.x+1,0,this.eraseAttr()),this.screen[a].chars.pop(),this.screen[a].dirty=!0,c.push(a++);return c}.call(this));return d},a.prototype.deleteColumns=function(){var a,b,c,d;for(c=params[0],b=this.rows+this.shift,d=[];c--;)a=this.shift,d.push(function(){var c;for(c=[];b>a;)this.screen[a].chars.splice(this.x,1),this.screen[a].chars.push(this.eraseAttr()),this.screen[a].dirty=!0,this.screen[a].wrap=!1,c.push(a++);return c}.call(this));return d},a.prototype.refreshStyle=function(){return document.getElementById("style").setAttribute("href","/style.css?"+(new Date).getTime()),setTimeout(this.resize.bind(this),300)},a.prototype.charsets={SCLD:{"`":"◆",a:"▒",b:" ",c:"\f",d:"\r",e:"\n",f:"°",g:"±",h:"␤",i:" ",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},UK:null,US:null,Dutch:null,Finnish:null,French:null,FrenchCanadian:null,German:null,Italian:null,NorwegianDanish:null,Spanish:null,Swedish:null,Swiss:null,ISOLatin:null},a}(),window.Terminal=c}).call(this); +(function(){var a,b,c,d,e,f,g,h,i,j=[].slice,k=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};e=h=null,g=!1,f=(new Date).getTime(),a=document.querySelectorAll.bind(document),document.addEventListener("DOMContentLoaded",function(){var a,b,d,e,h,i,k,l,m;return i=null,e=function(a){return l.send("S"+a)},a=function(){var a,b,c;return c=arguments[0],a=2<=arguments.length?j.call(arguments,1):[],b=a.join(","),"Resize"===c?l.send("R"+b):void 0},m="https:"===location.protocol?"wss://":"ws://",m+=document.location.host+"/ws"+location.pathname,l=new WebSocket(m),l.addEventListener("open",function(){return console.log("WebSocket open",arguments),i=new c(document.body,e,a),i.ws=l,window.butterfly=i,l.send("R"+i.cols+","+i.rows),f=(new Date).getTime()}),l.addEventListener("error",function(){return console.log("WebSocket error",arguments)}),b="",h=null,d="",l.addEventListener("message",function(a){return h&&clearTimeout(h),d+=a.data,i.stop&&(d=d.slice(-10240)),d.length>i.buffSize?k():h=setTimeout(k,1)}),k=function(){return i.write(d),i.stop&&(i.stop=!1,i.body.classList.remove("stopped")),d=""},l.addEventListener("close",function(){return console.log("WebSocket closed",arguments),setTimeout(function(){return i.write("Closed"),i.skipNextKey=!0,i.body.classList.add("dead")},1),g=!0,(new Date).getTime()-f>6e4?open("","_self").close():void 0}),addEventListener("beforeunload",function(){return g?void 0:"This will exit the terminal session"}),window.bench=function(a){var b;for(null==a&&(a=1e8),b="";b.lengthc?b.push(c):(c>2047&&(c=2047),b.push(192|c>>6),b.push(128|63&c)):255===c?b.push(0):(c>127&&(c=127),b.push(c))}}(this),g=function(b){return function(c,d,e){var f;return b.urxvtMouse?(d.x-=32,d.y-=32,d.x++,d.y++,void b.send("["+c+";"+d.x+";"+d.y+"M")):b.sgrMouse?(d.x-=32,d.y-=32,c-=32,void b.send("[<"+c+";"+d.x+";"+d.y+("mouseup"===e?"m":"M"))):(f=[],a(f,c),a(f,d.x),a(f,d.y),b.send(""+String.fromCharCode.apply(String,f)))}}(this),b=function(a){return function(b){var c,d,e,f,g;switch(b.type){case"mousedown":c=null!=b.button?+b.button:null!=b.which?b.which-1:null;break;case"mouseup":c=3;break;case"wheel":c=b.deltaY<0?64:65}return g=b.shiftKey?4:0,e=b.metaKey?8:0,d=b.ctrlKey?16:0,f=g|e|d,a.vt200Mouse?f&=d:a.normalMouse||(f=0),32+(f<<2)+c}}(this),c=function(a){return function(b){var c,d,e,f;return e=b.pageX,f=b.pageY-window.scrollY,d=a.body.clientWidth,c=window.innerHeight,e=Math.ceil(e/d*a.cols),f=Math.ceil(f/c*a.rows),0>e&&(e=0),e>a.cols&&(e=a.cols),0>f&&(f=0),f>a.rows&&(f=a.rows),e+=32,f+=32,{x:e,y:f,type:b.type}}}(this),addEventListener("contextmenu",function(a){return function(b){return a.mouseEvents?d(b):void 0}}(this)),addEventListener("mousedown",function(a){return function(b){var c,e;if(a.mouseEvents)return f(b),c=h.bind(a),addEventListener("mousemove",c),a.x10Mouse||addEventListener("mouseup",e=function(a){return f(a),removeEventListener("mousemove",c),removeEventListener("mouseup",e),d(a)}),d(b)}}(this)),addEventListener("wheel",function(a){return function(b){if(a.mouseEvents){if(a.x10Mouse)return;return f(b),d(b)}}}(this))},a.prototype.linkify=function(a){var b,c,d,e;return e=/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim,d=/(^|[^\/])(www\.[\S]+(\b|$))/gim,b=/[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim,function(){var f,g,h,i;for(h=a.split(" "),i=[],f=0,g=h.length;g>f;f++)c=h[f],i.push(c.replace(e,'$&').replace(d,'$1$2').replace(b,'$&'));return i}().join(" ")},a.prototype.refresh=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E;for(null==a&&(a=!1),w=this.body.querySelectorAll(".cursor"),k=0,l=w.length;l>k;k++)e=w[k],e.parentNode.replaceChild(this.document.createTextNode(e.textContent),e);for(s="",x=this.screen,j=r=0,m=x.length;m>r;j=++r)if(p=x[j],p.dirty||a){for(u="",E=j!==this.y+this.shift||this.cursorHidden?-(1/0):this.x,b=this.cloneAttr(this.defAttr),B=!1,i=t=0,y=this.cols-1;y>=0?y>=t:t>=y;i=y>=0?++t:--t){if(f=p.chars[i],f.html){u+=f.html;break}if(B)B=!1;else{if(c=f.ch,this.equalAttr(f,b)||(this.equalAttr(b,this.defAttr)||(u+=""),this.equalAttr(f,this.defAttr)||(d=[],C=[],u+="g&&(g+=8),d.push("fg-color-"+g)),"string"==typeof f.fg&&C.push("color: "+f.fg),"number"==typeof f.bg&&d.push("bg-color-"+f.bg),"string"==typeof f.bg&&C.push("background-color: "+f.bg),u+='class="',u+=d.join(" "),u+='"',C.length&&(u+=' style="'+C.join("; ")+'"'),u+=">")),i===E&&(u+=''),c.length>1)u+=c;else switch(c){case"&":u+="&";break;case"<":u+="<";break;case">":u+=">";break;default:" "===c?u+='':" ">=c?u+=" ":!this.forceWidth||"~">=c?u+=c:c>"＀"&&"￯">c?(B=!0,u+=''+c+""):u+=''+c+""}i===E&&(u+=""),b=f}}this.equalAttr(b,this.defAttr)||(u+=""),j===this.y+this.shift||f.html||(u=this.linkify(u)),p.wrap&&(u+="⏎"),this.children[j]?this.children[j].innerHTML=u:s+='
'+u+"
",this.screen[j].dirty=!1}if(""!==s){if(h=this.document.createElement("div"),h.className="group",h.innerHTML=s,this.body.appendChild(h),this.screen=this.screen.slice(-this.rows),this.shift=0,q=document.querySelectorAll(".line"),q.length>this.scrollback){for(z=Array.prototype.slice.call(q,0,q.length-this.scrollback),v=0,n=z.length;n>v;v++)p=z[v],p.remove();for(A=document.querySelectorAll(".group:empty"),D=0,o=A.length;o>D;D++)h=A[D],h.remove();q=document.querySelectorAll(".line")}this.children=Array.prototype.slice.call(q,-this.rows)}return this.scrollLock?void 0:this.nativeScrollTo()},a.prototype._cursorBlink=function(){var a;return this.cursorState^=1,(a=this.body.querySelector(".cursor"))?a.classList.contains("reverse-video")?a.classList.remove("reverse-video"):a.classList.add("reverse-video"):void 0},a.prototype.showCursor=function(){return this.cursorState?void 0:(this.cursorState=1,this.screen[this.y+this.shift].dirty=!0,this.refresh())},a.prototype.startBlink=function(){return this.cursorBlink?(this._blinker=function(a){return function(){return a._cursorBlink()}}(this),this.t_blink=setInterval(this._blinker,500)):void 0},a.prototype.refreshBlink=function(){return this.cursorBlink?(clearInterval(this.t_blink),this.t_blink=setInterval(this._blinker,500)):void 0},a.prototype.scroll=function(){var a,b,c,d,e;if(this.normal||0!==this.scrollTop||this.scrollBottom!==this.rows-1){for(this.screen.splice(this.shift+this.scrollBottom+1,0,this.blankLine()),this.screen.splice(this.shift+this.scrollTop,1),e=[],a=b=c=this.scrollTop,d=this.scrollBottom;d>=c?d>=b:b>=d;a=d>=c?++b:--b)e.push(this.screen[a+this.shift].dirty=!0);return e}return this.screen.push(this.blankLine()),this.shift++},a.prototype.unscroll=function(){var a,b,c,d,e;for(this.screen.splice(this.shift+this.scrollTop,0,this.blankLine(!0)),this.screen.splice(this.shift+this.scrollBottom+1,1),e=[],a=b=c=this.scrollTop,d=this.scrollBottom;d>=c?d>=b:b>=d;a=d>=c?++b:--b)e.push(this.screen[a+this.shift].dirty=!0);return e},a.prototype.nativeScrollTo=function(a){return null==a&&(a=2e9),window.scrollTo(0,a)},a.prototype.scrollDisplay=function(a){return this.nativeScrollTo(window.scrollY+a*this.charSize.height)},a.prototype.nextLine=function(){return this.y++,this.y>this.scrollBottom?(this.y--,this.scroll()):void 0},a.prototype.prevLine=function(){return this.y--,this.yj;){switch(g=c.charAt(j),this.state){case b.normal:switch(g){case"":this.bell();break;case"\n":case" ":case"\f":this.screen[this.y+this.shift].dirty=!0,this.nextLine();break;case"\r":this.x=0;break;case"\b":this.x>=this.cols&&this.x--,this.x>0&&this.x--;break;case" ":this.x=this.nextStop();break;case"":this.setgLevel(1);break;case"":this.setgLevel(0);break;case"":this.state=b.escaped;break;default:if(g>="̀"&&"ͯ">=g||g>="᪰"&&"᫿">=g||g>="᷀"&&"᷿">=g||g>="⃐"&&"⃿">=g||g>="︠"&&"︯">=g){if(z=this.x,A=this.y+this.shift,this.x>0)z-=1;else{if(!(this.y>0))break;A-=1,z=this.cols-1}this.screen[A].chars[z].ch+=g;break}if(g>=" "&&((null!=(s=this.charset)?s[g]:void 0)&&(g=this.charset[g]),this.x>=this.cols&&(this.autowrap&&(this.screen[this.y+this.shift].wrap=!0,this.nextLine()),this.x=0),this.putChar(g),this.x++,this.forceWidth&&g>"＀"&&"￯">g)){if(this.cols<2||this.x>=this.cols){this.putChar(" ");break}this.putChar(" "),this.x++}}break;case b.escaped:switch(g){case"[":this.params=[],this.currentParam=0,this.state=b.csi;break;case"]":this.params=[],this.currentParam=0,this.state=b.osc;break;case"P":this.params=[],this.currentParam=0,this.state=b.dcs;break;case"_":this.state=b.ignore;break;case"^":this.state=b.ignore;break;case"c":this.reset();break;case"E":this.x=0,this.index();break;case"D":this.index();break;case"M":this.reverseIndex();break;case"%":this.setgLevel(0),this.setgCharset(0,a.prototype.charsets.US),this.state=b.normal,j++;break;case"(":case")":case"*":case"+":case"-":case".":switch(g){case"(":this.gcharset=0;break;case")":case"-":this.gcharset=1;break;case"*":case".":this.gcharset=2;break;case"+":this.gcharset=3}this.state=b.charset;break;case"/":this.gcharset=3,this.state=b.charset,j--;break;case"n":this.setgLevel(2);break;case"o":this.setgLevel(3);break;case"|":this.setgLevel(3);break;case"}":this.setgLevel(2);break;case"~":this.setgLevel(1);break;case"7":this.saveCursor(),this.state=b.normal;break;case"8":this.restoreCursor(),this.state=b.normal;break;case"#":switch(this.state=b.normal,j++,q=c.charAt(j)){case"3":break;case"4":break;case"5":break;case"6":break;case"8":for(t=this.screen,k=0,m=t.length;m>k;k++)for(n=t[k],n.dirty=!0,f=o=0,u=n.chars.length;u>=0?u>=o:o>=u;f=u>=0?++o:--o)n.chars[f]=this.cloneAttr(this.curAttr,"E");this.x=this.y=0}break;case"H":this.tabSet();break;case"=":this.applicationKeypad=!0,this.state=b.normal;break;case">":this.applicationKeypad=!1,this.state=b.normal;break;default:this.state=b.normal,console.log("Unknown ESC control:",g)}break;case b.charset:switch(g){case"0":i=a.prototype.charsets.SCLD;break;case"A":i=a.prototype.charsets.UK;break;case"B":i=a.prototype.charsets.US;break;case"4":i=a.prototype.charsets.Dutch;break;case"C":case"5":i=a.prototype.charsets.Finnish;break;case"R":i=a.prototype.charsets.French;break;case"Q":i=a.prototype.charsets.FrenchCanadian;break;case"K":i=a.prototype.charsets.German;break;case"Y":i=a.prototype.charsets.Italian;break;case"E":case"6":i=a.prototype.charsets.NorwegianDanish;break;case"Z":i=a.prototype.charsets.Spanish;break;case"H":case"7":i=a.prototype.charsets.Swedish;break;case"=":i=a.prototype.charsets.Swiss;break;case"/":i=a.prototype.charsets.ISOLatin,j++;break;default:i=a.prototype.charsets.US}this.setgCharset(this.gcharset,i),this.gcharset=null,this.state=b.normal;break;case b.osc:if(""===g||""===g){switch(""===g&&j++,this.params.push(this.currentParam),this.params[0]){case 0:case 1:case 2:this.params[1]&&(this.title=this.params[1]+" - ƸӜƷ butterfly",this.handleTitle(this.title))}this.params=[],this.currentParam=0,this.state=b.normal}else this.params.length?this.currentParam+=g:g>="0"&&"9">=g?this.currentParam=10*this.currentParam+g.charCodeAt(0)-48:";"===g&&(this.params.push(this.currentParam),this.currentParam="");break;case b.csi:if("?"===g||">"===g||"!"===g){this.prefix=g;break}if(g>="0"&&"9">=g){this.currentParam=10*this.currentParam+g.charCodeAt(0)-48;break}if("$"===g||'"'===g||" "===g||"'"===g)break;if(" ">=g||g>="~"){"\b"===g&&(this.currentParam=this.currentParam/10&1),"\r"===g&&(this.x=0),["\n"," ","\f"].indexOf(g)>=0&&(this.screen[this.y+this.shift].dirty=!0,this.nextLine());break}if(this.params.push(this.currentParam),this.currentParam=0,";"===g)break;switch(this.state=b.normal,g){case"A":this.cursorUp(this.params);break;case"B":this.cursorDown(this.params);break;case"C":this.cursorForward(this.params);break;case"D":this.cursorBackward(this.params);break;case"H":this.cursorPos(this.params);break;case"J":this.eraseInDisplay(this.params);break;case"K":this.eraseInLine(this.params);break;case"m":this.prefix||this.charAttributes(this.params);break;case"n":this.prefix||this.deviceStatus(this.params);break;case"@":this.insertChars(this.params);break;case"E":this.cursorNextLine(this.params);break;case"F":this.cursorPrecedingLine(this.params);break;case"G":this.cursorCharAbsolute(this.params);break;case"L":this.insertLines(this.params);break;case"M":this.deleteLines(this.params);break;case"P":this.deleteChars(this.params);break;case"X":this.eraseChars(this.params);break;case"`":this.charPosAbsolute(this.params);break;case"a":this.HPositionRelative(this.params);break;case"c":this.sendDeviceAttributes(this.params);break;case"d":this.linePosAbsolute(this.params);break;case"e":this.VPositionRelative(this.params);break;case"f":this.HVPosition(this.params);break;case"h":this.setMode(this.params);break;case"l":this.resetMode(this.params);break;case"r":this.setScrollRegion(this.params);break;case"s":this.saveCursor(this.params);break;case"u":this.restoreCursor(this.params);break;case"I":this.cursorForwardTab(this.params);break;case"S":this.scrollUp(this.params);break;case"T":this.params.length<2&&!this.prefix&&this.scrollDown(this.params);break;case"Z":this.cursorBackwardTab(this.params);break;case"b":this.repeatPrecedingCharacter(this.params);break;case"g":this.tabClear(this.params);break;case"p":"!"===this.prefix&&this.softReset(this.params);break;default:console.error("Unknown CSI code: %s (%d).",g,g.charCodeAt(0))}this.prefix="";break;case b.dcs:if(""===g||""===g){switch(""===g&&j++,this.prefix){case"":if(r=this.currentParam,";"!==r[0]){console.error("Unknown DECUDK: "+r);break}if(r=r.slice(1),v=r.split("|",2),x=v[0],h=v[1],!h){console.error("No type for inline DECUDK: "+r);break}switch(x){case"HTML":w=html_sanitize(h,function(a){return a}),d=this.cloneAttr(this.curAttr),d.html='
'+w+"
",this.screen[this.y+this.shift].chars[this.x]=d,this.screen[this.y+this.shift].dirty=!0,this.screen[this.y+this.shift].wrap=!1,this.nextLine();break;case"IMAGE":h=encodeURI(h),h.indexOf(";")?(p=h.slice(0,h.indexOf(";")),e=h.slice(h.indexOf(";")+1)):(p="image",e=h),d=this.cloneAttr(this.curAttr),d.html='',this.screen[this.y+this.shift].chars[this.x]=d,this.screen[this.y+this.shift].dirty=!0,this.screen[this.y+this.shift].wrap=!1;break;case"PROMPT":this.send(h);break;case"TEXT":l+=h.length,c=c.slice(0,j+1)+h+c.slice(j+1);break;default:console.error("Unknown type "+x+" for DECUDK")}break;case"$q":switch(r=this.currentParam,y=!1,r){case'"q':r='0"q';break;case'"p':r='61"p';break;case"r":r=""+(this.scrollTop+1)+";"+(this.scrollBottom+1)+"r";break;case"m":r="0m";break;default:console.error("Unknown DCS Pt: %s.",r),r=""}this.send("P"+ +y+"$r"+r+"\\");break;case"+q":r=this.currentParam,y=!1,this.send("P"+ +y+"+r"+r+"\\");break;default:console.error("Unknown DCS prefix: %s.",this.prefix)}this.currentParam=0,this.prefix="",this.state=b.normal}else this.currentParam?this.currentParam+=g:this.prefix||"$"===g||"+"===g?2===this.prefix.length?this.currentParam=g:this.prefix+=g:this.currentParam=g;break;case b.ignore:(""===g||""===g)&&(""===g&&j++,this.state=b.normal)}j++}return this.screen[this.y+this.shift].dirty=!0,this.refresh()},a.prototype.writeln=function(a){return this.write(a+"\r\n")},a.prototype.keyDown=function(a){var b,c,e,f;if(a.keyCode>15&&a.keyCode<19)return!0;if((a.shiftKey||a.ctrlKey)&&45===a.keyCode)return!0;if(a.shiftKey&&a.ctrlKey&&(67===(e=a.keyCode)||86===e))return!0;if(a.altKey&&90===a.keyCode&&!this.skipNextKey)return this.skipNextKey=!0,this.body.classList.add("skip"),d(a);if(this.skipNextKey)return this.skipNextKey=!1,this.body.classList.remove("skip"),!0;switch(a.keyCode){case 8:if(c=a.altKey?"":"",a.shiftKey){c+="\b";break}c+="";break;case 9:if(a.shiftKey){c="";break}c=" ";break;case 13:c="\r";break;case 27:c="";break;case 37:if(this.applicationCursor){c="OD";break}c="";break;case 39:if(this.applicationCursor){c="OC";break}c="";break;case 38:if(this.applicationCursor){c="OA";break}if(a.ctrlKey)return this.scrollDisplay(-1),d(a);c="";break;case 40:if(this.applicationCursor){c="OB";break}if(a.ctrlKey)return this.scrollDisplay(1),d(a);c="";break;case 46:c="[3~";break;case 45:c="[2~";break;case 36:if(this.applicationKeypad){c="OH";break}c="OH";break;case 35:if(this.applicationKeypad){c="OF";break}c="OF";break;case 33:if(a.shiftKey){if(a.ctrlKey)break;return this.scrollDisplay(-(this.rows-1)),d(a)}c="[5~";break;case 34:if(a.shiftKey){if(a.ctrlKey)break;return this.scrollDisplay(this.rows-1),d(a)}c="[6~";break;case 112:c="OP";break;case 113:c="OQ";break;case 114:c="OR";break;case 115:c="OS";break;case 116:c="[15~";break;case 117:c="[17~";break;case 118:c="[18~";break;case 119:c="[19~";break;case 120:c="[20~";break;case 121:c="[21~";break;case 122:c="[23~";break;case 123:c="[24~";break;case 145:return this.scrollLock=!this.scrollLock,this.scrollLock?this.body.classList.add("locked"):this.body.classList.remove("locked"),d(a);default:if(a.ctrlKey)if(a.keyCode>=65&&a.keyCode<=90){if(67===a.keyCode){if(f=(new Date).getTime(),f-this.lastcc<500&&!this.stop){for(b=setTimeout(function(){});b--;)b!==this.t_bell&&b!==this.t_queue&&b!==this.t_blink&&clearTimeout(b);return this.body.classList.add("stopped"),this.stop=!0,this.send(" ")}if(this.stop)return!0;this.lastcc=f}c=String.fromCharCode(a.keyCode-64)}else 32===a.keyCode?c=String.fromCharCode(0):a.keyCode>=51&&a.keyCode<=55?c=String.fromCharCode(a.keyCode-51+27):56===a.keyCode?c=String.fromCharCode(127):219===a.keyCode?c=String.fromCharCode(27):221===a.keyCode&&(c=String.fromCharCode(29));else(a.altKey&&k.call(navigator.platform,"Mac")<0||a.metaKey&&k.call(navigator.platform,"Mac")>=0)&&(a.keyCode>=65&&a.keyCode<=90?c=""+String.fromCharCode(a.keyCode+32):192===a.keyCode?c="`":a.keyCode>=48&&a.keyCode<=57&&(c=""+(a.keyCode-48)))}return a.keyCode>=37&&a.keyCode<=40&&(a.ctrlKey?c=c.slice(0,-1)+"1;5"+c.slice(-1):a.altKey?c=c.slice(0,-1)+"1;3"+c.slice(-1):a.shiftKey&&(c=c.slice(0,-1)+"1;4"+c.slice(-1))),c?(this.showCursor(),this.send(c),d(a)):!0},a.prototype.setgLevel=function(a){return this.glevel=a,this.charset=this.charsets[a]},a.prototype.setgCharset=function(a,b){return this.charsets[a]=b,this.glevel===a?this.charset=b:void 0},a.prototype.keyPress=function(a){var b,c;if(this.skipNextKey===!1)return this.skipNextKey=null,!0;if(a.keyCode>15&&a.keyCode<19)return!0;if((a.shiftKey||a.ctrlKey)&&45===a.keyCode)return!0;if(a.shiftKey&&a.ctrlKey&&(67===(c=a.keyCode)||86===c))return!0;if(d(a),a.charCode)b=a.charCode;else if(null==a.which)b=a.keyCode;else{if(0===a.which||0===a.charCode)return!1;b=a.which}return!b||a.ctrlKey||a.altKey||a.metaKey?!1:(b=String.fromCharCode(b),this.showCursor(),this.send(b),!1)},a.prototype.bell=function(a){return null==a&&(a="bell"),this.visualBell?(this.body.classList.add(a),this.t_bell=setTimeout(function(b){return function(){return b.body.classList.remove(a)}}(this),this.visualBell)):void 0},a.prototype.resize=function(a,b){var c,d,e,f,g,h,i;if(null==a&&(a=null),null==b&&(b=null),g=this.cols,h=this.rows,this.computeCharSize(),this.cols=a||Math.floor(this.body.clientWidth/this.charSize.width),this.rows=b||Math.floor(window.innerHeight/this.charSize.height),i=window.innerHeight%this.charSize.height,this.body.style["padding-bottom"]=i+"px",a||b||g!==this.cols||h!==this.rows){if(this.ctl("Resize",this.cols,this.rows),gthis.cols)for(d=this.screen.length;d--;)for(;this.screen[d].chars.length>this.cols;)this.screen[d].chars.pop();if(this.setupStops(g),e=h,ethis.rows)for(;e-->this.rows;)this.screen.length>this.rows&&this.screen.pop(),this.children.length>this.rows&&(c=this.children.pop(),null!=c&&c.parentNode.removeChild(c));if(this.normal){if(gthis.cols)for(d=this.normal.screen.length;d--;)for(;this.normal.screen[d].chars.length>this.cols;)this.normal.screen[d].chars.pop();if(e=h,ethis.rows)for(;e-->this.rows;)this.normal.screen.length>this.rows&&this.normal.screen.pop()}return this.y>=this.rows&&(this.y=this.rows-1),this.x>=this.cols&&(this.x=this.cols-1),this.scrollTop=0,this.scrollBottom=this.rows-1,this.refresh(!0),a||b?this.reset():void 0}},a.prototype.resizeWindowPlease=function(a){var b,c;return b=window.innerWidth-this.body.clientWidth,c=a*this.charSize.width+b,resizeTo(c,window.innerHeight)},a.prototype.setupStops=function(a){var b;for(null!=a?this.tabs[a]||(a=this.prevStop(a)):(this.tabs={},a=0),b=[];a0;);return a>=this.cols?this.cols-1:0>a?0:a},a.prototype.nextStop=function(a){for(null==a&&(a=this.x);!this.tabs[++a]&&a=this.cols?this.cols-1:0>a?0:a},a.prototype.eraseRight=function(a,b){var c;for(c=this.screen[b+this.shift].chars;ab&&(b=1),this.y-=b,this.y<0?this.y=0:void 0},a.prototype.cursorDown=function(a){var b;return b=a[0],1>b&&(b=1),this.y+=b,this.y>=this.rows?this.y=this.rows-1:void 0},a.prototype.cursorForward=function(a){var b;return b=a[0],1>b&&(b=1),this.x+=b,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.cursorBackward=function(a){var b;return b=a[0],1>b&&(b=1),this.x-=b,this.x<0?this.x=0:void 0},a.prototype.cursorPos=function(a){var b,c;return c=a[0]-1,b=a.length>=2?a[1]-1:0,0>c?c=0:c>=this.rows&&(c=this.rows-1),0>b?b=0:b>=this.cols&&(b=this.cols-1),this.x=b,this.y=c+(this.originMode?this.scrollTop:0)},a.prototype.eraseInDisplay=function(a){var b,c,d,e;switch(a[0]){case 0:for(this.eraseRight(this.x,this.y),b=this.y+1,c=[];bb;)d=a[b],d>=30&&37>=d?this.curAttr.fg=d-30:d>=40&&47>=d?this.curAttr.bg=d-40:d>=90&&97>=d?(d+=8,this.curAttr.fg=d-90):d>=100&&107>=d?(d+=8,this.curAttr.bg=d-100):0===d?this.curAttr=this.cloneAttr(this.defAttr):1===d?this.curAttr.bold=!0:2===d?this.curAttr.faint=!0:3===d?this.curAttr.italic=!0:4===d?this.curAttr.underline=!0:5===d?this.curAttr.blink=1:6===d?this.curAttr.blink=2:7===d?this.curAttr.inverse=!0:8===d?this.curAttr.invisible=!0:9===d?this.curAttr.crossed=!0:10===d||(21===d?this.curAttr.bold=!1:22===d?(this.curAttr.bold=!1,this.curAttr.faint=!1):23===d?this.curAttr.italic=!1:24===d?this.curAttr.underline=!1:25===d?this.curAttr.blink=!1:27===d?this.curAttr.inverse=!1:28===d?this.curAttr.invisible=!1:29===d?this.curAttr.crossed=!1:39===d?this.curAttr.fg=257:49===d?this.curAttr.bg=256:38===d?2===a[b+1]?(b+=2,this.curAttr.fg="rgb("+a[b]+", "+a[b+1]+", "+a[b+2]+")",b+=2):5===a[b+1]&&(b+=2,this.curAttr.fg=255&a[b]):48===d?2===a[b+1]?(b+=2,this.curAttr.bg="rgb("+a[b]+", "+a[b+1]+", "+a[b+2]+")",b+=2):5===a[b+1]&&(b+=2,this.curAttr.bg=255&a[b]):100===d?(this.curAttr.fg=257,this.curAttr.bg=256):console.error("Unknown SGR attribute: %d.",d)),e.push(b++);return e},a.prototype.deviceStatus=function(a){if(this.prefix){if("?"===this.prefix&&6===a[0])return this.send("[?"+(this.y+1)+";"+(this.x+1)+"R")}else switch(a[0]){case 5:return this.send("");case 6:return this.send("["+(this.y+1)+";"+(this.x+1)+"R")}},a.prototype.insertChars=function(a){var b,c,d;for(c=a[0],1>c&&(c=1),d=this.y,b=this.x;c--&&bb&&(b=1),this.y+=b,this.y>=this.rows&&(this.y=this.rows-1),this.x=0},a.prototype.cursorPrecedingLine=function(a){var b;return b=a[0],1>b&&(b=1),this.y-=b,this.y<0&&(this.y=0),this.x=0},a.prototype.cursorCharAbsolute=function(a){var b;return b=a[0],1>b&&(b=1),this.x=b-1},a.prototype.insertLines=function(a){var b,c,d,e,f,g;for(d=a[0],1>d&&(d=1);d--;)this.screen.splice(this.y+this.shift,0,this.blankLine(!0)),this.screen.splice(this.scrollBottom+1+this.shift,1);for(g=[],b=c=e=this.y+this.shift,f=this.screen.length-1;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b].dirty=!0);return g},a.prototype.deleteLines=function(a){var b,c,d,e,f,g;for(d=a[0],1>d&&(d=1);d--;)this.screen.splice(this.scrollBottom+this.shift,0,this.blankLine(!0)),this.screen.splice(this.y+this.shift,1),this.normal||0!==this.scrollTop||this.scrollBottom!==this.rows-1||(this.children[this.y+this.shift].remove(),this.children.splice(this.y+this.shift,1));if(this.normal||0!==this.scrollTop||this.scrollBottom!==this.rows-1){for(g=[], +b=c=e=this.y+this.shift,f=this.screen.length-1;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b].dirty=!0);return g}},a.prototype.deleteChars=function(a){var b;for(b=a[0],1>b&&(b=1);b--;)this.screen[this.y+this.shift].chars.splice(this.x,1),this.screen[this.y+this.shift].chars.push(this.eraseAttr());return this.screen[this.y+this.shift].dirty=!0,this.screen[this.y+this.shift].wrap=!1},a.prototype.eraseChars=function(a){var b,c;for(c=a[0],1>c&&(c=1),b=this.x;c--&&bb&&(b=1),this.x=b-1,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.HPositionRelative=function(a){var b;return b=a[0],1>b&&(b=1),this.x+=b,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.sendDeviceAttributes=function(a){if(!(a[0]>0))if(this.prefix){if(">"===this.prefix){if(this.isterm("xterm"))return this.send("[>0;276;0c");if(this.isterm("rxvt-unicode"))return this.send("[>85;95;0c");if(this.isterm("linux"))return this.send(a[0]+"c");if(this.isterm("screen"))return this.send("[>83;40003;0c")}}else{if(this.isterm("xterm")||this.isterm("rxvt-unicode")||this.isterm("screen"))return this.send("[?1;2c");if(this.isterm("linux"))return this.send("[?6c")}},a.prototype.linePosAbsolute=function(a){var b;return b=a[0],1>b&&(b=1),this.y=b-1,this.y>=this.rows?this.y=this.rows-1:void 0},a.prototype.VPositionRelative=function(a){var b;return b=a[0],1>b&&(b=1),this.y+=b,this.y>=this.rows?this.y=this.rows-1:void 0},a.prototype.HVPosition=function(a){return a[0]<1&&(a[0]=1),a[1]<1&&(a[1]=1),this.y=a[0]-1,this.y>=this.rows&&(this.y=this.rows-1),this.x=a[1]-1,this.x>=this.cols?this.x=this.cols-1:void 0},a.prototype.setMode=function(b){var c,d,e;if("object"!=typeof b)if(this.prefix){if("?"===this.prefix)switch(b){case 1:return this.applicationCursor=!0;case 2:return this.setgCharset(0,a.prototype.charsets.US),this.setgCharset(1,a.prototype.charsets.US),this.setgCharset(2,a.prototype.charsets.US),this.setgCharset(3,a.prototype.charsets.US);case 3:return this.savedCols=this.cols,this.resize(132,this.rows),this.resizeWindowPlease(132),this.reset();case 6:return this.originMode=!0;case 7:return this.autowrap=!0;case 66:return this.applicationKeypad=!0;case 9:case 1e3:case 1002:case 1003:return this.x10Mouse=9===b,this.vt200Mouse=1e3===b,this.normalMouse=b>1e3,this.mouseEvents=!0,this.body.style.cursor="pointer";case 1004:return this.sendFocus=!0;case 1005:return this.utfMouse=!0;case 1006:return this.sgrMouse=!0;case 1015:return this.urxvtMouse=!0;case 25:return this.cursorHidden=!1;case 1049:case 47:case 1047:if(!this.normal)return e={screen:this.screen,x:this.x,y:this.y,shift:this.shift,scrollTop:this.scrollTop,scrollBottom:this.scrollBottom,tabs:this.tabs,curAttr:this.curAttr},this.reset(),this.normal=e,this.showCursor()}}else switch(b){case 4:this.insertMode=!0;break;case 20:this.convertEol=!0}else for(d=b.length,c=0;d>c;)this.setMode(b[c]),c++},a.prototype.resetMode=function(a){var b,c;if("object"!=typeof a)if(this.prefix){if("?"===this.prefix)switch(a){case 1:return this.applicationCursor=!1;case 3:return 132===this.cols&&this.savedCols&&this.resize(this.savedCols,this.rows),this.resizeWindowPlease(80),this.reset(),delete this.savedCols;case 6:return this.originMode=!1;case 7:return this.autowrap=!1;case 66:return this.applicationKeypad=!1;case 9:case 1e3:case 1002:case 1003:return this.x10Mouse=!1,this.vt200Mouse=!1,this.normalMouse=!1,this.mouseEvents=!1,this.body.style.cursor="";case 1004:return this.sendFocus=!1;case 1005:return this.utfMouse=!1;case 1006:return this.sgrMouse=!1;case 1015:return this.urxvtMouse=!1;case 25:return this.cursorHidden=!0;case 1049:case 47:case 1047:if(this.normal)return this.screen=this.normal.screen,this.x=this.normal.x,this.y=this.normal.y,this.shift=this.normal.shift,this.scrollTop=this.normal.scrollTop,this.scrollBottom=this.normal.scrollBottom,this.tabs=this.normal.tabs,this.curAttr=this.normal.curAttr,this.normal=null,this.refresh(!0),this.showCursor()}}else switch(a){case 4:this.insertMode=!1;break;case 20:this.convertEol=!1}else for(c=a.length,b=0;c>b;)this.resetMode(a[b]),b++},a.prototype.setScrollRegion=function(a){return this.prefix?void 0:(this.scrollTop=(a[0]||1)-1,this.scrollBottom=(a[1]||this.rows)-1,this.x=0,this.y=0)},a.prototype.saveCursor=function(a){return this.savedX=this.x,this.savedY=this.y},a.prototype.restoreCursor=function(a){return this.x=this.savedX||0,this.y=this.savedY||0},a.prototype.cursorForwardTab=function(a){var b,c;for(b=a[0]||1,c=[];b--;)c.push(this.x=this.nextStop());return c},a.prototype.scrollUp=function(a){var b,c,d,e,f,g;for(d=a[0]||1;d--;)this.screen.splice(this.scrollTop,1),this.screen.splice(this.scrollBottom,0,this.blankLine());for(g=[],b=c=e=this.scrollTop,f=this.scrollBottom;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b+this.shift].dirty=!0);return g},a.prototype.scrollDown=function(a){var b,c,d,e,f,g;for(d=a[0]||1;d--;)this.screen.splice(this.scrollBottom,1),this.screen.splice(this.scrollTop,0,this.blankLine());for(g=[],b=c=e=this.scrollTop,f=this.scrollBottom;f>=e?f>=c:c>=f;b=f>=e?++c:--c)g.push(this.screen[b+this.shift].dirty=!0);return g},a.prototype.initMouseTracking=function(a){},a.prototype.resetTitleModes=function(a){},a.prototype.cursorBackwardTab=function(a){var b,c;for(b=a[0]||1,c=[];b--;)c.push(this.x=this.prevStop());return c},a.prototype.repeatPrecedingCharacter=function(a){var b,c,d;for(d=a[0]||1,c=this.screen[this.y+this.shift].chars,b=c[this.x-1]||this.defAttr;d--;)c[this.x++]=b;return this.screen[this.y+this.shift].dirty=!0},a.prototype.tabClear=function(a){var b;return b=a[0],0>=b?delete this.tabs[this.x]:3===b?this.tabs={}:void 0},a.prototype.mediaCopy=function(a){},a.prototype.setResources=function(a){},a.prototype.disableModifiers=function(a){},a.prototype.setPointerMode=function(a){},a.prototype.softReset=function(a){return this.cursorHidden=!1,this.insertMode=!1,this.originMode=!1,this.autowrap=!0,this.applicationKeypad=!1,this.applicationCursor=!1,this.scrollTop=0,this.scrollBottom=this.rows-1,this.curAttr=this.defAttr,this.x=this.y=0,this.charset=null,this.glevel=0,this.charsets=[null]},a.prototype.requestAnsiMode=function(a){},a.prototype.requestPrivateMode=function(a){},a.prototype.setConformanceLevel=function(a){},a.prototype.loadLEDs=function(a){},a.prototype.setCursorStyle=function(a){},a.prototype.setCharProtectionAttr=function(a){},a.prototype.restorePrivateValues=function(a){},a.prototype.setAttrInRectangle=function(a){var b,c,d,e,f,g,h,i;for(i=a[0],e=a[1],c=a[2],g=a[3],b=a[4],h=[];c+1>i;){for(f=this.screen[i+this.shift].chars,this.screen[i+this.shift].dirty=!0,d=e;g>d;)f[d]=this.cloneAttr(b,f[d].ch),d++;h.push(i++)}return h},a.prototype.savePrivateValues=function(a){},a.prototype.manipulateWindow=function(a){},a.prototype.reverseAttrInRectangle=function(a){},a.prototype.setTitleModeFeature=function(a){},a.prototype.setWarningBellVolume=function(a){},a.prototype.setMarginBellVolume=function(a){},a.prototype.copyRectangle=function(a){},a.prototype.enableFilterRectangle=function(a){},a.prototype.requestParameters=function(a){},a.prototype.selectChangeExtent=function(a){},a.prototype.fillRectangle=function(a){var b,c,d,e,f,g,h,i;for(c=a[0],i=a[1],e=a[2],b=a[3],g=a[4],h=[];b+1>i;){for(f=this.screen[i+this.shift].chars,this.screen[i+this.shift].dirty=!0,d=e;g>d;)f[d]=this.cloneAttr(f[d][0],String.fromCharCode(c)),d++;h.push(i++)}return h},a.prototype.enableLocatorReporting=function(a){var b;return b=a[0]>0},a.prototype.eraseRectangle=function(a){var b,c,d,e,f,g,h;for(h=a[0],d=a[1],b=a[2],f=a[3],g=[];b+1>h;){for(e=this.screen[h+this.shift].chars,this.screen[h+this.shift].dirty=!0,c=d;f>c;)e[c]=this.eraseAttr(),c++;g.push(h++)}return g},a.prototype.setLocatorEvents=function(a){},a.prototype.selectiveEraseRectangle=function(a){},a.prototype.requestLocatorPosition=function(a){},a.prototype.insertColumns=function(){var a,b,c,d;for(c=params[0],b=this.rows+this.shift,d=[];c--;)a=this.shift,d.push(function(){var c;for(c=[];b>a;)this.screen[a].chars.splice(this.x+1,0,this.eraseAttr()),this.screen[a].chars.pop(),this.screen[a].dirty=!0,c.push(a++);return c}.call(this));return d},a.prototype.deleteColumns=function(){var a,b,c,d;for(c=params[0],b=this.rows+this.shift,d=[];c--;)a=this.shift,d.push(function(){var c;for(c=[];b>a;)this.screen[a].chars.splice(this.x,1),this.screen[a].chars.push(this.eraseAttr()),this.screen[a].dirty=!0,this.screen[a].wrap=!1,c.push(a++);return c}.call(this));return d},a.prototype.charsets={SCLD:{"`":"◆",a:"▒",b:" ",c:"\f",d:"\r",e:"\n",f:"°",g:"±",h:"␤",i:" ",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},UK:null,US:null,Dutch:null,Finnish:null,French:null,FrenchCanadian:null,German:null,Italian:null,NorwegianDanish:null,Spanish:null,Swedish:null,Swiss:null,ISOLatin:null},a}(),window.Terminal=c}).call(this); //# sourceMappingURL=main.min.js.map \ No newline at end of file diff --git a/butterfly/templates/index.html b/butterfly/templates/index.html index 2426e4c..9415605 100644 --- a/butterfly/templates/index.html +++ b/butterfly/templates/index.html @@ -10,11 +10,13 @@ Butterfly - + + diff --git a/coffees/ext/popup.coffee b/coffees/ext/popup.coffee new file mode 100644 index 0000000..fc59228 --- /dev/null +++ b/coffees/ext/popup.coffee @@ -0,0 +1,35 @@ + +class Popup + constructor: -> + @el = document.getElementById('popup') + @bound_click_maybe_close = @click_maybe_close.bind(@) + @bound_key_maybe_close = @key_maybe_close.bind(@) + + open: (html) -> + @el.innerHTML = html + @el.classList.remove 'hidden' + + addEventListener 'click', @bound_click_maybe_close + addEventListener 'keydown', @bound_key_maybe_close + + close: -> + removeEventListener 'click', @bound_click_maybe_close + removeEventListener 'keydown', @bound_key_maybe_close + @el.classList.add 'hidden' + @el.innerHTML = '' + + click_maybe_close: (e) -> + t = e.target + while t.parentElement + return true if Array.prototype.slice.call(@el.children).indexOf(t) > -1 + t = t.parentElement + @close() + cancel e + + key_maybe_close: (e) -> + return true unless e.keyCode is 27 + @close() + cancel e + +popup = new Popup() + diff --git a/coffees/ext/theme.coffee b/coffees/ext/theme.coffee new file mode 100644 index 0000000..0905ce1 --- /dev/null +++ b/coffees/ext/theme.coffee @@ -0,0 +1,70 @@ +_set_theme_href = (href) -> + document.getElementById('style').setAttribute('href', href) + img = document.createElement('img') + img.onerror = -> + setTimeout (-> butterfly?.resize()), 50 + img.src = href; + +_theme = localStorage?.getItem('theme') +_set_theme_href(_theme) if _theme + +@set_theme = (theme) -> + _theme = theme + localStorage?.setItem('theme', theme) + _set_theme_href(theme) if theme + +document.addEventListener 'keydown', (e) -> + +document.addEventListener 'keydown', (e) -> + return true unless e.altKey and e.keyCode is 83 + if e.shiftKey + style = document.getElementById('style').getAttribute('href') + style = style.split('?')[0] + document.getElementById('style').setAttribute( + 'href', style + '?' + (new Date().getTime())) + return cancel(e) + + + oReq = new XMLHttpRequest() + oReq.addEventListener 'load', -> + response = JSON.parse(@responseText) + themes = response.themes + + if themes.length is 0 + alert("No themes found in #{response.dir}.\n + Please install themes with butterfly.server.py --install-themes") + return + + inner = """ +
+

Pick a theme:

+ + +
+ """ + popup.open inner + + theme_list = document.getElementById('theme_list') + + theme_list.addEventListener 'change', -> set_theme theme_list.value + + oReq.open("GET", "/themes/list.json") + oReq.send() + + cancel e diff --git a/coffees/main.coffee b/coffees/main.coffee index 1c54e35..83e05e7 100644 --- a/coffees/main.coffee +++ b/coffees/main.coffee @@ -30,8 +30,6 @@ document.addEventListener 'DOMContentLoaded', -> params = args.join(',') if type == 'Resize' ws.send 'R' + params - else if type == 'Theme' - ws.send 'T' + params if location.protocol == 'https:' wsUrl = 'wss://' diff --git a/coffees/term.coffee b/coffees/term.coffee index 76de69b..9f4f1f0 100644 --- a/coffees/term.coffee +++ b/coffees/term.coffee @@ -1130,7 +1130,7 @@ class Terminal [type, content] = pt.split('|', 2) - if not content and type isnt 'SASS' + if not content console.error "No type for inline DECUDK: #{pt}" break @@ -1170,12 +1170,6 @@ class Terminal l += content.length data = data.slice(0, i + 1) + content + data.slice(i + 1) - when "SASS" - # sass file - if content.length - @ctl 'Theme', content - setTimeout @refreshStyle.bind(@), 50 - else console.error "Unknown type #{type} for DECUDK" @@ -3120,12 +3114,6 @@ class Terminal @screen[i].wrap = false i++ - refreshStyle: -> - document.getElementById('style').setAttribute( - 'href', '/style.css?' + new Date().getTime()) - setTimeout @resize.bind(@), 300 - - # DEC Special Character and Line Drawing Set. # http://vt100.net/docs/vt102-ug/table5-13.html # A lot of curses apps use this if they see TERM=xterm. diff --git a/setup.py b/setup.py index abcef43..45da483 100644 --- a/setup.py +++ b/setup.py @@ -25,6 +25,7 @@ options = dict( scripts=['butterfly.server.py'], packages=['butterfly'], install_requires=["tornado>=3.2", "pyOpenSSL", 'tornado_systemd'], + extras_requires=["libsass"], package_data={ 'butterfly': [ 'sass/*.sass', @@ -35,7 +36,8 @@ options = dict( 'static/*.min.js', 'templates/index.html', 'bin/*', - 'templates/motd' + 'templates/motd', + 'butterfly.conf.default' ] }, classifiers=[