terminus 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +61 -0
- data/bin/terminus +33 -0
- data/lib/public/js.packages.js +1 -0
- data/lib/public/style.css +44 -0
- data/lib/public/terminus.js +15 -0
- data/lib/terminus.rb +23 -0
- data/lib/terminus/application.rb +24 -0
- data/lib/terminus/server.rb +48 -0
- data/lib/views/bookmarklet.erb +40 -0
- data/lib/views/index.erb +29 -0
- metadata +133 -0
data/README.rdoc
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
= Terminus
|
2
|
+
|
3
|
+
* http://github.com/jcoglan/terminus
|
4
|
+
|
5
|
+
Terminus is a distributed JavaScript terminal. It lets you connect
|
6
|
+
web browsers you have open to a command-line console and run code
|
7
|
+
on all connected browsers at once. It's currently a toy, but it
|
8
|
+
might turn into a useful debugging and testing tool. We'll see.
|
9
|
+
|
10
|
+
|
11
|
+
== Installation
|
12
|
+
|
13
|
+
sudo gem install terminus
|
14
|
+
|
15
|
+
|
16
|
+
== Usage
|
17
|
+
|
18
|
+
In your terminal, run the +terminus+ command. You can optionally
|
19
|
+
specify a port for it to open up like this:
|
20
|
+
|
21
|
+
terminus --port 7004
|
22
|
+
|
23
|
+
You should see something like this:
|
24
|
+
|
25
|
+
Terminus running at http://0.0.0.0:7004
|
26
|
+
>>
|
27
|
+
|
28
|
+
This is the Terminus prompt - it's where you type in JavaScript
|
29
|
+
commands. Before you do that, though, visit http://localhost:7004
|
30
|
+
in your browser. From there you can grab a bookmarklet that lets
|
31
|
+
you connect any web page to the Terminus server. When you click
|
32
|
+
the bookmarklet, the current page will open a connection with
|
33
|
+
Terminus so that any commands you type into the shell are executed
|
34
|
+
on that page.
|
35
|
+
|
36
|
+
|
37
|
+
== License
|
38
|
+
|
39
|
+
(The MIT License)
|
40
|
+
|
41
|
+
Copyright (c) 2010 James Coglan
|
42
|
+
|
43
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
44
|
+
a copy of this software and associated documentation files (the
|
45
|
+
'Software'), to deal in the Software without restriction, including
|
46
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
47
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
48
|
+
permit persons to whom the Software is furnished to do so, subject to
|
49
|
+
the following conditions:
|
50
|
+
|
51
|
+
The above copyright notice and this permission notice shall be
|
52
|
+
included in all copies or substantial portions of the Software.
|
53
|
+
|
54
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
55
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
56
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
57
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
58
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
59
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
60
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
61
|
+
|
data/bin/terminus
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'readline'
|
5
|
+
require 'oyster'
|
6
|
+
require File.dirname(__FILE__) + '/../lib/terminus'
|
7
|
+
|
8
|
+
spec = Oyster.spec do
|
9
|
+
name "terminus -- controll web browsers from the command line"
|
10
|
+
synopsis "terminus [--port PORT]"
|
11
|
+
|
12
|
+
integer :port, :default => 7004
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
options = spec.parse
|
17
|
+
app = Terminus.create(options)
|
18
|
+
|
19
|
+
app.run!
|
20
|
+
puts "Terminus running at http://0.0.0.0:#{options[:port]}"
|
21
|
+
puts "Press CTRL-C to exit"
|
22
|
+
|
23
|
+
trap("INT") { app.stop! ; exit }
|
24
|
+
|
25
|
+
loop {
|
26
|
+
script, result = Readline.readline('>> '), nil
|
27
|
+
Readline::HISTORY.push(script)
|
28
|
+
app.execute(script) { |r| result = r }
|
29
|
+
}
|
30
|
+
|
31
|
+
rescue Oyster::HelpRendered
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
this.JS=this.JS||{};JS.Package=function(a){var b=JS.Package.OrderedSet;JS.Package._3(this);this._0=a;this._1=new b();this._4=new b();this._9=new b();this._2={};this._5={}};(function(f){var l=f.OrderedSet=function(a,b){this._a=this.list=[];this._3={};if(!a)return;for(var c=0,d=a.length;c<d;c++)this.push(b?b(a[c]):a[c])};l.prototype.push=function(a){var b=(a.id!==undefined)?a.id:a,c=this._3;if(c.hasOwnProperty(b))return;c[b]=this._a.length;this._a.push(a)};f._b=this;if((this.document||{}).getElementsByTagName){var m=document.getElementsByTagName('script')[0];f._i=(m.readyState!==undefined)}var h=f.prototype;h.addDependency=function(a){this._4.push(a)};h.addSoftDependency=function(a){this._9.push(a)};h.addName=function(a){this._1.push(a);f.getFromCache(a).pkg=this};h.onload=function(a){this._c=a};h.on=function(a,b,c){if(this._5[a])return b.call(c);var d=this._2[a]=this._2[a]||[];d.push([b,c])};h.fire=function(a){if(this._5[a])return false;this._5[a]=true;var b=this._2[a];if(!b)return true;delete this._2[a];for(var c=0,d=b.length;c<d;c++)b[c][0].call(b[c][1]);return true};h.isLoaded=function(a){if(!a&&this._6!==undefined)return this._6;var b=this._1.list,c=b.length,d,e;while(c--){d=b[c];e=f.getObject(d);if(e!==undefined)continue;if(a)throw new Error('Expected package at '+this._0+' to define '+d);else return this._6=false}return this._6=true};h.load=function(){if(!this.fire('request'))return;var c=this._4.list.concat(this._9.list),d='load',e={};e[d]=this._4.list;f.when(e,function(){f.when({complete:c,load:[this]},function(){this.fire('complete')},this);var a=this,b=function(){if(a._c)a._c();a.isLoaded(true);a.fire('load')};if(this.isLoaded()){this.fire('download');return this.fire('load')}if(this._0===undefined)throw new Error('No load path found for '+this._1.list[0]);typeof this._0==='function'?this._0(b):f.Loader.loadFile(this._0,b);this.fire('download')},this)};h.toString=function(){return'Package:'+this._1.list.join(',')};f.when=function(b,c,d){var e=[],g,j,i;for(g in b){if(!b.hasOwnProperty(g))continue;j=new f.OrderedSet(b[g],function(a){return f.getByName(a)});i=j.list.length;while(i--)e.push([g,j.list[i]])}var k=i=e.length;if(k===0)return c&&c.call(d);while(i--){e[i][1].on(e[i][0],function(){k-=1;if(k===0&&c)c.call(d)});e[i][1].load()}};f._d=1;f._e={};f._f={};f._3=function(a){a.id=this._d;this._d+=1};f.getByPath=function(a){var b=a.toString();return this._e[b]=this._e[b]||new this(a)};f.getByName=function(a){if(typeof a!=='string')return a;var b=this.getFromCache(a);if(b.pkg)return b.pkg;var c=new this();c.addName(a);return c};f.getFromCache=function(a){return this._f[a]=this._f[a]||{}};f.getObject=function(a){var b=this.getFromCache(a);if(b.obj!==undefined)return b.obj;var c=this._b,d=a.split('.'),e;while(e=d.shift())c=c&&c[e];return this.getFromCache(a).obj=c}})(JS.Package);JS.Package.DomLoader={usable:function(){return!!JS.Package.getObject('window.document.getElementsByTagName')},__FILE__:function(){var a=document.getElementsByTagName('script');return a[a.length-1].src},loadFile:function(c,d){var e=this,g=document.createElement('script');g.type='text/javascript';g.src=c;g.onload=g.onreadystatechange=function(){var a=g.readyState,b=g.status;if(!a||a==='loaded'||a==='complete'||(a===4&&b===200)){d();g.onload=g.onreadystatechange=e._g;g=null}};if(window.console&&console.info)console.info('Loading '+c);document.getElementsByTagName('head')[0].appendChild(g)},_g:function(){}};JS.Package.ServerLoader={usable:function(){return typeof JS.Package.getObject('load')==='function'&&typeof JS.Package.getObject('version')==='function'},setup:function(){var b=this;load=(function(a){return function(){b._h=arguments[0];return a.apply(JS.Package._b,arguments)}})(load)},__FILE__:function(){return this._h},loadFile:function(a,b){load(a);b()}};(function(){var a=[JS.Package.DomLoader,JS.Package.ServerLoader],b=a.length,c,d;for(c=0;c<b;c++){d=a[c];if(d.usable()){JS.Package.Loader=d;if(d.setup)d.setup();break}}})();JS.Package.DSL={__FILE__:function(){return JS.Package.Loader.__FILE__()},pkg:function(a,b){var c=b?JS.Package.getByPath(b):JS.Package.getByName(a);c.addName(a);return new JS.Package.Description(c)},file:function(a){var b=JS.Package.getByPath(a);return new JS.Package.Description(b)},load:function(a,b){JS.Package.Loader.loadFile(a,b)}};JS.Package.Description=function(a){this._7=a};(function(e){e._8=function(a,b){var c=b.length,a=this._7[a],d;for(d=0;d<c;d++)a.call(this._7,b[d]);return this};e.provides=function(){return this._8('addName',arguments)};e.requires=function(){return this._8('addDependency',arguments)};e.uses=function(){return this._8('addSoftDependency',arguments)};e.setup=function(a){this._7.onload(a);return this}})(JS.Package.Description.prototype);JS.Package.DSL.loader=JS.Package.DSL.file;JS.Packages=function(a){a.call(JS.Package.DSL)};JS.require=function(){var a=[],b=0;while(typeof arguments[b]==='string'){a.push(arguments[b]);b+=1}JS.Package.when({complete:a},arguments[b],arguments[b+1])};require=JS.require;
|
@@ -0,0 +1,44 @@
|
|
1
|
+
body {
|
2
|
+
background: #222;
|
3
|
+
margin: 0;
|
4
|
+
padding: 40px;
|
5
|
+
}
|
6
|
+
|
7
|
+
.container {
|
8
|
+
background: #fff;
|
9
|
+
color: #444;
|
10
|
+
margin: 0 auto;
|
11
|
+
padding: 40px;
|
12
|
+
width: 400px;
|
13
|
+
font: 16px/1.5 Georgia, Times New Roman, serif;
|
14
|
+
}
|
15
|
+
|
16
|
+
.footer {
|
17
|
+
margin: 0 auto;
|
18
|
+
padding: 40px;
|
19
|
+
width: 400px;
|
20
|
+
color: #fff;
|
21
|
+
font: 13px Helvetica, Arial, sans-serif;
|
22
|
+
}
|
23
|
+
|
24
|
+
h1 {
|
25
|
+
font: bold 64px Helvetica, Arial, sans-serif;
|
26
|
+
letter-spacing: -0.03em;
|
27
|
+
margin: 0 0 32px;
|
28
|
+
color: #f00846;
|
29
|
+
}
|
30
|
+
|
31
|
+
a {
|
32
|
+
color: #f00846;
|
33
|
+
text-decoration: none;
|
34
|
+
}
|
35
|
+
|
36
|
+
a:hover {
|
37
|
+
background: #f00846;
|
38
|
+
color: #fff;
|
39
|
+
}
|
40
|
+
|
41
|
+
p {
|
42
|
+
margin: 0;
|
43
|
+
}
|
44
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Terminus = {
|
2
|
+
connect: function(endpoint) {
|
3
|
+
if (this._client) return;
|
4
|
+
|
5
|
+
this._client = new Faye.Client(endpoint);
|
6
|
+
this._client.subscribe('/terminus/commands', function(message) {
|
7
|
+
this.execute(message.command);
|
8
|
+
}, this);
|
9
|
+
},
|
10
|
+
|
11
|
+
execute: function(command) {
|
12
|
+
eval(command);
|
13
|
+
}
|
14
|
+
};
|
15
|
+
|
data/lib/terminus.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rack'
|
3
|
+
require 'thin'
|
4
|
+
require 'eventmachine'
|
5
|
+
require 'faye'
|
6
|
+
require 'sinatra'
|
7
|
+
require 'packr'
|
8
|
+
|
9
|
+
%w[application server].each do |file|
|
10
|
+
require File.join(File.dirname(__FILE__), 'terminus', file)
|
11
|
+
end
|
12
|
+
|
13
|
+
Thin::Logging.silent = true
|
14
|
+
|
15
|
+
module Terminus
|
16
|
+
VERSION = '0.1.0'
|
17
|
+
FAYE_MOUNT = '/messaging'
|
18
|
+
|
19
|
+
def self.create(options = {})
|
20
|
+
Server.new(options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Application < Sinatra::Base
|
3
|
+
|
4
|
+
ROOT = File.expand_path(File.dirname(__FILE__) + '/../')
|
5
|
+
|
6
|
+
set :static, true
|
7
|
+
set :public, ROOT + '/public'
|
8
|
+
set :views, ROOT + '/views'
|
9
|
+
|
10
|
+
helpers do
|
11
|
+
def host
|
12
|
+
"http://#{ env['HTTP_HOST'] }"
|
13
|
+
end
|
14
|
+
|
15
|
+
def bookmarklet
|
16
|
+
Packr.pack(erb(:bookmarklet), :shrink_vars => true)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
get('/') { erb :index }
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Terminus
|
2
|
+
class Server
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute(script, &callback)
|
9
|
+
messenger.publish('/terminus/commands', :command => script)
|
10
|
+
end
|
11
|
+
|
12
|
+
def running?
|
13
|
+
not @server.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def run!
|
17
|
+
return if running?
|
18
|
+
handler = Rack::Handler.get('thin')
|
19
|
+
ensure_reactor_running!
|
20
|
+
handler.run(app, :Port => @options[:port]) { |s| @server = s }
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop!
|
24
|
+
return unless running?
|
25
|
+
@server.stop!
|
26
|
+
@server = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def app
|
32
|
+
return @app if defined?(@app)
|
33
|
+
frontend = Application.new
|
34
|
+
@app = Faye::RackAdapter.new(frontend, :mount => FAYE_MOUNT, :timeout => 15)
|
35
|
+
end
|
36
|
+
|
37
|
+
def messenger
|
38
|
+
app.get_client
|
39
|
+
end
|
40
|
+
|
41
|
+
def ensure_reactor_running!
|
42
|
+
Thread.new { EM.run unless EM.reactor_running? }
|
43
|
+
while not EM.reactor_running?; end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
(function() {
|
2
|
+
var faye = '<%= ::Terminus::FAYE_MOUNT %>',
|
3
|
+
host = '<%= host %>';
|
4
|
+
|
5
|
+
var withPackageManager = function(callback) {
|
6
|
+
if (window.JS && JS.Packages) return callback();
|
7
|
+
|
8
|
+
var script = document.createElement('script'),
|
9
|
+
head = document.getElementsByTagName('head')[0];
|
10
|
+
|
11
|
+
script.type = 'text/javascript';
|
12
|
+
script.src = host + '/js.packages.js';
|
13
|
+
|
14
|
+
script.onload = script.onreadystatechange = function() {
|
15
|
+
var state = script.readyState;
|
16
|
+
if (!state || state === 'loaded' || state === 'complete') {
|
17
|
+
script.onload = script.onreadystatechange = null;
|
18
|
+
head.removeChild(script);
|
19
|
+
callback();
|
20
|
+
}
|
21
|
+
};
|
22
|
+
head.appendChild(script);
|
23
|
+
};
|
24
|
+
|
25
|
+
withPackageManager(function() {
|
26
|
+
JS.Packages(function() {
|
27
|
+
this.file(host + faye + '/client.js')
|
28
|
+
.provides('Faye', 'Faye.Client');
|
29
|
+
|
30
|
+
this.file(host + '/terminus.js')
|
31
|
+
.requires('Faye.Client')
|
32
|
+
.provides('Terminus');
|
33
|
+
});
|
34
|
+
|
35
|
+
require('Terminus', function() {
|
36
|
+
Terminus.connect(host + faye);
|
37
|
+
});
|
38
|
+
});
|
39
|
+
})();
|
40
|
+
|
data/lib/views/index.erb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
6
|
+
<link rel="stylesheet" type="text/css" href="/style.css">
|
7
|
+
<title>Terminus</title>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<div class="container">
|
12
|
+
<h1><a href="javascript:<%= bookmarklet %>">Terminus</a>.</h1>
|
13
|
+
|
14
|
+
<p>Terminus is a distributed JavaScript console. You can find out
|
15
|
+
more at <a href="http://github.com/jcoglan/terminus">its GitHub page</a>.
|
16
|
+
To connect the console to your browser, you’ll need this
|
17
|
+
bookmarklet. Just drag the word ‘Terminus’ up to your
|
18
|
+
bookmark toolbar and click it to connect any page to your console.</p>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="footer">
|
22
|
+
<p>Copyright © 2010
|
23
|
+
<a href="http://jcoglan.com">James Coglan</a>.
|
24
|
+
Released under the MIT license.</p>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
</body>
|
28
|
+
</html>
|
29
|
+
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: terminus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Coglan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-04-05 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thin
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "1.2"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: eventmachine
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0.12"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: faye
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.3.2
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sinatra
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "1.0"
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: packr
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "3.1"
|
74
|
+
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: oyster
|
77
|
+
type: :runtime
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0.9"
|
84
|
+
version:
|
85
|
+
description:
|
86
|
+
email: jcoglan@googlemail.com
|
87
|
+
executables:
|
88
|
+
- terminus
|
89
|
+
extensions: []
|
90
|
+
|
91
|
+
extra_rdoc_files:
|
92
|
+
- README.rdoc
|
93
|
+
files:
|
94
|
+
- README.rdoc
|
95
|
+
- lib/terminus.rb
|
96
|
+
- lib/public/style.css
|
97
|
+
- lib/public/terminus.js
|
98
|
+
- lib/public/js.packages.js
|
99
|
+
- lib/views/bookmarklet.erb
|
100
|
+
- lib/views/index.erb
|
101
|
+
- lib/terminus/server.rb
|
102
|
+
- lib/terminus/application.rb
|
103
|
+
has_rdoc: true
|
104
|
+
homepage: http://github.com/jcoglan/terminus
|
105
|
+
licenses: []
|
106
|
+
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options:
|
109
|
+
- --main
|
110
|
+
- README.rdoc
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: "0"
|
118
|
+
version:
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: "0"
|
124
|
+
version:
|
125
|
+
requirements: []
|
126
|
+
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.3.5
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: Control multiple web browsers from the command line
|
132
|
+
test_files: []
|
133
|
+
|