diff --git a/confluent_client/bin/nodeattrib b/confluent_client/bin/nodeattrib index e47ec164..1195f07e 100755 --- a/confluent_client/bin/nodeattrib +++ b/confluent_client/bin/nodeattrib @@ -17,6 +17,7 @@ __author__ = 'alin37' +from getpass import getpass import optparse import os import signal @@ -47,6 +48,8 @@ argparser.add_option('-e', '--environment', action='store_true', 'same name') argparser.add_option('-c', '--clear', action='store_true', help='Clear attributes') +argparser.add_option('-p', '--prompt', action='store_true', + help='Prompt for attribute values interactively') (options, args) = argparser.parse_args() @@ -67,12 +70,24 @@ exitcode = 0 nodetype="noderange" if len(args) > 1: - if "=" in args[1] or options.clear or options.environment: + if "=" in args[1] or options.clear or options.environment or options.prompt: if "=" in args[1] and options.clear: print("Can not clear and set at the same time!") argparser.print_help() sys.exit(1) - exitcode=client.updateattrib(session,args,nodetype, noderange, options) + argassign = None + if options.prompt: + argassign = {} + for arg in args[1:]: + oneval = 1 + twoval = 2 + while oneval != twoval: + oneval = getpass('Enter value for {0}: '.format(arg)) + twoval = getpass('Confirm value for {0}: '.format(arg)) + if oneval != twoval: + print('Values did not match.') + argassign[arg] = twoval + exitcode=client.updateattrib(session,args,nodetype, noderange, options, argassign) try: # setting user output to what the user inputs if args[1] == 'all': diff --git a/confluent_client/confluent/client.py b/confluent_client/confluent/client.py index 40f2e2b7..b8c6c6f9 100644 --- a/confluent_client/confluent/client.py +++ b/confluent_client/confluent/client.py @@ -494,7 +494,7 @@ def printgroupattributes(session, requestargs, showtype, nodetype, noderange, op exitcode = 1 return exitcode -def updateattrib(session, updateargs, nodetype, noderange, options): +def updateattrib(session, updateargs, nodetype, noderange, options, dictassign=None): # update attribute exitcode = 0 if options.clear: @@ -527,6 +527,16 @@ def updateattrib(session, updateargs, nodetype, noderange, options): 'attributes/all', value, key) sys.exit(exitcode) + elif dictassign: + for key in dictassign: + if nodetype == 'nodegroups': + exitcode = session.simp_nodegroups_command(noderange, + 'attributes/all', + dictassign[key], key) + else: + exitcode = session.simp_nodegroups_command(noderange, + 'attributes/all', + dictassign[key], key) else: if "=" in updateargs[1]: try: diff --git a/confluent_common/setup.cfg b/confluent_common/setup.cfg deleted file mode 100644 index 88bee033..00000000 --- a/confluent_common/setup.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[metadata] -name = confluent_common -summary = Confluent Common Libraries -description-file = - README.txt -author = Jarrod Johnson -author-email = jjohnson2@lenovo.com -home-page = http://xcat.sf.net/ -classifier = - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python :: 2.6 - Programming Language :: Python :: 2.7 - -[files] diff --git a/confluent_server/setup.cfg b/confluent_server/setup.cfg deleted file mode 100644 index c3bf7855..00000000 --- a/confluent_server/setup.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[metadata] -name = confluent_server -summary = Confluent systems management daemon -description-file = - README.txt -author = Jarrod Johnson -author-email = jbjohnso@us.ibm.com -home-page = http://xcat.sf.net/ -classifier = - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python :: 2.6 - Programming Language :: Python :: 2.7 - -[files] -packages = - confluent - confluent/interface - confluent/config - diff --git a/confluent_web/js/consoles.js b/confluent_web/js/consoles.js deleted file mode 100644 index 6eb82d7b..00000000 --- a/confluent_web/js/consoles.js +++ /dev/null @@ -1,38 +0,0 @@ -function getRequest(url, success) { - var request = new XMLHttpRequest(); - request.open('GET', url, true); - request.setRequestHeader('Accept', 'application/json'); - request.onload = function() { - if (this.status >= 200 && this.status <= 400) { - success(JSON.parse(this.responseText)); - } - }; - request.send(); -} - -document.addEventListener('DOMContentLoaded', function() { - - getRequest("/confluent-api/nodes/", function( data) { - var items = []; - var options = []; - var nodename = ""; - data["_links"]["item"].forEach( function( val, key ) { - console.log(val); - if (typeof(val) == "object") { - nodename = val.href; - } else { - nodename = val; - } - console.log(nodename); - nodename = nodename.replace('/', ''); - var myrow = document.createElement('div'); - myrow.innerHTML = "
"; - document.getElementById("nodes").appendChild(myrow); - document.getElementById(nodename).addEventListener("click", function( event ) { - var tname = this.id; - var url = "/confluent-api/nodes/" + tname + "/console/session"; - new ConsoleWindow(url, tname); - }); - }); - }); -}); // end document diff --git a/confluent_web/js/consolewindow.js b/confluent_web/js/consolewindow.js deleted file mode 100644 index 9d6e920a..00000000 --- a/confluent_web/js/consolewindow.js +++ /dev/null @@ -1,742 +0,0 @@ -/** - * tty.js - * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) - * Copyright 2014, IBM Corporation - * Copyright 2014, Lenovo - */ - -;(function() { - -'use strict'; -/** - * Elements - */ - -var document = this.document - , window = this - , root - , body - , h1 - , open - , lights; - -/** - * Helpers - */ - -var EventEmitter = Terminal.EventEmitter - , inherits = Terminal.inherits - , on = Terminal.on - , off = Terminal.off - , cancel = Terminal.cancel; - -function postRequest(url, data, success) { - var request = new XMLHttpRequest(); - request.open('POST', url, true); - request.setRequestHeader('Content-Type', 'application/json'); - request.setRequestHeader('Accept', 'application/json'); - request.onload = function() { - if (this.status >= 200 && this.status < 400) { - success(JSON.parse(this.responseText)); - } - }; - if (data) { - request.send(JSON.stringify(data)); - } else { - request.send(""); - } - request = null; -} -/** - * Console - */ - -function ConsoleWindow(consoleurl, nodename) { - var self = this; - - if (!(this instanceof ConsoleWindow)) { - return new ConsoleWindow(consoleurl, nodename); - } - - EventEmitter.call(this); - - var el - , grip - , bar - , button - , title; - - el = document.createElement('div'); - el.className = 'window'; - - grip = document.createElement('div'); - grip.className = 'grip'; - - bar = document.createElement('div'); - bar.className = 'bar'; - - button = document.createElement('div'); - button.innerHTML = 'x'; - button.title = 'close'; - button.className = 'tab'; - - title = document.createElement('div'); - title.className = 'title'; - title.innerHTML = nodename; - - this.nodename = nodename; - this.element = el; - this.grip = grip; - this.bar = bar; - this.button = button; - this.title = title; - this.consoleurl = consoleurl; - - this.tabs = []; - this.focused = null; - - this.cols = 100; //Terminal.geometry[0]; - this.rows = 30; //Terminal.geometry[1]; - - el.appendChild(grip); - el.appendChild(bar); - bar.appendChild(title); - bar.appendChild(button); - document.body.appendChild(el); - - //tty.windows.push(this); - - this.createTab(); - this.focus(); - this.bind(); - - this.tabs[0].once('open', function() { - //tty.emit('open window', self); - self.emit('open'); - }); -} - -inherits(ConsoleWindow, EventEmitter); - -ConsoleWindow.prototype.bind = function() { - var self = this - , el = this.element - , bar = this.bar - , grip = this.grip - , button = this.button - , last = 0; - - on(button, 'click', function(ev) { - self.destroy(); - return cancel(ev); - }); - - on(grip, 'mousedown', function(ev) { - self.focus(); - self.resizing(ev); - return cancel(ev); - }); - - on(el, 'mousedown', function(ev) { - if (ev.target !== el && ev.target !== bar) return; - - self.focus(); - - cancel(ev); - - if (new Date - last < 600) { - return self.maximize(); - } - last = new Date; - - self.drag(ev); - - return cancel(ev); - }); -}; - -ConsoleWindow.prototype.focus = function() { - // Restack - var parent = this.element.parentNode; - if (parent) { - parent.removeChild(this.element); - parent.appendChild(this.element); - } - - // Focus Foreground Tab - this.focused.focus(); - - //tty.emit('focus window', this); - this.emit('focus'); -}; - -ConsoleWindow.prototype.destroy = function() { - if (this.destroyed) return; - this.destroyed = true; - - if (this.minimize) this.minimize(); - - //splice(tty.windows, this); - //if (tty.windows.length) tty.windows[0].focus(); - - this.element.parentNode.removeChild(this.element); - - this.each(function(term) { - term.destroy(); - }); - - //tty.emit('close window', this); - this.emit('close'); -}; - -ConsoleWindow.prototype.drag = function(ev) { - var self = this - , el = this.element; - - if (this.minimize) return; - - var drag = { - left: el.offsetLeft, - top: el.offsetTop, - pageX: ev.pageX, - pageY: ev.pageY - }; - - el.style.opacity = '0.60'; - el.style.cursor = 'move'; - document.documentElement.style.cursor = 'move'; - - function move(ev) { - el.style.left = - (drag.left + ev.pageX - drag.pageX) + 'px'; - var tmptop = (drag.top + ev.pageY - drag.pageY); - if (tmptop < 0) { - tmptop = 0; - } - el.style.top = tmptop + 'px'; - } - - function up() { - el.style.opacity = ''; - el.style.cursor = ''; - document.documentElement.style.cursor = ''; - - off(document, 'mousemove', move); - off(document, 'mouseup', up); - - var ev = { - left: el.style.left.replace(/\w+/g, ''), - top: el.style.top.replace(/\w+/g, '') - }; - - //tty.emit('drag window', self, ev); - self.emit('drag', ev); - } - - on(document, 'mousemove', move); - on(document, 'mouseup', up); -}; - -ConsoleWindow.prototype.resizing = function(ev) { - var self = this - , el = this.element - , term = this.focused; - - if (this.minimize) delete this.minimize; - - var resize = { - w: el.clientWidth, - h: el.clientHeight - }; - - el.style.overflow = 'hidden'; - el.style.opacity = '0.70'; - el.style.cursor = 'se-resize'; - document.documentElement.style.cursor = 'se-resize'; - term.element.style.height = '100%'; - - function move(ev) { - var x, y; - y = el.offsetHeight - term.element.clientHeight; - x = ev.pageX - el.offsetLeft; - y = (ev.pageY - el.offsetTop) - y; - el.style.width = x + 'px'; - el.style.height = y + 'px'; - } - - function up() { - var x, y; - - x = el.clientWidth / resize.w; - y = el.clientHeight / resize.h; - x = (x * term.cols) | 0; - y = (y * term.rows) | 0; - - self.resize(x, y); - - el.style.width = ''; - el.style.height = ''; - - el.style.overflow = ''; - el.style.opacity = ''; - el.style.cursor = ''; - document.documentElement.style.cursor = ''; - term.element.style.height = ''; - - off(document, 'mousemove', move); - off(document, 'mouseup', up); - } - - on(document, 'mousemove', move); - on(document, 'mouseup', up); -}; - -ConsoleWindow.prototype.maximize = function() { - if (this.minimize) return this.minimize(); - - var self = this - , el = this.element - , term = this.focused - , x - , y; - - var m = { - cols: term.cols, - rows: term.rows, - left: el.offsetLeft, - top: el.offsetTop, - root: root.className - }; - - this.minimize = function() { - delete this.minimize; - - el.style.left = m.left + 'px'; - el.style.top = m.top + 'px'; - el.style.width = ''; - el.style.height = ''; - term.element.style.width = ''; - term.element.style.height = ''; - el.style.boxSizing = ''; - self.grip.style.display = ''; - root.className = m.root; - - self.resize(m.cols, m.rows); - - //tty.emit('minimize window', self); - self.emit('minimize'); - }; - - window.scrollTo(0, 0); - - x = root.clientWidth / term.element.offsetWidth; - y = root.clientHeight / term.element.offsetHeight; - x = (x * term.cols) | 0; - y = (y * term.rows) | 0; - - el.style.left = '0px'; - el.style.top = '0px'; - el.style.width = '100%'; - el.style.height = '100%'; - term.element.style.width = '100%'; - term.element.style.height = '100%'; - el.style.boxSizing = 'border-box'; - this.grip.style.display = 'none'; - root.className = 'maximized'; - - this.resize(x, y); - - //tty.emit('maximize window', this); - this.emit('maximize'); -}; - -ConsoleWindow.prototype.resize = function(cols, rows) { - this.cols = cols; - this.rows = rows; - - this.each(function(term) { - term.resize(cols, rows); - }); - - //tty.emit('resize window', this, cols, rows); - this.emit('resize', cols, rows); -}; - -ConsoleWindow.prototype.each = function(func) { - var i = this.tabs.length; - while (i--) { - func(this.tabs[i], i); - } -}; - -ConsoleWindow.prototype.createTab = function() { - return new Tab(this, this.consoleurl); -}; - -ConsoleWindow.prototype.highlight = function() { - var self = this; - - this.element.style.borderColor = 'orange'; - setTimeout(function() { - self.element.style.borderColor = ''; - }, 200); - - this.focus(); -}; - -ConsoleWindow.prototype.focusTab = function(next) { - var tabs = this.tabs - , i = indexOf(tabs, this.focused) - , l = tabs.length; - - if (!next) { - if (tabs[--i]) return tabs[i].focus(); - if (tabs[--l]) return tabs[l].focus(); - } else { - if (tabs[++i]) return tabs[i].focus(); - if (tabs[0]) return tabs[0].focus(); - } - - return this.focused && this.focused.focus(); -}; - -ConsoleWindow.prototype.nextTab = function() { - return this.focusTab(true); -}; - -ConsoleWindow.prototype.previousTab = function() { - return this.focusTab(false); -}; - -/** - * Tab - */ - -function Tab(win, consoleurl) { - var self = this; - - var cols = win.cols - , rows = win.rows; - - Terminal.call(this, { - cols: cols, - rows: rows - }); - - var button = document.createElement('div'); - button.className = 'tab'; - button.innerHTML = '\u2022'; - //win.bar.appendChild(button); - - on(button, 'click', function(ev) { - if (ev.ctrlKey || ev.altKey || ev.metaKey || ev.shiftKey) { - self.destroy(); - } else { - self.focus(); - } - return cancel(ev); - }); - - this.id = ''; - this.consoleurl = consoleurl; - this.clientcount = 0; - this.connectstate = 'unconnected'; - this.lasterror = '' - this.window = win; - this.button = button; - this.element = null; - this.process = ''; - this.open(); - this.hookKeys(); - // Now begins the code that will embarass me when I actually know my way - // around javascript -jbjohnso - this.sessid = ''; - this.datapending = false; - this.waitingdata = false; - this.sentdata = function(data, textStatus, jqXHR) { - if (this.waitingdata) { - postRequest(consoleurl, { session: this.sessid, bytes: this.waitingdata }, this.sentdata); - this.waitingdata = false; - } else { - this.datapending = false; - } - }.bind(this); - this.on('data', function(data) { - // Send data to console from terminal - if (this.datapending) { - if (!this.waitingdata) { - this.waitingdata = data; - } else { - this.waitingdata = this.waitingdata + data; - } - return; - } - this.datapending = true; - postRequest(consoleurl, { session: this.sessid, bytes: data }, this.sentdata); - }.bind(this)); - this.gotdata = function(data, textStatus, jqXHR) { - if ("data" in data) { - this.write(data.data); - } - var updatetitle = false; - var updateinfo = []; - if ("connectstate" in data) { - updatetitle = true; - this.connectstate = data.connectstate; - } - if (this.connectstate != "connected") { - updateinfo.push(this.connectstate); - } else { - self.lasterror = ''; - } - if ("error" in data) { - updatetitle = true; - this.lasterror = data.error - } - if (this.lasterror != '') { - updateinfo.push(this.lasterror); - } - if ("clientcount" in data) { - updatetitle = true; - this.clientcount = data.clientcount; - } - if (this.clientcount > 1) { - updateinfo.push("clients: " + this.clientcount.toString()); - } - if (updatetitle == true) { - if (updateinfo.length > 0) { - this.window.title.innerHTML = this.window.nodename + " [" + updateinfo.join() + "]"; - } else { - this.window.title.innerHTML = this.window.nodename; - } - } - postRequest(consoleurl, { session: this.sessid }, this.gotdata); - }.bind(this); - this.gotsession = function(data, textStatus, jqXHR) { - this.sessid = data.session - postRequest(consoleurl, { session: this.sessid }, this.gotdata); - }.bind(this); - postRequest(consoleurl, false, this.gotsession); - - win.tabs.push(this); -}; - -inherits(Tab, Terminal); - -Tab.prototype._write = Tab.prototype.write; - -Tab.prototype.write = function(data) { - if (this.window.focused !== this) this.button.style.color = 'red'; - return this._write(data); -}; - -Tab.prototype._focus = Tab.prototype.focus; - -Tab.prototype.focus = function() { - if (Terminal.focus === this) return; - - var win = this.window; - - // maybe move to Tab.prototype.switch - if (win.focused !== this) { - if (win.focused) { - if (win.focused.element.parentNode) { - win.focused.element.parentNode.removeChild(win.focused.element); - } - win.focused.button.style.fontWeight = ''; - } - - win.element.appendChild(this.element); - win.focused = this; - - //win.title.innerHTML = this.process; - this.button.style.fontWeight = 'bold'; - this.button.style.color = ''; - } - - this._focus(); - - win.focus(); - - //tty.emit('focus tab', this); - this.emit('focus'); -}; - -Tab.prototype._resize = Tab.prototype.resize; - -Tab.prototype.resize = function(cols, rows) { - //this.socket.emit('resize', this.id, cols, rows); - this._resize(cols, rows); - //tty.emit('resize tab', this, cols, rows); - this.emit('resize', cols, rows); -}; - -Tab.prototype.__destroy = Tab.prototype.destroy; - -Tab.prototype._destroy = function() { - if (this.destroyed) return; - this.destroyed = true; - - var win = this.window; - - this.button.parentNode.removeChild(this.button); - if (this.element.parentNode) { - this.element.parentNode.removeChild(this.element); - } - - if (tty.terms[this.id]) delete tty.terms[this.id]; - splice(win.tabs, this); - - if (win.focused === this) { - win.previousTab(); - } - - if (!win.tabs.length) { - win.destroy(); - } - - this.__destroy(); -}; - -Tab.prototype.destroy = function() { - if (this.destroyed) return; - //TODO: politely let server know of client closure - this._destroy(); - //tty.emit('close tab', this); - this.emit('close'); -}; - -Tab.prototype.hookKeys = function() { - var self = this; - - // Alt-[jk] to quickly swap between windows. - this.on('key', function(key, ev) { - if (Terminal.focusKeys === false) { - return; - } - - var offset - , i; - - if (key === '\x1bj') { - offset = -1; - } else if (key === '\x1bk') { - offset = +1; - } else { - return; - } - - i = indexOf(tty.windows, this.window) + offset; - - this._ignoreNext(); - - if (tty.windows[i]) return tty.windows[i].highlight(); - - if (offset > 0) { - if (tty.windows[0]) return tty.windows[0].highlight(); - } else { - i = tty.windows.length - 1; - if (tty.windows[i]) return tty.windows[i].highlight(); - } - - return this.window.highlight(); - }); - - this.on('request paste', function(key) { - this.socket.emit('request paste', function(err, text) { - if (err) return; - self.send(text); - }); - }); - - this.on('request create', function() { - this.window.createTab(); - }); - - this.on('request term', function(key) { - if (this.window.tabs[key]) { - this.window.tabs[key].focus(); - } - }); - - this.on('request term next', function(key) { - this.window.nextTab(); - }); - - this.on('request term previous', function(key) { - this.window.previousTab(); - }); -}; - -Tab.prototype._ignoreNext = function() { - // Don't send the next key. - var handler = this.handler; - this.handler = function() { - this.handler = handler; - }; - var showCursor = this.showCursor; - this.showCursor = function() { - this.showCursor = showCursor; - }; -}; - -/** - * Program-specific Features - */ - -Tab.prototype._bindMouse = Tab.prototype.bindMouse; - -Tab.prototype.bindMouse = function() { - if (!Terminal.programFeatures) return this._bindMouse(); - - var self = this; - - var wheelEvent = 'onmousewheel' in window - ? 'mousewheel' - : 'DOMMouseScroll'; - - on(self.element, wheelEvent, function(ev) { - if (self.mouseEvents) return; - - if ((ev.type === 'mousewheel' && ev.wheelDeltaY > 0) - || (ev.type === 'DOMMouseScroll' && ev.detail < 0)) { - // page up - self.keyDown({keyCode: 33}); - } else { - // page down - self.keyDown({keyCode: 34}); - } - - return cancel(ev); - }); - - return this._bindMouse(); -}; - -/** - * Helpers - */ - -function indexOf(obj, el) { - var i = obj.length; - while (i--) { - if (obj[i] === el) return i; - } - return -1; -} - -function splice(obj, el) { - var i = indexOf(obj, el); - if (~i) obj.splice(i, 1); -} - -function sanitize(text) { - if (!text) return ''; - return (text + '').replace(/[&<>]/g, '') -} - -this.ConsoleWindow = ConsoleWindow; - -}).call(function() { - return this; -}()); diff --git a/confluent_web/js/term.js b/confluent_web/js/term.js deleted file mode 100644 index f26617dd..00000000 --- a/confluent_web/js/term.js +++ /dev/null @@ -1,5771 +0,0 @@ -/** - * term.js - an xterm emulator - * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) - * https://github.com/chjj/term.js - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Originally forked from (with the author's permission): - * Fabrice Bellard's javascript vt100 for jslinux: - * http://bellard.org/jslinux/ - * Copyright (c) 2011 Fabrice Bellard - * The original design remains. The terminal itself - * has been extended to include xterm CSI codes, among - * other features. - */ - -;(function() { - -/** - * Terminal Emulation References: - * http://vt100.net/ - * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt - * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html - * http://invisible-island.net/vttest/ - * http://www.inwap.com/pdp10/ansicode.txt - * http://linux.die.net/man/4/console_codes - * http://linux.die.net/man/7/urxvt - */ - -'use strict'; - -/** - * Shared - */ - -var window = this - , document = this.document; - -/** - * EventEmitter - */ - -function EventEmitter() { - this._events = this._events || {}; -} - -EventEmitter.prototype.addListener = function(type, listener) { - this._events[type] = this._events[type] || []; - this._events[type].push(listener); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.removeListener = function(type, listener) { - if (!this._events[type]) return; - - var obj = this._events[type] - , i = obj.length; - - while (i--) { - if (obj[i] === listener || obj[i].listener === listener) { - obj.splice(i, 1); - return; - } - } -}; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = function(type) { - if (this._events[type]) delete this._events[type]; -}; - -EventEmitter.prototype.once = function(type, listener) { - function on() { - var args = Array.prototype.slice.call(arguments); - this.removeListener(type, on); - return listener.apply(this, args); - } - on.listener = listener; - return this.on(type, on); -}; - -EventEmitter.prototype.emit = function(type) { - if (!this._events[type]) return; - - var args = Array.prototype.slice.call(arguments, 1) - , obj = this._events[type] - , l = obj.length - , i = 0; - - for (; i < l; i++) { - obj[i].apply(this, args); - } -}; - -EventEmitter.prototype.listeners = function(type) { - return this._events[type] = this._events[type] || []; -}; - -/** - * States - */ - -var normal = 0 - , escaped = 1 - , csi = 2 - , osc = 3 - , charset = 4 - , dcs = 5 - , ignore = 6; - -/** - * Terminal - */ - -function Terminal(options) { - var self = this; - - if (!(this instanceof Terminal)) { - return new Terminal(arguments[0], arguments[1], arguments[2]); - } - - EventEmitter.call(this); - - if (typeof options === 'number') { - options = { - cols: arguments[0], - rows: arguments[1], - handler: arguments[2] - }; - } - - options = options || {}; - - each(keys(Terminal.defaults), function(key) { - if (options[key] == null) { - options[key] = Terminal.options[key]; - // Legacy: - if (Terminal[key] !== Terminal.defaults[key]) { - options[key] = Terminal[key]; - } - } - self[key] = options[key]; - }); - - if (options.colors.length === 8) { - options.colors = options.colors.concat(Terminal._colors.slice(8)); - } else if (options.colors.length === 16) { - options.colors = options.colors.concat(Terminal._colors.slice(16)); - } else if (options.colors.length === 10) { - options.colors = options.colors.slice(0, -2).concat( - Terminal._colors.slice(8, -2), options.colors.slice(-2)); - } else if (options.colors.length === 18) { - options.colors = options.colors.slice(0, -2).concat( - Terminal._colors.slice(16, -2), options.colors.slice(-2)); - } - this.colors = options.colors; - - this.options = options; - - // this.context = options.context || window; - // this.document = options.document || document; - this.parent = options.body || options.parent - || (document ? document.getElementsByTagName('body')[0] : null); - - this.cols = options.cols || options.geometry[0]; - this.rows = options.rows || options.geometry[1]; - - if (options.handler) { - this.on('data', options.handler); - } - - this.ybase = 0; - this.ydisp = 0; - this.x = 0; - this.y = 0; - this.cursorState = 0; - this.cursorHidden = false; - this.convertEol; - this.state = 0; - this.queue = ''; - this.scrollTop = 0; - this.scrollBottom = this.rows - 1; - - // modes - this.applicationKeypad = false; - this.applicationCursor = false; - this.originMode = false; - this.insertMode = false; - this.wraparoundMode = false; - this.normal = null; - - // select modes - this.prefixMode = false; - this.selectMode = false; - this.visualMode = false; - this.searchMode = false; - this.searchDown; - this.entry = ''; - this.entryPrefix = 'Search: '; - this._real; - this._selected; - this._textarea; - - // charset - this.charset = null; - this.gcharset = null; - this.glevel = 0; - this.charsets = [null]; - - // mouse properties - this.decLocator; - this.x10Mouse; - this.vt200Mouse; - this.vt300Mouse; - this.normalMouse; - this.mouseEvents; - this.sendFocus; - this.utfMouse; - this.sgrMouse; - this.urxvtMouse; - - // misc - this.element; - this.children; - this.refreshStart; - this.refreshEnd; - this.savedX; - this.savedY; - this.savedCols; - - // stream - this.readable = true; - this.writable = true; - - this.defAttr = (0 << 18) | (257 << 9) | (256 << 0); - this.curAttr = this.defAttr; - - this.params = []; - this.currentParam = 0; - this.prefix = ''; - this.postfix = ''; - - this.lines = []; - var i = this.rows; - while (i--) { - this.lines.push(this.blankLine()); - } - - this.tabs; - this.setupStops(); -} - -inherits(Terminal, EventEmitter); - -// back_color_erase feature for xterm. -Terminal.prototype.eraseAttr = function() { - // if (this.is('screen')) return this.defAttr; - return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff); -}; - -/** - * Colors - */ - -// Colors 0-15 -Terminal.tangoColors = [ - // dark: - '#2e3436', - '#cc0000', - '#4e9a06', - '#c4a000', - '#3465a4', - '#75507b', - '#06989a', - '#d3d7cf', - // bright: - '#555753', - '#ef2929', - '#8ae234', - '#fce94f', - '#729fcf', - '#ad7fa8', - '#34e2e2', - '#eeeeec' -]; - -Terminal.xtermColors = [ - // dark: - '#000000', // black - '#cd0000', // red3 - '#00cd00', // green3 - '#cdcd00', // yellow3 - '#0000ee', // blue2 - '#cd00cd', // magenta3 - '#00cdcd', // cyan3 - '#e5e5e5', // gray90 - // bright: - '#7f7f7f', // gray50 - '#ff0000', // red - '#00ff00', // green - '#ffff00', // yellow - '#5c5cff', // rgb:5c/5c/ff - '#ff00ff', // magenta - '#00ffff', // cyan - '#ffffff' // white -]; - -// Colors 0-15 + 16-255 -// Much thanks to TooTallNate for writing this. -Terminal.colors = (function() { - var colors = Terminal.tangoColors.slice() - , r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff] - , i; - - // 16-231 - i = 0; - for (; i < 216; i++) { - out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]); - } - - // 232-255 (grey) - i = 0; - for (; i < 24; i++) { - r = 8 + i * 10; - out(r, r, r); - } - - function out(r, g, b) { - colors.push('#' + hex(r) + hex(g) + hex(b)); - } - - function hex(c) { - c = c.toString(16); - return c.length < 2 ? '0' + c : c; - } - - return colors; -})(); - -// Default BG/FG -Terminal.colors[256] = '#000000'; -Terminal.colors[257] = '#f0f0f0'; - -Terminal._colors = Terminal.colors.slice(); - -Terminal.vcolors = (function() { - var out = [] - , colors = Terminal.colors - , i = 0 - , color; - - for (; i < 256; i++) { - color = parseInt(colors[i].substring(1), 16); - out.push([ - (color >> 16) & 0xff, - (color >> 8) & 0xff, - color & 0xff - ]); - } - - return out; -})(); - -/** - * Options - */ - -Terminal.defaults = { - colors: Terminal.colors, - convertEol: false, - termName: 'xterm', - geometry: [80, 24], - cursorBlink: true, - visualBell: false, - popOnBell: false, - scrollback: 1000, - screenKeys: false, - debug: false, - useStyle: false - // programFeatures: false, - // focusKeys: false, -}; - -Terminal.options = {}; - -each(keys(Terminal.defaults), function(key) { - Terminal[key] = Terminal.defaults[key]; - Terminal.options[key] = Terminal.defaults[key]; -}); - -/** - * Focused Terminal - */ - -Terminal.focus = null; - -Terminal.prototype.focus = function() { - if (Terminal.focus === this) return; - - if (Terminal.focus) { - Terminal.focus.blur(); - } - - if (this.sendFocus) this.send('\x1b[I'); - this.showCursor(); - - // try { - // this.element.focus(); - // } catch (e) { - // ; - // } - - // this.emit('focus'); - - Terminal.focus = this; -}; - -Terminal.prototype.blur = function() { - if (Terminal.focus !== this) return; - - this.cursorState = 0; - this.refresh(this.y, this.y); - if (this.sendFocus) this.send('\x1b[O'); - - // try { - // this.element.blur(); - // } catch (e) { - // ; - // } - - // this.emit('blur'); - - Terminal.focus = null; -}; - -/** - * Initialize global behavior - */ - -Terminal.prototype.initGlobal = function() { - var document = this.document; - - Terminal._boundDocs = Terminal._boundDocs || []; - if (~indexOf(Terminal._boundDocs, document)) { - return; - } - Terminal._boundDocs.push(document); - - Terminal.bindPaste(document); - - Terminal.bindKeys(document); - - Terminal.bindCopy(document); - - if (this.isMobile) { - this.fixMobile(document); - } - - if (this.useStyle) { - Terminal.insertStyle(document, this.colors[256], this.colors[257]); - } -}; - -/** - * Bind to paste event - */ - -Terminal.bindPaste = function(document) { - // This seems to work well for ctrl-V and middle-click, - // even without the contentEditable workaround. - var window = document.defaultView; - on(window, 'paste', function(ev) { - var term = Terminal.focus; - if (!term) return; - if (ev.clipboardData) { - term.send(ev.clipboardData.getData('text/plain')); - } else if (term.context.clipboardData) { - term.send(term.context.clipboardData.getData('Text')); - } - // Not necessary. Do it anyway for good measure. - term.element.contentEditable = 'inherit'; - return cancel(ev); - }); -}; - -/** - * Global Events for key handling - */ - -Terminal.bindKeys = function(document) { - // We should only need to check `target === body` below, - // but we can check everything for good measure. - on(document, 'keydown', function(ev) { - if (!Terminal.focus) return; - var target = ev.target || ev.srcElement; - if (!target) return; - if (target === Terminal.focus.element - || target === Terminal.focus.context - || target === Terminal.focus.document - || target === Terminal.focus.body - || target === Terminal._textarea - || target === Terminal.focus.parent) { - return Terminal.focus.keyDown(ev); - } - }, true); - - on(document, 'keypress', function(ev) { - if (!Terminal.focus) return; - var target = ev.target || ev.srcElement; - if (!target) return; - if (target === Terminal.focus.element - || target === Terminal.focus.context - || target === Terminal.focus.document - || target === Terminal.focus.body - || target === Terminal._textarea - || target === Terminal.focus.parent) { - return Terminal.focus.keyPress(ev); - } - }, true); - - // If we click somewhere other than a - // terminal, unfocus the terminal. - on(document, 'mousedown', function(ev) { - if (!Terminal.focus) return; - - var el = ev.target || ev.srcElement; - if (!el) return; - - do { - if (el === Terminal.focus.element) return; - } while (el = el.parentNode); - - Terminal.focus.blur(); - }); -}; - -/** - * Copy Selection w/ Ctrl-C (Select Mode) - */ - -Terminal.bindCopy = function(document) { - var window = document.defaultView; - - // if (!('onbeforecopy' in document)) { - // // Copies to *only* the clipboard. - // on(window, 'copy', function fn(ev) { - // var term = Terminal.focus; - // if (!term) return; - // if (!term._selected) return; - // var text = term.grabText( - // term._selected.x1, term._selected.x2, - // term._selected.y1, term._selected.y2); - // term.emit('copy', text); - // ev.clipboardData.setData('text/plain', text); - // }); - // return; - // } - - // Copies to primary selection *and* clipboard. - // NOTE: This may work better on capture phase, - // or using the `beforecopy` event. - on(window, 'copy', function(ev) { - var term = Terminal.focus; - if (!term) return; - if (!term._selected) return; - var textarea = term.getCopyTextarea(); - var text = term.grabText( - term._selected.x1, term._selected.x2, - term._selected.y1, term._selected.y2); - term.emit('copy', text); - textarea.focus(); - textarea.textContent = text; - textarea.value = text; - textarea.setSelectionRange(0, text.length); - setTimeout(function() { - term.element.focus(); - term.focus(); - }, 1); - }); -}; - -/** - * Fix Mobile - */ - -Terminal.prototype.fixMobile = function(document) { - var self = this; - - var textarea = document.createElement('textarea'); - textarea.style.position = 'absolute'; - textarea.style.left = '-32000px'; - textarea.style.top = '-32000px'; - textarea.style.width = '0px'; - textarea.style.height = '0px'; - textarea.style.opacity = '0'; - textarea.style.backgroundColor = 'transparent'; - textarea.style.borderStyle = 'none'; - textarea.style.outlineStyle = 'none'; - textarea.autocapitalize = 'none'; - textarea.autocorrect = 'off'; - - document.getElementsByTagName('body')[0].appendChild(textarea); - - Terminal._textarea = textarea; - - setTimeout(function() { - textarea.focus(); - }, 1000); - - if (this.isAndroid) { - on(textarea, 'change', function() { - var value = textarea.textContent || textarea.value; - textarea.value = ''; - textarea.textContent = ''; - self.send(value + '\r'); - }); - } -}; - -/** - * Insert a default style - */ - -Terminal.insertStyle = function(document, bg, fg) { - var style = document.getElementById('term-style'); - if (style) return; - - var head = document.getElementsByTagName('head')[0]; - if (!head) return; - - var style = document.createElement('style'); - style.id = 'term-style'; - - // textContent doesn't work well with IE for