nirvana 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemspec +24 -0
- data/CHANGELOG.rdoc +2 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +49 -0
- data/Rakefile +35 -0
- data/bin/nirvana +4 -0
- data/bin/nirvana-websocket +4 -0
- data/deps.rip +4 -0
- data/lib/nirvana.rb +21 -0
- data/lib/nirvana/public/css/jquery.readline.css +11 -0
- data/lib/nirvana/public/css/jquery.repl.css +15 -0
- data/lib/nirvana/public/css/jquery.ui.autocomplete.css +347 -0
- data/lib/nirvana/public/css/nirvana.css +6 -0
- data/lib/nirvana/public/images/spinner.gif +0 -0
- data/lib/nirvana/public/index.html +35 -0
- data/lib/nirvana/public/js/jquery.hotkeys.js +99 -0
- data/lib/nirvana/public/js/jquery.min.js +154 -0
- data/lib/nirvana/public/js/jquery.readline.js +104 -0
- data/lib/nirvana/public/js/jquery.repl.js +87 -0
- data/lib/nirvana/public/js/jquery.ui.autocomplete.min.js +80 -0
- data/lib/nirvana/public/js/nirvana.js +24 -0
- data/lib/nirvana/shell.rb +55 -0
- data/lib/nirvana/util.rb +40 -0
- data/lib/nirvana/version.rb +3 -0
- data/lib/nirvana/websocket.rb +23 -0
- data/lib/ripl/web.rb +15 -0
- metadata +159 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
/*!
|
2
|
+
* jQuery UI 1.8.5
|
3
|
+
*
|
4
|
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
5
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
6
|
+
* http://jquery.org/license
|
7
|
+
*
|
8
|
+
* http://docs.jquery.com/UI
|
9
|
+
*/
|
10
|
+
(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.5",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,
|
11
|
+
NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,
|
12
|
+
"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");
|
13
|
+
if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind("mousedown.ui-disableSelection selectstart.ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,
|
14
|
+
"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c.style(this,h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c.style(this,
|
15
|
+
h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}});
|
16
|
+
c(function(){var a=document.createElement("div"),b=document.body;c.extend(a.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.appendChild(a).offsetHeight===100;b.removeChild(a).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,
|
17
|
+
d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)}})}})(jQuery);
|
18
|
+
;/*!
|
19
|
+
* jQuery UI Widget 1.8.5
|
20
|
+
*
|
21
|
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
22
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
23
|
+
* http://jquery.org/license
|
24
|
+
*
|
25
|
+
* http://docs.jquery.com/UI/Widget
|
26
|
+
*/
|
27
|
+
(function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)b(d).triggerHandler("remove");k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,
|
28
|
+
a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)===
|
29
|
+
"_")return h;e?this.each(function(){var g=b.data(this,a);if(!g)throw"cannot call methods on "+a+" prior to initialization; attempted to call method '"+d+"'";if(!b.isFunction(g[d]))throw"no such method '"+d+"' for "+a+" widget instance";var i=g[d].apply(g,f);if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",
|
30
|
+
widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+
|
31
|
+
"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}b.each(d,function(f,h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",
|
32
|
+
false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
|
33
|
+
;/*
|
34
|
+
* jQuery UI Position 1.8.5
|
35
|
+
*
|
36
|
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
37
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
38
|
+
* http://jquery.org/license
|
39
|
+
*
|
40
|
+
* http://docs.jquery.com/UI/Position
|
41
|
+
*/
|
42
|
+
(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.scrollTo&&d.document){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j=
|
43
|
+
{top:b.of.pageY,left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/
|
44
|
+
2;if(b.at[1]==="bottom")j.top+=k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+parseInt(c.curCSS(this,"marginRight",true))||0,w=m+q+parseInt(c.curCSS(this,"marginBottom",true))||0,i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]===
|
45
|
+
"center")i.top-=m/2;i.left=parseInt(i.left);i.top=parseInt(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();
|
46
|
+
b.left=d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];
|
47
|
+
b.left+=a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=
|
48
|
+
c(b),g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery);
|
49
|
+
;/*
|
50
|
+
* jQuery UI Autocomplete 1.8.5
|
51
|
+
*
|
52
|
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
53
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
54
|
+
* http://jquery.org/license
|
55
|
+
*
|
56
|
+
* http://docs.jquery.com/UI/Autocomplete
|
57
|
+
*
|
58
|
+
* Depends:
|
59
|
+
* jquery.ui.core.js
|
60
|
+
* jquery.ui.widget.js
|
61
|
+
* jquery.ui.position.js
|
62
|
+
*/
|
63
|
+
(function(e){e.widget("ui.autocomplete",{options:{appendTo:"body",delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},_create:function(){var a=this,b=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!a.options.disabled){var d=e.ui.keyCode;switch(c.keyCode){case d.PAGE_UP:a._move("previousPage",
|
64
|
+
c);break;case d.PAGE_DOWN:a._move("nextPage",c);break;case d.UP:a._move("previous",c);c.preventDefault();break;case d.DOWN:a._move("next",c);c.preventDefault();break;case d.ENTER:case d.NUMPAD_ENTER:a.menu.element.is(":visible")&&c.preventDefault();case d.TAB:if(!a.menu.active)return;a.menu.select(c);break;case d.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!=a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);
|
65
|
+
break}}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("<ul></ul>").addClass("ui-autocomplete").appendTo(e(this.options.appendTo||"body",b)[0]).mousedown(function(c){var d=a.menu.element[0];
|
66
|
+
c.target===d&&setTimeout(function(){e(document).one("mousedown",function(f){f.target!==a.element[0]&&f.target!==d&&!e.ui.contains(d,f.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,d){d=d.item.data("item.autocomplete");false!==a._trigger("focus",null,{item:d})&&/^key/.test(c.originalEvent.type)&&a.element.val(d.value)},selected:function(c,d){d=d.item.data("item.autocomplete");var f=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();
|
67
|
+
a.previous=f}if(false!==a._trigger("select",c,{item:d})){a.term=d.value;a.element.val(d.value)}a.close(c);a.selectedItem=d},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");
|
68
|
+
this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a,b){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(e(b||"body",this.element[0].ownerDocument)[0])},_initSource:function(){var a=this,b,c;if(e.isArray(this.options.source)){b=this.options.source;this.source=function(d,f){f(e.ui.autocomplete.filter(b,d.term))}}else if(typeof this.options.source==="string"){c=this.options.source;this.source=
|
69
|
+
function(d,f){a.xhr&&a.xhr.abort();a.xhr=e.getJSON(c,d,function(g,i,h){h===a.xhr&&f(g);a.xhr=null})}}else this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search")!==false)return this._search(a)},_search:function(a){this.element.addClass("ui-autocomplete-loading");this.source({term:a},this.response)},_response:function(a){if(a.length){a=
|
70
|
+
this._normalize(a);this._suggest(a);this._trigger("open")}else this.close();this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return e.map(a,function(b){if(typeof b===
|
71
|
+
"string")return{label:b,value:b};return e.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(a){var b=this.menu.element.empty().zIndex(this.element.zIndex()+1),c;this._renderMenu(b,a);this.menu.deactivate();this.menu.refresh();this.menu.element.show().position(e.extend({of:this.element},this.options.position));a=b.width("").outerWidth();c=this.element.outerWidth();b.outerWidth(Math.max(a,c))},_renderMenu:function(a,b){var c=this;e.each(b,function(d,f){c._renderItem(a,f)})},
|
72
|
+
_renderItem:function(a,b){return e("<li></li>").data("item.autocomplete",b).append(e("<a></a>").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},
|
73
|
+
filter:function(a,b){var c=new RegExp(e.ui.autocomplete.escapeRegex(b),"i");return e.grep(a,function(d){return c.test(d.label||d.value||d)})}})})(jQuery);
|
74
|
+
(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(b){if(e(b.target).closest(".ui-menu-item a").length){b.preventDefault();a.select(b)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",
|
75
|
+
-1).mouseenter(function(b){a.activate(b,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.attr("scrollTop"),f=this.element.height();if(c<0)this.element.attr("scrollTop",d+c);else c>=f&&this.element.attr("scrollTop",d+c-f+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:b})},
|
76
|
+
deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);
|
77
|
+
a.length?this.activate(c,a):this.activate(c,this.element.children(b))}else this.activate(c,this.element.children(b))},nextPage:function(a){if(this.hasScroll())if(!this.active||this.last())this.activate(a,this.element.children(":first"));else{var b=this.active.offset().top,c=this.element.height(),d=this.element.children("li").filter(function(){var f=e(this).offset().top-b-c+e(this).height();return f<10&&f>-10});d.length||(d=this.element.children(":last"));this.activate(a,d)}else this.activate(a,this.element.children(!this.active||
|
78
|
+
this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last"));else{var b=this.active.offset().top,c=this.element.height();result=this.element.children("li").filter(function(){var d=e(this).offset().top-b+c-e(this).height();return d<10&&d>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},
|
79
|
+
hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})})(jQuery);
|
80
|
+
;
|
@@ -0,0 +1,24 @@
|
|
1
|
+
(function($) {
|
2
|
+
if (!('WebSocket' in window)) { alert("This browser does NOT support websockets and thus nirvana fail :("); }
|
3
|
+
|
4
|
+
var ws = new WebSocket("ws://127.0.0.1:8080");
|
5
|
+
ws.onmessage = function(e) {
|
6
|
+
var data = e.data;
|
7
|
+
if (data.match(/^:AUTOCOMPLETE:/)) {
|
8
|
+
var completions = $.parseJSON(data.replace(/^:AUTOCOMPLETE: /, ''));
|
9
|
+
$.readline.finishCompletion(completions);
|
10
|
+
} else {
|
11
|
+
$.repl.logResult(data);
|
12
|
+
}
|
13
|
+
};
|
14
|
+
ws.onclose = function() {
|
15
|
+
$.repl.disable();
|
16
|
+
return $.repl.log("<div class='nirvana_exception'>nirvana: websocket closed</div>");
|
17
|
+
};
|
18
|
+
ws.onerror = function() {
|
19
|
+
return $.repl.log("<div class='nirvana_exception'>nirvana: websocket error</div>");
|
20
|
+
};
|
21
|
+
|
22
|
+
$.ws = function() { return ws };
|
23
|
+
$.ws.nirvanaComplete = function(val) { ws.send(':AUTOCOMPLETE: '+val); };
|
24
|
+
})(jQuery);
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'ripl/completion'
|
3
|
+
|
4
|
+
module Nirvana
|
5
|
+
module Shell
|
6
|
+
def web_loop_once(input)
|
7
|
+
super
|
8
|
+
@eval_error = nil
|
9
|
+
@input[/^:AUTOCOMPLETE:/] ? get_completions(@input) : loop_once
|
10
|
+
rescue Exception => e
|
11
|
+
exit if e.message[/^uncaught throw `ripl_exit'/]
|
12
|
+
html_error(e, "Internal #{@name} error: ")
|
13
|
+
end
|
14
|
+
|
15
|
+
def print_result(result)
|
16
|
+
@eval_error || format_result(@result)
|
17
|
+
end
|
18
|
+
|
19
|
+
def loop_eval(str)
|
20
|
+
@stdout, @stderr, result = Util.capture_all { super(str) }
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
def print_eval_error(error)
|
25
|
+
@eval_error = html_error(error, '')
|
26
|
+
end
|
27
|
+
|
28
|
+
def format_result(result)
|
29
|
+
output = Util.format_output @stdout + super
|
30
|
+
output = "<div class='nirvana_warning'>#{@stderr}</div>" + output unless @stderr.to_s.empty?
|
31
|
+
output
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def html_error(error, message)
|
36
|
+
"<span class='nirvana_exception'>#{Util.format_output(message + format_error(error))}</span>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_completions(input)
|
40
|
+
arr = completions input.sub(/^:AUTOCOMPLETE:\s*/, '')
|
41
|
+
':AUTOCOMPLETE: ' + JSON.generate(arr)
|
42
|
+
end
|
43
|
+
|
44
|
+
def completions(line_buffer)
|
45
|
+
input = line_buffer[/([^#{Bond::Readline::DefaultBreakCharacters}]+)$/,1]
|
46
|
+
arr = Bond.agent.call(input || line_buffer, line_buffer)
|
47
|
+
return [] if arr[0].to_s[/^Bond Error:/] #silence bond debug errors
|
48
|
+
return arr if input == line_buffer
|
49
|
+
chopped_input = line_buffer.sub(/#{Regexp.quote(input.to_s)}$/, '')
|
50
|
+
arr.map {|e| chopped_input + e }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Ripl::Shell.send :include, Nirvana::Shell
|
data/lib/nirvana/util.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'escape_utils'
|
3
|
+
|
4
|
+
module Nirvana
|
5
|
+
module Util
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def capture_stdout
|
9
|
+
out = StringIO.new
|
10
|
+
$stdout = out
|
11
|
+
yield
|
12
|
+
return out.string
|
13
|
+
ensure
|
14
|
+
$stdout = STDOUT
|
15
|
+
end
|
16
|
+
|
17
|
+
def capture_stderr
|
18
|
+
out = StringIO.new
|
19
|
+
$stderr = out
|
20
|
+
yield
|
21
|
+
return out.string
|
22
|
+
ensure
|
23
|
+
$stderr = STDERR
|
24
|
+
end
|
25
|
+
|
26
|
+
def capture_all
|
27
|
+
stdout, stderr, result = nil
|
28
|
+
stderr = capture_stderr do
|
29
|
+
stdout = capture_stdout do
|
30
|
+
result = yield
|
31
|
+
end
|
32
|
+
end
|
33
|
+
[stdout, stderr, result]
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_output(response)
|
37
|
+
EscapeUtils.escape_html(response).gsub("\n", "<br>").gsub("\t", " ").gsub(" ", " ")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'em-websocket'
|
2
|
+
require 'nirvana'
|
3
|
+
|
4
|
+
module Nirvana
|
5
|
+
module Websocket
|
6
|
+
def self.run
|
7
|
+
EventMachine.run do
|
8
|
+
EventMachine::WebSocket.start(:host => '127.0.0.1', :port => 8080) do |ws|
|
9
|
+
ws.onopen {
|
10
|
+
result = Nirvana.start_shell
|
11
|
+
ws.send(result) unless result.to_s.empty?
|
12
|
+
}
|
13
|
+
ws.onmessage {|msg| ws.send Ripl.shell.web_loop_once(msg) }
|
14
|
+
ws.onclose { Ripl.shell.after_loop }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
rescue
|
18
|
+
message = "Unable to start websocket since port 8080 is occupied"
|
19
|
+
message = $!.message unless $!.message[/no acceptor/]
|
20
|
+
abort "nirvana websocket error: #{message}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ripl/web.rb
ADDED
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nirvana
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Gabriel Horner
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-12 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: ripl
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 21
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 2
|
33
|
+
- 1
|
34
|
+
version: 0.2.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: escape_utils
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 11
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 1
|
49
|
+
- 8
|
50
|
+
version: 0.1.8
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: json_pure
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 1
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 4
|
65
|
+
- 3
|
66
|
+
version: 1.4.3
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: em-websocket
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 19
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
- 1
|
81
|
+
- 4
|
82
|
+
version: 0.1.4
|
83
|
+
type: :runtime
|
84
|
+
version_requirements: *id004
|
85
|
+
description: A ruby web shell that has autocompletion and readline behavior. It uses websockets, repl.js, readline.js and ripl for the shell engine.
|
86
|
+
email: gabriel.horner@gmail.com
|
87
|
+
executables:
|
88
|
+
- nirvana
|
89
|
+
- nirvana-websocket
|
90
|
+
extensions: []
|
91
|
+
|
92
|
+
extra_rdoc_files:
|
93
|
+
- README.rdoc
|
94
|
+
- LICENSE.txt
|
95
|
+
files:
|
96
|
+
- lib/nirvana/shell.rb
|
97
|
+
- lib/nirvana/util.rb
|
98
|
+
- lib/nirvana/version.rb
|
99
|
+
- lib/nirvana/websocket.rb
|
100
|
+
- lib/nirvana.rb
|
101
|
+
- lib/ripl/web.rb
|
102
|
+
- bin/nirvana
|
103
|
+
- bin/nirvana-websocket
|
104
|
+
- LICENSE.txt
|
105
|
+
- CHANGELOG.rdoc
|
106
|
+
- README.rdoc
|
107
|
+
- deps.rip
|
108
|
+
- Rakefile
|
109
|
+
- .gemspec
|
110
|
+
- lib/nirvana/public/css/jquery.readline.css
|
111
|
+
- lib/nirvana/public/css/jquery.repl.css
|
112
|
+
- lib/nirvana/public/css/jquery.ui.autocomplete.css
|
113
|
+
- lib/nirvana/public/css/nirvana.css
|
114
|
+
- lib/nirvana/public/index.html
|
115
|
+
- lib/nirvana/public/js/jquery.hotkeys.js
|
116
|
+
- lib/nirvana/public/js/jquery.min.js
|
117
|
+
- lib/nirvana/public/js/jquery.readline.js
|
118
|
+
- lib/nirvana/public/js/jquery.repl.js
|
119
|
+
- lib/nirvana/public/js/jquery.ui.autocomplete.min.js
|
120
|
+
- lib/nirvana/public/js/nirvana.js
|
121
|
+
- lib/nirvana/public/images/spinner.gif
|
122
|
+
has_rdoc: true
|
123
|
+
homepage: http://github.com/cldwalker/nirvana
|
124
|
+
licenses:
|
125
|
+
- MIT
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options: []
|
128
|
+
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
hash: 3
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
version: "0"
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
hash: 23
|
146
|
+
segments:
|
147
|
+
- 1
|
148
|
+
- 3
|
149
|
+
- 6
|
150
|
+
version: 1.3.6
|
151
|
+
requirements: []
|
152
|
+
|
153
|
+
rubyforge_project: tagaholic
|
154
|
+
rubygems_version: 1.3.7
|
155
|
+
signing_key:
|
156
|
+
specification_version: 3
|
157
|
+
summary: A ruby web shell that is very ape and very nice
|
158
|
+
test_files: []
|
159
|
+
|