Neurogami-rhesus 0.2.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/History.txt +3 -0
- data/Manifest.txt +13 -0
- data/README.md +234 -0
- data/Rakefile +39 -0
- data/bin/rhesus +106 -0
- data/lib/rhesus/core.rb +157 -0
- data/lib/rhesus/utils.rb +35 -0
- data/lib/rhesus.rb +41 -0
- data/lib/templates/about/about_controller.rb +8 -0
- data/lib/templates/about/about_model.rb +8 -0
- data/lib/templates/about/about_ui.rb +47 -0
- data/lib/templates/about/about_view.rb +11 -0
- data/lib/templates/basic/basic_controller.rb +21 -0
- data/lib/templates/basic/basic_model.rb +6 -0
- data/lib/templates/basic/basic_ui.rb +131 -0
- data/lib/templates/basic/basic_view.rb +35 -0
- data/lib/version.rb +16 -0
- data/spec/rhesus_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/test/.bacon +0 -0
- data/test/test_rhesus.rb +51 -0
- metadata +87 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
lib/rhesus.rb
|
2
|
+
lib/rhesus/core.rb
|
3
|
+
lib/rhesus/utils.rb
|
4
|
+
lib/templates/splash_screen
|
5
|
+
lib/templates/basic/basic_view.rb
|
6
|
+
lib/templates/basic/basic_ui.rb
|
7
|
+
lib/templates/basic/basic_model.rb
|
8
|
+
lib/templates/basic/basic_controller.rb
|
9
|
+
lib/templates/about/about_ui.rb
|
10
|
+
lib/templates/about/about_controller.rb
|
11
|
+
lib/templates/about/about_view.rb
|
12
|
+
lib/templates/about/about_model.rb
|
13
|
+
lib/version.rb
|
data/README.md
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
rhesus
|
2
|
+
=======
|
3
|
+
|
4
|
+
by James Britt
|
5
|
+
http://www.neurogami.com
|
6
|
+
|
7
|
+
DESCRIPTION
|
8
|
+
-----------
|
9
|
+
|
10
|
+
Rhesus is a script for copying over pre-built templates with optional embedded Erb stuff.
|
11
|
+
|
12
|
+
It started as a way to make jump-starting [Jipmanzee](http://neurogami.github.com/Jimpanzee/) apps easier, but the user-defined templates need not have anything to do with any special library.
|
13
|
+
|
14
|
+
Basically, you create a skeleton of the files you want as templates in some well-named subdirectory of ~/.rhesus.
|
15
|
+
|
16
|
+
If any of those files contain Erb variables, they will be used to prompt the use for values.
|
17
|
+
|
18
|
+
The same value gets applied in all cases where that variable is used. Some magic is used to handle proper casing for class and file names.
|
19
|
+
|
20
|
+
The results are copied out to some dir realtive to where you invoked the 'rhesus' script.
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
FEATURES/PROBLEMS
|
25
|
+
-----------------
|
26
|
+
|
27
|
+
|
28
|
+
Generates files for you to jump-start projects that have common code.
|
29
|
+
|
30
|
+
Makes asorted assumptions and needs more testing with a variety of template sources
|
31
|
+
|
32
|
+
SYNOPSIS
|
33
|
+
-----------
|
34
|
+
|
35
|
+
Make sure you have GitHub added as a gem server source. See FIXME
|
36
|
+
|
37
|
+
$ sudo gem install Neurogami-rhesus
|
38
|
+
|
39
|
+
cd to an existing project, or wherever you want to splat out the generated code:
|
40
|
+
|
41
|
+
$ jimpanzee cool-app
|
42
|
+
$ cd cool-app
|
43
|
+
|
44
|
+
Run `rhesus list` to see the available templates
|
45
|
+
|
46
|
+
$ rhesus list
|
47
|
+
|
48
|
+
|
49
|
+
Run `rhesus gen` to generate code from a template. You may optionally pass the name
|
50
|
+
of a template, but if you leave that out you'll get a list to pick from.
|
51
|
+
|
52
|
+
|
53
|
+
$ rhesus gen
|
54
|
+
1: jimpanzee.about
|
55
|
+
2: jimpanzee.basic
|
56
|
+
3: jimpanzee.midi
|
57
|
+
|
58
|
+
Enter the number of the template to use:
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
The code assumes you have a directory `.rhesus` in your home directory (+~/.rhesus+)
|
63
|
+
|
64
|
+
That directory holds the template sets.
|
65
|
+
|
66
|
+
Each set is just a top-level directory containing the skeleton files and directories to use:
|
67
|
+
|
68
|
+
|
69
|
+
james@james06:~/.rhesus$ tree
|
70
|
+
.
|
71
|
+
|-- jimpanzee.about
|
72
|
+
| `-- src
|
73
|
+
| `-- about
|
74
|
+
| |-- about_controller.rb
|
75
|
+
| |-- about_model.rb
|
76
|
+
| |-- about_ui.rb
|
77
|
+
| `-- about_view.rb
|
78
|
+
|-- jimpanzee.basic
|
79
|
+
| `-- src
|
80
|
+
| `-- klassname
|
81
|
+
| |-- klassname_controller.rb
|
82
|
+
| |-- klassname_model.rb
|
83
|
+
| |-- klassname_ui.rb
|
84
|
+
| `-- klassname_view.rb
|
85
|
+
`-- jimpanzee.midi
|
86
|
+
|-- com
|
87
|
+
| `-- neurogami
|
88
|
+
| `-- ResourceLoader.java
|
89
|
+
|-- lib
|
90
|
+
| |-- java
|
91
|
+
| | |-- libWiiuseJ.so
|
92
|
+
| | |-- libwiiuse.so
|
93
|
+
| | |-- miglayout-3.6.jar
|
94
|
+
| | `-- wiiusej.jar
|
95
|
+
| `-- ruby
|
96
|
+
| |-- README.txt
|
97
|
+
| |-- wii_api_manager.rb
|
98
|
+
| |-- wiimotable.rb
|
99
|
+
| `-- wiimote_event_listener.rb
|
100
|
+
`-- src
|
101
|
+
|-- mainclass
|
102
|
+
| |-- mainclass_controller.rb
|
103
|
+
| |-- mainclass_model.rb
|
104
|
+
| |-- mainclass_ui.rb
|
105
|
+
| `-- mainclass_view.rb
|
106
|
+
|-- midi.rb
|
107
|
+
|-- resolver.rb
|
108
|
+
|-- resource_loader.rb
|
109
|
+
`-- spinner_dialog.rb
|
110
|
+
|
111
|
+
|
112
|
+
What you call these directories is up to you; there is no code in place to do anything clever with the names (such
|
113
|
+
as grouping projects and templates). But something like that may be added if managing growing numbers of templates
|
114
|
+
becomes an issue. So, the suggested format is `project_type.template_name`
|
115
|
+
|
116
|
+
Rhesus starts with some assumptions about what files might be using Erb. You can add your own file extensions by placing a `haz_vars.txt` file in your `.rhesus` folder.
|
117
|
+
|
118
|
+
By default, the extensions are: `rb txt rhtml ini yml yaml`.
|
119
|
+
|
120
|
+
When you select a template set, Rhesus scans these files for Erb variables. It then prompts
|
121
|
+
you to provide values. If you use any of these variable names in file or path names then Rhesus
|
122
|
+
will apply those values to the names and paths when applying the template.
|
123
|
+
|
124
|
+
You need to be sure, then, to only use the same variable name across files when you want them to all
|
125
|
+
have the same value. That is, if `foo.rb` and `baz.ini` both use `<%= my_var %>`, then the resulting text
|
126
|
+
will have the same value used in both.
|
127
|
+
|
128
|
+
If a file in a template set is not among the file types that may have Erb (e.g., jar, dll, gif)
|
129
|
+
then it will be copied over as-is.
|
130
|
+
|
131
|
+
|
132
|
+
For example:
|
133
|
+
|
134
|
+
|
135
|
+
`jimpanze.basic` has this structure:
|
136
|
+
|
137
|
+
|
138
|
+
jimpanzee.basic
|
139
|
+
| `-- src
|
140
|
+
| `-- klassname
|
141
|
+
| |-- klassname_controller.rb
|
142
|
+
| |-- klassname_model.rb
|
143
|
+
| |-- klassname_ui.rb
|
144
|
+
| `-- klassname_view.rb
|
145
|
+
|
146
|
+
|
147
|
+
The file `klassname_controller.rb` has Erb to define the name of the class:
|
148
|
+
|
149
|
+
class <%= klassname %>Controller < ApplicationController
|
150
|
+
set_model '<%= klassname %>Model'
|
151
|
+
set_view '<%= klassname %>View'
|
152
|
+
|
153
|
+
|
154
|
+
When `jimpanze.basic` is selected for code generation, Rhesus scans the template files and picks out variable names used inside Erb brackets (i.e., `<%= this_is_the_variable %>` )
|
155
|
+
|
156
|
+
When the list of all such variables in all the files is assembled, rhesus prompts for a value for each one.
|
157
|
+
|
158
|
+
|
159
|
+
Using template jimpanzee.basic
|
160
|
+
Value for klassname:
|
161
|
+
|
162
|
+
The value entered will than be used for *all* instances of `klassname` in Erb. It will also be used to alter any file or
|
163
|
+
folder names that contain that as well.
|
164
|
+
|
165
|
+
|
166
|
+
Assume you gave the value of `Goober`
|
167
|
+
|
168
|
+
Since the template directory has `src/klassname`, and several files with that string, the generated code will look like this
|
169
|
+
|
170
|
+
| `-- src
|
171
|
+
| `-- goober
|
172
|
+
| |-- goober_controller.rb
|
173
|
+
| |-- goober_model.rb
|
174
|
+
| |-- goober_ui.rb
|
175
|
+
| `-- goober_view.rb
|
176
|
+
|
177
|
+
|
178
|
+
Inside the files, the code will also have this value:
|
179
|
+
|
180
|
+
|
181
|
+
class GooberController < ApplicationController
|
182
|
+
set_model 'GooberModel'
|
183
|
+
set_view 'GooberView'
|
184
|
+
|
185
|
+
|
186
|
+
Some assumptions are made in writing out the code. Variables inside files are replaces as-is.
|
187
|
+
|
188
|
+
That is, if you want `Goober` in your text, use `Goober`. If instead you want `goober`, use that.
|
189
|
+
|
190
|
+
However, for file and folder names, variable values are snake-cased. That's why you end up with
|
191
|
+
`src/goober/goober_controller.rb`.
|
192
|
+
|
193
|
+
A value of `FooBar`, for example, would create `src/foo_bar/foo_bar.rb`. But the string `FooBar` would be used inside the generated files.
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
REQUIREMENTS
|
199
|
+
-------------
|
200
|
+
|
201
|
+
Ruby.
|
202
|
+
|
203
|
+
|
204
|
+
INSTALL
|
205
|
+
------
|
206
|
+
|
207
|
+
sudo gem install Neurogaim-rhesus
|
208
|
+
|
209
|
+
|
210
|
+
LICENSE
|
211
|
+
-------
|
212
|
+
|
213
|
+
(The MIT License)
|
214
|
+
|
215
|
+
Copyright (c) 2009 James Britt
|
216
|
+
|
217
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
218
|
+
a copy of this software and associated documentation files (the
|
219
|
+
'Software'), to deal in the Software without restriction, including
|
220
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
221
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
222
|
+
permit persons to whom the Software is furnished to do so, subject to
|
223
|
+
the following conditions:
|
224
|
+
|
225
|
+
The above copyright notice and this permission notice shall be
|
226
|
+
included in all copies or substantial portions of the Software.
|
227
|
+
|
228
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
229
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
230
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
231
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
232
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
233
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
234
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
begin
|
10
|
+
load 'tasks/setup.rb'
|
11
|
+
rescue LoadError
|
12
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ensure_in_path 'lib'
|
17
|
+
require 'version'
|
18
|
+
|
19
|
+
#task :default => 'spec:run'
|
20
|
+
|
21
|
+
PROJ.name = 'rhesus'
|
22
|
+
PROJ.authors = 'James Britt / Neurogami'
|
23
|
+
PROJ.email = 'james@neurogami.com'
|
24
|
+
PROJ.url = 'http://code.neurogami.com'
|
25
|
+
PROJ.version = Neurogami::Rhesus::VERSION
|
26
|
+
PROJ.readme_file = 'README.md'
|
27
|
+
PROJ.summary = "Really simple, practical code generator."
|
28
|
+
|
29
|
+
# PROJ.spec.opts << '--color'
|
30
|
+
|
31
|
+
desc "Bacon specs"
|
32
|
+
task 'test:bacon' do
|
33
|
+
sh "bacon test/test_rhesus.rb"
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
desc 'test'
|
38
|
+
task :test => 'test:bacon'
|
39
|
+
# EOF
|
data/bin/rhesus
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib rhesus]))
|
4
|
+
|
5
|
+
def help(message = nil)
|
6
|
+
puts message + "\\\n-----------------------------------\\\n" unless message.nil?
|
7
|
+
puts <<-ENDL
|
8
|
+
Usage:
|
9
|
+
rhesus -h/--help
|
10
|
+
rhesus -v/--version
|
11
|
+
rhesus command [options]
|
12
|
+
|
13
|
+
Commands:
|
14
|
+
list
|
15
|
+
lists available templates.
|
16
|
+
|
17
|
+
gen <template-name>
|
18
|
+
Generates files fom given template name.
|
19
|
+
|
20
|
+
ENDL
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_template template_name
|
24
|
+
puts "Using template #{template_name}"
|
25
|
+
|
26
|
+
var_set = {}
|
27
|
+
|
28
|
+
Neurogami::Rhesus::Core.required_vars_for_template_set(template_name).each do |var|
|
29
|
+
print "Value for #{var}: "
|
30
|
+
var_set[var] = gets.strip
|
31
|
+
end
|
32
|
+
|
33
|
+
if var_set.empty?
|
34
|
+
puts "The templates have no variables. "
|
35
|
+
print "Is this OK? [Y/n]"
|
36
|
+
|
37
|
+
if gets.strip =~ /n|N/
|
38
|
+
puts "OK, exiting"
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
else
|
43
|
+
puts "Using values "
|
44
|
+
var_set.each { |k,v| puts "#{k}: #{v}" }
|
45
|
+
|
46
|
+
print "Is this OK? [Y/n]"
|
47
|
+
|
48
|
+
if gets.strip =~ /n|N/
|
49
|
+
puts "OK, exiting"
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
print "Under what directory do you want these files written? "
|
56
|
+
location = gets.strip
|
57
|
+
location = './' if location.empty?
|
58
|
+
|
59
|
+
Neurogami::Rhesus::Core::selected_template_files(template_name).each do |path|
|
60
|
+
next unless File.file?(path)
|
61
|
+
Neurogami::Rhesus::Core::process template_name, var_set, location, path
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def list_templates
|
67
|
+
puts Neurogami::Rhesus::Core.templates
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def generate_from_template
|
72
|
+
if ARGV.first
|
73
|
+
puts "Generate from #{ARGV.first} template"
|
74
|
+
else
|
75
|
+
Neurogami::Rhesus::Core.templates.each_with_index do |template, idx|
|
76
|
+
puts "#{idx+1}: #{template}"
|
77
|
+
end
|
78
|
+
item = 0
|
79
|
+
while item < 1 || item-1 > Neurogami::Rhesus::Core.templates.size
|
80
|
+
print "Enter the number of the template to use: "
|
81
|
+
item = gets.to_i
|
82
|
+
end
|
83
|
+
|
84
|
+
process_template Neurogami::Rhesus::Core.templates[item-1]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
#-------------------------------------------------
|
88
|
+
if ARGV.empty?
|
89
|
+
help
|
90
|
+
else
|
91
|
+
option = ARGV.shift
|
92
|
+
case option
|
93
|
+
when "-h" || "--help"
|
94
|
+
help
|
95
|
+
when "-v" || "--version"
|
96
|
+
puts "Rhesus version #{Rhesus.version}"
|
97
|
+
when "list"
|
98
|
+
puts "Templates"
|
99
|
+
list_templates
|
100
|
+
when"gen"
|
101
|
+
generate_from_template
|
102
|
+
else
|
103
|
+
puts "Nothing known about #{ARGV[0]}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
data/lib/rhesus/core.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
class String
|
5
|
+
def to_snake_case
|
6
|
+
snake_case self
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_camel_case
|
10
|
+
camelize self
|
11
|
+
end
|
12
|
+
|
13
|
+
#def identifier_to_path!
|
14
|
+
# self.gsub! ':', '/'
|
15
|
+
#end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Neurogami
|
19
|
+
module Rhesus
|
20
|
+
|
21
|
+
class Core
|
22
|
+
|
23
|
+
haz_vars = %w{ rb txt rhtml ini yml yaml }
|
24
|
+
@@re = haz_vars.map { |x| '\.' + x }.join( '|')
|
25
|
+
@@re = Regexp.new "(#{@@re})$"
|
26
|
+
|
27
|
+
# http://refactormycode.com/codes/281-given-a-hash-of-variables-render-an-erb-template
|
28
|
+
@@m = Module.new do
|
29
|
+
class << self
|
30
|
+
public :binding
|
31
|
+
def meta
|
32
|
+
class << self; self; end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class << meta
|
37
|
+
public :define_method
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.create_methods_from_hash variables_hash
|
43
|
+
variables_hash.each do |name, value|
|
44
|
+
@@m.meta.define_method(name) { value }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.process_template f, variables_hash
|
49
|
+
create_methods_from_hash variables_hash
|
50
|
+
t = ERB.new(IO.read(f), 0, "%<>")
|
51
|
+
t.result @@m.binding
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.projects
|
55
|
+
get_projects_directories.map { |path|
|
56
|
+
path.sub! user_template_directory + '/', ''
|
57
|
+
#path.identifier_to_path!
|
58
|
+
path
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
def self.tuple_base_name_pair name
|
65
|
+
[snake_case(name), camelize(name)]
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def self.required_vars_for_template_set template_name
|
70
|
+
#template_name.identifier_to_path!
|
71
|
+
vars = {}
|
72
|
+
|
73
|
+
selected_template_files(template_name).map do |path|
|
74
|
+
next unless File.file? path
|
75
|
+
next unless path =~ @@re
|
76
|
+
|
77
|
+
required_vars(path).each do |v|
|
78
|
+
vars[v] = v
|
79
|
+
end
|
80
|
+
end
|
81
|
+
vars.keys.sort
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.templates
|
85
|
+
get_project_template_files.map do |path|
|
86
|
+
# Remove the base path
|
87
|
+
path.sub! user_template_directory + '/', ''
|
88
|
+
path
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.required_vars f
|
93
|
+
vars = {}
|
94
|
+
IO.readlines(f).each do |l|
|
95
|
+
l =~ /(<%=)\s*(\S+)\s*(%>)/
|
96
|
+
if $&
|
97
|
+
varname = $2
|
98
|
+
varname.strip!
|
99
|
+
varname = varname.split('.').first
|
100
|
+
vars[varname] = varname
|
101
|
+
end
|
102
|
+
end
|
103
|
+
vars.keys
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
# Isolate any methods that touch the file system so we can test more easily
|
110
|
+
def self.get_projects_directories
|
111
|
+
Dir.glob user_template_directory + '/*'
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.get_project_template_files
|
115
|
+
Dir.glob user_template_directory + '/*'
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.selected_template_files template_name
|
119
|
+
# template_name.identifier_to_path!
|
120
|
+
Dir.glob user_template_directory + '/' + template_name + '/**/*'
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.add_user_haz_vars
|
124
|
+
if File.exist?(File.expand_path( '~/.rhesus/haz_vars.txt'))
|
125
|
+
IO.readlines(File.expand_path( '~/.rhesus/haz_vars.txt')).each { |x| haz_vars << x.strip unless x.strip.empty? }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.user_dir_exists?
|
130
|
+
File.exists? user_template_directory
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.user_template_directory
|
134
|
+
File.expand_path "~/.rhesus"
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.process template_name, var_set, location, path
|
138
|
+
relative_path = path.sub user_template_directory , ''
|
139
|
+
short_path = path.sub user_template_directory, ''
|
140
|
+
real_path = short_path.sub(template_name + '/', '')
|
141
|
+
var_set.each { |k,v| real_path.gsub!( k, v.to_snake_case ) }
|
142
|
+
write_to = location + real_path
|
143
|
+
destination_dir = File.expand_path(File.dirname(write_to))
|
144
|
+
FileUtils.mkdir_p destination_dir
|
145
|
+
|
146
|
+
# Do a straight file copy unless this file might be using Erb
|
147
|
+
if path =~ @@re
|
148
|
+
text = process_template path, var_set
|
149
|
+
File.open(File.expand_path(write_to), "w"){|f| f.puts text }
|
150
|
+
else
|
151
|
+
FileUtils.cp path, File.expand_path( write_to )
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/rhesus/utils.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rhesus/core'
|
3
|
+
|
4
|
+
def snake_case name
|
5
|
+
name.gsub(/\B[A-Z]/, '_\&').downcase
|
6
|
+
end
|
7
|
+
|
8
|
+
def template_base_dir
|
9
|
+
File.expand_path( File.join( File.dirname(__FILE__), '..', 'templates' ) )
|
10
|
+
end
|
11
|
+
|
12
|
+
def copy_over_prebuilt_template base_path, name
|
13
|
+
%w{model view controller ui}.each do |unit|
|
14
|
+
FileUtils.mkdir_p File.join(base_path, name)
|
15
|
+
from = File.join( template_base_dir, name , name + '_' + unit + '.rb')
|
16
|
+
dest = File.join(base_path, name, name + '_' + unit + '.rb' )
|
17
|
+
warn "cp '#{from}' to '#{dest}'"
|
18
|
+
FileUtils.cp from, dest
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup_directory path
|
23
|
+
FileUtils.mkdir_p path.gsub("\\", "/")
|
24
|
+
FileUtils.cd path
|
25
|
+
path.split("/").last
|
26
|
+
end
|
27
|
+
|
28
|
+
def camelize name, first_letter_in_uppercase = true
|
29
|
+
name = name.to_s
|
30
|
+
if first_letter_in_uppercase
|
31
|
+
name.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
32
|
+
else
|
33
|
+
name[0..0] + camelize( name[1..-1])
|
34
|
+
end
|
35
|
+
end
|
data/lib/rhesus.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Neurogami
|
2
|
+
|
3
|
+
module Rhesus
|
4
|
+
|
5
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
6
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
7
|
+
|
8
|
+
# Returns the library path for the module. If any arguments are given,
|
9
|
+
# they will be joined to the end of the libray path using
|
10
|
+
# <tt>File.join</tt>.
|
11
|
+
#
|
12
|
+
def self.libpath *args
|
13
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the lpath for the module. If any arguments are given,
|
17
|
+
# they will be joined to the end of the path using
|
18
|
+
# <tt>File.join</tt>.
|
19
|
+
#
|
20
|
+
def self.path *args
|
21
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
25
|
+
# directory below this file that has the same name as the filename passed
|
26
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
27
|
+
# the _filename_ does not have to be equivalent to the directory.
|
28
|
+
#
|
29
|
+
def self.require_all_libs_relative_to fname, dir = nil
|
30
|
+
dir ||= ::File.basename fname, '.*'
|
31
|
+
search_me = ::File.expand_path(
|
32
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
33
|
+
|
34
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
35
|
+
end
|
36
|
+
|
37
|
+
end # module Rhesus
|
38
|
+
|
39
|
+
Rhesus.require_all_libs_relative_to __FILE__
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'mb_swing_wrappers'
|
2
|
+
include Monkeybars::Swing
|
3
|
+
|
4
|
+
class AboutFrame < Frame
|
5
|
+
|
6
|
+
FRAME_WIDTH = 600
|
7
|
+
FRAME_HEIGHT = 130
|
8
|
+
|
9
|
+
LABEL_WIDTH = 400
|
10
|
+
LABEL_HEIGHT = 60
|
11
|
+
|
12
|
+
# Make sure our components are available!
|
13
|
+
attr_accessor :default_button, :default_label, :menu_bar, :about_menu, :exit_menu
|
14
|
+
|
15
|
+
def initialize *args
|
16
|
+
super
|
17
|
+
self.minimum_width = FRAME_WIDTH
|
18
|
+
self.minimum_height = FRAME_HEIGHT
|
19
|
+
set_up_components
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_up_components
|
23
|
+
component_panel = Panel.new
|
24
|
+
|
25
|
+
# If we were clever we would define a method that took a single hex value, like CSS.
|
26
|
+
component_panel.background_color 255, 255, 255
|
27
|
+
component_panel.size FRAME_WIDTH, FRAME_HEIGHT
|
28
|
+
|
29
|
+
# This code uses the MiG layout manager.
|
30
|
+
# To learn more about MiGLayout, see:
|
31
|
+
# http://www.miglayout.com/
|
32
|
+
component_panel.layout = Java::net::miginfocom::swing::MigLayout.new("wrap 2")
|
33
|
+
|
34
|
+
@default_label = Label.new do |l|
|
35
|
+
# A nicer way to set fonts would be welcome
|
36
|
+
l.font = java::awt.Font.new "Lucida Grande", 0, 18
|
37
|
+
l.minimum_dimensions LABEL_WIDTH, LABEL_HEIGHT
|
38
|
+
l.text = "ABOUT: Neurogami::SwingSet rulez!"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add components to panel
|
42
|
+
component_panel.add @default_label, "gap unrelated"
|
43
|
+
add component_panel
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class __NAME__Controller < ApplicationController
|
2
|
+
set_model '__NAME__Model'
|
3
|
+
set_view '__NAME__View'
|
4
|
+
|
5
|
+
|
6
|
+
def default_button_action_performed
|
7
|
+
transfer[:new_text] = "In-line Swing classes from Ruby rulez!"
|
8
|
+
signal :set_new_text
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def about_menu_action_performed
|
13
|
+
AboutController.instance.show
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def exit_menu_action_performed
|
18
|
+
close
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# Your View class will almost certainly need a Java Swing class to show to the user.
|
2
|
+
#
|
3
|
+
# To understand how Monkeybars views work, see:
|
4
|
+
#
|
5
|
+
# http://wwww.jimpanzee.org/understanding-views
|
6
|
+
#
|
7
|
+
# Each View class has a class method, 'set_java_class', to which you pass
|
8
|
+
# the Swing class to use for the actual GUI.
|
9
|
+
#
|
10
|
+
# It accepts either a string or a class constant.
|
11
|
+
# If you pass a string, the View class will look for a compiled Java file of that name
|
12
|
+
# and use that:
|
13
|
+
#
|
14
|
+
# set_java_class 'basic.ExampleFrame'
|
15
|
+
# # assumes you are providing the Java Swing class ExampleFrame.class, in the package 'basic'
|
16
|
+
# # and that it is on the $LOAD_PATH
|
17
|
+
#
|
18
|
+
# If passed a class constant, the View class assumes it already exists and uses it.
|
19
|
+
#
|
20
|
+
# set_java_class ExampleFrame
|
21
|
+
# # assumes you are have defined the Ruby class ExampleFrame and that it
|
22
|
+
# # embodies a usable Swing class.
|
23
|
+
#
|
24
|
+
# If you are creating a complex application you would do best to use a WYSIWYG Swing editor
|
25
|
+
# (such as provided for free in Netbeans) and compiling the resulting code to a .class file.
|
26
|
+
#
|
27
|
+
# However, if you prefer to define your UI using Ruby you can do so by creating a class
|
28
|
+
# that inherits, for example, from javax::swing.JPanel
|
29
|
+
#
|
30
|
+
# The generated code presented here defines some simple Ruby classes to wrap a few Swing components.
|
31
|
+
# It is meant to give some idea on how this can be done; it is by no means a complete Ruby/Swing UI tool.
|
32
|
+
#
|
33
|
+
# Note that you don't have to place this code in the same file as your Monkeybars View class,
|
34
|
+
# but it needs to be processed before your view code sets its Java class.
|
35
|
+
|
36
|
+
|
37
|
+
require 'mb_swing_wrappers'
|
38
|
+
include Monkeybars::Swing
|
39
|
+
|
40
|
+
|
41
|
+
# This is the main class used by your view.
|
42
|
+
#
|
43
|
+
# Important: Make sure that all components are exposed as accessors so
|
44
|
+
# that the View code can use them.
|
45
|
+
class __NAME__Frame < Frame
|
46
|
+
|
47
|
+
FRAME_WIDTH = 600
|
48
|
+
FRAME_HEIGHT = 130
|
49
|
+
|
50
|
+
LABEL_WIDTH = 400
|
51
|
+
LABEL_HEIGHT = 60
|
52
|
+
|
53
|
+
# Make sure our components are available!
|
54
|
+
attr_accessor :default_button, :default_label, :menu_bar, :about_menu, :exit_menu
|
55
|
+
|
56
|
+
def about_menu
|
57
|
+
@about_menu
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize args
|
61
|
+
super
|
62
|
+
self.minimum_width = FRAME_WIDTH
|
63
|
+
self.minimum_height = FRAME_HEIGHT
|
64
|
+
set_up_components
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_up_components
|
68
|
+
component_panel = Panel.new
|
69
|
+
|
70
|
+
# If we were clever we would define a method that took a single hex value, like CSS.
|
71
|
+
component_panel.background_color 255, 255, 255
|
72
|
+
component_panel.size FRAME_WIDTH, FRAME_HEIGHT
|
73
|
+
|
74
|
+
# This code uses the MiG layout manager.
|
75
|
+
# To learn more about MiGLayout, see:
|
76
|
+
# http://www.miglayout.com/
|
77
|
+
component_panel.layout = Java::net::miginfocom::swing::MigLayout.new("wrap 2")
|
78
|
+
|
79
|
+
@menu_bar = MenuBar.new do |menu_bar|
|
80
|
+
@file_menu = Menu.new do |m|
|
81
|
+
|
82
|
+
@exit_menu = MenuItem.new do |mi|
|
83
|
+
mi.name = 'exit_menu'
|
84
|
+
mi.mnemonic= Monkeybars::Key.symbol_to_code :VK_X
|
85
|
+
mi.text ="Exit"
|
86
|
+
end
|
87
|
+
|
88
|
+
m.name = 'file_menu'
|
89
|
+
m.text ="File"
|
90
|
+
m.add exit_menu
|
91
|
+
end
|
92
|
+
|
93
|
+
@help_menu = Menu.new do |m|
|
94
|
+
@about_menu = MenuItem.new do |mi|
|
95
|
+
mi.name = 'about_menu'
|
96
|
+
mi.mnemonic= Monkeybars::Key.symbol_to_code :VK_A
|
97
|
+
mi.text ="About"
|
98
|
+
end
|
99
|
+
|
100
|
+
m.name = 'help_menu'
|
101
|
+
m.text = 'Help'
|
102
|
+
m.add about_menu
|
103
|
+
end
|
104
|
+
# Worth noting: you can add the mnu item objects directly, which NetBeans doesn't seem to allow
|
105
|
+
menu_bar.add @file_menu
|
106
|
+
menu_bar.add @help_menu
|
107
|
+
set_jmenu_bar menu_bar
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
@default_label = Label.new do |l|
|
112
|
+
# A nicer way to set fonts would be welcome
|
113
|
+
l.font = java::awt.Font.new "Lucida Grande", 0, 18
|
114
|
+
l.minimum_dimensions LABEL_WIDTH, LABEL_HEIGHT
|
115
|
+
l.text = "Neurogami::SwingSet rulez!"
|
116
|
+
end
|
117
|
+
|
118
|
+
# We need to set a name so that the controller can catch events from this button
|
119
|
+
@default_button = Button.new do |b|
|
120
|
+
b.name = "default_button"
|
121
|
+
b.text = "Click me!"
|
122
|
+
end
|
123
|
+
|
124
|
+
# Add components to panel
|
125
|
+
component_panel.add @default_button, 'grow x'
|
126
|
+
component_panel.add @default_label, "gap unrelated"
|
127
|
+
add component_panel
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require '__name___ui'
|
2
|
+
|
3
|
+
# This is our Monkeybars View code
|
4
|
+
class __NAME__View < ApplicationView
|
5
|
+
set_java_class __NAME__Frame # Defined in __name___ui.rb
|
6
|
+
|
7
|
+
# Signals are a way to have the controller pass requests to the view.
|
8
|
+
# To understand Moneybars signals, see:
|
9
|
+
# http://www.jimpanzee.org/understanding-signals
|
10
|
+
define_signal :name => :set_new_text , :handler => :handle_new_text
|
11
|
+
|
12
|
+
# @load@ is called when the UI is opened. You can think of it as a subsitute for 'initialize',
|
13
|
+
# which, in the parent code, is already used for high-lelve preperations and should not
|
14
|
+
# be replaced without a good understanding of how it works.
|
15
|
+
#
|
16
|
+
# To understand the Monkeybars View lifecycle, see:
|
17
|
+
# http://www.jimpanzee.org/understanding-views
|
18
|
+
def load
|
19
|
+
# Helper method defined in application_view ro all views can use it
|
20
|
+
set_frame_icon 'images/mb_default_icon_16x16.png'
|
21
|
+
move_to_center # Built in to each Monkeybars View class.
|
22
|
+
# Set up some basics content for our UI ...
|
23
|
+
default_label.text = "Monkeybars is the bomb!"
|
24
|
+
end
|
25
|
+
|
26
|
+
# This is the method invoked when the view receives the set_new_text signal
|
27
|
+
# is received. All such signal handlers need to accept model and transfer objects.
|
28
|
+
#
|
29
|
+
# To understand Moneybars signals, see:
|
30
|
+
# http://www.jimpanzee.org/understanding-signals
|
31
|
+
def handle_new_text model, transfer
|
32
|
+
default_label.text = transfer[:new_text]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/version.rb
ADDED
data/spec/rhesus_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(
|
3
|
+
File.join(File.dirname(__FILE__), %w[.. lib rhesus]))
|
4
|
+
|
5
|
+
Spec::Runner.configure do |config|
|
6
|
+
# == Mock Framework
|
7
|
+
#
|
8
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
9
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
10
|
+
#
|
11
|
+
# config.mock_with :mocha
|
12
|
+
# config.mock_with :flexmock
|
13
|
+
# config.mock_with :rr
|
14
|
+
end
|
15
|
+
|
16
|
+
# EOF
|
data/test/.bacon
ADDED
File without changes
|
data/test/test_rhesus.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bacon'
|
3
|
+
require 'lib/rhesus/core'
|
4
|
+
|
5
|
+
describe 'A rhesus directory' do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@nrc = Neurogami::Rhesus::Core
|
9
|
+
class Neurogami::Rhesus::Core
|
10
|
+
#def self.user_template_directory
|
11
|
+
# "~/.rhesus"
|
12
|
+
#end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
it 'should be in the home directory' do
|
20
|
+
@nrc.user_template_directory.should.equal '/home/james/.rhesus'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should exist' do
|
24
|
+
@nrc.user_dir_exists?.should.equal true
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should not be empty ' do
|
28
|
+
@nrc.projects.size.should.not.equal 0
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should hold 5 project templates ' do
|
32
|
+
@nrc.templates.size.should.equal 5
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
#it 'should have 4 files in the monkeybars:about template set' do
|
37
|
+
#end
|
38
|
+
|
39
|
+
#it 'returns a project template reference given the qualified name "monkeybars:about"' do
|
40
|
+
# pt = @nrc.get "monkeybars:about"
|
41
|
+
# pt.class.should.equal Neurogami::Rhesus::TemplateSet
|
42
|
+
#end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
__END__
|
47
|
+
|
48
|
+
What are the key useful things we might want?
|
49
|
+
|
50
|
+
* List available templates
|
51
|
+
* Use one of those templates
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Neurogami-rhesus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Britt / Neurogami
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-30 00:00:00 -07:00
|
13
|
+
default_executable: rhesus
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bones
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.5.0
|
24
|
+
version:
|
25
|
+
description: Rhesus is a script for copying over pre-built templates with optional embedded Erb stuff. It started as a way to make jump-starting Monkeybars apps easier, but the user-defined tempaltes need not have anything to do with Monkeybars.
|
26
|
+
email: james@neurogami.com
|
27
|
+
executables:
|
28
|
+
- rhesus
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- bin/rhesus
|
35
|
+
files:
|
36
|
+
- History.txt
|
37
|
+
- Manifest.txt
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- bin/rhesus
|
41
|
+
- lib/rhesus.rb
|
42
|
+
- lib/rhesus/core.rb
|
43
|
+
- lib/rhesus/utils.rb
|
44
|
+
- lib/templates/about/about_controller.rb
|
45
|
+
- lib/templates/about/about_model.rb
|
46
|
+
- lib/templates/about/about_ui.rb
|
47
|
+
- lib/templates/about/about_view.rb
|
48
|
+
- lib/templates/basic/basic_controller.rb
|
49
|
+
- lib/templates/basic/basic_model.rb
|
50
|
+
- lib/templates/basic/basic_ui.rb
|
51
|
+
- lib/templates/basic/basic_view.rb
|
52
|
+
- lib/version.rb
|
53
|
+
- spec/rhesus_spec.rb
|
54
|
+
- spec/spec_helper.rb
|
55
|
+
- test/.bacon
|
56
|
+
- test/test_rhesus.rb
|
57
|
+
has_rdoc: false
|
58
|
+
homepage: http://code.neurogami.com
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options:
|
61
|
+
- --main
|
62
|
+
- README.md
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
76
|
+
version:
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project: !binary |
|
80
|
+
AA==
|
81
|
+
|
82
|
+
rubygems_version: 1.2.0
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Really simple, practical code generator.
|
86
|
+
test_files:
|
87
|
+
- test/test_rhesus.rb
|