websocket-gui 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f9b2ada3cef153c8ebd85ff255e143068f21dcd
4
+ data.tar.gz: 0d95a12c9c9fdf239b5f9f4ca26d598766a600cd
5
+ SHA512:
6
+ metadata.gz: b1ba9084cbfcd657ea4e3cda19fbf071ce5497925d2537ca5d219b30b7038eb4c225dfbe4efbb1a7fe753df9721953b8d110a4843fb2a5776e4aed2efe289fc8
7
+ data.tar.gz: 7bf16018e44381dded3b25ea882ed0155d9339b6bdc631ff832ec8c8078ae9e927ab04270d47150dfbbe2f8e0d031225c075e71be51a49207d4b8a7c5ccc05f5
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.swp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jason
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # Websocket Gui
2
+ This gem uses Sinatra, EventMachine, and Web Sockets to make it easy to use the browser as a GUI for Ruby apps that
3
+ would otherwise be stuck in the console.
4
+
5
+
6
+ ## Using Websocket Gui
7
+ To use this gem, make a class that extends WebsocketGui::Base and a HTML/JS file to serve as the GUI.
8
+
9
+
10
+ ### Configuration
11
+ The following configuration options are available:
12
+ :socket_port (8080)
13
+ :socket_host (127.0.0.1)
14
+ :http_port (3000)
15
+ :http_host (127.0.0.1)
16
+ :view (:index)
17
+ :tick_interval (nil)
18
+
19
+ The options can be set in several ways, each level overriding the previous:
20
+ 1 In declaring your subclass of WebsocketGui::Base (like tick\_interval below)
21
+ 1 By passing an options hash to the initializer
22
+ 1 By passing an options hash to the run! method
23
+
24
+
25
+ ### project-root/app.rb
26
+ require 'websocket-gui'
27
+
28
+ class App < WebsocketGui::Base
29
+
30
+ # specify the name of the file containing the HTML of the app (this is a single-page app)
31
+ # ex. Look in root directory for frontendfile.erb instead of index.erb (which is the default)
32
+ #view :frontendfile
33
+
34
+ # set the time (seconds) between calls to 'on_tick'
35
+ # if nil (default), on_tick will not fire
36
+ tick_interval 0.1
37
+
38
+ # code for the on_tick event
39
+ on_tick do |connected|
40
+ @tick_block.call(connected)
41
+ end
42
+
43
+ # code for the on_socket_open event
44
+ on_socket_open do |handshake|
45
+ socket_send "Welcome!!!"
46
+ puts "Client connection opened:"
47
+ puts "#{handshake.inspect}"
48
+ end
49
+
50
+ # code for the on_socket_recv event
51
+ on_socket_recv do |msg|
52
+ puts "Received message from client: #{msg.strip}"
53
+ socket_send "I received your message: #{msg.strip}"
54
+ end
55
+
56
+ # code for the on_socket_close event
57
+ on_socket_close do
58
+ puts "Socket closed."
59
+ end
60
+ end
61
+
62
+ # specify options in the constructor and/or the run method.
63
+ instance = App.new http_port: 3000, http_host: '127.0.0.1'
64
+ instance.run! socket_port: 8080, socket_host: '127.0.0.1'
65
+
66
+
67
+
68
+ ### project-root/index.erb
69
+
70
+ <!doctype html>
71
+ <html>
72
+ <head>
73
+ <title>Test Web Sockets</title>
74
+ <meta charset="utf-8" />
75
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
76
+ </head>
77
+
78
+ <body>
79
+ <div id="connectedContainer" style="display:none;">
80
+ <textarea id="input"></textarea>
81
+ <input type="button" id="send" value="Send" />
82
+
83
+ <ul id="output"></ul>
84
+ <input type="button" id="disconnect" value="Disconnect" />
85
+ </div>
86
+ <div id="notConnectedContainer">
87
+ <input type="button" id="connect" value="Connect" />
88
+ </div>
89
+ <script type="text/javascript">
90
+ var socket;
91
+ var connect = function () {
92
+ socket = new WebSocket("ws://localhost:8080");
93
+ var writeMessage = function (msg) {
94
+ $("<li></li>").text (msg).appendTo ($("#output"));
95
+ };
96
+ socket.onmessage = function (evt) {
97
+ writeMessage (evt.data);
98
+ };
99
+ socket.onclose = function () {
100
+ writeMessage ("Socket Closed!");
101
+ $("#connectedContainer").hide ();
102
+ $("#notConnectedContainer").show();
103
+ $("#output li").remove ();
104
+ }
105
+ socket.onopen = function () {
106
+ writeMessage ("Socket Opened!");
107
+ $("#connectedContainer").show ();
108
+ $("#notConnectedContainer").hide ();
109
+ }
110
+ $("#send").on ('click', function () {
111
+ var input = $("#input");
112
+ if (input.val ())
113
+ {
114
+ socket.send(input.val ());
115
+ input.val ('');
116
+ }
117
+ });
118
+ }
119
+ $("#connect").on ('click', function () { connect (); } );
120
+ $("#disconnect").on ('click', function () { socket.close (); });
121
+
122
+ </script>
123
+ </body>
124
+ </html>
125
+
126
+
127
+ ## file structure
128
+ project-root/
129
+ app.rb
130
+ index.erb
131
+ ... (up to you)
132
+
133
+
134
+ ## running the app (from the project dir)
135
+ $ ruby app.rb
136
+
137
+ This will start the socket server and sinatra, and launch a browser with your view.
138
+
139
+
140
+ ## todo
141
+ * Create a small JS library that wraps the native websocket and makes it easy to post events to the server.
142
+ * Expand event handlers so you can write events like `on_start do |params|` instead of having to do parse raw strings and do everything in on\_socket\_recv
143
+
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'date'
5
+
6
+ #################################################################################
7
+ #
8
+ # Some utilities to find out info about the package
9
+ #
10
+ #################################################################################
11
+
12
+ def name
13
+ @name ||= Dir['*.gemspec'].first.split('.').first
14
+ end
15
+
16
+ def version
17
+ line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
18
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
19
+ end
20
+
21
+ def gemspec_file
22
+ "#{name}.gemspec"
23
+ end
24
+
25
+ def gem_file
26
+ "pkg/#{name}-#{version}.gem"
27
+ end
28
+
29
+ #################################################################################
30
+ #
31
+ # Tasks
32
+ #
33
+ #################################################################################
34
+
35
+ desc "Run the tests"
36
+ task :default => :spec
37
+
38
+ require 'rspec/core/rake_task'
39
+ RSpec::Core::RakeTask.new(:spec)
40
+
41
+ desc "Build gem locally"
42
+ task :build => :validate do
43
+ system "gem build #{name}.gemspec"
44
+ FileUtils.mkdir_p "pkg"
45
+ FileUtils.mv "#{name}-#{version}.gem", gem_file
46
+ end
47
+
48
+ desc "Publish the gem to rubygems.org"
49
+ task :publish => :build do
50
+ system "gem push #{gem_file}"
51
+ end
52
+
53
+ desc "Install gem locally"
54
+ task :install => :build do
55
+ system "gem install #{gem_file}"
56
+ end
57
+
58
+ desc "Validate #{gemspec_file}"
59
+ task :validate do
60
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
61
+ unless libfiles.empty?
62
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
63
+ exit!
64
+ end
65
+ unless Dir['VERSION*'].empty?
66
+ puts "A `VERSION` file at root level violates Gem best practices."
67
+ exit!
68
+ end
69
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../../lib/websocket-gui', __FILE__)
2
+
3
+ class ExampleWebSocketApp < WebsocketGui::Base
4
+
5
+ tick_interval 5
6
+
7
+ on_tick do |connected|
8
+ puts "Tick: " + (connected ? "connected" : "not connected")
9
+ socket_send "Tick"
10
+ end
11
+
12
+ on_socket_open do |handshake|
13
+ socket_send "Socket opened. Welcome!!!"
14
+ puts "Client connection opened.\n Handshake:\n #{handshake.inspect}"
15
+ end
16
+
17
+ on_socket_recv do |msg|
18
+ puts "Received message from client: #{msg.strip}"
19
+ socket_send "I received your message: #{msg.strip}"
20
+ end
21
+
22
+ on_socket_close do
23
+ puts "Socket closed."
24
+ end
25
+ end
26
+
27
+ if __FILE__ == $0
28
+ example = ExampleWebSocketApp.new
29
+ example.run!
30
+ end
@@ -0,0 +1,63 @@
1
+ <!doctype html>
2
+
3
+ <html>
4
+
5
+ <head>
6
+ <title>Test Web Sockets</title>
7
+ <meta charset="utf-8" />
8
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
9
+ <style type="text/css">
10
+
11
+ </style>
12
+ </head>
13
+
14
+ <body>
15
+ <div id="connectedContainer" style="display:none;">
16
+ <textarea id="input"></textarea>
17
+ <input type="button" id="send" value="Send" />
18
+
19
+ <ul id="output"></ul>
20
+ <input type="button" id="disconnect" value="Disconnect" />
21
+ </div>
22
+ <div id="notConnectedContainer">
23
+ <input type="button" id="connect" value="Connect" />
24
+ </div>
25
+
26
+ <script type="text/javascript">
27
+ var socket;
28
+ var connect = function () {
29
+ socket = new WebSocket("ws://localhost:8080");
30
+ var writeMessage = function (msg) {
31
+ $("<li></li>").text (msg).appendTo ($("#output"));
32
+ };
33
+ socket.onmessage = function (evt) {
34
+ writeMessage (evt.data);
35
+ };
36
+ socket.onclose = function () {
37
+ writeMessage ("Socket Closed!");
38
+ $("#connectedContainer").hide ();
39
+ $("#notConnectedContainer").show();
40
+ $("#output li").remove ();
41
+ }
42
+ socket.onopen = function () {
43
+ writeMessage ("Socket Opened!");
44
+ $("#connectedContainer").show ();
45
+ $("#notConnectedContainer").hide ();
46
+ }
47
+ $("#send").on ('click', function () {
48
+ var input = $("#input");
49
+ if (input.val ())
50
+ {
51
+ socket.send(input.val ());
52
+ input.val ('');
53
+ }
54
+ });
55
+ }
56
+
57
+ $("#connect").on ('click', function () { connect (); } );
58
+ $("#disconnect").on ('click', function () { socket.close (); });
59
+
60
+ </script>
61
+ </body>
62
+
63
+ </html>
@@ -0,0 +1,79 @@
1
+ module WebsocketGui
2
+
3
+ class Base
4
+
5
+ # class-level config, so you can wire your settings into your class
6
+ # These can also be provided when calling run!
7
+ @@config = {
8
+ socket_port: 8080,
9
+ socket_host: '127.0.0.1',
10
+ http_port: 3000,
11
+ http_host: '127.0.0.1',
12
+ tick_interval: nil,
13
+ view: :index,
14
+ }
15
+ def self.method_missing(method, *args, &block)
16
+ if block_given?
17
+ @@config[method] = block
18
+ else
19
+ @@config[method] = args.first
20
+ end
21
+ end
22
+
23
+ attr_reader :config
24
+
25
+ def initialize(config = {})
26
+ @config = @@config.merge(config)
27
+ end
28
+
29
+ # start the socket server and the web server, and launch a browser to fetch the view from the web server
30
+ def run!(runtime_config = {})
31
+ @config.merge! runtime_config
32
+
33
+ EM.run do
34
+ if @config[:tick_interval]
35
+ EM.add_periodic_timer(@config[:tick_interval]) do
36
+ socket_trigger(:on_tick, @socket_connected)
37
+ end
38
+ end
39
+
40
+ EventMachine::WebSocket.run(host: @config[:socket_host], port: @config[:socket_port]) do |socket|
41
+ @socket_active = socket
42
+ socket.onopen do |handshake|
43
+ @socket_connected = true
44
+ socket_trigger(:on_socket_open, handshake)
45
+ end
46
+
47
+ socket.onmessage do |msg|
48
+ socket_trigger(:on_socket_recv, msg)
49
+ end
50
+
51
+ socket.onclose do
52
+ socket_trigger(:on_socket_close)
53
+ @socket_connected = false
54
+ end
55
+ end
56
+
57
+ Launchy.open("http://#{@config[:http_host]}:#{@config[:http_port]}/")
58
+ WebsocketGui::SinatraWrapper.view_path = @config[:view]
59
+ WebsocketGui::SinatraWrapper.run!(
60
+ port: @config[:http_port],
61
+ bind: @config[:http_host])
62
+ end
63
+ end
64
+
65
+ def socket_send(msg)
66
+ @socket_active.send msg if @socket_connected
67
+ end
68
+
69
+ def socket_close
70
+ @socket_active.stop if @socket_connected
71
+ end
72
+
73
+ private
74
+
75
+ def socket_trigger(method, *args)
76
+ self.instance_exec(*args, &@config[method]) if @config[method].kind_of? Proc
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,18 @@
1
+ module WebsocketGui
2
+ class SinatraWrapper < Sinatra::Base
3
+
4
+ set :views, './'
5
+
6
+ get '/' do
7
+ erb self.class.view_path
8
+ end
9
+
10
+ def self.view_path
11
+ @view_path || :index
12
+ end
13
+
14
+ def self.view_path=(view_path)
15
+ @view_path = view_path.to_sym
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module WebsocketGui
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,10 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require "em-websocket"
4
+ require "sinatra"
5
+ require "thin"
6
+ require "launchy"
7
+
8
+ require "websocket-gui/base"
9
+ require "websocket-gui/sinatra_wrapper"
10
+
data/spec/base_spec.rb ADDED
@@ -0,0 +1,44 @@
1
+ # the example loads dependencies AND gives us an example class to test
2
+ require File.expand_path('../../examples/example', __FILE__)
3
+
4
+ describe ExampleWebSocketApp do
5
+
6
+ it { should respond_to(:run!) }
7
+ it { should respond_to(:socket_send) }
8
+ it { should respond_to(:socket_close) }
9
+ its(:config) { should be_an_instance_of(Hash) }
10
+
11
+ context "override Base defaults" do
12
+ let(:example) {
13
+ ExampleWebSocketApp.new(http_port: 80, http_host: "localhost")
14
+ }
15
+ let(:config) { example.config }
16
+
17
+ it "has defaults inherited from Base" do
18
+ config[:socket_port].should equal(8080)
19
+ config[:socket_host].should match('127.0.0.1')
20
+ end
21
+
22
+ it "overrides defaults in subclass definition" do
23
+ config[:tick_interval].should equal(5)
24
+ config[:on_tick].should be_a_kind_of(Proc)
25
+ end
26
+
27
+ it "overrides defaults in constructor" do
28
+ config[:http_port].should equal(80)
29
+ config[:http_host].should match('localhost')
30
+ end
31
+ end
32
+
33
+ context "override subclass defaults" do
34
+ let(:example) {
35
+ ExampleWebSocketApp.new(tick_interval: 1)
36
+ }
37
+ let(:config) { example.config }
38
+
39
+ it "overrides already overridden defaults in constructor" do
40
+ config[:tick_interval].should equal(1)
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,18 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'websocket-gui/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "websocket-gui"
8
+ spec.version = WebsocketGui::VERSION
9
+ spec.authors = ["Jason Pollentier"]
10
+ spec.email = ["pollentj@gmail.com"]
11
+ spec.description = %q{Use Sinatra, Websockets, and EventMachine to create
12
+ an event-based GUI for Ruby projects that would otherwise be stuck in the console.
13
+ }
14
+ spec.summary = %q{Use the browser as a GUI for local Ruby apps.}
15
+ spec.homepage = ""
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.required_ruby_version = '~> 2.0'
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_runtime_dependency 'em-websocket', '~> 0.5.0'
28
+ spec.add_runtime_dependency 'sinatra', '~> 1.4.3'
29
+ spec.add_runtime_dependency 'thin', '>= 1.5.1'
30
+ spec.add_runtime_dependency 'launchy', '~> 2.3.0'
31
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: websocket-gui
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jason Pollentier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: em-websocket
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.5.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.5.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: sinatra
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 1.4.3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 1.4.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: thin
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: 1.5.1
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: 1.5.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: launchy
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 2.3.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 2.3.0
111
+ description: |
112
+ Use Sinatra, Websockets, and EventMachine to create
113
+ an event-based GUI for Ruby projects that would otherwise be stuck in the console.
114
+ email:
115
+ - pollentj@gmail.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - .gitignore
121
+ - .rspec
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - examples/example.rb
127
+ - examples/index.erb
128
+ - lib/websocket-gui.rb
129
+ - lib/websocket-gui/base.rb
130
+ - lib/websocket-gui/sinatra_wrapper.rb
131
+ - lib/websocket-gui/version.rb
132
+ - spec/base_spec.rb
133
+ - spec/spec_helper.rb
134
+ - websocket-gui.gemspec
135
+ homepage: ''
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ~>
146
+ - !ruby/object:Gem::Version
147
+ version: '2.0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.0.7
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Use the browser as a GUI for local Ruby apps.
159
+ test_files:
160
+ - spec/base_spec.rb
161
+ - spec/spec_helper.rb