bowline 0.6.2 → 0.6.3
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.txt +2 -8
- data/TODO +0 -2
- data/VERSION +1 -1
- data/bowline.gemspec +5 -2
- data/lib/bowline.rb +6 -9
- data/lib/bowline/app_config.rb +21 -34
- data/lib/bowline/binders.rb +69 -63
- data/lib/bowline/binders/observer.rb +1 -1
- data/lib/bowline/binders/singleton.rb +0 -5
- data/lib/bowline/commands/console.rb +2 -23
- data/lib/bowline/commands/generate.rb +2 -2
- data/lib/bowline/commands/init.rb +12 -0
- data/lib/bowline/commands/run.rb +1 -1
- data/lib/bowline/desktop.rb +1 -1
- data/lib/bowline/desktop/bridge.rb +35 -18
- data/lib/bowline/desktop/js.rb +8 -14
- data/lib/bowline/desktop/network.rb +1 -1
- data/lib/bowline/desktop/path.rb +18 -1
- data/lib/bowline/desktop/runtime.rb +20 -8
- data/lib/bowline/desktop/window_manager.rb +3 -3
- data/lib/bowline/ext/array.rb +2 -2
- data/lib/bowline/ext/object.rb +3 -3
- data/lib/bowline/generators.rb +43 -0
- data/lib/bowline/generators/application.rb +7 -3
- data/lib/bowline/initializer.rb +75 -22
- data/lib/bowline/library.rb +11 -27
- data/lib/bowline/tasks/app.rake +45 -9
- data/lib/bowline/tasks/libs.rake +0 -8
- data/lib/bowline/version.rb +1 -1
- data/templates/config/environment.rb +0 -4
- data/templates/config/environments/development.rb +0 -0
- data/templates/config/environments/production.rb +0 -0
- data/templates/main_window.rb +1 -1
- data/templates/script/init +2 -1
- data/templates/window.rb +1 -1
- metadata +6 -3
data/README.txt
CHANGED
@@ -12,7 +12,7 @@ Ruby, HTML and JS desktop application framework.
|
|
12
12
|
* Uses Webkit
|
13
13
|
* View in HTML/JavaScript
|
14
14
|
* Binding between HTML & Ruby
|
15
|
-
* Cross platform (
|
15
|
+
* Cross platform (OSX & Ubuntu) - Windows soon
|
16
16
|
|
17
17
|
= INTRODUCTION
|
18
18
|
|
@@ -114,12 +114,7 @@ Suffice to say, the HTML looks a bit like this:
|
|
114
114
|
<a href="#" class="destroy">Delete</a>
|
115
115
|
</div>
|
116
116
|
</div>
|
117
|
-
|
118
|
-
Now, were you to have a user object, you could do something like
|
119
|
-
this to update the HTML.
|
120
|
-
|
121
|
-
# TODO
|
122
|
-
|
117
|
+
|
123
118
|
= METHODS IN BINDERS
|
124
119
|
|
125
120
|
You can call both class and instance methods of the binders.
|
@@ -189,7 +184,6 @@ Usage for a collection (of users):
|
|
189
184
|
def admins
|
190
185
|
# This just replaces all the listed
|
191
186
|
# users with just admins
|
192
|
-
# TODO
|
193
187
|
self.items = User.admins.all
|
194
188
|
end
|
195
189
|
end
|
data/TODO
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.3
|
data/bowline.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bowline}
|
8
|
-
s.version = "0.6.
|
8
|
+
s.version = "0.6.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alex MacCaw"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-04-06}
|
13
13
|
s.default_executable = %q{bowline-gen}
|
14
14
|
s.description = %q{Ruby/JS GUI framework}
|
15
15
|
s.email = %q{alex@leadthinking.com}
|
@@ -55,6 +55,7 @@ Gem::Specification.new do |s|
|
|
55
55
|
"lib/bowline/commands/build.rb",
|
56
56
|
"lib/bowline/commands/console.rb",
|
57
57
|
"lib/bowline/commands/generate.rb",
|
58
|
+
"lib/bowline/commands/init.rb",
|
58
59
|
"lib/bowline/commands/run.rb",
|
59
60
|
"lib/bowline/desktop.rb",
|
60
61
|
"lib/bowline/desktop/app.rb",
|
@@ -102,6 +103,8 @@ Gem::Specification.new do |s|
|
|
102
103
|
"templates/config/boot.rb",
|
103
104
|
"templates/config/database.yml",
|
104
105
|
"templates/config/environment.rb",
|
106
|
+
"templates/config/environments/development.rb",
|
107
|
+
"templates/config/environments/production.rb",
|
105
108
|
"templates/gitignore",
|
106
109
|
"templates/helper.rb",
|
107
110
|
"templates/main_window.rb",
|
data/lib/bowline.rb
CHANGED
@@ -7,24 +7,19 @@ require 'active_support/core_ext/hash/indifferent_access'
|
|
7
7
|
Thread.abort_on_exception = true
|
8
8
|
|
9
9
|
module Bowline
|
10
|
-
def
|
10
|
+
def library_path
|
11
11
|
File.expand_path(
|
12
|
-
File.join(File.dirname(__FILE__),
|
12
|
+
File.join(File.dirname(__FILE__), "..")
|
13
13
|
)
|
14
14
|
end
|
15
|
-
module_function :
|
16
|
-
|
17
|
-
def assets_path
|
18
|
-
File.join(lib_path, "assets")
|
19
|
-
end
|
20
|
-
module_function :assets_path
|
15
|
+
module_function :library_path
|
21
16
|
|
22
17
|
module Base
|
23
18
|
end
|
24
19
|
end
|
25
20
|
|
26
21
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
27
|
-
$LOAD_PATH << File.join(Bowline.
|
22
|
+
$LOAD_PATH << File.join(Bowline.library_path, 'vendor')
|
28
23
|
|
29
24
|
require 'bowline/version'
|
30
25
|
|
@@ -46,9 +41,11 @@ require 'bowline/desktop/dock'
|
|
46
41
|
require 'bowline/desktop/host'
|
47
42
|
require 'bowline/desktop/misc'
|
48
43
|
require 'bowline/desktop/network'
|
44
|
+
require 'bowline/desktop/path'
|
49
45
|
require 'bowline/desktop/sound'
|
50
46
|
require 'bowline/desktop/window_methods'
|
51
47
|
require 'bowline/desktop/window'
|
48
|
+
require 'bowline/desktop/runtime'
|
52
49
|
require 'bowline/desktop/js'
|
53
50
|
require 'bowline/desktop/proxy'
|
54
51
|
require 'bowline/desktop/bridge'
|
data/lib/bowline/app_config.rb
CHANGED
@@ -1,41 +1,28 @@
|
|
1
|
+
require 'supermodel'
|
2
|
+
|
1
3
|
module Bowline
|
2
|
-
class AppConfig
|
3
|
-
|
4
|
-
def initialize(path)
|
5
|
-
@path = path
|
6
|
-
@keys = {}
|
7
|
-
load!
|
8
|
-
end
|
9
|
-
|
10
|
-
def load!
|
11
|
-
return unless File.exist?(path)
|
12
|
-
@keys = YAML::load(File.read(path))
|
13
|
-
end
|
14
|
-
|
15
|
-
def dump!
|
16
|
-
File.open(path, "w+") {|f| f.write(YAML::dump(keys)) }
|
17
|
-
end
|
18
|
-
|
19
|
-
def delete(key)
|
20
|
-
@keys.delete(key)
|
21
|
-
dump!
|
22
|
-
end
|
4
|
+
class AppConfig < SuperModel::Base
|
5
|
+
include SuperModel::Marshal::Model
|
23
6
|
|
24
|
-
|
25
|
-
|
7
|
+
class << self
|
8
|
+
def instance
|
9
|
+
@instance ||= create
|
10
|
+
end
|
11
|
+
|
12
|
+
def marshal_records(record = nil)
|
13
|
+
self.instance.load(record.attributes) if record
|
14
|
+
self.instance
|
15
|
+
end
|
26
16
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
keys[$`] = args.first
|
31
|
-
dump!
|
32
|
-
when "?"
|
33
|
-
keys[$`]
|
34
|
-
end
|
35
|
-
else
|
36
|
-
return keys[method_name] if keys.include?(method_name)
|
37
|
-
super
|
17
|
+
def load!(path)
|
18
|
+
self.instance.load_path(path)
|
19
|
+
self.instance
|
38
20
|
end
|
39
21
|
end
|
22
|
+
|
23
|
+
def load_path(path)
|
24
|
+
return unless path && File.exist?(path)
|
25
|
+
load(YAML::load(File.read(path)))
|
26
|
+
end
|
40
27
|
end
|
41
28
|
end
|
data/lib/bowline/binders.rb
CHANGED
@@ -60,7 +60,60 @@ module Bowline
|
|
60
60
|
extend Bowline::Desktop::Bridge::ClassMethods
|
61
61
|
js_expose
|
62
62
|
|
63
|
-
|
63
|
+
module Async
|
64
|
+
protected
|
65
|
+
def async(*methods)
|
66
|
+
if block_given?
|
67
|
+
Thread.new(callback_proc) do |proc|
|
68
|
+
begin
|
69
|
+
self.callback_proc = proc
|
70
|
+
yield
|
71
|
+
rescue => e
|
72
|
+
Bowline::Logging.log_error(e)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
else
|
76
|
+
methods.each do |method|
|
77
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
78
|
+
def #{method}_with_async(*args, &block)
|
79
|
+
async { #{method}_without_async(*args, &block) }
|
80
|
+
end
|
81
|
+
EOS
|
82
|
+
alias_method_chain method, :async
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
extend Async
|
89
|
+
include Async
|
90
|
+
class << self; extend Async; end
|
91
|
+
|
92
|
+
class << self
|
93
|
+
def callback_proc(proc = nil) #:nodoc:
|
94
|
+
Thread.current[:callback] = proc if proc
|
95
|
+
Thread.current[:callback]
|
96
|
+
end
|
97
|
+
alias_method :callback_proc=, :callback_proc
|
98
|
+
|
99
|
+
def callback(result = nil)
|
100
|
+
result = yield if block_given?
|
101
|
+
callback_proc.call(result)
|
102
|
+
end
|
103
|
+
|
104
|
+
def js_invoke(window, callback, method, *args) #:nodoc:
|
105
|
+
self.callback_proc = callback
|
106
|
+
if method == :setup
|
107
|
+
setup(window)
|
108
|
+
else
|
109
|
+
send(method, *args)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def instance_invoke(id, method, *args) #:nodoc:
|
114
|
+
self.new(id).send(method, *args)
|
115
|
+
end
|
116
|
+
|
64
117
|
# An array of window currently bound.
|
65
118
|
def windows
|
66
119
|
@windows ||= []
|
@@ -68,10 +121,11 @@ module Bowline
|
|
68
121
|
|
69
122
|
def setup(window) #:nodoc:
|
70
123
|
self.windows << window
|
124
|
+
self.windows.uniq!
|
71
125
|
if initial_items = initial
|
72
126
|
self.items = initial_items
|
73
127
|
end
|
74
|
-
|
128
|
+
callback(true)
|
75
129
|
end
|
76
130
|
|
77
131
|
# Called by a window's JavaScript whenever that window is bound to this Binder.
|
@@ -84,18 +138,6 @@ module Bowline
|
|
84
138
|
def initial
|
85
139
|
end
|
86
140
|
|
87
|
-
def js_invoke(window, method, *args) #:nodoc:
|
88
|
-
if method == :setup
|
89
|
-
setup(window)
|
90
|
-
else
|
91
|
-
send(method, *args)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def instance_invoke(id, meth, *args) #:nodoc:
|
96
|
-
self.new(id).send(meth, *args)
|
97
|
-
end
|
98
|
-
|
99
141
|
# Calls .find on the klass sent to the bind method.
|
100
142
|
# This is used internally, to find records when the page
|
101
143
|
# invoke instance methods.
|
@@ -133,8 +175,8 @@ module Bowline
|
|
133
175
|
# Remove an item from the binder, updating the HTML.
|
134
176
|
# This method is normally only called internally by
|
135
177
|
# the bound class's after_destroy callback.
|
136
|
-
def
|
137
|
-
bowline.
|
178
|
+
def destroyed(item)
|
179
|
+
bowline.destroyed(
|
138
180
|
name,
|
139
181
|
item.id
|
140
182
|
).call
|
@@ -174,62 +216,26 @@ module Bowline
|
|
174
216
|
# See Bowline::logger
|
175
217
|
def logger
|
176
218
|
Bowline::logger
|
177
|
-
end
|
178
|
-
|
179
|
-
# Trigger events on all elements
|
180
|
-
# bound to this binder.
|
181
|
-
# Example:
|
182
|
-
# trigger(:reload, {:key => :value})
|
183
|
-
def trigger(event, data = nil)
|
184
|
-
bowline.trigger(
|
185
|
-
name,
|
186
|
-
format_event(event),
|
187
|
-
data
|
188
|
-
).call
|
189
|
-
end
|
190
|
-
|
191
|
-
# Helper method to trigger a loading
|
192
|
-
# event either side of a block:
|
193
|
-
# loading {
|
194
|
-
# # Slow code, e.g. http call
|
195
|
-
# }
|
196
|
-
def loading(&block)
|
197
|
-
trigger(:loading, true)
|
198
|
-
yield
|
199
|
-
trigger(:loading, false)
|
200
|
-
end
|
201
|
-
|
202
|
-
def format_event(name) #:nodoc:
|
203
|
-
name.is_a?(Array) ?
|
204
|
-
name.join('.') :
|
205
|
-
name.to_s
|
206
|
-
end
|
219
|
+
end
|
207
220
|
end
|
208
|
-
|
209
|
-
# jQuery element object
|
210
|
-
attr_reader :element
|
211
|
-
|
221
|
+
|
212
222
|
# Instance of the bound class' record
|
213
223
|
attr_reader :item
|
214
224
|
|
215
225
|
def initialize(id, *args) #:nodoc:
|
216
|
-
@
|
217
|
-
self.class.name, id
|
218
|
-
)
|
219
|
-
@item = self.class.find(id)
|
226
|
+
@item = self.class.find(id)
|
220
227
|
end
|
221
228
|
|
222
229
|
protected
|
223
|
-
|
224
|
-
|
225
|
-
# trigger(:highlight)
|
226
|
-
def trigger(event, data = nil)
|
227
|
-
element.trigger(
|
228
|
-
self.class.format_event(event),
|
229
|
-
data
|
230
|
-
).call
|
230
|
+
def callback_proc(*args) #:nodoc
|
231
|
+
self.class.callback_proc(*args)
|
231
232
|
end
|
232
|
-
|
233
|
+
alias_method :callback_proc=, :callback_proc
|
234
|
+
|
235
|
+
def callback(*args, &block)
|
236
|
+
self.class.callback(*args, &block)
|
237
|
+
end
|
238
|
+
|
233
239
|
# Remove element from the view
|
234
240
|
def remove!
|
235
241
|
self.class.removed(item)
|
@@ -1,23 +1,2 @@
|
|
1
|
-
|
2
|
-
require "
|
3
|
-
require "irb/completion"
|
4
|
-
|
5
|
-
options = {}
|
6
|
-
OptionParser.new do |opt|
|
7
|
-
opt.banner = "Usage: console [environment] [options]"
|
8
|
-
opt.on("--debugger", "Enable ruby-debugging for the console.") { |v| options[:debugger] = v }
|
9
|
-
opt.parse!(ARGV)
|
10
|
-
end
|
11
|
-
|
12
|
-
if options[:debugger]
|
13
|
-
begin
|
14
|
-
require "ruby-debug"
|
15
|
-
puts "=> Debugger enabled"
|
16
|
-
rescue Exception
|
17
|
-
puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
|
18
|
-
exit
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
require "#{APP_ROOT}/config/environment"
|
23
|
-
IRB.start
|
1
|
+
ENV["APP_IRB"] = "1"
|
2
|
+
require "bowline/commands/run"
|
@@ -1,3 +1,3 @@
|
|
1
|
-
require
|
1
|
+
require "bowline/generators"
|
2
2
|
|
3
|
-
Bowline::Generators.run_cli(APP_ROOT,
|
3
|
+
Bowline::Generators.run_cli(APP_ROOT, "bowline", Bowline::Version::STRING, ARGV)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
unless Bowline::Desktop.enabled?
|
2
|
+
raise "Script not executed by bowline-desktop"
|
3
|
+
end
|
4
|
+
|
5
|
+
require Bowline.root.join(*%w{config environment})
|
6
|
+
|
7
|
+
if ENV["APP_IRB"]
|
8
|
+
require "irb"
|
9
|
+
require "irb/completion"
|
10
|
+
IRB.start
|
11
|
+
Bowline::Desktop::App.exit
|
12
|
+
end
|
data/lib/bowline/commands/run.rb
CHANGED
data/lib/bowline/desktop.rb
CHANGED
@@ -30,8 +30,8 @@ module Bowline
|
|
30
30
|
true
|
31
31
|
end
|
32
32
|
|
33
|
-
def js_invoke(window, method, *args)
|
34
|
-
send(method, *args)
|
33
|
+
def js_invoke(window, callback, method, *args)
|
34
|
+
callback.call(send(method, *args))
|
35
35
|
end
|
36
36
|
RUBY
|
37
37
|
end
|
@@ -40,20 +40,31 @@ module Bowline
|
|
40
40
|
class Message #:nodoc:
|
41
41
|
include Bowline::Logging
|
42
42
|
|
43
|
-
attr_reader :window, :id, :klass, :
|
43
|
+
attr_reader :window, :id, :klass, :method_name, :args
|
44
44
|
|
45
45
|
def initialize(window, atts)
|
46
|
-
@window
|
47
|
-
atts
|
48
|
-
@id
|
49
|
-
@klass
|
50
|
-
@
|
51
|
-
@args
|
46
|
+
@window = window
|
47
|
+
atts = atts.with_indifferent_access
|
48
|
+
@id = atts[:id]
|
49
|
+
@klass = atts[:klass]
|
50
|
+
@method_name = atts[:method].to_sym
|
51
|
+
@args = atts[:args] || []
|
52
52
|
end
|
53
53
|
|
54
54
|
def callback?
|
55
55
|
@id != -1
|
56
56
|
end
|
57
|
+
|
58
|
+
def callback(result)
|
59
|
+
return unless callback?
|
60
|
+
proxy = Proxy.new(window)
|
61
|
+
proxy = proxy.Bowline.invokeCallback(
|
62
|
+
id, result.to_js.to_json
|
63
|
+
)
|
64
|
+
Runtime.main {
|
65
|
+
window.run_script(proxy.to_s)
|
66
|
+
}
|
67
|
+
end
|
57
68
|
|
58
69
|
def invoke
|
59
70
|
if klass == "_window"
|
@@ -62,14 +73,19 @@ module Bowline
|
|
62
73
|
# TODO - security concerns with constantize
|
63
74
|
object = klass.constantize
|
64
75
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
76
|
+
|
77
|
+
trace "JS invoking: #{klass}.#{method_name}(#{args.join(',')})"
|
78
|
+
|
79
|
+
if object.respond_to?(:js_exposed?) &&
|
80
|
+
object.js_exposed?(method_name)
|
81
|
+
|
82
|
+
object.js_invoke(
|
83
|
+
window,
|
84
|
+
method(:callback),
|
85
|
+
method_name,
|
86
|
+
*args
|
87
|
+
)
|
88
|
+
|
73
89
|
else
|
74
90
|
raise "Method not allowed"
|
75
91
|
end
|
@@ -82,7 +98,8 @@ module Bowline
|
|
82
98
|
result = JSON.parse(str)
|
83
99
|
Message.new(window, result).invoke
|
84
100
|
rescue => e
|
85
|
-
Bowline::Logging.
|
101
|
+
Bowline::Logging.trace(str)
|
102
|
+
Bowline::Logging.log_error(e)
|
86
103
|
end
|
87
104
|
module_function :call
|
88
105
|
end
|
data/lib/bowline/desktop/js.rb
CHANGED
@@ -55,20 +55,15 @@ module Bowline
|
|
55
55
|
raise e
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
59
|
-
def poll
|
60
|
-
run_scripts
|
61
|
-
end
|
62
|
-
module_function :poll
|
63
58
|
|
64
|
-
def setup
|
59
|
+
def setup! #:nodoc:
|
65
60
|
Desktop.on_idle(method(:poll))
|
66
61
|
end
|
67
|
-
module_function :setup
|
62
|
+
module_function :setup!
|
68
63
|
|
69
|
-
def eval(
|
70
|
-
script = Script.new(
|
71
|
-
if
|
64
|
+
def eval(window, string, method = nil, &block)
|
65
|
+
script = Script.new(window, string, method||block)
|
66
|
+
if Runtime.main_thread? && script.ready?
|
72
67
|
script.call
|
73
68
|
else
|
74
69
|
scripts << script
|
@@ -77,18 +72,17 @@ module Bowline
|
|
77
72
|
module_function :eval
|
78
73
|
|
79
74
|
private
|
80
|
-
def
|
75
|
+
def poll
|
81
76
|
ready_scripts = scripts.select(&:ready?)
|
82
77
|
ready_scripts.each do |script|
|
83
78
|
script.call
|
84
79
|
scripts.delete(script)
|
85
80
|
end
|
86
81
|
end
|
87
|
-
module_function :
|
82
|
+
module_function :poll
|
88
83
|
|
89
|
-
# TODO - thread safety, needs mutex
|
90
84
|
def scripts
|
91
|
-
|
85
|
+
@scripts ||= []
|
92
86
|
end
|
93
87
|
module_function :scripts
|
94
88
|
end
|
data/lib/bowline/desktop/path.rb
CHANGED
@@ -8,6 +8,12 @@ module Bowline
|
|
8
8
|
# * Windows: "C:\Documents and Settings\username\My Documents"
|
9
9
|
# * Mac: ~/Documents
|
10
10
|
|
11
|
+
# Get the users home dir
|
12
|
+
def home
|
13
|
+
Gem.user_home
|
14
|
+
end
|
15
|
+
module_function :home
|
16
|
+
|
11
17
|
##
|
12
18
|
# :singleton-method: data
|
13
19
|
# Get the app's data dir.
|
@@ -16,11 +22,22 @@ module Bowline
|
|
16
22
|
# * Mac: appinfo.app/Contents/SharedSupport bundle subdirectory
|
17
23
|
|
18
24
|
##
|
19
|
-
# :singleton-method: user_data
|
20
25
|
# Get the app's user data dir.
|
21
26
|
# * Unix: ~/.appinfo
|
22
27
|
# * Windows: "C:\Documents and Settings\username\Application Data\appinfo"
|
23
28
|
# * Mac: "~/Library/Application Support/appinfo".
|
29
|
+
def user_data
|
30
|
+
conf = Bowline.configuration
|
31
|
+
case Bowline::Platform.type
|
32
|
+
when :linux
|
33
|
+
File.join(home, "." + conf.name)
|
34
|
+
when :win32
|
35
|
+
File.join(home, "Application Data", conf.name)
|
36
|
+
when :osx
|
37
|
+
File.join(home, "Library", "Application Support", conf.name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
module_function :user_data
|
24
41
|
|
25
42
|
##
|
26
43
|
# :singleton-method: temp
|
@@ -1,17 +1,30 @@
|
|
1
|
+
require "thread"
|
2
|
+
|
1
3
|
module Bowline
|
2
4
|
module Desktop
|
3
5
|
module Runtime
|
4
|
-
def setup
|
6
|
+
def setup! #:nodoc:
|
5
7
|
Desktop.on_tick(method(:poll))
|
6
8
|
end
|
7
|
-
module_function :setup
|
9
|
+
module_function :setup!
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
# Run block/method in main thread
|
12
|
+
def main(method = nil, &block)
|
13
|
+
proc = method||block
|
14
|
+
if main_thread?
|
15
|
+
proc.call
|
16
|
+
else
|
17
|
+
procs << proc
|
18
|
+
end
|
19
|
+
end
|
20
|
+
module_function :main
|
21
|
+
|
22
|
+
def main_thread?
|
23
|
+
Thread.current == Thread.main
|
11
24
|
end
|
12
|
-
module_function :
|
25
|
+
module_function :main_thread?
|
13
26
|
|
14
|
-
private
|
27
|
+
private
|
15
28
|
def poll
|
16
29
|
while proc = procs.shift
|
17
30
|
proc.call
|
@@ -19,9 +32,8 @@ module Bowline
|
|
19
32
|
end
|
20
33
|
module_function :poll
|
21
34
|
|
22
|
-
# TODO - thread safety, needs mutex
|
23
35
|
def procs
|
24
|
-
|
36
|
+
@procs ||= []
|
25
37
|
end
|
26
38
|
module_function :procs
|
27
39
|
end
|
@@ -4,7 +4,7 @@ module Bowline
|
|
4
4
|
# It's the usual way of interfacing with your application's windows,
|
5
5
|
# and all of Bowline's windows normally inherit from it.
|
6
6
|
#
|
7
|
-
# You'll need to call the setup method, before calling using this class.
|
7
|
+
# You'll need to call the setup! method, before calling using this class.
|
8
8
|
# If the window is deallocated (i.e. closed), you'll need to call it again.
|
9
9
|
# It's worth not calling the setup method before you need it, since it'll
|
10
10
|
# increase the amount of CPU your application uses.
|
@@ -55,7 +55,7 @@ module Bowline
|
|
55
55
|
# Call this method to allocate a new window.
|
56
56
|
# You'll need to do this before using it,
|
57
57
|
# or after it has been closed.
|
58
|
-
def setup
|
58
|
+
def setup!
|
59
59
|
return unless Desktop.enabled?
|
60
60
|
return if @window && !@window.dealocated?
|
61
61
|
if self.name == "MainWindow"
|
@@ -68,7 +68,7 @@ module Bowline
|
|
68
68
|
@script_callback = Proc.new {|str|
|
69
69
|
Bowline::Desktop::Bridge.call(self, str)
|
70
70
|
}
|
71
|
-
@window.script_callback = @script_callback
|
71
|
+
@window.script_callback = @script_callback
|
72
72
|
end
|
73
73
|
|
74
74
|
# Evaluate JavaScript in this window. Pass
|
data/lib/bowline/ext/array.rb
CHANGED
data/lib/bowline/ext/object.rb
CHANGED
@@ -2,9 +2,9 @@ class Object
|
|
2
2
|
# Aim is to convert the object into:
|
3
3
|
# * A hash or
|
4
4
|
# * An array of hashes
|
5
|
-
def to_js
|
6
|
-
if respond_to?(:
|
7
|
-
|
5
|
+
def to_js(*args)
|
6
|
+
if respond_to?(:serializable_hash)
|
7
|
+
serializable_hash(*args)
|
8
8
|
elsif respond_to?(:attributes)
|
9
9
|
attributes
|
10
10
|
else
|
data/lib/bowline/generators.rb
CHANGED
@@ -2,6 +2,43 @@ gem "templater", ">= 0.3.2"
|
|
2
2
|
require "templater"
|
3
3
|
require "rbconfig"
|
4
4
|
|
5
|
+
module Templater
|
6
|
+
module Actions
|
7
|
+
class Touch < Action
|
8
|
+
|
9
|
+
def initialize(generator, name, destination, options={})
|
10
|
+
self.generator = generator
|
11
|
+
self.name = name
|
12
|
+
self.destination = destination
|
13
|
+
self.options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def render
|
17
|
+
''
|
18
|
+
end
|
19
|
+
|
20
|
+
def exists?
|
21
|
+
::File.exists?(destination)
|
22
|
+
end
|
23
|
+
|
24
|
+
def identical?
|
25
|
+
exists?
|
26
|
+
end
|
27
|
+
|
28
|
+
def invoke!
|
29
|
+
callback(:before)
|
30
|
+
::FileUtils.touch(destination)
|
31
|
+
callback(:after)
|
32
|
+
end
|
33
|
+
|
34
|
+
def revoke!
|
35
|
+
::FileUtils.rm_rf(::File.expand_path(destination))
|
36
|
+
end
|
37
|
+
|
38
|
+
end # Touch
|
39
|
+
end # Actions
|
40
|
+
end # Templater
|
41
|
+
|
5
42
|
module Bowline
|
6
43
|
module Generators #:nodoc: all
|
7
44
|
extend Templater::Manifold
|
@@ -27,6 +64,12 @@ module Bowline
|
|
27
64
|
"#!/usr/bin/env #{RbConfig::CONFIG["RUBY_INSTALL_NAME"]}"
|
28
65
|
end
|
29
66
|
|
67
|
+
def self.touch(name, destination)
|
68
|
+
empty_directories << Templater::ActionDescription.new(name) do |generator|
|
69
|
+
Templater::Actions::Touch.new(generator, name, destination)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
30
73
|
def self.source_root
|
31
74
|
File.join(File.dirname(__FILE__), *%w[.. .. templates])
|
32
75
|
end
|
@@ -5,11 +5,11 @@ module Bowline::Generators
|
|
5
5
|
DESC
|
6
6
|
|
7
7
|
def app_id
|
8
|
-
[
|
8
|
+
["bowline", name].join(".")
|
9
9
|
end
|
10
10
|
|
11
11
|
def destination_root
|
12
|
-
#
|
12
|
+
# TODO - only works relative
|
13
13
|
File.join(@destination_root, base_name)
|
14
14
|
end
|
15
15
|
|
@@ -19,7 +19,6 @@ module Bowline::Generators
|
|
19
19
|
|
20
20
|
first_argument :name, :required => true, :desc => "application name"
|
21
21
|
|
22
|
-
empty_directory :tmp, "tmp"
|
23
22
|
empty_directory :vendor, "vendor"
|
24
23
|
empty_directory :lib, "lib"
|
25
24
|
empty_directory :db, "db"
|
@@ -60,7 +59,12 @@ module Bowline::Generators
|
|
60
59
|
file(action.downcase.gsub(/[^a-z0-9]+/, '_').to_sym, action, action)
|
61
60
|
}
|
62
61
|
|
62
|
+
glob! "config/environments"
|
63
|
+
|
63
64
|
empty_directory :initializers, "config/initializers"
|
65
|
+
empty_directory :first_run, "config/first_run"
|
66
|
+
|
67
|
+
touch "app_first_run"
|
64
68
|
|
65
69
|
file :readme, "../README.txt", "README"
|
66
70
|
end
|
data/lib/bowline/initializer.rb
CHANGED
@@ -34,6 +34,22 @@ module Bowline
|
|
34
34
|
def root
|
35
35
|
Pathname.new(APP_ROOT) if defined?(APP_ROOT)
|
36
36
|
end
|
37
|
+
|
38
|
+
def public_path
|
39
|
+
root && root.join("public")
|
40
|
+
end
|
41
|
+
|
42
|
+
def assets_path
|
43
|
+
File.join(library_path, "assets")
|
44
|
+
end
|
45
|
+
|
46
|
+
def env
|
47
|
+
@env ||= ActiveSupport::StringInquirer.new(ENV["APP_ENV"] || "development")
|
48
|
+
end
|
49
|
+
|
50
|
+
def irb?
|
51
|
+
!!ENV["APP_IRB"]
|
52
|
+
end
|
37
53
|
end
|
38
54
|
|
39
55
|
class Initializer #:nodoc:
|
@@ -61,7 +77,14 @@ module Bowline
|
|
61
77
|
@configuration = configuration
|
62
78
|
@loaded_plugins = []
|
63
79
|
end
|
64
|
-
|
80
|
+
|
81
|
+
def set_environment
|
82
|
+
production_path = Bowline.root.join("app_production")
|
83
|
+
ENV["APP_ENV"] ||= begin
|
84
|
+
production_path.exist? ? "production" : "development"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
65
88
|
def require_frameworks
|
66
89
|
configuration.frameworks.each { |framework| require(framework.to_s) }
|
67
90
|
end
|
@@ -158,7 +181,7 @@ module Bowline
|
|
158
181
|
# Loads support for "whiny nil" (noisy warnings when methods are invoked
|
159
182
|
# on +nil+ values) if Configuration#whiny_nils is true.
|
160
183
|
def initialize_whiny_nils
|
161
|
-
require(
|
184
|
+
require("active_support/whiny_nil") if configuration.whiny_nils
|
162
185
|
end
|
163
186
|
|
164
187
|
# Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes.
|
@@ -197,18 +220,32 @@ module Bowline
|
|
197
220
|
end
|
198
221
|
|
199
222
|
def load_plugins
|
200
|
-
Dir.glob(File.join(configuration.plugin_glob,
|
223
|
+
Dir.glob(File.join(configuration.plugin_glob, "init.rb")).sort.each do |path|
|
201
224
|
config = configuration # Need local config variable
|
202
225
|
eval(IO.read(path), binding, path)
|
203
226
|
end
|
204
227
|
end
|
205
228
|
|
229
|
+
def load_application_environment
|
230
|
+
require(Bowline.root.join(*%w{config environments}, Bowline.env))
|
231
|
+
end
|
232
|
+
|
206
233
|
def load_application_initializers
|
207
234
|
Dir.glob(configuration.initializer_glob).sort.each do |initializer|
|
208
235
|
load(initializer)
|
209
236
|
end
|
210
237
|
end
|
211
238
|
|
239
|
+
def load_application_first_run
|
240
|
+
first_run = Bowline.root.join("app_first_run")
|
241
|
+
if first_run.exist?
|
242
|
+
first_run.unlink
|
243
|
+
Dir.glob(configuration.first_run_glob).sort.each do |initializer|
|
244
|
+
load(initializer)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
212
249
|
def after_initialize
|
213
250
|
configuration.after_initialize_blocks.each do |block|
|
214
251
|
block.call
|
@@ -253,31 +290,39 @@ module Bowline
|
|
253
290
|
# Creates a class called AppConfig from configuration
|
254
291
|
# variables found in config/application.yml
|
255
292
|
def load_app_config
|
256
|
-
Object.const_set("AppConfig", AppConfig.
|
293
|
+
Object.const_set("AppConfig", AppConfig.load!(configuration.app_config_file))
|
257
294
|
end
|
258
295
|
|
259
|
-
def
|
260
|
-
return unless
|
261
|
-
|
296
|
+
def initialize_desktop
|
297
|
+
return unless Desktop.enabled?
|
298
|
+
Desktop::Runtime.setup!
|
299
|
+
Desktop::JS.setup!
|
262
300
|
end
|
263
301
|
|
264
302
|
def initialize_windows
|
265
|
-
return unless
|
266
|
-
MainWindow.setup
|
303
|
+
return unless Desktop.enabled?
|
304
|
+
MainWindow.setup!
|
267
305
|
MainWindow.title = configuration.name
|
268
306
|
end
|
269
307
|
|
270
308
|
def initialize_trap
|
271
|
-
return unless
|
309
|
+
return unless Desktop.enabled?
|
272
310
|
trap("INT") {
|
273
|
-
|
311
|
+
Desktop::App.exit
|
274
312
|
}
|
275
313
|
end
|
276
314
|
|
315
|
+
def initialize_path
|
316
|
+
# Dir::tmpdir/Tempfile uses this
|
317
|
+
ENV["TMPDIR"] = Desktop::Path.temp if Desktop.enabled?
|
318
|
+
FileUtils.mkdir_p(Desktop::Path.user_data)
|
319
|
+
end
|
320
|
+
|
277
321
|
def initialize_marshal
|
278
322
|
return unless defined?(SuperModel)
|
279
|
-
|
280
|
-
|
323
|
+
path = configuration.marshal_path
|
324
|
+
path = path.call if path.is_a?(Proc)
|
325
|
+
SuperModel::Marshal.path = path
|
281
326
|
SuperModel::Marshal.load
|
282
327
|
at_exit {
|
283
328
|
SuperModel::Marshal.dump
|
@@ -287,6 +332,8 @@ module Bowline
|
|
287
332
|
def process
|
288
333
|
Bowline.configuration = configuration
|
289
334
|
|
335
|
+
set_environment
|
336
|
+
|
290
337
|
set_load_path
|
291
338
|
load_gems
|
292
339
|
|
@@ -314,16 +361,18 @@ module Bowline
|
|
314
361
|
load_plugins
|
315
362
|
load_application_classes
|
316
363
|
load_application_helpers
|
317
|
-
|
318
|
-
load_application_initializers
|
319
364
|
|
320
|
-
|
321
|
-
|
322
|
-
initialize_js
|
365
|
+
initialize_desktop
|
323
366
|
initialize_windows
|
324
367
|
initialize_trap
|
325
|
-
|
368
|
+
initialize_path
|
326
369
|
initialize_marshal
|
370
|
+
|
371
|
+
load_application_environment
|
372
|
+
load_application_initializers
|
373
|
+
load_application_first_run
|
374
|
+
|
375
|
+
after_initialize
|
327
376
|
|
328
377
|
Bowline.initialized = true
|
329
378
|
end
|
@@ -419,9 +468,8 @@ module Bowline
|
|
419
468
|
attr_accessor :time_zone
|
420
469
|
|
421
470
|
attr_accessor :plugin_glob
|
422
|
-
|
423
471
|
attr_accessor :helper_glob
|
424
|
-
|
472
|
+
attr_accessor :first_run_glob
|
425
473
|
attr_accessor :initializer_glob
|
426
474
|
|
427
475
|
# Set the application's name.
|
@@ -473,6 +521,7 @@ module Bowline
|
|
473
521
|
self.plugin_glob = default_plugin_glob
|
474
522
|
self.helper_glob = default_helper_glob
|
475
523
|
self.initializer_glob = default_initalizer_glob
|
524
|
+
self.first_run_glob = default_first_run_glob
|
476
525
|
self.publisher = default_publisher
|
477
526
|
self.copyright = default_copyright
|
478
527
|
|
@@ -589,7 +638,7 @@ module Bowline
|
|
589
638
|
end
|
590
639
|
|
591
640
|
def default_marshal_path
|
592
|
-
File.join(
|
641
|
+
Proc.new { File.join(Desktop::Path.user_data, 'marshal.db') }
|
593
642
|
end
|
594
643
|
|
595
644
|
def default_cache_classes
|
@@ -611,6 +660,10 @@ module Bowline
|
|
611
660
|
def default_initalizer_glob
|
612
661
|
File.join(root_path, *%w{ config initializers **/*.rb })
|
613
662
|
end
|
663
|
+
|
664
|
+
def default_first_run_glob
|
665
|
+
File.join(root_path, *%w{ config first_run **/*.rb })
|
666
|
+
end
|
614
667
|
|
615
668
|
def default_publisher
|
616
669
|
"Bowline"
|
data/lib/bowline/library.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
1
3
|
module Bowline
|
2
4
|
# Provides paths to Bowline's required libraries.
|
3
5
|
module Library
|
@@ -8,50 +10,32 @@ module Bowline
|
|
8
10
|
# Path to a folder stored under the users
|
9
11
|
# home directory containing the downloaded libraries.
|
10
12
|
def path
|
11
|
-
|
12
|
-
File.
|
13
|
+
Pathname.new(
|
14
|
+
File.expand_path(
|
15
|
+
File.join(Gem.user_home, ".bowline")
|
16
|
+
)
|
13
17
|
)
|
14
18
|
end
|
15
|
-
module_function :path
|
16
19
|
|
17
20
|
# Path to the bowline-desktop binary
|
18
21
|
def desktop_path
|
19
|
-
|
22
|
+
path.join("bowline-desktop")
|
20
23
|
end
|
21
|
-
module_function :desktop_path
|
22
24
|
|
23
25
|
def libs_path
|
24
|
-
|
26
|
+
path.join("libs")
|
25
27
|
end
|
26
|
-
module_function :libs_path
|
27
28
|
|
28
29
|
def local_build_path
|
29
|
-
|
30
|
+
Bowline.root.join("build")
|
30
31
|
end
|
31
|
-
module_function :local_build_path
|
32
32
|
|
33
33
|
# Returns true if all required libraries exist.
|
34
34
|
def ready?
|
35
35
|
File.exist?(desktop_path) &&
|
36
36
|
File.directory?(libs_path)
|
37
37
|
end
|
38
|
-
|
39
|
-
|
40
|
-
private
|
41
|
-
# Borrowed from Rubygems
|
42
|
-
def home_path
|
43
|
-
['HOME', 'USERPROFILE'].each do |homekey|
|
44
|
-
return ENV[homekey] if ENV[homekey]
|
45
|
-
end
|
46
|
-
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
|
47
|
-
return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
|
48
|
-
end
|
49
|
-
begin
|
50
|
-
File.expand_path("~")
|
51
|
-
rescue
|
52
|
-
File::ALT_SEPARATOR ? "C:/" : "/"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
module_function :home_path
|
38
|
+
|
39
|
+
extend self
|
56
40
|
end
|
57
41
|
end
|
data/lib/bowline/tasks/app.rake
CHANGED
@@ -1,9 +1,43 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'erb'
|
3
3
|
require 'rbconfig'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'zip/zip'
|
4
6
|
|
5
7
|
namespace :app do
|
6
|
-
namespace :build do
|
8
|
+
namespace :build do
|
9
|
+
task :zip => :environment do
|
10
|
+
unless Bowline::Library.ready?
|
11
|
+
Rake::Task["libs:setup"].invoke
|
12
|
+
end
|
13
|
+
|
14
|
+
config = Bowline.configuration
|
15
|
+
|
16
|
+
build_path = Bowline::Library.local_build_path
|
17
|
+
FileUtils.mkdir_p(build_path)
|
18
|
+
|
19
|
+
app_path = File.join(build_path, "#{config.name}.zip")
|
20
|
+
FileUtils.rm_rf(app_path)
|
21
|
+
|
22
|
+
dirs = Dir[Bowline.root.join("**/**").to_s]
|
23
|
+
dirs.delete(build_path)
|
24
|
+
dirs.delete(Bowline.root.join("log").to_s)
|
25
|
+
dirs.delete(Bowline.root.join(*%w{db migrate}).to_s)
|
26
|
+
dirs.delete_if {|i| i =~ /\.svn|\.DS_Store|\.git/ }
|
27
|
+
|
28
|
+
Zip::ZipFile.open(app_path, Zip::ZipFile::CREATE) do |zf|
|
29
|
+
# This is horrible - but RubyZIP's API sucks
|
30
|
+
blank = Tempfile.new("blank")
|
31
|
+
zf.add("app_first_run", blank.path)
|
32
|
+
zf.add("app_production", blank.path)
|
33
|
+
|
34
|
+
dirs.each do |dir|
|
35
|
+
name = dir.sub(Bowline.root.to_s + "/", "")
|
36
|
+
zf.add(name, dir)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
7
41
|
task :osx => :environment do
|
8
42
|
unless Bowline::Library.ready?
|
9
43
|
Rake::Task["libs:setup"].invoke
|
@@ -11,7 +45,7 @@ namespace :app do
|
|
11
45
|
|
12
46
|
config = Bowline.configuration
|
13
47
|
assets_path = File.join(Bowline.assets_path, "osx")
|
14
|
-
build_path = Bowline::Library.local_build_path
|
48
|
+
build_path = Bowline::Library.local_build_path.to_s
|
15
49
|
app_path = File.join(build_path, "#{config.name}.app")
|
16
50
|
FileUtils.rm_rf(app_path)
|
17
51
|
contents_path = File.join(app_path, "Contents")
|
@@ -32,7 +66,7 @@ namespace :app do
|
|
32
66
|
# Make icon
|
33
67
|
makeicns = File.join(assets_path, "makeicns")
|
34
68
|
if config.icon
|
35
|
-
makeicns_in = File.expand_path(config.icon,
|
69
|
+
makeicns_in = File.expand_path(config.icon, Bowline.root)
|
36
70
|
else
|
37
71
|
makeicns_in = File.join(assets_path, "bowline.png")
|
38
72
|
end
|
@@ -41,13 +75,15 @@ namespace :app do
|
|
41
75
|
`#{makeicns} -in #{makeicns_in} -out #{makeicns_out}`
|
42
76
|
|
43
77
|
# Copy App
|
44
|
-
dirs = Dir[File.join(APP_ROOT,
|
78
|
+
dirs = Dir[File.join(APP_ROOT, "**")]
|
45
79
|
dirs.delete(build_path)
|
46
|
-
dirs.delete(File.join(APP_ROOT,
|
47
|
-
dirs.delete(File.join(APP_ROOT,
|
48
|
-
dirs.
|
49
|
-
dirs.
|
50
|
-
|
80
|
+
dirs.delete(File.join(APP_ROOT, "log"))
|
81
|
+
dirs.delete(File.join(APP_ROOT, *%w{db migrate}))
|
82
|
+
dirs.delete_if {|i| i =~ /\.svn|\.DS_Store|\.git/ }
|
83
|
+
FileUtils.cp_r(dirs, ".")
|
84
|
+
|
85
|
+
FileUtils.touch("app_production")
|
86
|
+
FileUtils.touch("app_first_run")
|
51
87
|
end
|
52
88
|
|
53
89
|
# Copy Bowline binary & libs
|
data/lib/bowline/tasks/libs.rake
CHANGED
@@ -34,14 +34,6 @@ def unzip(fpath, tpath)
|
|
34
34
|
}
|
35
35
|
end
|
36
36
|
|
37
|
-
def sym_or_copy(from, to)
|
38
|
-
begin
|
39
|
-
FileUtils.ln_s(from, to)
|
40
|
-
rescue NotImplementedError
|
41
|
-
FileUtils.cp_r(from, to)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
37
|
namespace :libs do
|
46
38
|
desc "Download Bowline's binary and pre-compiled libs"
|
47
39
|
task :download => :environment do
|
data/lib/bowline/version.rb
CHANGED
@@ -7,8 +7,4 @@ Bowline::Initializer.run do |config|
|
|
7
7
|
config.version = "0.0.1"
|
8
8
|
config.publisher = "Example"
|
9
9
|
config.url = "http://example.com"
|
10
|
-
|
11
|
-
# config.gem "activerecord"
|
12
|
-
# config.gem "net-mdns", :lib => 'net/dns/mdns'
|
13
|
-
# config.gem "rubyzip", :lib => 'zip/zip'
|
14
10
|
end
|
File without changes
|
File without changes
|
data/templates/main_window.rb
CHANGED
data/templates/script/init
CHANGED
data/templates/window.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 6
|
8
|
-
-
|
9
|
-
version: 0.6.
|
8
|
+
- 3
|
9
|
+
version: 0.6.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alex MacCaw
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-04-06 00:00:00 +01:00
|
18
18
|
default_executable: bowline-gen
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/bowline/commands/build.rb
|
119
119
|
- lib/bowline/commands/console.rb
|
120
120
|
- lib/bowline/commands/generate.rb
|
121
|
+
- lib/bowline/commands/init.rb
|
121
122
|
- lib/bowline/commands/run.rb
|
122
123
|
- lib/bowline/desktop.rb
|
123
124
|
- lib/bowline/desktop/app.rb
|
@@ -165,6 +166,8 @@ files:
|
|
165
166
|
- templates/config/boot.rb
|
166
167
|
- templates/config/database.yml
|
167
168
|
- templates/config/environment.rb
|
169
|
+
- templates/config/environments/development.rb
|
170
|
+
- templates/config/environments/production.rb
|
168
171
|
- templates/gitignore
|
169
172
|
- templates/helper.rb
|
170
173
|
- templates/main_window.rb
|